Merge branch 'AttachmentsToChat'
This commit is contained in:
@@ -12,6 +12,8 @@ public class MessageResponse {
|
||||
private String content;
|
||||
private LocalDateTime timestamp;
|
||||
private Boolean isRead;
|
||||
private String attachmentName;
|
||||
private String attachmentUrl;
|
||||
|
||||
public MessageResponse() {
|
||||
}
|
||||
@@ -87,4 +89,20 @@ public class MessageResponse {
|
||||
public void setIsRead(Boolean isRead) {
|
||||
this.isRead = isRead;
|
||||
}
|
||||
|
||||
public String getAttachmentName() {
|
||||
return attachmentName;
|
||||
}
|
||||
|
||||
public void setAttachmentName(String attachmentName) {
|
||||
this.attachmentName = attachmentName;
|
||||
}
|
||||
|
||||
public String getAttachmentUrl() {
|
||||
return attachmentUrl;
|
||||
}
|
||||
|
||||
public void setAttachmentUrl(String attachmentUrl) {
|
||||
this.attachmentUrl = attachmentUrl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@ import org.example.petshopdesktop.api.dto.auth.AvatarUploadResponse;
|
||||
import org.example.petshopdesktop.api.dto.auth.UserInfoResponse;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class AuthApi {
|
||||
private static final AuthApi INSTANCE = new AuthApi();
|
||||
@@ -33,4 +35,10 @@ public class AuthApi {
|
||||
public void deleteAvatar() throws Exception {
|
||||
apiClient.delete("/api/v1/auth/me/avatar");
|
||||
}
|
||||
|
||||
public void forgotPassword(String usernameOrEmail) throws Exception {
|
||||
Map<String, String> body = new HashMap<>();
|
||||
body.put("usernameOrEmail", usernameOrEmail);
|
||||
apiClient.post("/api/v1/auth/forgot-password", body, Object.class);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,9 @@ import javafx.scene.control.DatePicker;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.Tab;
|
||||
import javafx.scene.control.TabPane;
|
||||
import javafx.scene.control.ToggleButton;
|
||||
import javafx.scene.control.ToggleGroup;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.VBox;
|
||||
import org.example.petshopdesktop.api.dto.analytics.DailySales;
|
||||
import org.example.petshopdesktop.api.dto.analytics.DashboardResponse;
|
||||
@@ -98,6 +101,20 @@ public class AnalyticsController {
|
||||
@FXML
|
||||
private ComboBox<String> cbTopN;
|
||||
|
||||
@FXML
|
||||
private ComboBox<String> cbStoreFilter;
|
||||
|
||||
@FXML
|
||||
private HBox hbViewToggle;
|
||||
|
||||
@FXML
|
||||
private ToggleButton tbnMyAnalytics;
|
||||
|
||||
@FXML
|
||||
private ToggleButton tbnStoreAnalytics;
|
||||
|
||||
private String viewMode = "store";
|
||||
|
||||
private List<SaleResponse> cachedSales = new ArrayList<>();
|
||||
private FilterState currentFilter = new FilterState();
|
||||
|
||||
@@ -124,8 +141,29 @@ public class AnalyticsController {
|
||||
cbPaymentFilter.setItems(FXCollections.observableArrayList("All"));
|
||||
cbPaymentFilter.getSelectionModel().selectFirst();
|
||||
|
||||
cbStoreFilter.setItems(FXCollections.observableArrayList("All Stores"));
|
||||
cbStoreFilter.getSelectionModel().selectFirst();
|
||||
|
||||
lblFilterSummary.setText("All time");
|
||||
|
||||
ToggleGroup tgViewMode = new ToggleGroup();
|
||||
tbnMyAnalytics.setToggleGroup(tgViewMode);
|
||||
tbnStoreAnalytics.setToggleGroup(tgViewMode);
|
||||
tbnStoreAnalytics.setSelected(true);
|
||||
tgViewMode.selectedToggleProperty().addListener((obs, oldVal, newVal) -> {
|
||||
if (newVal == null) {
|
||||
(viewMode.equals("mine") ? tbnMyAnalytics : tbnStoreAnalytics).setSelected(true);
|
||||
return;
|
||||
}
|
||||
viewMode = (newVal == tbnMyAnalytics) ? "mine" : "store";
|
||||
updateViewModeStyles();
|
||||
updateStoreFilterVisibility();
|
||||
applyCurrentFilter();
|
||||
});
|
||||
|
||||
hbViewToggle.setVisible(true);
|
||||
hbViewToggle.setManaged(true);
|
||||
|
||||
loadAnalyticsData();
|
||||
}
|
||||
|
||||
@@ -182,6 +220,8 @@ public class AnalyticsController {
|
||||
Platform.runLater(() -> {
|
||||
cachedSales = sales;
|
||||
derivePaymentMethods();
|
||||
deriveStores();
|
||||
updateStoreFilterVisibility();
|
||||
applyCurrentFilter();
|
||||
btnRefresh.setDisable(false);
|
||||
});
|
||||
@@ -196,9 +236,36 @@ public class AnalyticsController {
|
||||
}).start();
|
||||
}
|
||||
|
||||
private void updateViewModeStyles() {
|
||||
String selectedStyle = "-fx-background-color: #4ECDC4; -fx-text-fill: white; -fx-cursor: hand; -fx-focus-color: transparent; -fx-faint-focus-color: transparent;";
|
||||
String unselectedStyle = "-fx-background-color: #e2e8f0; -fx-text-fill: #475569; -fx-cursor: hand; -fx-focus-color: transparent; -fx-faint-focus-color: transparent;";
|
||||
if (viewMode.equals("mine")) {
|
||||
tbnMyAnalytics.setStyle(selectedStyle + " -fx-background-radius: 6 0 0 6;");
|
||||
tbnStoreAnalytics.setStyle(unselectedStyle + " -fx-background-radius: 0 6 6 0;");
|
||||
} else {
|
||||
tbnMyAnalytics.setStyle(unselectedStyle + " -fx-background-radius: 6 0 0 6;");
|
||||
tbnStoreAnalytics.setStyle(selectedStyle + " -fx-background-radius: 0 6 6 0;");
|
||||
}
|
||||
}
|
||||
|
||||
private void applyCurrentFilter() {
|
||||
try {
|
||||
List<SaleResponse> filtered = filterSales(cachedSales, currentFilter);
|
||||
List<SaleResponse> salesForMode;
|
||||
if (viewMode.equals("mine")) {
|
||||
String myName = UserSession.getInstance().getEmployeeName();
|
||||
salesForMode = cachedSales.stream()
|
||||
.filter(s -> myName != null && myName.equalsIgnoreCase(s.getEmployeeName() != null ? s.getEmployeeName() : ""))
|
||||
.collect(Collectors.toList());
|
||||
} else {
|
||||
salesForMode = cachedSales;
|
||||
}
|
||||
String storeFilter = currentFilter.storeFilter;
|
||||
if (!storeFilter.equals("All Stores") && !storeFilter.isBlank()) {
|
||||
salesForMode = salesForMode.stream()
|
||||
.filter(s -> storeFilter.equalsIgnoreCase(s.getStoreName() != null ? s.getStoreName() : ""))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
List<SaleResponse> filtered = filterSales(salesForMode, currentFilter);
|
||||
String start = currentFilter.startDate.isEmpty() ? LocalDate.now().minusDays(6).toString() : currentFilter.startDate;
|
||||
String end = currentFilter.endDate.isEmpty() ? LocalDate.now().toString() : currentFilter.endDate;
|
||||
|
||||
@@ -256,6 +323,31 @@ public class AnalyticsController {
|
||||
}
|
||||
}
|
||||
|
||||
private void deriveStores() {
|
||||
Set<String> stores = new TreeSet<>();
|
||||
for (SaleResponse s : cachedSales) {
|
||||
if (s.getStoreName() != null && !s.getStoreName().isBlank()) {
|
||||
stores.add(s.getStoreName());
|
||||
}
|
||||
}
|
||||
List<String> items = new ArrayList<>();
|
||||
items.add("All Stores");
|
||||
items.addAll(stores);
|
||||
String current = cbStoreFilter.getValue();
|
||||
cbStoreFilter.setItems(FXCollections.observableArrayList(items));
|
||||
if (current != null && items.contains(current)) {
|
||||
cbStoreFilter.setValue(current);
|
||||
} else {
|
||||
cbStoreFilter.getSelectionModel().selectFirst();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateStoreFilterVisibility() {
|
||||
boolean show = UserSession.getInstance().isAdmin() && viewMode.equals("store");
|
||||
cbStoreFilter.setVisible(show);
|
||||
cbStoreFilter.setManaged(show);
|
||||
}
|
||||
|
||||
private void updateFilterSummary() {
|
||||
String start = currentFilter.startDate;
|
||||
String end = currentFilter.endDate;
|
||||
@@ -392,11 +484,12 @@ public class AnalyticsController {
|
||||
}
|
||||
|
||||
private void applyRoleVisibility(boolean isAdmin) {
|
||||
chartEmployeePerformance.setVisible(isAdmin);
|
||||
chartEmployeePerformance.setManaged(isAdmin);
|
||||
boolean showEmpChart = isAdmin && viewMode.equals("store");
|
||||
chartEmployeePerformance.setVisible(showEmpChart);
|
||||
chartEmployeePerformance.setManaged(showEmpChart);
|
||||
if (chartEmployeePerformance.getParent() != null) {
|
||||
chartEmployeePerformance.getParent().setVisible(isAdmin);
|
||||
chartEmployeePerformance.getParent().setManaged(isAdmin);
|
||||
chartEmployeePerformance.getParent().setVisible(showEmpChart);
|
||||
chartEmployeePerformance.getParent().setManaged(showEmpChart);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -612,6 +705,7 @@ public class AnalyticsController {
|
||||
dpEndDate.setValue(null);
|
||||
cbPaymentFilter.getSelectionModel().selectFirst();
|
||||
cbTopN.getSelectionModel().selectFirst();
|
||||
cbStoreFilter.getSelectionModel().selectFirst();
|
||||
currentFilter = new FilterState();
|
||||
applyCurrentFilter();
|
||||
}
|
||||
@@ -630,6 +724,8 @@ public class AnalyticsController {
|
||||
currentFilter.paymentMethod = pm != null ? pm : "All";
|
||||
int topNPos = cbTopN.getSelectionModel().getSelectedIndex();
|
||||
currentFilter.topN = (topNPos >= 0 && topNPos < TOP_N_VALUES.length) ? TOP_N_VALUES[topNPos] : 5;
|
||||
String sf = cbStoreFilter.getValue();
|
||||
currentFilter.storeFilter = (sf != null && !sf.isBlank()) ? sf : "All Stores";
|
||||
applyCurrentFilter();
|
||||
}
|
||||
|
||||
@@ -638,5 +734,6 @@ public class AnalyticsController {
|
||||
String endDate = "";
|
||||
String paymentMethod = "All";
|
||||
int topN = 5;
|
||||
String storeFilter = "All Stores";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,13 +7,17 @@ import javafx.collections.transformation.FilteredList;
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.control.*;
|
||||
import javafx.scene.image.ImageView;
|
||||
import javafx.scene.layout.StackPane;
|
||||
import javafx.stage.Modality;
|
||||
import javafx.stage.Stage;
|
||||
import org.example.petshopdesktop.api.dto.user.UserResponse;
|
||||
import org.example.petshopdesktop.api.endpoints.CustomerApi;
|
||||
import org.example.petshopdesktop.util.ActivityLogger;
|
||||
import org.example.petshopdesktop.util.DesktopImageSupport;
|
||||
import org.example.petshopdesktop.util.TableViewSupport;
|
||||
|
||||
import java.util.Comparator;
|
||||
@@ -25,6 +29,9 @@ public class CustomerAccountsController {
|
||||
@FXML
|
||||
private TableView<UserResponse> tvCustomers;
|
||||
|
||||
@FXML
|
||||
private TableColumn<UserResponse, String> colCustomerAvatar;
|
||||
|
||||
@FXML
|
||||
private TableColumn<UserResponse, String> colCustomerUsername;
|
||||
|
||||
@@ -69,6 +76,13 @@ public class CustomerAccountsController {
|
||||
|
||||
@FXML
|
||||
public void initialize() {
|
||||
colCustomerAvatar.setCellValueFactory(data -> {
|
||||
Long id = data.getValue().getId();
|
||||
if (id == null) return new javafx.beans.property.SimpleStringProperty("");
|
||||
return new javafx.beans.property.SimpleStringProperty("/api/v1/users/" + id + "/avatar/file");
|
||||
});
|
||||
configureAvatarColumn(colCustomerAvatar);
|
||||
|
||||
colCustomerUsername.setCellValueFactory(data -> new javafx.beans.property.SimpleStringProperty(data.getValue().getUsername()));
|
||||
colCustomerName.setCellValueFactory(data -> new javafx.beans.property.SimpleStringProperty(data.getValue().getFullName()));
|
||||
colCustomerEmail.setCellValueFactory(data -> new javafx.beans.property.SimpleStringProperty(data.getValue().getEmail()));
|
||||
@@ -94,6 +108,27 @@ public class CustomerAccountsController {
|
||||
refresh();
|
||||
}
|
||||
|
||||
private void configureAvatarColumn(TableColumn<UserResponse, String> column) {
|
||||
column.setCellFactory(col -> new TableCell<>() {
|
||||
private final ImageView imageView = new ImageView();
|
||||
private final StackPane container = new StackPane(imageView);
|
||||
{
|
||||
container.setAlignment(Pos.CENTER);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateItem(String item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
if (empty || item == null || item.isBlank()) {
|
||||
setGraphic(null);
|
||||
return;
|
||||
}
|
||||
DesktopImageSupport.loadImageInto(imageView, item, 48, 48);
|
||||
setGraphic(container);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@FXML
|
||||
void btnRefreshClicked(ActionEvent event) {
|
||||
txtSearchCustomer.clear();
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
package org.example.petshopdesktop.controllers;
|
||||
|
||||
import javafx.application.Platform;
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.control.Alert;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.PasswordField;
|
||||
import javafx.scene.control.TextInputDialog;
|
||||
import javafx.scene.control.TextField;
|
||||
import javafx.scene.layout.StackPane;
|
||||
import javafx.stage.Stage;
|
||||
@@ -14,6 +17,7 @@ import org.example.petshopdesktop.api.ApiClient;
|
||||
import org.example.petshopdesktop.api.dto.auth.LoginRequest;
|
||||
import org.example.petshopdesktop.api.dto.auth.LoginResponse;
|
||||
import org.example.petshopdesktop.api.dto.auth.UserInfoResponse;
|
||||
import org.example.petshopdesktop.api.endpoints.AuthApi;
|
||||
import org.example.petshopdesktop.auth.Role;
|
||||
import org.example.petshopdesktop.auth.UserSession;
|
||||
import org.example.petshopdesktop.ui.SvgWebViewFactory;
|
||||
@@ -105,6 +109,42 @@ public class LoginController {
|
||||
}
|
||||
}
|
||||
|
||||
@FXML
|
||||
void lnkForgotPasswordClicked(ActionEvent event) {
|
||||
TextInputDialog dialog = new TextInputDialog();
|
||||
dialog.setTitle("Forgot Password");
|
||||
dialog.setHeaderText("Reset your password");
|
||||
dialog.setContentText("Enter your username or email:");
|
||||
|
||||
dialog.showAndWait().ifPresent(input -> {
|
||||
if (input.trim().isEmpty()) return;
|
||||
new Thread(() -> {
|
||||
try {
|
||||
AuthApi.getInstance().forgotPassword(input.trim());
|
||||
Platform.runLater(() -> {
|
||||
Alert alert = new Alert(Alert.AlertType.INFORMATION);
|
||||
alert.setTitle("Reset Link Sent");
|
||||
alert.setHeaderText(null);
|
||||
alert.setContentText("If this account exists, a password reset link has been sent to the associated email.");
|
||||
alert.showAndWait();
|
||||
});
|
||||
} catch (Exception e) {
|
||||
ActivityLogger.getInstance().logException(
|
||||
"LoginController.lnkForgotPasswordClicked",
|
||||
e,
|
||||
"Forgot password request for: " + input.trim());
|
||||
Platform.runLater(() -> {
|
||||
Alert alert = new Alert(Alert.AlertType.ERROR);
|
||||
alert.setTitle("Error");
|
||||
alert.setHeaderText(null);
|
||||
alert.setContentText("Could not send reset link. Please try again.");
|
||||
alert.showAndWait();
|
||||
});
|
||||
}
|
||||
}).start();
|
||||
});
|
||||
}
|
||||
|
||||
private void openMainLayout() {
|
||||
try {
|
||||
FXMLLoader loader = new FXMLLoader(
|
||||
|
||||
@@ -199,6 +199,12 @@ public class SaleController {
|
||||
@FXML
|
||||
private Label lblLoyaltyDiscount;
|
||||
|
||||
@FXML
|
||||
private HBox hbPointsToEarn;
|
||||
|
||||
@FXML
|
||||
private Label lblPointsToEarn;
|
||||
|
||||
private final ObservableList<SaleCartItem> cartItems = FXCollections.observableArrayList();
|
||||
private final ObservableList<SaleLineItem> saleItems = FXCollections.observableArrayList();
|
||||
private FilteredList<SaleLineItem> filteredSales;
|
||||
@@ -389,12 +395,15 @@ public class SaleController {
|
||||
|
||||
task.setOnSucceeded(event -> {
|
||||
selectedCustomerData = task.getValue();
|
||||
if (selectedCustomerData != null && selectedCustomerData.getLoyaltyPoints() != null && selectedCustomerData.getLoyaltyPoints() >= 20) {
|
||||
lblLoyaltyPoints.setText(selectedCustomerData.getLoyaltyPoints() + " pts available");
|
||||
if (selectedCustomerData != null) {
|
||||
int pts = selectedCustomerData.getLoyaltyPoints() != null ? selectedCustomerData.getLoyaltyPoints() : 0;
|
||||
lblLoyaltyPoints.setText(pts + " pts available");
|
||||
lblLoyaltyPoints.setVisible(true);
|
||||
lblLoyaltyPoints.setManaged(true);
|
||||
chkUseLoyaltyPoints.setVisible(true);
|
||||
chkUseLoyaltyPoints.setManaged(true);
|
||||
boolean canRedeem = pts >= 20;
|
||||
chkUseLoyaltyPoints.setVisible(canRedeem);
|
||||
chkUseLoyaltyPoints.setManaged(canRedeem);
|
||||
if (!canRedeem) chkUseLoyaltyPoints.setSelected(false);
|
||||
} else {
|
||||
lblLoyaltyPoints.setVisible(false);
|
||||
lblLoyaltyPoints.setManaged(false);
|
||||
@@ -701,6 +710,8 @@ public class SaleController {
|
||||
hbCouponDiscount.setManaged(false);
|
||||
hbLoyaltyDiscount.setVisible(false);
|
||||
hbLoyaltyDiscount.setManaged(false);
|
||||
hbPointsToEarn.setVisible(false);
|
||||
hbPointsToEarn.setManaged(false);
|
||||
cbCustomer.setValue(null);
|
||||
selectedCustomerData = null;
|
||||
lblLoyaltyPoints.setVisible(false);
|
||||
@@ -875,6 +886,16 @@ public class SaleController {
|
||||
}
|
||||
|
||||
lblCartTotal.setText(currency.format(Math.max(0, total.doubleValue())));
|
||||
|
||||
if (selectedCustomerData != null) {
|
||||
int pointsToEarn = (int) Math.max(0, total.doubleValue());
|
||||
lblPointsToEarn.setText("+" + pointsToEarn + " pts");
|
||||
hbPointsToEarn.setVisible(true);
|
||||
hbPointsToEarn.setManaged(true);
|
||||
} else {
|
||||
hbPointsToEarn.setVisible(false);
|
||||
hbPointsToEarn.setManaged(false);
|
||||
}
|
||||
}
|
||||
|
||||
private BigDecimal calculateCouponDiscount(BigDecimal subtotal) {
|
||||
|
||||
@@ -7,8 +7,11 @@ import javafx.collections.transformation.FilteredList;
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.control.*;
|
||||
import javafx.scene.image.ImageView;
|
||||
import javafx.scene.layout.StackPane;
|
||||
import javafx.scene.layout.VBox;
|
||||
import javafx.stage.Modality;
|
||||
import javafx.stage.Stage;
|
||||
@@ -16,6 +19,7 @@ import org.example.petshopdesktop.api.dto.employee.EmployeeResponse;
|
||||
import org.example.petshopdesktop.api.endpoints.EmployeeApi;
|
||||
import org.example.petshopdesktop.auth.UserSession;
|
||||
import org.example.petshopdesktop.util.ActivityLogger;
|
||||
import org.example.petshopdesktop.util.DesktopImageSupport;
|
||||
import org.example.petshopdesktop.util.TableViewSupport;
|
||||
|
||||
import java.util.Comparator;
|
||||
@@ -26,6 +30,7 @@ public class StaffAccountsController {
|
||||
|
||||
@FXML private VBox staffSection;
|
||||
@FXML private TableView<EmployeeResponse> tvStaff;
|
||||
@FXML private TableColumn<EmployeeResponse, String> colStaffAvatar;
|
||||
@FXML private TableColumn<EmployeeResponse, String> colUsername;
|
||||
@FXML private TableColumn<EmployeeResponse, String> colName;
|
||||
@FXML private TableColumn<EmployeeResponse, String> colEmail;
|
||||
@@ -47,6 +52,13 @@ public class StaffAccountsController {
|
||||
|
||||
@FXML
|
||||
public void initialize() {
|
||||
colStaffAvatar.setCellValueFactory(data -> {
|
||||
Long id = data.getValue().getId();
|
||||
if (id == null) return new javafx.beans.property.SimpleStringProperty("");
|
||||
return new javafx.beans.property.SimpleStringProperty("/api/v1/users/" + id + "/avatar/file");
|
||||
});
|
||||
configureAvatarColumn(colStaffAvatar);
|
||||
|
||||
colUsername.setCellValueFactory(data -> new javafx.beans.property.SimpleStringProperty(data.getValue().getUsername()));
|
||||
colName.setCellValueFactory(data -> new javafx.beans.property.SimpleStringProperty(data.getValue().getFullName()));
|
||||
colEmail.setCellValueFactory(data -> new javafx.beans.property.SimpleStringProperty(data.getValue().getEmail()));
|
||||
@@ -81,6 +93,27 @@ public class StaffAccountsController {
|
||||
refresh();
|
||||
}
|
||||
|
||||
private void configureAvatarColumn(TableColumn<EmployeeResponse, String> column) {
|
||||
column.setCellFactory(col -> new TableCell<>() {
|
||||
private final ImageView imageView = new ImageView();
|
||||
private final StackPane container = new StackPane(imageView);
|
||||
{
|
||||
container.setAlignment(Pos.CENTER);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateItem(String item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
if (empty || item == null || item.isBlank()) {
|
||||
setGraphic(null);
|
||||
return;
|
||||
}
|
||||
DesktopImageSupport.loadImageInto(imageView, item, 48, 48);
|
||||
setGraphic(container);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@FXML
|
||||
void btnRefreshClicked(ActionEvent event) {
|
||||
txtSearch.clear();
|
||||
|
||||
Reference in New Issue
Block a user