From e1c0f43c3e7e0f27f4dfc9e5ae0769e01a05127c Mon Sep 17 00:00:00 2001 From: TudorOrban <130213626+TudorOrban@users.noreply.github.com> Date: Fri, 22 Mar 2024 16:18:05 +0200 Subject: [PATCH 01/11] Start fixing FallbackManager --- .../main/service/NavigationServiceImpl.java | 9 ++++---- .../controller/ProductsController.java | 21 +++++++++++++++---- .../shared/fallback/FallbackManager.java | 13 ++++++++++++ .../controller/PageSelectorController.java | 17 ++++----------- .../shared/search/model/SearchParams.java | 12 +++++------ src/main/resources/css/page-elements.css | 6 ++++++ .../features/product/ProductsView.fxml | 14 +++++++++---- .../shared/fallback/ErrorFallbackView.fxml | 4 ++-- .../shared/fallback/FallbackManagerView.fxml | 4 ++-- .../shared/search/PageSelectorView.fxml | 4 ---- 10 files changed, 64 insertions(+), 40 deletions(-) diff --git a/src/main/java/org/chainoptim/desktop/core/main/service/NavigationServiceImpl.java b/src/main/java/org/chainoptim/desktop/core/main/service/NavigationServiceImpl.java index 2db35c5a..a74644e9 100644 --- a/src/main/java/org/chainoptim/desktop/core/main/service/NavigationServiceImpl.java +++ b/src/main/java/org/chainoptim/desktop/core/main/service/NavigationServiceImpl.java @@ -78,17 +78,16 @@ public void switchView(String viewKey) { if (Objects.equals(currentViewKey, viewKey)) { return; } - System.out.println(viewCache); + + // Reset fallback state between pages + fallbackManager.reset(); // Get view from cache or load it Node view = viewCache.computeIfAbsent(viewKey, this::loadView); // Display view if (view != null) { - threadRunner.runLater(() -> { - mainContentArea.getChildren().setAll(view); - fallbackManager.reset(); - }); + threadRunner.runLater(() -> mainContentArea.getChildren().setAll(view)); currentViewKey = viewKey; } } diff --git a/src/main/java/org/chainoptim/desktop/features/product/controller/ProductsController.java b/src/main/java/org/chainoptim/desktop/features/product/controller/ProductsController.java index 21cfbd71..50107056 100644 --- a/src/main/java/org/chainoptim/desktop/features/product/controller/ProductsController.java +++ b/src/main/java/org/chainoptim/desktop/features/product/controller/ProductsController.java @@ -42,6 +42,10 @@ public class ProductsController implements Initializable { @FXML private HeaderController headerController; @FXML + private StackPane contentOrFallbackContainer; + @FXML + private ScrollPane productsScrollPane; + @FXML private PageSelectorController pageSelectorController; @FXML private StackPane pageSelectorContainer; @@ -81,8 +85,8 @@ public ProductsController(ProductService productService, public void initialize(URL location, ResourceBundle resources) { initializeHeader(); loadFallbackManager(); - loadProducts(); setUpListeners(); + loadProducts(); initializePageSelector(); } @@ -112,15 +116,16 @@ private void loadFallbackManager() { } private void loadProducts() { + fallbackManager.reset(); + fallbackManager.setLoading(true); + User currentUser = TenantContext.getCurrentUser(); if (currentUser == null) { Platform.runLater(() -> fallbackManager.setLoading(false)); return; } - - fallbackManager.setLoading(true); - Integer organizationId = currentUser.getOrganization().getId(); + productService.getProductsByOrganizationIdAdvanced(organizationId, searchParams) .thenApply(this::handleProductResponse) .exceptionally(this::handleProductException) @@ -132,6 +137,14 @@ private void setUpListeners() { searchParams.getSearchQueryProperty().addListener((observable, oldValue, newValue) -> loadProducts()); searchParams.getAscendingProperty().addListener((observable, oldValue, newValue) -> loadProducts()); searchParams.getSortOptionProperty().addListener((observable, oldValue, newValue) -> loadProducts()); + + // Listen to empty fallback state + fallbackManager.isEmptyProperty().addListener((observable, oldValue, newValue) -> { + productsScrollPane.setVisible(newValue); + productsScrollPane.setManaged(newValue); + fallbackContainer.setVisible(!newValue); + fallbackContainer.setManaged(!newValue); + }); } private void initializePageSelector() { diff --git a/src/main/java/org/chainoptim/desktop/shared/fallback/FallbackManager.java b/src/main/java/org/chainoptim/desktop/shared/fallback/FallbackManager.java index 7862d52c..f65124b5 100644 --- a/src/main/java/org/chainoptim/desktop/shared/fallback/FallbackManager.java +++ b/src/main/java/org/chainoptim/desktop/shared/fallback/FallbackManager.java @@ -12,6 +12,11 @@ public class FallbackManager { private final BooleanProperty isLoading = new SimpleBooleanProperty(false); private final BooleanProperty noOrganization = new SimpleBooleanProperty(false); private final BooleanProperty noResults = new SimpleBooleanProperty(false); + private final BooleanProperty isEmpty = new SimpleBooleanProperty(true); + + public FallbackManager() { + isEmpty.bind(isLoadingProperty().not().and(noOrganizationProperty().not().and(noResultsProperty().not().and(errorMessageProperty().isEmpty())))); + } public String getErrorMessage() { return errorMessage.get(); @@ -67,4 +72,12 @@ public void reset() { setNoOrganization(false); setNoResults(false); } + + public BooleanProperty isEmptyProperty() { + return isEmpty; + } + + public boolean isEmpty() { + return isEmpty.get(); + } } \ No newline at end of file diff --git a/src/main/java/org/chainoptim/desktop/shared/search/controller/PageSelectorController.java b/src/main/java/org/chainoptim/desktop/shared/search/controller/PageSelectorController.java index 094ae1ae..1eb1726e 100644 --- a/src/main/java/org/chainoptim/desktop/shared/search/controller/PageSelectorController.java +++ b/src/main/java/org/chainoptim/desktop/shared/search/controller/PageSelectorController.java @@ -14,33 +14,24 @@ public class PageSelectorController { - @FXML private Pagination pagination; private final SearchParams searchParams; -// private final PaginatedResults paginatedResults; -private long totalItems; @Inject - public PageSelectorController( - SearchParams searchParams - // PaginatedResults paginatedResults - ) { + public PageSelectorController(SearchParams searchParams) { this.searchParams = searchParams; - //this.paginatedResults = paginatedResults; } @FXML public void initialize(long totalItems) { int itemsPerPage = searchParams.getItemsPerPage(); - this.totalItems = totalItems; int pageCount = (int) Math.ceil((double) totalItems / itemsPerPage); pagination.setPageCount(pageCount); pagination.setCurrentPageIndex(searchParams.getPage() - 1); - pagination.currentPageIndexProperty().addListener((obs, oldIndex, newIndex) -> { - searchParams.setPage(newIndex.intValue() + 1); - }); + pagination.currentPageIndexProperty().addListener((obs, oldIndex, newIndex) -> + searchParams.setPage(newIndex.intValue() + 1) + ); } - } diff --git a/src/main/java/org/chainoptim/desktop/shared/search/model/SearchParams.java b/src/main/java/org/chainoptim/desktop/shared/search/model/SearchParams.java index b66adcf0..c5848aa2 100644 --- a/src/main/java/org/chainoptim/desktop/shared/search/model/SearchParams.java +++ b/src/main/java/org/chainoptim/desktop/shared/search/model/SearchParams.java @@ -7,18 +7,18 @@ public class SearchParams { - private StringProperty searchQuery; - private StringProperty sortOption; - private BooleanProperty ascending; - private IntegerProperty page; - private IntegerProperty itemsPerPage; + private final StringProperty searchQuery; + private final StringProperty sortOption; + private final BooleanProperty ascending; + private final IntegerProperty page; + private final IntegerProperty itemsPerPage; public SearchParams() { searchQuery = new SimpleStringProperty(""); sortOption = new SimpleStringProperty("createdAt"); ascending = new SimpleBooleanProperty(true); page = new SimpleIntegerProperty(1); - itemsPerPage = new SimpleIntegerProperty(4); + itemsPerPage = new SimpleIntegerProperty(10); } public BooleanProperty getAscendingProperty() { diff --git a/src/main/resources/css/page-elements.css b/src/main/resources/css/page-elements.css index d2bfd8d1..e46318f5 100644 --- a/src/main/resources/css/page-elements.css +++ b/src/main/resources/css/page-elements.css @@ -59,6 +59,12 @@ -fx-font-weight: normal; } +.error-message { + -fx-font-size: 16px; + -fx-font-weight: bold; + -fx-text-fill: #111111; +} + /* Just for tests: */ .test { -fx-background-color: #efb3b3; diff --git a/src/main/resources/org/chainoptim/desktop/features/product/ProductsView.fxml b/src/main/resources/org/chainoptim/desktop/features/product/ProductsView.fxml index c0479b14..4a5f6642 100644 --- a/src/main/resources/org/chainoptim/desktop/features/product/ProductsView.fxml +++ b/src/main/resources/org/chainoptim/desktop/features/product/ProductsView.fxml @@ -1,6 +1,7 @@ + - + + + + + + + - - - + + diff --git a/src/main/resources/org/chainoptim/desktop/shared/fallback/ErrorFallbackView.fxml b/src/main/resources/org/chainoptim/desktop/shared/fallback/ErrorFallbackView.fxml index 115372b4..b20aaaf2 100644 --- a/src/main/resources/org/chainoptim/desktop/shared/fallback/ErrorFallbackView.fxml +++ b/src/main/resources/org/chainoptim/desktop/shared/fallback/ErrorFallbackView.fxml @@ -9,9 +9,9 @@ fx:controller="org.chainoptim.desktop.shared.fallback.ErrorFallbackController"> - + - diff --git a/src/main/resources/org/chainoptim/desktop/shared/fallback/FallbackManagerView.fxml b/src/main/resources/org/chainoptim/desktop/shared/fallback/FallbackManagerView.fxml index d1a85d84..c2416ec8 100644 --- a/src/main/resources/org/chainoptim/desktop/shared/fallback/FallbackManagerView.fxml +++ b/src/main/resources/org/chainoptim/desktop/shared/fallback/FallbackManagerView.fxml @@ -1,10 +1,10 @@ - - \ No newline at end of file + \ No newline at end of file diff --git a/src/main/resources/org/chainoptim/desktop/shared/search/PageSelectorView.fxml b/src/main/resources/org/chainoptim/desktop/shared/search/PageSelectorView.fxml index ef447de1..ceaa3a36 100644 --- a/src/main/resources/org/chainoptim/desktop/shared/search/PageSelectorView.fxml +++ b/src/main/resources/org/chainoptim/desktop/shared/search/PageSelectorView.fxml @@ -1,8 +1,4 @@ - - - - From d8b0ddaf9bb38cf5a45e781c1dc0ad982f8ad482 Mon Sep 17 00:00:00 2001 From: TudorOrban <130213626+TudorOrban@users.noreply.github.com> Date: Fri, 22 Mar 2024 16:44:16 +0200 Subject: [PATCH 02/11] Improve FallbackManagerController by only loading fallback views on init --- .../controller/ProductsController.java | 2 - .../fallback/FallbackManagerController.java | 71 +++++++++++-------- .../features/product/ProductsView.fxml | 2 +- 3 files changed, 44 insertions(+), 31 deletions(-) diff --git a/src/main/java/org/chainoptim/desktop/features/product/controller/ProductsController.java b/src/main/java/org/chainoptim/desktop/features/product/controller/ProductsController.java index 50107056..dbe8fd12 100644 --- a/src/main/java/org/chainoptim/desktop/features/product/controller/ProductsController.java +++ b/src/main/java/org/chainoptim/desktop/features/product/controller/ProductsController.java @@ -42,8 +42,6 @@ public class ProductsController implements Initializable { @FXML private HeaderController headerController; @FXML - private StackPane contentOrFallbackContainer; - @FXML private ScrollPane productsScrollPane; @FXML private PageSelectorController pageSelectorController; diff --git a/src/main/java/org/chainoptim/desktop/shared/fallback/FallbackManagerController.java b/src/main/java/org/chainoptim/desktop/shared/fallback/FallbackManagerController.java index cc006514..0c942914 100644 --- a/src/main/java/org/chainoptim/desktop/shared/fallback/FallbackManagerController.java +++ b/src/main/java/org/chainoptim/desktop/shared/fallback/FallbackManagerController.java @@ -4,13 +4,12 @@ import javafx.fxml.FXML; import javafx.fxml.FXMLLoader; import javafx.scene.Node; -import javafx.scene.layout.Region; import javafx.scene.layout.StackPane; import lombok.Data; import java.io.IOException; -import java.net.URL; -import java.util.Objects; +import java.util.HashMap; +import java.util.Map; @Data public class FallbackManagerController { @@ -20,52 +19,68 @@ public class FallbackManagerController { private FallbackManager fallbackManager; + private Map loadedViews = new HashMap<>(); + private Map loadedControllers = new HashMap<>(); + @Inject public FallbackManagerController(FallbackManager fallbackManager) { this.fallbackManager = fallbackManager; + } + + @FXML + public void initialize() { + loadFallbackViews(); setupChangeListeners(); + updateView(); + } + + private void loadFallbackViews() { + String[] viewPaths = { + "/org/chainoptim/desktop/shared/fallback/ErrorFallbackView.fxml", + "/org/chainoptim/desktop/shared/fallback/LoadingFallbackView.fxml", + "/org/chainoptim/desktop/shared/fallback/NoOrganizationFallbackView.fxml", + "/org/chainoptim/desktop/shared/fallback/NoResultsFallbackView.fxml" + }; + + for (String path : viewPaths) { + try { + FXMLLoader loader = new FXMLLoader(getClass().getResource(path)); + Node view = loader.load(); + Object controller = loader.getController(); + + loadedViews.put(path, view); + loadedControllers.put(path, controller); + } catch (IOException e) { + e.printStackTrace(); + } + } } private void setupChangeListeners() { fallbackManager.errorMessageProperty().addListener((obs, oldVal, newVal) -> updateView()); - fallbackManager.isLoadingProperty().addListener((obs, oldVal, newVal) -> { - System.out.println("isLoading changed to: " + newVal); - updateView(); - }); + fallbackManager.isLoadingProperty().addListener((obs, oldVal, newVal) -> updateView()); fallbackManager.noOrganizationProperty().addListener((obs, oldVal, newVal) -> updateView()); fallbackManager.noResultsProperty().addListener((obs, oldVal, newVal) -> updateView()); } - @FXML - public void initialize() { - updateView(); - } - private void updateView() { String viewPath = determineViewPathBasedOnState(); + if (!viewPath.isEmpty()) { - try { - URL url = getClass().getResource(viewPath); - if (url == null) { - return; - } - System.out.println("Update to view: " + url); - FXMLLoader loader = new FXMLLoader(url); - Node fallbackView = loader.load(); - if (viewPath == "/org/chainoptim/desktop/shared/fallback/ErrorFallbackView.fxml") { - ErrorFallbackController controller = loader.getController(); - controller.initialize(fallbackManager.getErrorMessage()); - } - fallbackContentHolder.getChildren().setAll(fallbackView); - } catch (IOException e) { - e.printStackTrace(); + Node view = loadedViews.get(viewPath); + fallbackContentHolder.getChildren().setAll(view); + + // Set error message in case of error + Object controller = loadedControllers.get(viewPath); + if (viewPath.equals("/org/chainoptim/desktop/shared/fallback/ErrorFallbackView.fxml")) { + ((ErrorFallbackController)controller).initialize(fallbackManager.getErrorMessage()); } } else { - // No fallback fallbackContentHolder.getChildren().clear(); fallbackContentHolder.setPrefSize(0, 0); } } + private String determineViewPathBasedOnState() { if (!fallbackManager.getErrorMessage().isEmpty()) { return "/org/chainoptim/desktop/shared/fallback/ErrorFallbackView.fxml"; diff --git a/src/main/resources/org/chainoptim/desktop/features/product/ProductsView.fxml b/src/main/resources/org/chainoptim/desktop/features/product/ProductsView.fxml index 4a5f6642..7fde0259 100644 --- a/src/main/resources/org/chainoptim/desktop/features/product/ProductsView.fxml +++ b/src/main/resources/org/chainoptim/desktop/features/product/ProductsView.fxml @@ -9,7 +9,7 @@ - + From b4aa9e8d185f8a09db0df2b96e21e29ba68e2dfd Mon Sep 17 00:00:00 2001 From: TudorOrban <130213626+TudorOrban@users.noreply.github.com> Date: Sat, 23 Mar 2024 11:26:57 +0200 Subject: [PATCH 03/11] Fix Loading Spinner with FontAwesome icon --- .../product/controller/ProductController.java | 52 +++++++++++------- .../fallback/FallbackManagerController.java | 4 +- .../fallback/LoadingFallbackController.java | 35 +++++++----- src/main/resources/css/fallback.css | 32 +++++++++++ src/main/resources/css/globals.css | 3 +- src/main/resources/css/page-elements.css | 22 -------- src/main/resources/img/spinner-solid.png | Bin 0 -> 6485 bytes .../desktop/features/product/ProductView.fxml | 6 +- .../features/product/ProductsView.fxml | 4 +- .../shared/fallback/LoadingFallbackView.fxml | 8 +-- 10 files changed, 98 insertions(+), 68 deletions(-) create mode 100644 src/main/resources/css/fallback.css create mode 100644 src/main/resources/img/spinner-solid.png diff --git a/src/main/java/org/chainoptim/desktop/features/product/controller/ProductController.java b/src/main/java/org/chainoptim/desktop/features/product/controller/ProductController.java index a9cc8616..d23f3170 100644 --- a/src/main/java/org/chainoptim/desktop/features/product/controller/ProductController.java +++ b/src/main/java/org/chainoptim/desktop/features/product/controller/ProductController.java @@ -1,5 +1,6 @@ package org.chainoptim.desktop.features.product.controller; +import javafx.scene.layout.VBox; import org.chainoptim.desktop.MainApplication; import org.chainoptim.desktop.core.main.service.CurrentSelectionService; import org.chainoptim.desktop.features.product.model.Product; @@ -31,6 +32,8 @@ public class ProductController implements Initializable { private Product product; + @FXML + private VBox contentContainer; @FXML private StackPane fallbackContainer; @@ -62,14 +65,41 @@ public void initialize(URL location, ResourceBundle resources) { Integer productId = currentSelectionService.getSelectedId(); if (productId == null) { System.out.println("Missing product id."); - fallbackManager.setErrorMessage("Failed to load product."); + fallbackManager.setErrorMessage("Failed to load product: missing product ID."); } + setupListeners(); loadProduct(productId); - setupTabListeners(); + } + + private void setupListeners() { + overviewTab.selectedProperty().addListener((observable, wasSelected, isNowSelected) -> { + if (Boolean.TRUE.equals(isNowSelected) && overviewTab.getContent() == null) { + loadTabContent(overviewTab, "/org/chainoptim/desktop/features/product/ProductOverviewView.fxml", this.product); + } + }); + productionTab.selectedProperty().addListener((observable, wasSelected, isNowSelected) -> { + if (Boolean.TRUE.equals(isNowSelected) && productionTab.getContent() == null) { + loadTabContent(productionTab, "/org/chainoptim/desktop/features/product/ProductProductionView.fxml", this.product); + } + }); + evaluationTab.selectedProperty().addListener((observable, wasSelected, isNowSelected) -> { + if (Boolean.TRUE.equals(isNowSelected) && evaluationTab.getContent() == null) { + loadTabContent(evaluationTab, "/org/chainoptim/desktop/features/product/ProductEvaluationView.fxml", this.product); + } + }); + + fallbackManager.isEmptyProperty().addListener((observable, oldValue, newValue) -> { + contentContainer.setVisible(newValue); + contentContainer.setManaged(newValue); + fallbackContainer.setVisible(!newValue); + fallbackContainer.setManaged(!newValue); + }); } private void loadProduct(Integer productId) { + fallbackManager.reset(); +// fallbackManager.setErrorMessage("New Error"); fallbackManager.setLoading(true); productService.getProductWithStages(productId) @@ -101,24 +131,6 @@ private Optional handleProductException(Throwable ex) { return Optional.empty(); } - private void setupTabListeners() { - overviewTab.selectedProperty().addListener((observable, wasSelected, isNowSelected) -> { - if (Boolean.TRUE.equals(isNowSelected) && overviewTab.getContent() == null) { - loadTabContent(overviewTab, "/org/chainoptim/desktop/features/product/ProductOverviewView.fxml", this.product); - } - }); - productionTab.selectedProperty().addListener((observable, wasSelected, isNowSelected) -> { - if (Boolean.TRUE.equals(isNowSelected) && productionTab.getContent() == null) { - loadTabContent(productionTab, "/org/chainoptim/desktop/features/product/ProductProductionView.fxml", this.product); - } - }); - evaluationTab.selectedProperty().addListener((observable, wasSelected, isNowSelected) -> { - if (Boolean.TRUE.equals(isNowSelected) && evaluationTab.getContent() == null) { - loadTabContent(evaluationTab, "/org/chainoptim/desktop/features/product/ProductEvaluationView.fxml", this.product); - } - }); - } - private void loadTabContent(Tab tab, String fxmlFilepath, Product product) { try { FXMLLoader loader = new FXMLLoader(getClass().getResource(fxmlFilepath)); diff --git a/src/main/java/org/chainoptim/desktop/shared/fallback/FallbackManagerController.java b/src/main/java/org/chainoptim/desktop/shared/fallback/FallbackManagerController.java index 0c942914..037b85aa 100644 --- a/src/main/java/org/chainoptim/desktop/shared/fallback/FallbackManagerController.java +++ b/src/main/java/org/chainoptim/desktop/shared/fallback/FallbackManagerController.java @@ -68,13 +68,13 @@ private void updateView() { if (!viewPath.isEmpty()) { Node view = loadedViews.get(viewPath); - fallbackContentHolder.getChildren().setAll(view); - // Set error message in case of error Object controller = loadedControllers.get(viewPath); if (viewPath.equals("/org/chainoptim/desktop/shared/fallback/ErrorFallbackView.fxml")) { ((ErrorFallbackController)controller).initialize(fallbackManager.getErrorMessage()); } + + fallbackContentHolder.getChildren().setAll(view); } else { fallbackContentHolder.getChildren().clear(); fallbackContentHolder.setPrefSize(0, 0); diff --git a/src/main/java/org/chainoptim/desktop/shared/fallback/LoadingFallbackController.java b/src/main/java/org/chainoptim/desktop/shared/fallback/LoadingFallbackController.java index 2f5df69d..adce5cba 100644 --- a/src/main/java/org/chainoptim/desktop/shared/fallback/LoadingFallbackController.java +++ b/src/main/java/org/chainoptim/desktop/shared/fallback/LoadingFallbackController.java @@ -1,28 +1,35 @@ package org.chainoptim.desktop.shared.fallback; -import javafx.animation.FadeTransition; +import javafx.animation.Animation; +import javafx.animation.Interpolator; +import javafx.animation.RotateTransition; import javafx.fxml.FXML; -import javafx.scene.Group; -import javafx.scene.Scene; -import javafx.scene.control.Label; -import javafx.scene.control.ProgressIndicator; -import javafx.scene.control.Spinner; -import javafx.scene.control.SpinnerValueFactory; -import javafx.scene.layout.AnchorPane; -import javafx.scene.layout.Pane; -import javafx.scene.layout.VBox; -import javafx.scene.paint.Color; -import javafx.scene.shape.Rectangle; +import javafx.scene.Node; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; import javafx.util.Duration; +import java.util.Objects; + public class LoadingFallbackController { @FXML - private ProgressIndicator loadingSpinner; + private ImageView customSpinner; @FXML public void initialize() { - loadingSpinner.setVisible(true); + Image image = new Image(Objects.requireNonNull(getClass().getResourceAsStream("/img/spinner-solid.png"))); + customSpinner.setImage(image); + customSpinner.setFitHeight(52); + customSpinner.setFitWidth(52); + applySpinAnimation(customSpinner); } + public void applySpinAnimation(Node node) { + RotateTransition rotateTransition = new RotateTransition(Duration.seconds(2), node); + rotateTransition.setByAngle(360); + rotateTransition.setCycleCount(Animation.INDEFINITE); + rotateTransition.setInterpolator(Interpolator.LINEAR); + rotateTransition.play(); + } } diff --git a/src/main/resources/css/fallback.css b/src/main/resources/css/fallback.css new file mode 100644 index 00000000..d40313bc --- /dev/null +++ b/src/main/resources/css/fallback.css @@ -0,0 +1,32 @@ +.fallback-container { + -fx-spacing: 10px; +} + +.fallback-title { + -fx-font-size: 20px; + -fx-font-weight: bold; +} + +.fallback-text { + -fx-font-size: 16px; + -fx-font-weight: normal; +} + +.error-message { + -fx-font-size: 16px; + -fx-font-weight: bold; + -fx-text-fill: #111111; +} + +.spinner-rotate { + -fx-animation: spin 2s infinite linear; +} + +@keyframes spin { + from { + -fx-rotate: 0; + } + to { + -fx-rotate: 360; + } +} diff --git a/src/main/resources/css/globals.css b/src/main/resources/css/globals.css index 282eed8a..847ef652 100644 --- a/src/main/resources/css/globals.css +++ b/src/main/resources/css/globals.css @@ -6,4 +6,5 @@ @import url("entity-card.css"); @import url("entity-page.css"); @import url("table.css"); -@import url("factory-production.css"); \ No newline at end of file +@import url("factory-production.css"); +@import url("fallback.css"); \ No newline at end of file diff --git a/src/main/resources/css/page-elements.css b/src/main/resources/css/page-elements.css index e46318f5..85430bed 100644 --- a/src/main/resources/css/page-elements.css +++ b/src/main/resources/css/page-elements.css @@ -43,28 +43,6 @@ -fx-text-fill: white; } - -/* Everything related to the fallbacks: */ -.fallback-container { - -fx-spacing: 10px; -} - -.fallback-title { - -fx-font-size: 20px; - -fx-font-weight: bold; -} - -.fallback-text { - -fx-font-size: 16px; - -fx-font-weight: normal; -} - -.error-message { - -fx-font-size: 16px; - -fx-font-weight: bold; - -fx-text-fill: #111111; -} - /* Just for tests: */ .test { -fx-background-color: #efb3b3; diff --git a/src/main/resources/img/spinner-solid.png b/src/main/resources/img/spinner-solid.png new file mode 100644 index 0000000000000000000000000000000000000000..51ae98413ec6875672c4cc5932d2e5f0017b42fc GIT binary patch literal 6485 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 - - + - + diff --git a/src/main/resources/org/chainoptim/desktop/features/product/ProductsView.fxml b/src/main/resources/org/chainoptim/desktop/features/product/ProductsView.fxml index 7fde0259..b1a1cb3f 100644 --- a/src/main/resources/org/chainoptim/desktop/features/product/ProductsView.fxml +++ b/src/main/resources/org/chainoptim/desktop/features/product/ProductsView.fxml @@ -10,14 +10,14 @@ - + - + diff --git a/src/main/resources/org/chainoptim/desktop/shared/fallback/LoadingFallbackView.fxml b/src/main/resources/org/chainoptim/desktop/shared/fallback/LoadingFallbackView.fxml index 4145d79c..8a7d474f 100644 --- a/src/main/resources/org/chainoptim/desktop/shared/fallback/LoadingFallbackView.fxml +++ b/src/main/resources/org/chainoptim/desktop/shared/fallback/LoadingFallbackView.fxml @@ -1,13 +1,13 @@ - - + + fx:controller="org.chainoptim.desktop.shared.fallback.LoadingFallbackController" + prefWidth="400" prefHeight="600"> - + From 580b44d5674ae1bc0442c513a40642f574d90b5f Mon Sep 17 00:00:00 2001 From: TudorOrban <130213626+TudorOrban@users.noreply.github.com> Date: Sat, 23 Mar 2024 14:33:37 +0200 Subject: [PATCH 04/11] Fix positioning of FallbackManagerView throughout feature pages --- .../controller/FactoriesController.java | 42 +++++++---- .../factory/controller/FactoryController.java | 35 ++++++++-- .../product/controller/ProductController.java | 38 ++++++---- .../controller/ProductsController.java | 65 +++++++++-------- .../controller/SupplierController.java | 70 ++++++++++++------- .../controller/SuppliersController.java | 58 +++++++++------ .../controller/WarehouseController.java | 46 ++++++------ .../controller/WarehousesController.java | 57 +++++++++------ .../shared/fallback/FallbackManager.java | 1 + src/main/resources/css/fallback.css | 4 ++ .../features/factory/FactoriesView.fxml | 15 ++-- .../desktop/features/factory/FactoryView.fxml | 18 +++-- .../desktop/features/product/ProductView.fxml | 20 +++--- .../features/product/ProductsView.fxml | 2 +- .../features/supplier/SupplierView.fxml | 41 ++++++----- .../features/supplier/SuppliersView.fxml | 20 ++++-- .../features/warehouse/WarehouseView.fxml | 13 ++-- .../features/warehouse/WarehousesView.fxml | 25 +++---- .../shared/search/PageSelectorView.fxml | 5 +- 19 files changed, 354 insertions(+), 221 deletions(-) diff --git a/src/main/java/org/chainoptim/desktop/features/factory/controller/FactoriesController.java b/src/main/java/org/chainoptim/desktop/features/factory/controller/FactoriesController.java index a29c365b..7e55eda4 100644 --- a/src/main/java/org/chainoptim/desktop/features/factory/controller/FactoriesController.java +++ b/src/main/java/org/chainoptim/desktop/features/factory/controller/FactoriesController.java @@ -8,6 +8,7 @@ import javafx.scene.Node; import javafx.scene.control.Button; import javafx.scene.control.Label; +import javafx.scene.control.ScrollPane; import javafx.scene.layout.StackPane; import javafx.scene.layout.VBox; import org.chainoptim.desktop.core.abstraction.ControllerFactory; @@ -44,13 +45,15 @@ public class FactoriesController implements Initializable { @FXML private PageSelectorController pageSelectorController; @FXML + private ScrollPane factoriesScrollPane; + @FXML + private VBox factoriesVBox; + @FXML private StackPane pageSelectorContainer; @FXML private StackPane fallbackContainer; @FXML private StackPane headerContainer; - @FXML - private VBox factoriesVBox; private final SearchParams searchParams; private final Map sortOptions = Map.of( @@ -81,9 +84,9 @@ public FactoriesController(FactoryService factoryService, public void initialize(URL location, ResourceBundle resourceBundle) { initializeHeader(); loadFallbackManager(); + setUpListeners(); loadFactories(); initializePageSelector(); - setUpListeners(); } private void initializeHeader() { @@ -102,6 +105,15 @@ private void initializeHeader() { } } + private void loadFallbackManager() { + // Load view into fallbackContainer + Node fallbackView = fxmlLoaderService.loadView( + "/org/chainoptim/desktop/shared/fallback/FallbackManagerView.fxml", + controllerFactory::createController + ); + fallbackContainer.getChildren().add(fallbackView); + } + private void initializePageSelector() { // Load view into pageSelectorContainer and initialize it with appropriate values FXMLLoader loader = fxmlLoaderService.setUpLoader( @@ -119,32 +131,32 @@ private void initializePageSelector() { } } - private void loadFallbackManager() { - // Load view into fallbackContainer - Node fallbackView = fxmlLoaderService.loadView( - "/org/chainoptim/desktop/shared/fallback/FallbackManagerView.fxml", - controllerFactory::createController - ); - fallbackContainer.getChildren().add(fallbackView); - } - private void setUpListeners() { // Listen to changes in search params searchParams.getSearchQueryProperty().addListener((observable, oldValue, newValue) -> loadFactories()); searchParams.getAscendingProperty().addListener((observable, oldValue, newValue) -> loadFactories()); searchParams.getSortOptionProperty().addListener((observable, oldValue, newValue) -> loadFactories()); + + // Listen to empty fallback state + fallbackManager.isEmptyProperty().addListener((observable, oldValue, newValue) -> { + factoriesScrollPane.setVisible(newValue); + factoriesScrollPane.setManaged(newValue); + fallbackContainer.setVisible(!newValue); + fallbackContainer.setManaged(!newValue); + }); } private void loadFactories() { + fallbackManager.reset(); + fallbackManager.setLoading(true); + User currentUser = TenantContext.getCurrentUser(); if (currentUser == null) { Platform.runLater(() -> fallbackManager.setLoading(false)); return; } - - fallbackManager.setLoading(true); - Integer organizationId = currentUser.getOrganization().getId(); + factoryService.getFactoriesByOrganizationIdAdvanced(organizationId, searchParams) .thenApply(this::handleFactoryResponse) .exceptionally(this::handleFactoryException) diff --git a/src/main/java/org/chainoptim/desktop/features/factory/controller/FactoryController.java b/src/main/java/org/chainoptim/desktop/features/factory/controller/FactoryController.java index 9857530c..df51a208 100644 --- a/src/main/java/org/chainoptim/desktop/features/factory/controller/FactoryController.java +++ b/src/main/java/org/chainoptim/desktop/features/factory/controller/FactoryController.java @@ -5,6 +5,7 @@ import javafx.scene.control.Tab; import javafx.scene.control.TabPane; import org.chainoptim.desktop.MainApplication; +import org.chainoptim.desktop.core.abstraction.ControllerFactory; import org.chainoptim.desktop.core.main.service.CurrentSelectionService; import org.chainoptim.desktop.shared.util.DataReceiver; import org.chainoptim.desktop.features.factory.model.Factory; @@ -17,6 +18,7 @@ import javafx.fxml.Initializable; import javafx.scene.control.Label; import javafx.scene.layout.StackPane; +import org.chainoptim.desktop.shared.util.resourceloader.FXMLLoaderService; import java.io.IOException; import java.net.URL; @@ -27,13 +29,12 @@ public class FactoryController implements Initializable { private final FactoryService factoryService; private final CurrentSelectionService currentSelectionService; + private final FXMLLoaderService fxmlLoaderService; + private final ControllerFactory controllerFactory; private final FallbackManager fallbackManager; private Factory factory; - @FXML - private FactoryProductionController graphController; - @FXML private StackPane fallbackContainer; @@ -56,25 +57,40 @@ public class FactoryController implements Initializable { @Inject public FactoryController(FactoryService factoryService, CurrentSelectionService currentSelectionService, + FXMLLoaderService fxmlLoaderService, + ControllerFactory controllerFactory, FallbackManager fallbackManager) { this.factoryService = factoryService; this.currentSelectionService = currentSelectionService; + this.fxmlLoaderService = fxmlLoaderService; + this.controllerFactory = controllerFactory; this.fallbackManager = fallbackManager; } @Override public void initialize(URL location, ResourceBundle resources) { + loadFallbackManager(); + setupTabListeners(); Integer factoryId = currentSelectionService.getSelectedId(); - if (factoryId == null) { + if (factoryId != null) { + loadFactory(factoryId); + } else { System.out.println("Missing factory id."); fallbackManager.setErrorMessage("Failed to load factory."); } + } - loadFactory(factoryId); - setupTabListeners(); + private void loadFallbackManager() { + // Load view into fallbackContainer + Node fallbackView = fxmlLoaderService.loadView( + "/org/chainoptim/desktop/shared/fallback/FallbackManagerView.fxml", + controllerFactory::createController + ); + fallbackContainer.getChildren().add(fallbackView); } private void loadFactory(Integer factoryId) { + fallbackManager.reset(); fallbackManager.setLoading(true); factoryService.getFactoryById(factoryId) @@ -126,6 +142,13 @@ private void setupTabListeners() { loadTabContent(performanceTab, "/org/chainoptim/desktop/features/factory/FactoryPerformanceView.fxml", this.factory); } }); + + fallbackManager.isEmptyProperty().addListener((observable, oldValue, newValue) -> { + tabPane.setVisible(newValue); + tabPane.setManaged(newValue); + fallbackContainer.setVisible(!newValue); + fallbackContainer.setManaged(!newValue); + }); } private void loadTabContent(Tab tab, String fxmlFilepath, Factory factory) { diff --git a/src/main/java/org/chainoptim/desktop/features/product/controller/ProductController.java b/src/main/java/org/chainoptim/desktop/features/product/controller/ProductController.java index d23f3170..f002c8ae 100644 --- a/src/main/java/org/chainoptim/desktop/features/product/controller/ProductController.java +++ b/src/main/java/org/chainoptim/desktop/features/product/controller/ProductController.java @@ -1,7 +1,7 @@ package org.chainoptim.desktop.features.product.controller; -import javafx.scene.layout.VBox; import org.chainoptim.desktop.MainApplication; +import org.chainoptim.desktop.core.abstraction.ControllerFactory; import org.chainoptim.desktop.core.main.service.CurrentSelectionService; import org.chainoptim.desktop.features.product.model.Product; import org.chainoptim.desktop.features.product.service.ProductService; @@ -18,6 +18,7 @@ import javafx.scene.control.Tab; import javafx.scene.control.TabPane; import javafx.scene.layout.StackPane; +import org.chainoptim.desktop.shared.util.resourceloader.FXMLLoaderService; import java.io.IOException; import java.net.URL; @@ -28,12 +29,12 @@ public class ProductController implements Initializable { private final ProductService productService; private final CurrentSelectionService currentSelectionService; + private final FXMLLoaderService fxmlLoaderService; + private final ControllerFactory controllerFactory; private final FallbackManager fallbackManager; private Product product; - @FXML - private VBox contentContainer; @FXML private StackPane fallbackContainer; @@ -53,23 +54,37 @@ public class ProductController implements Initializable { @Inject public ProductController(ProductService productService, - FallbackManager fallbackManager, - CurrentSelectionService currentSelectionService) { + FXMLLoaderService fxmlLoaderService, + ControllerFactory controllerFactory, + CurrentSelectionService currentSelectionService, + FallbackManager fallbackManager) { this.productService = productService; - this.fallbackManager = fallbackManager; this.currentSelectionService = currentSelectionService; + this.fxmlLoaderService = fxmlLoaderService; + this.controllerFactory = controllerFactory; + this.fallbackManager = fallbackManager; } @Override public void initialize(URL location, ResourceBundle resources) { + loadFallbackManager(); + setupListeners(); Integer productId = currentSelectionService.getSelectedId(); - if (productId == null) { + if (productId != null) { + loadProduct(productId); + } else { System.out.println("Missing product id."); fallbackManager.setErrorMessage("Failed to load product: missing product ID."); } + } - setupListeners(); - loadProduct(productId); + private void loadFallbackManager() { + // Load view into fallbackContainer + Node fallbackView = fxmlLoaderService.loadView( + "/org/chainoptim/desktop/shared/fallback/FallbackManagerView.fxml", + controllerFactory::createController + ); + fallbackContainer.getChildren().add(fallbackView); } private void setupListeners() { @@ -90,8 +105,8 @@ private void setupListeners() { }); fallbackManager.isEmptyProperty().addListener((observable, oldValue, newValue) -> { - contentContainer.setVisible(newValue); - contentContainer.setManaged(newValue); + tabPane.setVisible(newValue); + tabPane.setManaged(newValue); fallbackContainer.setVisible(!newValue); fallbackContainer.setManaged(!newValue); }); @@ -99,7 +114,6 @@ private void setupListeners() { private void loadProduct(Integer productId) { fallbackManager.reset(); -// fallbackManager.setErrorMessage("New Error"); fallbackManager.setLoading(true); productService.getProductWithStages(productId) diff --git a/src/main/java/org/chainoptim/desktop/features/product/controller/ProductsController.java b/src/main/java/org/chainoptim/desktop/features/product/controller/ProductsController.java index dbe8fd12..9b11a1da 100644 --- a/src/main/java/org/chainoptim/desktop/features/product/controller/ProductsController.java +++ b/src/main/java/org/chainoptim/desktop/features/product/controller/ProductsController.java @@ -28,7 +28,6 @@ import java.net.URL; import java.util.*; - public class ProductsController implements Initializable { private final ProductService productService; @@ -42,17 +41,17 @@ public class ProductsController implements Initializable { @FXML private HeaderController headerController; @FXML - private ScrollPane productsScrollPane; - @FXML private PageSelectorController pageSelectorController; @FXML - private StackPane pageSelectorContainer; + private ScrollPane productsScrollPane; @FXML - private StackPane fallbackContainer; + private VBox productsVBox; @FXML private StackPane headerContainer; @FXML - private VBox productsVBox; + private StackPane fallbackContainer; + @FXML + private StackPane pageSelectorContainer; private long totalCount; @@ -113,21 +112,20 @@ private void loadFallbackManager() { fallbackContainer.getChildren().add(fallbackView); } - private void loadProducts() { - fallbackManager.reset(); - fallbackManager.setLoading(true); - - User currentUser = TenantContext.getCurrentUser(); - if (currentUser == null) { - Platform.runLater(() -> fallbackManager.setLoading(false)); - return; + private void initializePageSelector() { + // Load view into pageSelectorContainer and initialize it with appropriate values + FXMLLoader loader = fxmlLoaderService.setUpLoader( + "/org/chainoptim/desktop/shared/search/PageSelectorView.fxml", + controllerFactory::createController + ); + try { + Node pageSelectorView = loader.load(); + pageSelectorContainer.getChildren().add(pageSelectorView); + pageSelectorController = loader.getController(); + searchParams.getPageProperty().addListener((observable, oldPage, newPage) -> loadProducts()); + } catch (IOException e) { + e.printStackTrace(); } - Integer organizationId = currentUser.getOrganization().getId(); - - productService.getProductsByOrganizationIdAdvanced(organizationId, searchParams) - .thenApply(this::handleProductResponse) - .exceptionally(this::handleProductException) - .thenRun(() -> Platform.runLater(() -> fallbackManager.setLoading(false))); } private void setUpListeners() { @@ -145,20 +143,21 @@ private void setUpListeners() { }); } - private void initializePageSelector() { - // Load view into pageSelectorContainer and initialize it with appropriate values - FXMLLoader loader = fxmlLoaderService.setUpLoader( - "/org/chainoptim/desktop/shared/search/PageSelectorView.fxml", - controllerFactory::createController - ); - try { - Node pageSelectorView = loader.load(); - pageSelectorContainer.getChildren().add(pageSelectorView); - pageSelectorController = loader.getController(); - searchParams.getPageProperty().addListener((observable, oldPage, newPage) -> loadProducts()); - } catch (IOException e) { - e.printStackTrace(); + private void loadProducts() { + fallbackManager.reset(); + fallbackManager.setLoading(true); + + User currentUser = TenantContext.getCurrentUser(); + if (currentUser == null) { + Platform.runLater(() -> fallbackManager.setLoading(false)); + return; } + Integer organizationId = currentUser.getOrganization().getId(); + + productService.getProductsByOrganizationIdAdvanced(organizationId, searchParams) + .thenApply(this::handleProductResponse) + .exceptionally(this::handleProductException) + .thenRun(() -> Platform.runLater(() -> fallbackManager.setLoading(false))); } private Optional> handleProductResponse(Optional> productsOptional) { diff --git a/src/main/java/org/chainoptim/desktop/features/supplier/controller/SupplierController.java b/src/main/java/org/chainoptim/desktop/features/supplier/controller/SupplierController.java index 2db883f6..224d1b8b 100644 --- a/src/main/java/org/chainoptim/desktop/features/supplier/controller/SupplierController.java +++ b/src/main/java/org/chainoptim/desktop/features/supplier/controller/SupplierController.java @@ -66,13 +66,54 @@ public SupplierController(SupplierService supplierService, @Override public void initialize(URL location, ResourceBundle resources) { + loadFallbackManager(); + setupListeners(); Integer supplierId = currentSelectionService.getSelectedId(); - if (supplier == null) { + if (supplierId != null) { + loadSupplier(supplierId); + } else { System.out.println("Missing supplier id."); fallbackManager.setErrorMessage("Failed to load supplier."); } - loadSupplier(supplierId); - setupTabListeners(); + } + + private void loadFallbackManager() { + // Load view into fallbackContainer + Node fallbackView = fxmlLoaderService.loadView( + "/org/chainoptim/desktop/shared/fallback/FallbackManagerView.fxml", + controllerFactory::createController + ); + fallbackContainer.getChildren().add(fallbackView); + } + + private void setupListeners() { + overviewTab.selectedProperty().addListener((observable, wasSelected, isNowSelected) -> { + if (Boolean.TRUE.equals(isNowSelected) && overviewTab.getContent() == null) { + loadTabContent(overviewTab, "/org/chainoptim/desktop/features/supplier/SupplierOverviewView.fxml", this.supplier); + } + }); + ordersTab.selectedProperty().addListener((observable, wasSelected, isNowSelected) -> { + if (Boolean.TRUE.equals(isNowSelected) && ordersTab.getContent() == null) { + loadTabContent(ordersTab, "/org/chainoptim/desktop/features/supplier/SupplierOrdersView.fxml", this.supplier); + } + }); + shipmentsTab.selectedProperty().addListener((observable, wasSelected, isNowSelected) -> { + if (Boolean.TRUE.equals(isNowSelected) && shipmentsTab.getContent() == null) { + loadTabContent(ordersTab, "/org/chainoptim/desktop/features/supplier/SupplierShipmentsView.fxml", this.supplier); + } + }); + performanceTab.selectedProperty().addListener((observable, wasSelected, isNowSelected) -> { + if (Boolean.TRUE.equals(isNowSelected) && performanceTab.getContent() == null) { + loadTabContent(performanceTab, "/org/chainoptim/desktop/features/supplier/SupplierPerformanceView.fxml", this.supplier); + } + }); + + fallbackManager.isEmptyProperty().addListener((observable, oldValue, newValue) -> { + tabPane.setVisible(newValue); + tabPane.setManaged(newValue); + fallbackContainer.setVisible(!newValue); + fallbackContainer.setManaged(!newValue); + }); } private void loadSupplier(Integer supplierId) { @@ -110,29 +151,6 @@ private Optional handleSupplierException(Throwable ex) { return Optional.empty(); } - private void setupTabListeners() { - overviewTab.selectedProperty().addListener((observable, wasSelected, isNowSelected) -> { - if (Boolean.TRUE.equals(isNowSelected) && overviewTab.getContent() == null) { - loadTabContent(overviewTab, "/org/chainoptim/desktop/features/supplier/SupplierOverviewView.fxml", this.supplier); - } - }); - ordersTab.selectedProperty().addListener((observable, wasSelected, isNowSelected) -> { - if (Boolean.TRUE.equals(isNowSelected) && ordersTab.getContent() == null) { - loadTabContent(ordersTab, "/org/chainoptim/desktop/features/supplier/SupplierOrdersView.fxml", this.supplier); - } - }); - shipmentsTab.selectedProperty().addListener((observable, wasSelected, isNowSelected) -> { - if (Boolean.TRUE.equals(isNowSelected) && shipmentsTab.getContent() == null) { - loadTabContent(ordersTab, "/org/chainoptim/desktop/features/supplier/SupplierShipmentsView.fxml", this.supplier); - } - }); - performanceTab.selectedProperty().addListener((observable, wasSelected, isNowSelected) -> { - if (Boolean.TRUE.equals(isNowSelected) && performanceTab.getContent() == null) { - loadTabContent(performanceTab, "/org/chainoptim/desktop/features/supplier/SupplierPerformanceView.fxml", this.supplier); - } - }); - } - private void loadTabContent(Tab tab, String fxmlFilepath, Supplier supplier) { try { FXMLLoader loader = new FXMLLoader(getClass().getResource(fxmlFilepath)); diff --git a/src/main/java/org/chainoptim/desktop/features/supplier/controller/SuppliersController.java b/src/main/java/org/chainoptim/desktop/features/supplier/controller/SuppliersController.java index bf27e86d..55d52900 100644 --- a/src/main/java/org/chainoptim/desktop/features/supplier/controller/SuppliersController.java +++ b/src/main/java/org/chainoptim/desktop/features/supplier/controller/SuppliersController.java @@ -8,6 +8,7 @@ import javafx.scene.Node; import javafx.scene.control.Button; import javafx.scene.control.Label; +import javafx.scene.control.ScrollPane; import javafx.scene.layout.StackPane; import javafx.scene.layout.VBox; import org.chainoptim.desktop.core.abstraction.ControllerFactory; @@ -43,15 +44,17 @@ public class SuppliersController implements Initializable { @FXML private HeaderController headerController; @FXML - private StackPane headerContainer; - @FXML private PageSelectorController pageSelectorController; @FXML - private StackPane pageSelectorContainer; + private ScrollPane suppliersScrollPane; + @FXML + private VBox suppliersVBox; + @FXML + private StackPane headerContainer; @FXML private StackPane fallbackContainer; @FXML - private VBox suppliersVBox; + private StackPane pageSelectorContainer; private long totalCount; @@ -82,26 +85,11 @@ public SuppliersController(SupplierService supplierService, public void initialize(URL location, ResourceBundle resources) { initializeHeader(); loadFallbackManager(); - loadSuppliers(); setUpListeners(); + loadSuppliers(); initializePageSelector(); } - private void initializePageSelector() { - FXMLLoader loader = fxmlLoaderService.setUpLoader( - "/org/chainoptim/desktop/shared/search/PageSelectorView.fxml", - controllerFactory::createController - ); - try { - Node pageSelectorView = loader.load(); - pageSelectorContainer.getChildren().add(pageSelectorView); - pageSelectorController = loader.getController(); - searchParams.getPageProperty().addListener((observable, oldPage, newPage) -> loadSuppliers()); - } catch (IOException e) { - e.printStackTrace(); - } - } - private void initializeHeader() { FXMLLoader loader = fxmlLoaderService.setUpLoader( "/org/chainoptim/desktop/core/main/HeaderView.fxml", @@ -125,22 +113,46 @@ private void loadFallbackManager() { fallbackContainer.getChildren().add(fallbackView); } + private void initializePageSelector() { + FXMLLoader loader = fxmlLoaderService.setUpLoader( + "/org/chainoptim/desktop/shared/search/PageSelectorView.fxml", + controllerFactory::createController + ); + try { + Node pageSelectorView = loader.load(); + pageSelectorContainer.getChildren().add(pageSelectorView); + pageSelectorController = loader.getController(); + searchParams.getPageProperty().addListener((observable, oldPage, newPage) -> loadSuppliers()); + } catch (IOException e) { + e.printStackTrace(); + } + } + private void setUpListeners() { searchParams.getSearchQueryProperty().addListener((observable, oldValue, newValue) -> loadSuppliers()); searchParams.getAscendingProperty().addListener((observable, oldValue, newValue) -> loadSuppliers()); searchParams.getSortOptionProperty().addListener((observable, oldValue, newValue) -> loadSuppliers()); + + // Listen to empty fallback state + fallbackManager.isEmptyProperty().addListener((observable, oldValue, newValue) -> { + suppliersScrollPane.setVisible(newValue); + suppliersScrollPane.setManaged(newValue); + fallbackContainer.setVisible(!newValue); + fallbackContainer.setManaged(!newValue); + }); } private void loadSuppliers() { + fallbackManager.reset(); + fallbackManager.setLoading(true); + User currentUser = TenantContext.getCurrentUser(); if (currentUser == null) { Platform.runLater(() -> fallbackManager.setLoading(false)); return; } - - fallbackManager.setLoading(true); - Integer organizationId = currentUser.getOrganization().getId(); + supplierService.getSuppliersByOrganizationIdAdvanced(organizationId, searchParams) .thenApply(this::handleSupplierResponse) .exceptionally(this::handleSupplierException) diff --git a/src/main/java/org/chainoptim/desktop/features/warehouse/controller/WarehouseController.java b/src/main/java/org/chainoptim/desktop/features/warehouse/controller/WarehouseController.java index 1fdb81c3..7d491459 100644 --- a/src/main/java/org/chainoptim/desktop/features/warehouse/controller/WarehouseController.java +++ b/src/main/java/org/chainoptim/desktop/features/warehouse/controller/WarehouseController.java @@ -63,14 +63,15 @@ public WarehouseController(WarehouseService warehouseService, @Override public void initialize (URL location, ResourceBundle resources) { + loadFallbackManager(); + setupListeners(); Integer warehouseId = currentSelectionService.getSelectedId(); - if (warehouseId == null) { + if (warehouseId != null) { + loadWarehouse(warehouseId); + } else { System.out.println("Missing warehouse id."); fallbackManager.setErrorMessage("Failed to load warehouse."); } - loadFallbackManager(); - loadWarehouse(warehouseId); - setupTabListeners(); } private void loadFallbackManager() { @@ -82,6 +83,26 @@ private void loadFallbackManager() { fallbackContainer.getChildren().add(fallbackView); } + private void setupListeners() { + overviewTab.selectedProperty().addListener((observable, wasSelected, isNowSelected) -> { + if (Boolean.TRUE.equals(isNowSelected) && overviewTab.getContent() == null) { + loadTabContent(overviewTab, "/org/chainoptim/desktop/features/warehouse/WarehouseOverviewView.fxml", this.warehouse); + } + }); + inventoryTab.selectedProperty().addListener((observable, wasSelected, isNowSelected) -> { + if (Boolean.TRUE.equals(isNowSelected) && inventoryTab.getContent() == null) { + loadTabContent(inventoryTab, "/org/chainoptim/desktop/features/warehouse/WarehouseInventoryView.fxml", this.warehouse); + } + }); + + fallbackManager.isEmptyProperty().addListener((observable, oldValue, newValue) -> { + tabPane.setVisible(newValue); + tabPane.setManaged(newValue); + fallbackContainer.setVisible(!newValue); + fallbackContainer.setManaged(!newValue); + }); + } + private void loadWarehouse(Integer warehouseId) { fallbackManager.reset(); fallbackManager.setLoading(true); @@ -113,19 +134,6 @@ private Optional handleWarehouseException(Throwable ex) { return Optional.empty(); } - private void setupTabListeners() { - overviewTab.selectedProperty().addListener((observable, wasSelected, isNowSelected) -> { - if (Boolean.TRUE.equals(isNowSelected) && overviewTab.getContent() == null) { - loadTabContent(overviewTab, "/org/chainoptim/desktop/features/warehouse/WarehouseOverviewView.fxml", this.warehouse); - } - }); - inventoryTab.selectedProperty().addListener((observable, wasSelected, isNowSelected) -> { - if (Boolean.TRUE.equals(isNowSelected) && inventoryTab.getContent() == null) { - loadTabContent(inventoryTab, "/org/chainoptim/desktop/features/warehouse/WarehouseInventoryView.fxml", this.warehouse); - } - }); - } - private void loadTabContent(Tab tab, String fxmlFilepath, Warehouse warehouse) { try { FXMLLoader loader = new FXMLLoader(getClass().getResource(fxmlFilepath)); @@ -144,8 +152,4 @@ private void handleEditWarehouse() { System.out.println("Edit Warehouse Working"); } - - - - } diff --git a/src/main/java/org/chainoptim/desktop/features/warehouse/controller/WarehousesController.java b/src/main/java/org/chainoptim/desktop/features/warehouse/controller/WarehousesController.java index 5973ab91..3a33fd70 100644 --- a/src/main/java/org/chainoptim/desktop/features/warehouse/controller/WarehousesController.java +++ b/src/main/java/org/chainoptim/desktop/features/warehouse/controller/WarehousesController.java @@ -8,6 +8,7 @@ import javafx.scene.Node; import javafx.scene.control.Button; import javafx.scene.control.Label; +import javafx.scene.control.ScrollPane; import javafx.scene.layout.StackPane; import javafx.scene.layout.VBox; import org.chainoptim.desktop.core.abstraction.ControllerFactory; @@ -44,15 +45,17 @@ public class WarehousesController implements Initializable { @FXML private HeaderController headerController; @FXML - private StackPane headerContainer; - @FXML private PageSelectorController pageSelectorController; @FXML + private ScrollPane warehousesScrollPane; + @FXML + private VBox warehousesVBox; + @FXML + private StackPane headerContainer; + @FXML private StackPane pageSelectorContainer; @FXML private StackPane fallbackContainer; - @FXML - private VBox warehousesVBox; private long totalCount; @@ -84,26 +87,11 @@ public WarehousesController(WarehouseService warehouseService, public void initialize(URL location, ResourceBundle resources) { initializeHeader(); loadFallbackManager(); - loadWarehouses(); setUpListeners(); + loadWarehouses(); initializePageSelector(); } - private void initializePageSelector() { - FXMLLoader loader = fxmlLoaderService.setUpLoader( - "/org/chainoptim/desktop/shared/search/PageSelectorView.fxml", - controllerFactory::createController - ); - try { - Node pageSelectorView = loader.load(); - pageSelectorContainer.getChildren().add(pageSelectorView); - pageSelectorController = loader.getController(); - searchParams.getPageProperty().addListener((observable, oldValue, newValue) -> loadWarehouses()); - } catch (IOException e) { - e.printStackTrace(); - } - } - private void initializeHeader() { FXMLLoader loader = fxmlLoaderService.setUpLoader( "/org/chainoptim/desktop/core/main/HeaderView.fxml", @@ -127,21 +115,46 @@ private void loadFallbackManager() { fallbackContainer.getChildren().add(fallbackView); } + private void initializePageSelector() { + FXMLLoader loader = fxmlLoaderService.setUpLoader( + "/org/chainoptim/desktop/shared/search/PageSelectorView.fxml", + controllerFactory::createController + ); + try { + Node pageSelectorView = loader.load(); + pageSelectorContainer.getChildren().add(pageSelectorView); + pageSelectorController = loader.getController(); + searchParams.getPageProperty().addListener((observable, oldValue, newValue) -> loadWarehouses()); + } catch (IOException e) { + e.printStackTrace(); + } + } + private void setUpListeners() { searchParams.getSearchQueryProperty().addListener((observable, oldValue, newValue) -> loadWarehouses()); searchParams.getAscendingProperty().addListener((observable, oldValue, newValue) -> loadWarehouses()); searchParams.getSortOptionProperty().addListener((observable, oldValue, newValue) -> loadWarehouses()); + + // Listen to empty fallback state + fallbackManager.isEmptyProperty().addListener((observable, oldValue, newValue) -> { + warehousesScrollPane.setVisible(newValue); + warehousesScrollPane.setManaged(newValue); + fallbackContainer.setVisible(!newValue); + fallbackContainer.setManaged(!newValue); + }); } private void loadWarehouses() { + fallbackManager.reset(); + fallbackManager.setLoading(true); + User currentUser = TenantContext.getCurrentUser(); if (currentUser == null) { Platform.runLater(() -> fallbackManager.setLoading(false)); return; } - fallbackManager.setLoading(true); - Integer organizationId = currentUser.getOrganization().getId(); + warehouseService.getWarehousesByOrganizationIdAdvanced(organizationId, searchParams) .thenApply(this::handleWarehouseResponse) .exceptionally(this::handleWarehouseException) diff --git a/src/main/java/org/chainoptim/desktop/shared/fallback/FallbackManager.java b/src/main/java/org/chainoptim/desktop/shared/fallback/FallbackManager.java index f65124b5..9b9fe2a3 100644 --- a/src/main/java/org/chainoptim/desktop/shared/fallback/FallbackManager.java +++ b/src/main/java/org/chainoptim/desktop/shared/fallback/FallbackManager.java @@ -23,6 +23,7 @@ public String getErrorMessage() { } public void setErrorMessage(String errorMessage) { + System.out.println("Setting error message: " + errorMessage); this.errorMessage.set(errorMessage); } diff --git a/src/main/resources/css/fallback.css b/src/main/resources/css/fallback.css index d40313bc..abd376f2 100644 --- a/src/main/resources/css/fallback.css +++ b/src/main/resources/css/fallback.css @@ -30,3 +30,7 @@ -fx-rotate: 360; } } + +.page-fallback-container { + -fx-padding: 160px; +} \ No newline at end of file diff --git a/src/main/resources/org/chainoptim/desktop/features/factory/FactoriesView.fxml b/src/main/resources/org/chainoptim/desktop/features/factory/FactoriesView.fxml index a6d357f0..33bd7290 100644 --- a/src/main/resources/org/chainoptim/desktop/features/factory/FactoriesView.fxml +++ b/src/main/resources/org/chainoptim/desktop/features/factory/FactoriesView.fxml @@ -1,16 +1,23 @@ + - + + + + + + + - - - + + diff --git a/src/main/resources/org/chainoptim/desktop/features/factory/FactoryView.fxml b/src/main/resources/org/chainoptim/desktop/features/factory/FactoryView.fxml index 55fb7e90..fed81182 100644 --- a/src/main/resources/org/chainoptim/desktop/features/factory/FactoryView.fxml +++ b/src/main/resources/org/chainoptim/desktop/features/factory/FactoryView.fxml @@ -1,15 +1,15 @@ - - + fx:controller="org.chainoptim.desktop.features.factory.controller.FactoryController"> + @@ -18,13 +18,17 @@ diff --git a/src/test/java/org/chainoptim/desktop/core/main/service/NavigationServiceTest.java b/src/test/java/org/chainoptim/desktop/core/main/service/NavigationServiceTest.java index 9f58711e..ca6f744f 100644 --- a/src/test/java/org/chainoptim/desktop/core/main/service/NavigationServiceTest.java +++ b/src/test/java/org/chainoptim/desktop/core/main/service/NavigationServiceTest.java @@ -40,8 +40,8 @@ void setUp() { @Test void switchViewCacheWorks() { - navigationService.switchView("Products?id=1"); - navigationService.switchView("Products?id=2"); + navigationService.switchView("Products?id=1", true); + navigationService.switchView("Products?id=2", true); Assertions.assertTrue(NavigationServiceImpl.getViewCache().containsKey("Products?id=1")); Assertions.assertTrue(NavigationServiceImpl.getViewCache().containsKey("Products?id=2")); From 9d713a05f71da3c8e1ca5f1f1e1438b125e04eb0 Mon Sep 17 00:00:00 2001 From: TudorOrban <130213626+TudorOrban@users.noreply.github.com> Date: Sat, 23 Mar 2024 17:59:48 +0200 Subject: [PATCH 08/11] Add Update Factory functionality (including location) --- .../main/service/NavigationServiceImpl.java | 31 +-- .../factory/controller/FactoryController.java | 7 +- .../controller/UpdateFactoryController.java | 177 ++++++++++++++++++ .../factory/dto/UpdateFactoryDTO.java | 5 + .../service/FactoryWriteServiceImpl.java | 4 +- .../SelectOrCreateLocationController.java | 5 + .../features/location/model/Location.java | 5 + src/main/resources/css/sidebar.css | 1 - src/main/resources/img/arrow-left-solid.png | Bin 0 -> 5872 bytes .../chainoptim/desktop/core/main/AppView.fxml | 12 +- .../desktop/core/main/SidebarView.fxml | 8 +- .../features/factory/UpdateFactoryView.fxml | 27 +++ 12 files changed, 253 insertions(+), 29 deletions(-) create mode 100644 src/main/java/org/chainoptim/desktop/features/factory/controller/UpdateFactoryController.java create mode 100644 src/main/resources/img/arrow-left-solid.png create mode 100644 src/main/resources/org/chainoptim/desktop/features/factory/UpdateFactoryView.fxml diff --git a/src/main/java/org/chainoptim/desktop/core/main/service/NavigationServiceImpl.java b/src/main/java/org/chainoptim/desktop/core/main/service/NavigationServiceImpl.java index 6fb3a07b..f509120a 100644 --- a/src/main/java/org/chainoptim/desktop/core/main/service/NavigationServiceImpl.java +++ b/src/main/java/org/chainoptim/desktop/core/main/service/NavigationServiceImpl.java @@ -48,27 +48,30 @@ public NavigationServiceImpl(FXMLLoaderService fxmlLoaderService, private static final Map viewCache = new HashMap<>(); private final Map viewMap = Map.ofEntries( - // Main pages Map.entry("Overview", "/org/chainoptim/desktop/core/main/OverviewView.fxml"), Map.entry("Organization", "/org/chainoptim/desktop/core/organization/OrganizationView.fxml"), + Map.entry("Products", "/org/chainoptim/desktop/features/product/ProductsView.fxml"), - Map.entry("Factories", "/org/chainoptim/desktop/features/factory/FactoriesView.fxml"), - Map.entry("Warehouses", "/org/chainoptim/desktop/features/warehouse/WarehousesView.fxml"), - Map.entry("Suppliers", "/org/chainoptim/desktop/features/supplier/SuppliersView.fxml"), - Map.entry("Clients", "/org/chainoptim/desktop/features/client/ClientsView.fxml"), - // Dynamic route pages Map.entry("Product", "/org/chainoptim/desktop/features/product/ProductView.fxml"), - Map.entry("Factory", "/org/chainoptim/desktop/features/factory/FactoryView.fxml"), - Map.entry("Warehouse", "/org/chainoptim/desktop/features/warehouse/WarehouseView.fxml"), - Map.entry("Supplier", "/org/chainoptim/desktop/features/supplier/SupplierView.fxml"), - Map.entry("Client", "/org/chainoptim/desktop/features/client/ClientView.fxml"), - - // Create forms Map.entry("Create-Product", "/org/chainoptim/desktop/features/product/CreateProductView.fxml"), + + Map.entry("Factories", "/org/chainoptim/desktop/features/factory/FactoriesView.fxml"), + Map.entry("Factory", "/org/chainoptim/desktop/features/factory/FactoryView.fxml"), Map.entry("Create-Factory", "/org/chainoptim/desktop/features/factory/CreateFactoryView.fxml"), + Map.entry("Update-Factory", "/org/chainoptim/desktop/features/factory/UpdateFactoryView.fxml"), + + Map.entry("Warehouses", "/org/chainoptim/desktop/features/warehouse/WarehousesView.fxml"), + Map.entry("Warehouse", "/org/chainoptim/desktop/features/warehouse/WarehouseView.fxml"), Map.entry("Create-Warehouse", "/org/chainoptim/desktop/features/warehouse/CreateWarehouseView.fxml"), + + Map.entry("Suppliers", "/org/chainoptim/desktop/features/supplier/SuppliersView.fxml"), + Map.entry("Supplier", "/org/chainoptim/desktop/features/supplier/SupplierView.fxml"), Map.entry("Create-Supplier", "/org/chainoptim/desktop/features/supplier/CreateSupplierView.fxml"), + + Map.entry("Clients", "/org/chainoptim/desktop/features/client/ClientsView.fxml"), + Map.entry("Client", "/org/chainoptim/desktop/features/client/ClientView.fxml"), Map.entry("Create-Client", "/org/chainoptim/desktop/features/client/CreateClientView.fxml"), + Map.entry("Create-Stage", "/org/chainoptim/desktop/features/client/CreateFactoryStageView.fxml") ); @@ -150,4 +153,8 @@ public void goBack() { public static void invalidateViewCache() { viewCache.clear(); } + + public static void invalidateViewCache(String viewKey) { + viewCache.remove(viewKey); + } } diff --git a/src/main/java/org/chainoptim/desktop/features/factory/controller/FactoryController.java b/src/main/java/org/chainoptim/desktop/features/factory/controller/FactoryController.java index df51a208..0501d286 100644 --- a/src/main/java/org/chainoptim/desktop/features/factory/controller/FactoryController.java +++ b/src/main/java/org/chainoptim/desktop/features/factory/controller/FactoryController.java @@ -7,6 +7,7 @@ import org.chainoptim.desktop.MainApplication; import org.chainoptim.desktop.core.abstraction.ControllerFactory; import org.chainoptim.desktop.core.main.service.CurrentSelectionService; +import org.chainoptim.desktop.core.main.service.NavigationService; import org.chainoptim.desktop.shared.util.DataReceiver; import org.chainoptim.desktop.features.factory.model.Factory; import org.chainoptim.desktop.features.factory.service.FactoryService; @@ -28,6 +29,7 @@ public class FactoryController implements Initializable { private final FactoryService factoryService; + private final NavigationService navigationService; private final CurrentSelectionService currentSelectionService; private final FXMLLoaderService fxmlLoaderService; private final ControllerFactory controllerFactory; @@ -56,11 +58,13 @@ public class FactoryController implements Initializable { @Inject public FactoryController(FactoryService factoryService, + NavigationService navigationService, CurrentSelectionService currentSelectionService, FXMLLoaderService fxmlLoaderService, ControllerFactory controllerFactory, FallbackManager fallbackManager) { this.factoryService = factoryService; + this.navigationService = navigationService; this.currentSelectionService = currentSelectionService; this.fxmlLoaderService = fxmlLoaderService; this.controllerFactory = controllerFactory; @@ -166,7 +170,8 @@ private void loadTabContent(Tab tab, String fxmlFilepath, Factory factory) { @FXML private void handleEditFactory() { - System.out.println("Edit Factory Working"); + currentSelectionService.setSelectedId(factory.getId()); + navigationService.switchView("Update-Factory?id=" + factory.getId(), true); } } diff --git a/src/main/java/org/chainoptim/desktop/features/factory/controller/UpdateFactoryController.java b/src/main/java/org/chainoptim/desktop/features/factory/controller/UpdateFactoryController.java new file mode 100644 index 00000000..b5094c5f --- /dev/null +++ b/src/main/java/org/chainoptim/desktop/features/factory/controller/UpdateFactoryController.java @@ -0,0 +1,177 @@ +package org.chainoptim.desktop.features.factory.controller; + +import javafx.fxml.Initializable; +import org.chainoptim.desktop.core.abstraction.ControllerFactory; +import org.chainoptim.desktop.core.main.service.CurrentSelectionService; +import org.chainoptim.desktop.core.main.service.NavigationService; +import org.chainoptim.desktop.core.main.service.NavigationServiceImpl; +import org.chainoptim.desktop.features.factory.dto.UpdateFactoryDTO; +import org.chainoptim.desktop.features.factory.model.Factory; +import org.chainoptim.desktop.features.factory.service.FactoryService; +import org.chainoptim.desktop.features.factory.service.FactoryWriteService; +import org.chainoptim.desktop.shared.common.uielements.SelectOrCreateLocationController; +import org.chainoptim.desktop.shared.fallback.FallbackManager; +import org.chainoptim.desktop.shared.util.resourceloader.FXMLLoaderService; + +import com.google.inject.Inject; +import javafx.application.Platform; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.scene.Node; +import javafx.scene.control.TextField; +import javafx.scene.layout.StackPane; + +import java.io.IOException; +import java.net.URL; +import java.util.Optional; +import java.util.ResourceBundle; + +public class UpdateFactoryController implements Initializable { + + private final FactoryService factoryService; + private final FactoryWriteService factoryWriteService; + private final NavigationService navigationService; + private final CurrentSelectionService currentSelectionService; + private final FXMLLoaderService fxmlLoaderService; + private final ControllerFactory controllerFactory; + private final FallbackManager fallbackManager; + + private Factory factory; + + private SelectOrCreateLocationController selectOrCreateLocationController; + + @FXML + private StackPane fallbackContainer; + @FXML + private StackPane selectOrCreateLocationContainer; + @FXML + private TextField nameField; + + @Inject + public UpdateFactoryController( + FactoryService factoryService, + FactoryWriteService factoryWriteService, + NavigationService navigationService, + CurrentSelectionService currentSelectionService, + FallbackManager fallbackManager, + FXMLLoaderService fxmlLoaderService, + ControllerFactory controllerFactory + ) { + this.factoryService = factoryService; + this.factoryWriteService = factoryWriteService; + this.navigationService = navigationService; + this.currentSelectionService = currentSelectionService; + this.fxmlLoaderService = fxmlLoaderService; + this.controllerFactory = controllerFactory; + this.fallbackManager = fallbackManager; + } + + @FXML + public void initialize(URL location, ResourceBundle resources) { + loadFallbackManager(); + loadSelectOrCreateLocation(); + loadFactory(currentSelectionService.getSelectedId()); + } + + private void loadFallbackManager() { + Node fallbackView = fxmlLoaderService.loadView( + "/org/chainoptim/desktop/shared/fallback/FallbackManagerView.fxml", + controllerFactory::createController + ); + fallbackContainer.getChildren().add(fallbackView); + } + + private void loadSelectOrCreateLocation() { + FXMLLoader loader = fxmlLoaderService.setUpLoader( + "/org/chainoptim/desktop/shared/common/uielements/SelectOrCreateLocationView.fxml", + controllerFactory::createController + ); + try { + Node selectOrCreateLocationView = loader.load(); + selectOrCreateLocationController = loader.getController(); + selectOrCreateLocationContainer.getChildren().add(selectOrCreateLocationView); + selectOrCreateLocationController.initialize(); + } catch (IOException ex) { + ex.printStackTrace(); + } + } + + private void loadFactory(Integer factoryId) { + fallbackManager.reset(); + fallbackManager.setLoading(true); + + factoryService.getFactoryById(factoryId) + .thenApply(this::handleFactoryResponse) + .exceptionally(this::handleFactoryException) + .thenRun(() -> Platform.runLater(() -> fallbackManager.setLoading(false))); + } + + private Optional handleFactoryResponse(Optional factoryOptional) { + Platform.runLater(() -> { + if (factoryOptional.isEmpty()) { + fallbackManager.setErrorMessage("Failed to load factory."); + return; + } + factory = factoryOptional.get(); + + nameField.setText(factory.getName()); + selectOrCreateLocationController.setSelectedLocation(factory.getLocation()); + }); + + return factoryOptional; + } + + private Optional handleFactoryException(Throwable ex) { + Platform.runLater(() -> fallbackManager.setErrorMessage("Failed to load factory.")); + return Optional.empty(); + } + + @FXML + private void handleSubmit() { + fallbackManager.reset(); + fallbackManager.setLoading(true); + + UpdateFactoryDTO factoryDTO = getUpdateFactoryDTO(); + + System.out.println(factoryDTO); + + factoryWriteService.updateFactory(factoryDTO) + .thenAccept(factoryOptional -> + Platform.runLater(() -> { + if (factoryOptional.isEmpty()) { + fallbackManager.setErrorMessage("Failed to create factory."); + return; + } + fallbackManager.setLoading(false); + + // Manage navigation, invalidating previous factory cache + Factory updatedFactory = factoryOptional.get(); + String factoryPage = "Factory?id=" + updatedFactory.getId(); + NavigationServiceImpl.invalidateViewCache(factoryPage); + currentSelectionService.setSelectedId(updatedFactory.getId()); + navigationService.switchView(factoryPage, true); + }) + ) + .exceptionally(ex -> { + ex.printStackTrace(); + return null; + }); + } + + private UpdateFactoryDTO getUpdateFactoryDTO() { + UpdateFactoryDTO factoryDTO = new UpdateFactoryDTO(); + factoryDTO.setId(factory.getId()); + factoryDTO.setName(nameField.getText()); + + if (selectOrCreateLocationController.isCreatingNewLocation()) { + factoryDTO.setCreateLocation(true); + factoryDTO.setLocation(selectOrCreateLocationController.getNewLocationDTO()); + } else { + factoryDTO.setCreateLocation(false); + factoryDTO.setLocationId(selectOrCreateLocationController.getSelectedLocation().getId()); + } + + return factoryDTO; + } +} + diff --git a/src/main/java/org/chainoptim/desktop/features/factory/dto/UpdateFactoryDTO.java b/src/main/java/org/chainoptim/desktop/features/factory/dto/UpdateFactoryDTO.java index d596fdf1..18848f7b 100644 --- a/src/main/java/org/chainoptim/desktop/features/factory/dto/UpdateFactoryDTO.java +++ b/src/main/java/org/chainoptim/desktop/features/factory/dto/UpdateFactoryDTO.java @@ -1,5 +1,7 @@ package org.chainoptim.desktop.features.factory.dto; +import org.chainoptim.desktop.shared.features.location.dto.CreateLocationDTO; + import lombok.Data; @Data @@ -7,4 +9,7 @@ public class UpdateFactoryDTO { private Integer id; private String name; + private Integer locationId; + private CreateLocationDTO location; + private boolean createLocation; } diff --git a/src/main/java/org/chainoptim/desktop/features/factory/service/FactoryWriteServiceImpl.java b/src/main/java/org/chainoptim/desktop/features/factory/service/FactoryWriteServiceImpl.java index 09d64097..ce865d70 100644 --- a/src/main/java/org/chainoptim/desktop/features/factory/service/FactoryWriteServiceImpl.java +++ b/src/main/java/org/chainoptim/desktop/features/factory/service/FactoryWriteServiceImpl.java @@ -1,12 +1,12 @@ package org.chainoptim.desktop.features.factory.service; -import com.fasterxml.jackson.core.type.TypeReference; import org.chainoptim.desktop.core.user.util.TokenManager; import org.chainoptim.desktop.features.factory.dto.CreateFactoryDTO; import org.chainoptim.desktop.features.factory.dto.UpdateFactoryDTO; import org.chainoptim.desktop.features.factory.model.Factory; import org.chainoptim.desktop.shared.util.JsonUtil; +import com.fasterxml.jackson.core.type.TypeReference; import java.net.HttpURLConnection; import java.net.URI; import java.net.http.HttpClient; @@ -77,7 +77,7 @@ public CompletableFuture> updateFactory(UpdateFactoryDTO facto HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(routeAddress)) - .POST(HttpRequest.BodyPublishers.ofString(requestBody, StandardCharsets.UTF_8)) + .PUT(HttpRequest.BodyPublishers.ofString(requestBody, StandardCharsets.UTF_8)) .headers(HEADER_KEY, headerValue) .headers("Content-Type", "application/json") .build(); diff --git a/src/main/java/org/chainoptim/desktop/shared/common/uielements/SelectOrCreateLocationController.java b/src/main/java/org/chainoptim/desktop/shared/common/uielements/SelectOrCreateLocationController.java index 7a50a9cb..d85e5f5a 100644 --- a/src/main/java/org/chainoptim/desktop/shared/common/uielements/SelectOrCreateLocationController.java +++ b/src/main/java/org/chainoptim/desktop/shared/common/uielements/SelectOrCreateLocationController.java @@ -123,6 +123,11 @@ public Location getSelectedLocation() { return locationComboBox.getSelectionModel().getSelectedItem(); } + public void setSelectedLocation(Location location) { + locationComboBox.getSelectionModel().select(location); + + } + public CreateLocationDTO getNewLocationDTO() { CreateLocationDTO locationDTO = new CreateLocationDTO(); locationDTO.setOrganizationId(organizationId); diff --git a/src/main/java/org/chainoptim/desktop/shared/features/location/model/Location.java b/src/main/java/org/chainoptim/desktop/shared/features/location/model/Location.java index 1fc78b21..8e0e4928 100644 --- a/src/main/java/org/chainoptim/desktop/shared/features/location/model/Location.java +++ b/src/main/java/org/chainoptim/desktop/shared/features/location/model/Location.java @@ -23,4 +23,9 @@ public String getFormattedLocation() { return formattedCity + formattedState + formattedCountry; } + @Override + public String toString() { + return getFormattedLocation(); + } + } diff --git a/src/main/resources/css/sidebar.css b/src/main/resources/css/sidebar.css index 09e9527d..7906aea1 100644 --- a/src/main/resources/css/sidebar.css +++ b/src/main/resources/css/sidebar.css @@ -1,4 +1,3 @@ - .sidebar { -fx-background-color: #000000; -fx-border-color: #333; diff --git a/src/main/resources/img/arrow-left-solid.png b/src/main/resources/img/arrow-left-solid.png new file mode 100644 index 0000000000000000000000000000000000000000..63259da2fad13ead77c087ab243fdb95d2ed35f1 GIT binary patch literal 5872 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 - - - - - - + fx:controller="org.chainoptim.desktop.core.main.controller.AppController" + style="-fx-background-color: #ffffff;"> @@ -18,8 +13,7 @@
- +
-
\ No newline at end of file diff --git a/src/main/resources/org/chainoptim/desktop/core/main/SidebarView.fxml b/src/main/resources/org/chainoptim/desktop/core/main/SidebarView.fxml index 367bbb2b..df755ffc 100644 --- a/src/main/resources/org/chainoptim/desktop/core/main/SidebarView.fxml +++ b/src/main/resources/org/chainoptim/desktop/core/main/SidebarView.fxml @@ -10,16 +10,16 @@ diff --git a/src/main/resources/org/chainoptim/desktop/features/factory/UpdateFactoryView.fxml b/src/main/resources/org/chainoptim/desktop/features/factory/UpdateFactoryView.fxml new file mode 100644 index 00000000..e28ff6f2 --- /dev/null +++ b/src/main/resources/org/chainoptim/desktop/features/factory/UpdateFactoryView.fxml @@ -0,0 +1,27 @@ + + + + + + + + + + + +