diff --git a/client/pom.xml b/client/pom.xml index ebbef30..b9eb186 100644 --- a/client/pom.xml +++ b/client/pom.xml @@ -21,13 +21,7 @@ commons 0.0.1-SNAPSHOT - - - org.slf4j - slf4j-api - 2.0.17 - compile - + com.fasterxml.jackson.core jackson-databind diff --git a/client/src/main/java/client/Ingredient/IngredientController.java b/client/src/main/java/client/Ingredient/IngredientController.java index e674ab6..429fecd 100644 --- a/client/src/main/java/client/Ingredient/IngredientController.java +++ b/client/src/main/java/client/Ingredient/IngredientController.java @@ -23,7 +23,7 @@ public class IngredientController { private final RestTemplate restTemplate = new RestTemplate(); // Simplified REST client @FXML - public void handleDeleteIngredient(ActionEvent event) { + private void handleDeleteIngredient(ActionEvent event) { // Get selected ingredient Ingredient selectedIngredient = ingredientListView.getSelectionModel().getSelectedItem(); if (selectedIngredient == null) { diff --git a/client/src/main/java/client/MyModule.java b/client/src/main/java/client/MyModule.java index 14eaa3e..4d027ca 100644 --- a/client/src/main/java/client/MyModule.java +++ b/client/src/main/java/client/MyModule.java @@ -21,11 +21,6 @@ import client.scenes.nutrition.NutritionDetailsCtrl; import client.scenes.nutrition.NutritionViewCtrl; import client.scenes.recipe.IngredientListCtrl; import client.scenes.recipe.RecipeStepListCtrl; -import client.scenes.shopping.ShoppingListCtrl; -import client.scenes.shopping.ShoppingListNewItemPromptCtrl; -import client.service.ShoppingListService; -import client.service.ShoppingListServiceImpl; -import client.service.ShoppingListViewModel; import client.utils.ConfigService; import client.utils.LocaleManager; import client.utils.server.ServerUtils; @@ -62,10 +57,6 @@ public class MyModule implements Module { binder.bind(new TypeLiteral>() {}).toInstance( new WebSocketDataService<>() ); - binder.bind(ShoppingListNewItemPromptCtrl.class).in(Scopes.SINGLETON); - binder.bind(ShoppingListCtrl.class).in(Scopes.SINGLETON); - binder.bind(ShoppingListViewModel.class).toInstance(new ShoppingListViewModel()); - binder.bind(ShoppingListService.class).to(ShoppingListServiceImpl.class); binder.bind(new TypeLiteral>() {}).toInstance( new WebSocketDataService<>() ); diff --git a/client/src/main/java/client/UI.java b/client/src/main/java/client/UI.java index da3a2b3..752dbaf 100644 --- a/client/src/main/java/client/UI.java +++ b/client/src/main/java/client/UI.java @@ -2,7 +2,6 @@ package client; import client.scenes.FoodpalApplicationCtrl; import client.scenes.MainCtrl; -import client.scenes.ServerConnectionDialogCtrl; import client.utils.server.ServerUtils; import com.google.inject.Injector; import javafx.application.Application; @@ -28,14 +27,9 @@ public class UI extends Application { var serverUtils = INJECTOR.getInstance(ServerUtils.class); if (!serverUtils.isServerAvailable()) { - var connectionHandler = INJECTOR.getInstance(ServerConnectionDialogCtrl.class); - boolean serverConnected = connectionHandler.promptForURL(); - - if(!serverConnected){ - var msg = "User Cancelled Server connection. Shutting down"; - System.err.print(msg); - return; - } + var msg = "Server needs to be started before the client, but it does not seem to be available. Shutting down."; + System.err.println(msg); + return; } var foodpal = FXML.load(FoodpalApplicationCtrl.class, "client", "scenes", "FoodpalApplication.fxml"); diff --git a/client/src/main/java/client/exception/DuplicateIngredientException.java b/client/src/main/java/client/exception/DuplicateIngredientException.java deleted file mode 100644 index af04346..0000000 --- a/client/src/main/java/client/exception/DuplicateIngredientException.java +++ /dev/null @@ -1,20 +0,0 @@ -package client.exception; - -public class DuplicateIngredientException extends Exception{ - private final String ingredientName; - - public DuplicateIngredientException(String ingredientName){ - super("An ingredient with name " + ingredientName + " already exists, please provide a different name"); - this.ingredientName = ingredientName; - } - - public DuplicateIngredientException(String ingredientName, String message){ - super(message); - this.ingredientName = ingredientName; - } - - public String getIngredientName() { - return ingredientName; - } - -} diff --git a/client/src/main/java/client/scenes/FoodpalApplicationCtrl.java b/client/src/main/java/client/scenes/FoodpalApplicationCtrl.java index 181279b..e7cb0df 100644 --- a/client/src/main/java/client/scenes/FoodpalApplicationCtrl.java +++ b/client/src/main/java/client/scenes/FoodpalApplicationCtrl.java @@ -2,17 +2,17 @@ package client.scenes; import java.io.IOException; +import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Optional; import java.util.logging.Logger; +import java.util.stream.Collectors; -import client.UI; import client.exception.InvalidModificationException; import client.scenes.nutrition.NutritionViewCtrl; import client.scenes.recipe.RecipeDetailCtrl; -import client.scenes.shopping.ShoppingListCtrl; import client.utils.Config; import client.utils.ConfigService; import client.utils.DefaultValueFactory; @@ -21,6 +21,7 @@ import client.utils.LocaleManager; import client.utils.server.ServerUtils; import client.utils.WebSocketDataService; import client.utils.WebSocketUtils; +import commons.Ingredient; import commons.Recipe; import commons.ws.Topics; @@ -31,20 +32,14 @@ import commons.ws.messages.Message; import commons.ws.messages.UpdateRecipeMessage; import jakarta.inject.Inject; import javafx.application.Platform; -import javafx.beans.property.ListProperty; -import javafx.beans.property.SimpleListProperty; -import javafx.collections.FXCollections; -import javafx.collections.ListChangeListener; import javafx.fxml.FXML; -import javafx.scene.Scene; import javafx.scene.control.Alert; import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.control.ListCell; import javafx.scene.control.ListView; +import javafx.scene.control.TextInputDialog; import javafx.scene.control.ToggleButton; -import javafx.scene.paint.Color; -import javafx.stage.Stage; import org.apache.commons.lang3.NotImplementedException; import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Pair; @@ -70,7 +65,8 @@ public class FoodpalApplicationCtrl implements LocaleAware { @FXML public ListView recipeList; - private final ListProperty favouriteRecipeList = new SimpleListProperty<>(); + @FXML + private ListView ingredientListView; @FXML private Button addRecipeButton; @@ -88,8 +84,7 @@ public class FoodpalApplicationCtrl implements LocaleAware { @FXML private ToggleButton favouritesOnlyToggle; - @FXML - private Button manageIngredientsButton; + private List allRecipes = new ArrayList<>(); @FXML private Label updatedBadge; @@ -205,12 +200,6 @@ public class FoodpalApplicationCtrl implements LocaleAware { } //gives star in front fav items boolean fav = config.isFavourite(item.getId()); setText((fav ? "★ " : "") + item.getName()); - - if(fav){ - setTextFill(Color.BLUE); - }else{ - setTextFill(Color.BLACK); - } } }); // When your selection changes, update details in the panel @@ -288,13 +277,6 @@ public class FoodpalApplicationCtrl implements LocaleAware { openSelectedRecipe(); } }); - recipeList.getItems().addListener((ListChangeListener.Change c) -> { - favouriteRecipeList.set( - FXCollections.observableList( - recipeList.getItems().stream().filter(r -> config.isFavourite(r.getId())).toList() - )); - System.out.println(favouriteRecipeList); - }); this.initializeSearchBar(); refresh(); @@ -308,9 +290,6 @@ public class FoodpalApplicationCtrl implements LocaleAware { removeRecipeButton.setText(getLocaleString("menu.button.remove.recipe")); cloneRecipeButton.setText(getLocaleString("menu.button.clone")); recipesLabel.setText(getLocaleString("menu.label.recipes")); - - favouritesOnlyToggle.setText(getLocaleString("menu.button.favourites")); - manageIngredientsButton.setText(getLocaleString("menu.button.ingredients")); } @Override @@ -333,7 +312,8 @@ public class FoodpalApplicationCtrl implements LocaleAware { logger.severe(msg); printError(msg); } - recipeList.getItems().setAll(recipes); + + allRecipes = new ArrayList<>(recipes); applyRecipeFilterAndKeepSelection(); showUpdatedBadge(); @@ -429,21 +409,17 @@ public class FoodpalApplicationCtrl implements LocaleAware { public void applyRecipeFilterAndKeepSelection() { Recipe selected = recipeList.getSelectionModel().getSelectedItem(); Long selectedId = selected == null ? null : selected.getId(); - List view = recipeList.getItems().stream().toList(); + + List view = allRecipes; if (favouritesOnlyToggle != null && favouritesOnlyToggle.isSelected()) { - view = favouriteRecipeList.get(); - recipeList.getItems().setAll(view); - } - try { - if (favouritesOnlyToggle != null && !favouritesOnlyToggle.isSelected()) { - recipeList.getItems().setAll(server.getRecipes(config.getRecipeLanguages())); - } - } - catch (IOException | InterruptedException e) { - logger.severe(e.getMessage()); + view = allRecipes.stream() + .filter(r -> config.isFavourite(r.getId())) + .collect(Collectors.toList()); } + recipeList.getItems().setAll(view); + // restore selection if possible if (selectedId != null) { Recipe match = view.stream() @@ -463,6 +439,114 @@ public class FoodpalApplicationCtrl implements LocaleAware { this.recipeDetailController.refreshFavouriteButton(); this.recipeDetailController.setVisible(!recipeList.getItems().isEmpty()); } + + //Delete Ingredient button click + @FXML + private void handleDeleteIngredient() { + // Get selected ingredient + Ingredient selectedIngredient = ingredientListView.getSelectionModel().getSelectedItem(); + + if (selectedIngredient == null) { + // Show an error message if no ingredient is selected + showError("No ingredient selected", "Please select an ingredient to delete."); + return; + } + + // Check if the ingredient is used in any recipe + checkIngredientUsage(selectedIngredient); + } + + // Check if ingredient is used in any recipe before deleting + private void checkIngredientUsage(Ingredient ingredient) { + try { + long usageCount = server.getIngredientUsage(ingredient.getId()); // Check ingredient usage via ServerUtils + + if (usageCount > 0) { + // If ingredient is used, show a warning dialog + showWarningDialog(ingredient, usageCount); + } else { + // If not used, delete + deleteIngredient(ingredient); + } + } catch (IOException | InterruptedException e) { + showError("Error", "Failed to check ingredient usage: " + e.getMessage()); + } + } + + private void deleteIngredient(Ingredient ingredient) { + try { + server.deleteIngredient(ingredient.getId()); // Call ServerUtils to delete the ingredient + showConfirmation("Success", "Ingredient '" + ingredient.getName() + "' has been deleted."); + refreshIngredientList(); // refresh the ingredient list + } catch (IOException | InterruptedException e) { + showError("Error", "Failed to delete ingredient: " + e.getMessage()); + } + } + + private void showWarningDialog(Ingredient ingredient, long usedInRecipes) { + Alert alert = new Alert(Alert.AlertType.WARNING); + } + + private void showError(String title, String message) { + Alert alert = new Alert(Alert.AlertType.ERROR); + alert.setTitle(title); + alert.setHeaderText(null); + alert.setContentText(message); + alert.showAndWait(); + } + + private void showConfirmation(String title, String message) { + Alert alert = new Alert(Alert.AlertType.INFORMATION); + alert.setTitle(title); + alert.setHeaderText(null); + alert.setContentText(message); + alert.showAndWait(); + } + + private void refreshIngredientList() { + // Refresh + ingredientListView.getItems().clear(); + + } + + + @FXML + private void handleAddIngredient() { + //ask the user for the ingredient name + TextInputDialog dialog = new TextInputDialog(); + dialog.setTitle("Add Ingredient"); + dialog.setHeaderText("Enter the ingredient name:"); + dialog.setContentText("Ingredient:"); + + // Wait for the user to enter a value + Optional result = dialog.showAndWait(); + + result.ifPresent(name -> { + // Create a new Ingredient object + Ingredient newIngredient = new Ingredient(); + newIngredient.setName(name); + + // Add the new ingredient to the ListView + ingredientListView.getItems().add(newIngredient); + }); + } + + // display ingredient name + @FXML + private void initializeIngredients() { + ingredientListView.setCellFactory(list -> new ListCell() { + @Override + protected void updateItem(Ingredient item, boolean empty) { + super.updateItem(item, empty); + if (empty || item == null) { + setText(null); + } else { + setText(item.getName()); // Display the ingredient name in the ListView + } + } + }); + } + @FXML private void openIngredientsPopup() { try { @@ -474,7 +558,7 @@ public class FoodpalApplicationCtrl implements LocaleAware { var root = pair.getValue(); var stage = new javafx.stage.Stage(); - stage.setTitle(getLocaleString("menu.ingredients.title")); + stage.setTitle("Nutrition values view"); stage.initModality(javafx.stage.Modality.APPLICATION_MODAL); stage.setScene(new javafx.scene.Scene(root)); stage.showAndWait(); @@ -514,14 +598,6 @@ public class FoodpalApplicationCtrl implements LocaleAware { updatedBadgeTimer.playFromStart(); } - public void openShoppingListWindow() throws IOException { - var root = UI.getFXML().load(ShoppingListCtrl.class, "client", "scenes", "shopping", "ShoppingList.fxml"); - Stage stage = new Stage(); - stage.setTitle(this.getLocaleString("menu.shopping.title")); - stage.setScene(new Scene(root.getValue())); - stage.show(); - } - } diff --git a/client/src/main/java/client/scenes/Ingredient/IngredientListCtrl.java b/client/src/main/java/client/scenes/Ingredient/IngredientListCtrl.java index c06a04a..dfcd7be 100644 --- a/client/src/main/java/client/scenes/Ingredient/IngredientListCtrl.java +++ b/client/src/main/java/client/scenes/Ingredient/IngredientListCtrl.java @@ -1,17 +1,11 @@ package client.scenes.Ingredient; -import client.exception.DuplicateIngredientException; import client.scenes.nutrition.NutritionDetailsCtrl; -import client.utils.LocaleAware; -import client.utils.LocaleManager; import client.utils.server.ServerUtils; import commons.Ingredient; import jakarta.inject.Inject; import javafx.fxml.FXML; - import javafx.scene.control.Alert; -import javafx.scene.control.Button; -import javafx.scene.control.Label; import javafx.scene.control.ListCell; import javafx.scene.control.ListView; import javafx.scene.control.TextInputDialog; @@ -25,18 +19,10 @@ import java.util.logging.Logger; //TODO and check for capital letter milk and MILK are seen as different -public class IngredientListCtrl implements LocaleAware { +public class IngredientListCtrl { + private final ServerUtils server; - private final LocaleManager localeManager; private final Logger logger = Logger.getLogger(IngredientListCtrl.class.getName()); - - @FXML - public Label ingredientsLabel; - public Button addButton; - public Button refreshButton; - public Button deleteButton; - public Button closeButton; - @FXML private ListView ingredientListView; @FXML @@ -45,30 +31,14 @@ public class IngredientListCtrl implements LocaleAware { @Inject public IngredientListCtrl( ServerUtils server, - LocaleManager localeManager, NutritionDetailsCtrl nutritionDetailsCtrl ) { this.server = server; - this.localeManager = localeManager; this.nutritionDetailsCtrl = nutritionDetailsCtrl; } - @Override - public void updateText() { - ingredientsLabel.setText(getLocaleString("menu.label.ingredients")); - addButton.setText(getLocaleString("menu.button.add")); - refreshButton.setText(getLocaleString("menu.button.refresh")); - deleteButton.setText(getLocaleString("menu.button.delete")); - closeButton.setText(getLocaleString("menu.button.close")); - } - - @Override - public LocaleManager getLocaleManager() { - return this.localeManager; - } - - @Override - public void initializeComponents() { + @FXML + public void initialize() { ingredientListView.setCellFactory(list -> new ListCell<>() { @Override protected void updateItem(Ingredient item, boolean empty) { @@ -90,7 +60,6 @@ public class IngredientListCtrl implements LocaleAware { refresh(); } - @FXML private void addIngredient() { TextInputDialog dialog = new TextInputDialog(); @@ -114,11 +83,10 @@ public class IngredientListCtrl implements LocaleAware { refresh(); // reload list from server } catch (IOException | InterruptedException e) { showError("Failed to create ingredient: " + e.getMessage()); - } catch (DuplicateIngredientException e) { - throw new RuntimeException(e); } } + @FXML private void refresh() { try { diff --git a/client/src/main/java/client/scenes/LangSelectMenuCtrl.java b/client/src/main/java/client/scenes/LangSelectMenuCtrl.java index 76fdef8..cc764f0 100644 --- a/client/src/main/java/client/scenes/LangSelectMenuCtrl.java +++ b/client/src/main/java/client/scenes/LangSelectMenuCtrl.java @@ -1,6 +1,5 @@ package client.scenes; -import client.utils.Config; import client.utils.LocaleAware; import client.utils.LocaleManager; import com.google.inject.Inject; @@ -42,12 +41,11 @@ public class LangSelectMenuCtrl implements LocaleAware { String lang = langSelectMenu.getSelectionModel().getSelectedItem(); logger.info("Switching locale to " + lang); manager.setLocale(Locale.of(lang)); - initializeComponents(); } @Override public void initializeComponents() { - langSelectMenu.getItems().setAll(Config.languages); + langSelectMenu.getItems().setAll("en", "pl", "nl", "zht", "zhc", "tok", "tr"); langSelectMenu.setValue(manager.getLocale().getLanguage()); langSelectMenu.setConverter(new StringConverter() { @Override diff --git a/client/src/main/java/client/scenes/LanguageFilterCtrl.java b/client/src/main/java/client/scenes/LanguageFilterCtrl.java index fd1de08..80d01a0 100644 --- a/client/src/main/java/client/scenes/LanguageFilterCtrl.java +++ b/client/src/main/java/client/scenes/LanguageFilterCtrl.java @@ -1,6 +1,5 @@ package client.scenes; -import client.utils.Config; import client.utils.ConfigService; import client.utils.LocaleAware; import client.utils.LocaleManager; @@ -55,7 +54,7 @@ public class LanguageFilterCtrl implements LocaleAware { public void initializeComponents() { var items = this.langFilterMenu.getItems(); - final List languages = List.of(Config.languages); + final List languages = List.of("en", "nl", "pl", "tok", "tr"); this.selectedLanguages = this.configService.getConfig().getRecipeLanguages(); this.updateMenuButtonDisplay(); diff --git a/client/src/main/java/client/scenes/SearchBarCtrl.java b/client/src/main/java/client/scenes/SearchBarCtrl.java index c37f188..065455c 100644 --- a/client/src/main/java/client/scenes/SearchBarCtrl.java +++ b/client/src/main/java/client/scenes/SearchBarCtrl.java @@ -10,15 +10,11 @@ import javafx.animation.PauseTransition; import javafx.concurrent.Task; import javafx.fxml.FXML; import javafx.scene.control.TextField; -import javafx.scene.input.KeyCode; import javafx.util.Duration; import java.io.IOException; -import java.util.Arrays; import java.util.List; -import java.util.Locale; import java.util.function.Consumer; -import java.util.stream.Collectors; /** * Controller for the search bar component. @@ -103,11 +99,7 @@ public class SearchBarCtrl implements LocaleAware { currentSearchTask = new Task<>() { @Override protected List call() throws IOException, InterruptedException { - var recipes = serverUtils.getRecipesFiltered( - "", - configService.getConfig().getRecipeLanguages() - ); - return applyMultiTermAndFilter(recipes, filter); + return serverUtils.getRecipesFiltered(filter, configService.getConfig().getRecipeLanguages()); } }; @@ -154,61 +146,8 @@ public class SearchBarCtrl implements LocaleAware { }); this.searchField.setOnKeyReleased(event -> { - if (event.getCode() == KeyCode.ESCAPE) { - searchField.clear(); - this.onSearch(); - return; - } // This cancels the current debounce timer and restarts it. this.searchDebounce.playFromStart(); }); } - private List applyMultiTermAndFilter(List recipes, String query) { - if (recipes == null) { - return List.of(); - } - if (query == null || query.isBlank()) { - return recipes; - } - - var tokens = Arrays.stream(query.toLowerCase(Locale.ROOT).split("[\\s,]+")) - .map(String::trim) - .filter(s -> !s.isBlank()) - .filter(s -> !s.equals("and")) - .toList(); - - if (tokens.isEmpty()) { - return recipes; - } - - return recipes.stream() - .filter(r -> { - var sb = new StringBuilder(); - - if (r.getName() != null) { - sb.append(r.getName()).append(' '); - } - - if (r.getIngredients() != null) { - r.getIngredients().forEach(i -> { - if (i != null) { - sb.append(i).append(' '); - } - }); - } - - if (r.getPreparationSteps() != null) { - r.getPreparationSteps().forEach(s -> { - if (s != null) { - sb.append(s).append(' '); - } - }); - } - - var haystack = sb.toString().toLowerCase(Locale.ROOT); - return tokens.stream().allMatch(haystack::contains); - }) - .collect(Collectors.toList()); - } - } diff --git a/client/src/main/java/client/scenes/ServerConnectionDialogCtrl.java b/client/src/main/java/client/scenes/ServerConnectionDialogCtrl.java deleted file mode 100644 index 4283d01..0000000 --- a/client/src/main/java/client/scenes/ServerConnectionDialogCtrl.java +++ /dev/null @@ -1,94 +0,0 @@ -package client.scenes; - - -import client.utils.ConfigService; -import client.utils.server.ServerUtils; -import com.google.inject.Inject; -import javafx.scene.control.Alert; -import javafx.scene.control.ButtonType; -import javafx.scene.control.TextInputDialog; - -import java.util.Optional; - - -public class ServerConnectionDialogCtrl { - - private final ConfigService configService; - private final ServerUtils serverUtils; - - - - @Inject - public ServerConnectionDialogCtrl(ConfigService configService, ServerUtils serverUtils) { - this.configService = configService; - this.serverUtils = serverUtils; - - } - - /** - * - * @return a boolean for if the user got connected to server or - */ - public boolean promptForURL(){ - Alert error = new Alert(Alert.AlertType.ERROR); //creates an error alert - error.setTitle("Server is Unavailable"); - error.setHeaderText("Unable to connect to Server"); - error.setContentText("The server at " + configService.getConfig().getServerUrl() - + " is not available\n\n Would you like to try a different Server URL?"); - - error.getButtonTypes().setAll(ButtonType.YES, ButtonType.NO); - Optional userChoice = error.showAndWait(); //asks if user wants to input server URL - - if(userChoice.isEmpty() || userChoice.get() == ButtonType.NO){ - return false; - } - - while(true){ // Keeps asking the user until either a valid url is provided or the user exits - TextInputDialog dialog = - new TextInputDialog(configService.getConfig().getServerUrl()); - dialog.setTitle("Enter new server URL"); - dialog.setContentText("Server URL:"); - Optional userRes = dialog.showAndWait(); - if(userRes.isEmpty()){ - return false; //user cancelled the operation - } - String newServer = userRes.get().trim(); - - if(newServer.isEmpty()){ - Alert alert = new Alert(Alert.AlertType.WARNING); - alert.setTitle("Invalid Input"); - alert.setHeaderText("Invalid server URL"); - alert.setContentText("Please enter a valid URL"); - alert.showAndWait(); - continue; - } - configService.getConfig().setServerUrl(newServer); - if(serverUtils.isServerAvailable()){ - configService.save(); - Alert success = new Alert(Alert.AlertType.INFORMATION); - success.setTitle("Success"); - success.setHeaderText("Connected to Server"); - success.setContentText("Successfully connected to the server!"); - success.showAndWait(); - return true; - } - else{ - Alert retry = new Alert(Alert.AlertType.ERROR); - retry.setTitle("Failed"); - retry.setHeaderText("Failed to connect to Server"); - retry.setContentText("Would you like to try another URL?"); - retry.getButtonTypes().setAll(ButtonType.YES, ButtonType.NO); - Optional result = retry.showAndWait(); - if(result.isEmpty() || result.get() == ButtonType.NO){ - return false; - } - - } - - } - } - - - - -} diff --git a/client/src/main/java/client/scenes/nutrition/NutritionDetailsCtrl.java b/client/src/main/java/client/scenes/nutrition/NutritionDetailsCtrl.java index d8351f3..c7c968f 100644 --- a/client/src/main/java/client/scenes/nutrition/NutritionDetailsCtrl.java +++ b/client/src/main/java/client/scenes/nutrition/NutritionDetailsCtrl.java @@ -66,7 +66,7 @@ public class NutritionDetailsCtrl implements LocaleAware { this.proteinInputElement.textProperty().bindBidirectional(vm.proteinProperty(), new NumberStringConverter()); this.carbInputElement.textProperty().bindBidirectional(vm.carbsProperty(), new NumberStringConverter()); this.estimatedKcalLabel.textProperty().bind(Bindings.createStringBinding( - () -> String.format("Estimated energy value: %.1f kcal/100g", vm.getKcal()), vm.kcalProperty() + () -> String.format("Estimated energy value: %.1f", vm.getKcal()), vm.kcalProperty() )); }); this.nutritionValueContainer.addEventHandler(KeyEvent.KEY_RELEASED, event -> { diff --git a/client/src/main/java/client/scenes/recipe/IngredientListCtrl.java b/client/src/main/java/client/scenes/recipe/IngredientListCtrl.java index 679e05d..7bb392f 100644 --- a/client/src/main/java/client/scenes/recipe/IngredientListCtrl.java +++ b/client/src/main/java/client/scenes/recipe/IngredientListCtrl.java @@ -8,7 +8,6 @@ import com.google.inject.Inject; import commons.FormalIngredient; import commons.Recipe; import java.util.ArrayList; -import java.util.Comparator; import java.util.List; import java.util.function.Consumer; @@ -79,13 +78,7 @@ public class IngredientListCtrl implements LocaleAware { if (recipe == null) { this.ingredients = FXCollections.observableArrayList(new ArrayList<>()); } else { - List ingredientList = recipe - .getIngredients() - .stream() - .sorted(Comparator.comparing(ingredient -> ingredient - .getIngredient() - .getName())) - .toList(); + List ingredientList = recipe.getIngredients(); this.ingredients = FXCollections.observableArrayList(ingredientList); } diff --git a/client/src/main/java/client/scenes/recipe/IngredientsPopupCtrl.java b/client/src/main/java/client/scenes/recipe/IngredientsPopupCtrl.java index 091befd..de27245 100644 --- a/client/src/main/java/client/scenes/recipe/IngredientsPopupCtrl.java +++ b/client/src/main/java/client/scenes/recipe/IngredientsPopupCtrl.java @@ -1,7 +1,6 @@ package client.scenes.recipe; import client.utils.server.ServerUtils; -import client.exception.DuplicateIngredientException; import commons.Ingredient; import jakarta.inject.Inject; import javafx.fxml.FXML; @@ -68,15 +67,8 @@ public class IngredientsPopupCtrl { server.createIngredient(name); // calls POST /api/ingredients refresh(); // reload list from server } catch (IOException | InterruptedException e) { - showError("Failed to create ingredient: " + e.getMessage()); - } catch (DuplicateIngredientException e) { - showError("An ingredient with the name " + name + " already exists." + - " Please provide a different name."); //checks if error received has the DUPLICATE string and creates a showError instance with an appropriate error message and description - } - - } diff --git a/client/src/main/java/client/scenes/recipe/RecipeDetailCtrl.java b/client/src/main/java/client/scenes/recipe/RecipeDetailCtrl.java index d923ffd..d072669 100644 --- a/client/src/main/java/client/scenes/recipe/RecipeDetailCtrl.java +++ b/client/src/main/java/client/scenes/recipe/RecipeDetailCtrl.java @@ -2,7 +2,6 @@ package client.scenes.recipe; import client.exception.UpdateException; import client.scenes.FoodpalApplicationCtrl; -import client.service.ShoppingListService; import client.utils.Config; import client.utils.ConfigService; import client.utils.LocaleAware; @@ -11,7 +10,6 @@ import client.utils.PrintExportService; import client.utils.server.ServerUtils; import client.utils.WebSocketDataService; import com.google.inject.Inject; -import commons.FormalIngredient; import commons.Recipe; import java.io.File; @@ -20,9 +18,6 @@ import java.nio.file.Path; import java.util.Optional; import java.util.function.BiConsumer; import java.util.function.Consumer; - -import javafx.beans.binding.Bindings; -import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.scene.control.Button; import javafx.scene.control.ComboBox; @@ -49,12 +44,8 @@ public class RecipeDetailCtrl implements LocaleAware { private final FoodpalApplicationCtrl appCtrl; private final ConfigService configService; private final WebSocketDataService webSocketDataService; - private final ShoppingListService shoppingListService; public Spinner scaleSpinner; - public Label inferredKcalLabel; - public Spinner servingsSpinner; - public Label inferredServeSizeLabel; @FXML private IngredientListCtrl ingredientListController; @@ -71,14 +62,12 @@ public class RecipeDetailCtrl implements LocaleAware { ServerUtils server, FoodpalApplicationCtrl appCtrl, ConfigService configService, - ShoppingListService listService, WebSocketDataService webSocketDataService) { this.localeManager = localeManager; this.server = server; this.appCtrl = appCtrl; this.configService = configService; this.webSocketDataService = webSocketDataService; - this.shoppingListService = listService; } @FXML @@ -165,20 +154,12 @@ public class RecipeDetailCtrl implements LocaleAware { // If there is a scale // Prevents issues from first startup - if (scaleSpinner.getValue() != null && servingsSpinner.getValue() != null) { + if (scaleSpinner.getValue() != null) { Double scale = scaleSpinner.getValue(); + // see impl. creates a scaled context for the recipe such that its non-scaled value is kept as a reference. this.recipeView = new ScalableRecipeView(recipe, scale); - // TODO i18n - inferredKcalLabel.textProperty().bind(Bindings.createStringBinding(() -> - String.format("Inferred %.1f kcal/100g for this recipe", - Double.isNaN(this.recipeView.scaledKcalProperty().get()) ? - 0.0 : this.recipeView.scaledKcalProperty().get()) - , this.recipeView.scaledKcalProperty())); - recipeView.servingsProperty().set(servingsSpinner.getValue()); - inferredServeSizeLabel.textProperty().bind(Bindings.createStringBinding( - () -> String.format("Inferred size per serving: %.1f g", recipeView.servingSizeProperty().get()), - recipeView.servingSizeProperty())); + // expose the scaled view to list controllers this.ingredientListController.refetchFromRecipe(this.recipeView.getScaled()); this.stepListController.refetchFromRecipe(this.recipeView.getScaled()); @@ -405,7 +386,7 @@ public class RecipeDetailCtrl implements LocaleAware { public void initializeComponents() { initStepsIngredientsList(); // creates a new scale spinner with an arbitrary max scale - scaleSpinner.setValueFactory(new SpinnerValueFactory.DoubleSpinnerValueFactory(1, Double.MAX_VALUE, 1)); + scaleSpinner.setValueFactory(new SpinnerValueFactory.DoubleSpinnerValueFactory(0, Double.MAX_VALUE, 1)); scaleSpinner.setEditable(true); scaleSpinner.valueProperty().addListener((observable, oldValue, newValue) -> { if (newValue == null) { @@ -414,23 +395,6 @@ public class RecipeDetailCtrl implements LocaleAware { // triggers a UI update each time the spinner changes to a different value. setCurrentlyViewedRecipe(recipe); }); - servingsSpinner.setValueFactory(new SpinnerValueFactory.IntegerSpinnerValueFactory(1, Integer.MAX_VALUE, 1)); - servingsSpinner.setEditable(true); - servingsSpinner.valueProperty().addListener((observable, oldValue, newValue) -> { - if (newValue == null) { - return; - } - setCurrentlyViewedRecipe(recipe); - }); - langSelector.getItems().addAll(Config.languages); - } - - public void handleAddAllToShoppingList(ActionEvent actionEvent) { - System.out.println("handleAddAllToShoppingList"); - // TODO BACKLOG Add overview screen - recipe.getIngredients().stream() - .filter(x -> x.getClass().equals(FormalIngredient.class)) - .map(FormalIngredient.class::cast) - .forEach(x -> shoppingListService.putIngredient(x, recipe)); + langSelector.getItems().addAll("en", "nl", "pl", "tok"); } } diff --git a/client/src/main/java/client/scenes/recipe/ScalableRecipeView.java b/client/src/main/java/client/scenes/recipe/ScalableRecipeView.java index e9192ab..db5de91 100644 --- a/client/src/main/java/client/scenes/recipe/ScalableRecipeView.java +++ b/client/src/main/java/client/scenes/recipe/ScalableRecipeView.java @@ -4,19 +4,14 @@ import commons.Recipe; import javafx.beans.binding.Bindings; import javafx.beans.binding.ObjectBinding; import javafx.beans.property.DoubleProperty; -import javafx.beans.property.IntegerProperty; import javafx.beans.property.ObjectProperty; import javafx.beans.property.SimpleDoubleProperty; -import javafx.beans.property.SimpleIntegerProperty; import javafx.beans.property.SimpleObjectProperty; public class ScalableRecipeView { private final ObjectProperty recipe = new SimpleObjectProperty<>(); private final ObjectProperty scaled = new SimpleObjectProperty<>(); private final DoubleProperty scale = new SimpleDoubleProperty(); - private final DoubleProperty scaledKcal = new SimpleDoubleProperty(); - private final IntegerProperty servings = new SimpleIntegerProperty(); - private final DoubleProperty servingSize = new SimpleDoubleProperty(); public ScalableRecipeView( Recipe recipe, Double scale @@ -27,11 +22,10 @@ public class ScalableRecipeView { () -> Recipe.getScaled(this.recipe.get(), this.scale.get()), this.recipe, this.scale); this.scaled.bind(binding); - this.scaledKcal.bind(Bindings.createDoubleBinding(() -> this.scaled.get().kcal(), this.scaled)); - this.servingSize.bind(Bindings.createDoubleBinding( - () -> this.scaled.get().weight() * ( 1.0 / this.servings.get()), - this.servings) - ); + } + + public double getScale() { + return scale.get(); } public Recipe getRecipe() { @@ -42,14 +36,15 @@ public class ScalableRecipeView { return scaled.get(); } - public DoubleProperty scaledKcalProperty() { - return scaledKcal; + public DoubleProperty scaleProperty() { + return scale; } - public IntegerProperty servingsProperty() { - return servings; + public ObjectProperty scaledProperty() { + return scaled; } - public DoubleProperty servingSizeProperty() { - return servingSize; + + public ObjectProperty recipeProperty() { + return recipe; } } diff --git a/client/src/main/java/client/scenes/shopping/ShoppingListCell.java b/client/src/main/java/client/scenes/shopping/ShoppingListCell.java deleted file mode 100644 index d684435..0000000 --- a/client/src/main/java/client/scenes/shopping/ShoppingListCell.java +++ /dev/null @@ -1,67 +0,0 @@ -package client.scenes.shopping; - -import client.scenes.recipe.OrderedEditableListCell; -import commons.FormalIngredient; -import javafx.scene.Node; -import javafx.scene.control.Label; -import javafx.scene.control.Spinner; -import javafx.scene.control.SpinnerValueFactory; -import javafx.scene.input.KeyCode; -import javafx.scene.input.KeyEvent; -import javafx.scene.layout.HBox; -import javafx.util.Pair; - -import java.util.Optional; - -public class ShoppingListCell extends OrderedEditableListCell>> { - private Node makeEditor() { - HBox editor = new HBox(); - Spinner amountInput = new Spinner<>(); - FormalIngredient ingredient = getItem().getKey(); - amountInput.setEditable(true); - amountInput.setValueFactory(new SpinnerValueFactory.DoubleSpinnerValueFactory(0, Double.MAX_VALUE, ingredient.getAmount())); - Label textLabel = new Label(getItem().getKey().getUnitSuffix() + " of " + getItem().getKey().getIngredient().getName()); - editor.getChildren().addAll(amountInput, textLabel); - editor.addEventHandler(KeyEvent.KEY_RELEASED, e -> { - if (e.getCode() != KeyCode.ENTER) { - return; - } - Pair> pair = getItem(); - pair.getKey().setAmount(amountInput.getValue()); - commitEdit(pair); - }); - return editor; - } - @Override - public void startEdit() { - super.startEdit(); - this.setText(""); - this.setGraphic(makeEditor()); - } - @Override - protected void updateItem(Pair> item, boolean empty) { - super.updateItem(item, empty); - - if (empty) { - this.setText(""); - return; - } - - String display = item.getKey().toString() + - item.getValue().map(recipe -> { - return " (" + recipe + ")"; - }).orElse(""); - - this.setText(display); - } - @Override - public void cancelEdit() { - super.cancelEdit(); - } - - @Override - public void commitEdit(Pair> newValue) { - super.commitEdit(newValue); - } - -} diff --git a/client/src/main/java/client/scenes/shopping/ShoppingListCtrl.java b/client/src/main/java/client/scenes/shopping/ShoppingListCtrl.java deleted file mode 100644 index ec08c62..0000000 --- a/client/src/main/java/client/scenes/shopping/ShoppingListCtrl.java +++ /dev/null @@ -1,81 +0,0 @@ -package client.scenes.shopping; - -import client.UI; -import client.service.ShoppingListService; -import client.utils.LocaleAware; -import client.utils.LocaleManager; -import com.google.inject.Inject; -import commons.FormalIngredient; -import javafx.event.ActionEvent; -import javafx.fxml.FXML; -import javafx.scene.Node; -import javafx.scene.Parent; -import javafx.scene.Scene; -import javafx.scene.control.ListView; -import javafx.stage.Modality; -import javafx.stage.Stage; -import javafx.util.Pair; - -import java.util.Optional; - -public class ShoppingListCtrl implements LocaleAware { - ShoppingListService shopping; - - LocaleManager localeManager; - - @FXML - private ListView>> shoppingListView; - @Inject - public ShoppingListCtrl( - ShoppingListService shopping, - LocaleManager localeManager - ) { - this.shopping = shopping; - this.localeManager = localeManager; - } - - @Override - public void updateText() { - - } - - @Override - public LocaleManager getLocaleManager() { - return this.localeManager; - } - - public void initializeComponents() { - this.shoppingListView.setEditable(true); - this.shoppingListView.setCellFactory(l -> new ShoppingListCell()); - this.shoppingListView.getItems().setAll( - this.shopping.getItems() - ); - } - private void refreshList() { - this.shoppingListView.getItems().setAll( - this.shopping.getItems() - ); - } - - public void handleAddItem(ActionEvent actionEvent) { - Stage stage = new Stage(); - Pair root = UI.getFXML().load(ShoppingListNewItemPromptCtrl.class, - "client", "scenes", "shopping", "ShoppingListItemAddModal.fxml"); - root.getKey().setNewValueConsumer(fi -> { - this.shopping.putIngredient(fi); - refreshList(); - }); - stage.setScene(new Scene(root.getValue())); - stage.setTitle("My modal window"); - stage.initModality(Modality.WINDOW_MODAL); - stage.initOwner( - ((Node)actionEvent.getSource()).getScene().getWindow() ); - stage.show(); - } - - public void handleRemoveItem(ActionEvent actionEvent) { - var x = this.shoppingListView.getSelectionModel().getSelectedItem(); - this.shopping.getItems().remove(x); - refreshList(); - } -} diff --git a/client/src/main/java/client/scenes/shopping/ShoppingListNewItemPromptCtrl.java b/client/src/main/java/client/scenes/shopping/ShoppingListNewItemPromptCtrl.java deleted file mode 100644 index 09bd44f..0000000 --- a/client/src/main/java/client/scenes/shopping/ShoppingListNewItemPromptCtrl.java +++ /dev/null @@ -1,96 +0,0 @@ -package client.scenes.shopping; - -import client.utils.LocaleAware; -import client.utils.LocaleManager; -import client.utils.server.ServerUtils; -import com.google.inject.Inject; -import commons.FormalIngredient; -import commons.Ingredient; -import commons.Unit; -import javafx.beans.property.ObjectProperty; -import javafx.beans.property.SimpleObjectProperty; -import javafx.event.ActionEvent; -import javafx.scene.control.MenuButton; -import javafx.scene.control.MenuItem; -import javafx.scene.control.Spinner; -import javafx.scene.control.SpinnerValueFactory; -import javafx.stage.Stage; - -import java.io.IOException; -import java.util.Arrays; -import java.util.function.Consumer; -import java.util.function.Function; - -public class ShoppingListNewItemPromptCtrl implements LocaleAware { - public MenuButton ingredientSelection; - private final ObjectProperty selected = new SimpleObjectProperty<>(); - private final ObjectProperty selectedUnit = new SimpleObjectProperty<>(); - private final ServerUtils server; - private final LocaleManager localeManager; - private Consumer newValueConsumer; - public MenuButton unitSelect; - public Spinner amountSelect; - - @Inject - public ShoppingListNewItemPromptCtrl(ServerUtils server, LocaleManager localeManager) { - this.server = server; - this.localeManager = localeManager; - } - - public void setNewValueConsumer(Consumer consumer) { - this.newValueConsumer = consumer; - } - - public void confirmAdd(ActionEvent actionEvent) { - if (selected.get() == null || selectedUnit.get() == null) { - System.err.println("You must select both an ingredient and an unit"); - return; - } - FormalIngredient fi = new FormalIngredient(selected.get(), amountSelect.getValue(), selectedUnit.get().suffix); - newValueConsumer.accept(fi); - Stage stage = (Stage) ingredientSelection.getScene().getWindow(); - stage.close(); - } - - public void cancelAdd(ActionEvent actionEvent) { - } - private void makeMenuItems( - MenuButton menu, - Iterable items, - Function labelMapper, - Consumer onSelect) { - // Iterates over the list of items and applies the label and onSelect handlers. - for (T item : items) { - MenuItem mi = new MenuItem(); - mi.setText(labelMapper.apply(item)); - mi.setOnAction(_ -> { - menu.setText(labelMapper.apply(item)); - onSelect.accept(item); - }); - menu.getItems().add(mi); - } - } - @Override - public void updateText() { - - } - @Override - public void initializeComponents() { - try { - amountSelect.setValueFactory( - new SpinnerValueFactory.DoubleSpinnerValueFactory(0, Double.MAX_VALUE, 0)); - amountSelect.setEditable(true); - makeMenuItems(ingredientSelection, server.getIngredients(), Ingredient::getName, selected::set); - makeMenuItems(unitSelect, - Arrays.stream(Unit.values()).filter(u -> u.formal).toList(), - Unit::toString, selectedUnit::set); - } catch (IOException | InterruptedException e) { - System.err.println(e.getMessage()); - } - } - - @Override - public LocaleManager getLocaleManager() { - return localeManager; - } -} diff --git a/client/src/main/java/client/service/NonFunctionalShoppingListService.java b/client/src/main/java/client/service/NonFunctionalShoppingListService.java deleted file mode 100644 index d85b320..0000000 --- a/client/src/main/java/client/service/NonFunctionalShoppingListService.java +++ /dev/null @@ -1,62 +0,0 @@ -package client.service; - -import com.google.inject.Inject; -import commons.FormalIngredient; -import commons.Recipe; -import javafx.util.Pair; -import org.apache.commons.lang3.NotImplementedException; - -import java.util.List; -import java.util.Optional; - -public class NonFunctionalShoppingListService extends ShoppingListService { - @Inject - public NonFunctionalShoppingListService(ShoppingListViewModel viewModel) { - super(viewModel); - } - - @Override - public void putIngredient(FormalIngredient ingredient) { - throw new NotImplementedException(); - } - - @Override - public void putIngredient(FormalIngredient ingredient, Recipe recipe) { - throw new NotImplementedException(); - } - - @Override - public void putIngredient(FormalIngredient ingredient, String recipeName) { - throw new NotImplementedException(); - } - - @Override - public void putArbitraryItem(String name) { - throw new NotImplementedException(); - } - - @Override - public FormalIngredient purgeIngredient(Long id) { - throw new NotImplementedException(); - } - - @Override - public FormalIngredient purgeIngredient(String ingredientName) { - throw new NotImplementedException(); - } - - @Override - public void reset() { - throw new NotImplementedException(); - } - - @Override - public List>> getItems() { - throw new NotImplementedException(); - } - - @Override - public String makePrintable() { - throw new NotImplementedException(); - } -} diff --git a/client/src/main/java/client/service/ShoppingListItem.java b/client/src/main/java/client/service/ShoppingListItem.java deleted file mode 100644 index 91dd98a..0000000 --- a/client/src/main/java/client/service/ShoppingListItem.java +++ /dev/null @@ -1,6 +0,0 @@ -package client.service; - -import commons.FormalIngredient; -public class ShoppingListItem { - private FormalIngredient i; -} diff --git a/client/src/main/java/client/service/ShoppingListService.java b/client/src/main/java/client/service/ShoppingListService.java deleted file mode 100644 index 04ef26b..0000000 --- a/client/src/main/java/client/service/ShoppingListService.java +++ /dev/null @@ -1,38 +0,0 @@ -package client.service; - -import com.google.inject.Inject; -import commons.FormalIngredient; -import commons.Recipe; -import javafx.util.Pair; - -import java.util.List; -import java.util.Optional; - -public abstract class ShoppingListService { - private ShoppingListViewModel viewModel; - @Inject - public ShoppingListService(ShoppingListViewModel viewModel) { - this.viewModel = viewModel; - } - - public ShoppingListViewModel getViewModel() { - return viewModel; - } - - public void setViewModel(ShoppingListViewModel viewModel) { - this.viewModel = viewModel; - } - - public abstract void putIngredient(FormalIngredient ingredient); - public abstract void putIngredient(FormalIngredient ingredient, Recipe recipe); - public abstract void putIngredient(FormalIngredient ingredient, String recipeName); - public abstract void putArbitraryItem(String name); - - public abstract FormalIngredient purgeIngredient(Long id); - public abstract FormalIngredient purgeIngredient(String ingredientName); - - public abstract void reset(); - - public abstract List>> getItems(); - public abstract String makePrintable(); -} diff --git a/client/src/main/java/client/service/ShoppingListServiceImpl.java b/client/src/main/java/client/service/ShoppingListServiceImpl.java deleted file mode 100644 index 9941ee6..0000000 --- a/client/src/main/java/client/service/ShoppingListServiceImpl.java +++ /dev/null @@ -1,71 +0,0 @@ -package client.service; - -import com.google.inject.Inject; -import commons.FormalIngredient; -import commons.Recipe; -import javafx.util.Pair; - -import java.util.List; -import java.util.Optional; -import java.util.logging.Logger; - -public class ShoppingListServiceImpl extends ShoppingListService { - private final Logger logger = Logger.getLogger(ShoppingListServiceImpl.class.getName()); - @Inject - public ShoppingListServiceImpl( - ShoppingListViewModel model - ) { - super(model); - } - - @Override - public void putIngredient(FormalIngredient ingredient) { - getViewModel().getListItems().add(new Pair<>(ingredient, Optional.empty())); - } - - @Override - public void putIngredient(FormalIngredient ingredient, Recipe recipe) { - Pair> val = new Pair<>(ingredient, Optional.of(recipe.getName())); - logger.info("putting ingredients into shopping list: " + val); - getViewModel().getListItems().add(val); - } - - @Override - public void putIngredient(FormalIngredient ingredient, String recipeName) { - getViewModel().getListItems().add(new Pair<>(ingredient, Optional.of(recipeName))); - } - - @Override - public void putArbitraryItem(String name) { - - } - - @Override - public FormalIngredient purgeIngredient(Long id) { - return null; - } - - @Override - public FormalIngredient purgeIngredient(String ingredientName) { - FormalIngredient fi = getViewModel().getListItems().stream() - .filter(i -> - i.getKey().getIngredient().getName().equals(ingredientName)) - .findFirst().orElseThrow(NullPointerException::new).getKey(); - return null; - } - - @Override - public void reset() { - getViewModel().getListItems().clear(); - } - - @Override - public List>> getItems() { - return getViewModel().getListItems(); - } - - @Override - public String makePrintable() { - return "TODO"; - } -} diff --git a/client/src/main/java/client/service/ShoppingListViewModel.java b/client/src/main/java/client/service/ShoppingListViewModel.java deleted file mode 100644 index aaaa237..0000000 --- a/client/src/main/java/client/service/ShoppingListViewModel.java +++ /dev/null @@ -1,26 +0,0 @@ -package client.service; - -import commons.FormalIngredient; -import javafx.beans.property.ListProperty; -import javafx.beans.property.SimpleListProperty; -import javafx.collections.FXCollections; -import javafx.collections.ObservableList; -import javafx.util.Pair; -import org.apache.commons.lang3.NotImplementedException; - -import java.util.Optional; - -public class ShoppingListViewModel { - /** - * The formal ingredient provides the ingredient and its amount, - * and the string (optional) describes the recipe where it came from. - */ - private final ListProperty>> listItems = new SimpleListProperty<>(FXCollections.observableArrayList()); - public void addArbitrary() { - throw new NotImplementedException(); - } - - public ObservableList>> getListItems() { - return listItems.get(); - } -} diff --git a/client/src/main/java/client/utils/Config.java b/client/src/main/java/client/utils/Config.java index d3c3823..a70d55c 100644 --- a/client/src/main/java/client/utils/Config.java +++ b/client/src/main/java/client/utils/Config.java @@ -5,7 +5,6 @@ import java.util.List; public class Config { private String language = "en"; - public static String[] languages = {"en", "nl", "pl", "tok", "zhc", "zht"}; private List recipeLanguages = new ArrayList<>(); private String serverUrl = "http://localhost:8080"; diff --git a/client/src/main/java/client/utils/server/Endpoints.java b/client/src/main/java/client/utils/server/Endpoints.java index 6c23870..5b31304 100644 --- a/client/src/main/java/client/utils/server/Endpoints.java +++ b/client/src/main/java/client/utils/server/Endpoints.java @@ -4,9 +4,7 @@ import client.utils.ConfigService; import com.google.inject.Inject; import java.net.URI; -import java.net.URLEncoder; import java.net.http.HttpRequest; -import java.nio.charset.StandardCharsets; import java.util.List; public class Endpoints { @@ -83,23 +81,9 @@ public class Endpoints { } public HttpRequest.Builder getRecipesWith(String params) { - if (params != null && params.contains("search=")) { - int start = params.indexOf("search=") + "search=".length(); - int end = params.indexOf('&', start); - if (end == -1) { - end = params.length(); - } - - String rawValue = params.substring(start, end); - String encodedValue = URLEncoder.encode(rawValue, StandardCharsets.UTF_8); - - params = params.substring(0, start) + encodedValue + params.substring(end); - } - return this.http(this.createApiUrl("/recipes?" + params)).GET(); } - public HttpRequest.Builder createIngredient(HttpRequest.BodyPublisher body) { String url = this.createApiUrl("/ingredients"); diff --git a/client/src/main/java/client/utils/server/ServerUtils.java b/client/src/main/java/client/utils/server/ServerUtils.java index 8bd7f3b..5330fdd 100644 --- a/client/src/main/java/client/utils/server/ServerUtils.java +++ b/client/src/main/java/client/utils/server/ServerUtils.java @@ -1,18 +1,19 @@ package client.utils.server; import client.utils.ConfigService; -import client.exception.DuplicateIngredientException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.inject.Inject; import commons.Ingredient; import commons.Recipe; import commons.RecipeIngredient; +import jakarta.ws.rs.ProcessingException; import jakarta.ws.rs.client.ClientBuilder; import org.glassfish.jersey.client.ClientConfig; import java.io.IOException; +import java.net.ConnectException; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; @@ -170,9 +171,10 @@ public class ServerUtils { .target(this.endpoints.baseUrl()) // .request(APPLICATION_JSON) // .get(); - } - catch(Exception e){ - return false; //any exception caught will return false, not just processing exception. + } catch (ProcessingException e) { + if (e.getCause() instanceof ConnectException) { + return false; + } } return true; } @@ -268,7 +270,7 @@ public class ServerUtils { //creates new ingredients in the ingredient list - public Ingredient createIngredient(String name) throws IOException, InterruptedException, DuplicateIngredientException { + public Ingredient createIngredient(String name) throws IOException, InterruptedException { Ingredient ingredient = new Ingredient(name, 0.0, 0.0, 0.0); String json = objectMapper.writeValueAsString(ingredient); @@ -276,11 +278,6 @@ public class ServerUtils { .build(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); - final int DUPLICATE_STATUS_CODE = 409; - if (response.statusCode() == DUPLICATE_STATUS_CODE) { - throw new DuplicateIngredientException(name); - } - if (response.statusCode() != statusOK) { throw new IOException("Failed to create ingredient. Server responds with: " + response.body()); } diff --git a/client/src/main/resources/client/scenes/FoodpalApplication.fxml b/client/src/main/resources/client/scenes/FoodpalApplication.fxml index adfffba..c777543 100644 --- a/client/src/main/resources/client/scenes/FoodpalApplication.fxml +++ b/client/src/main/resources/client/scenes/FoodpalApplication.fxml @@ -70,9 +70,6 @@ - - - - - - - + + -