Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add factories #40

Merged
merged 5 commits into from
Mar 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/main/java/module-info.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
requires java.prefs;
requires org.json;
requires java.base;
requires java.desktop;

// Http
requires java.net.http;
Expand Down Expand Up @@ -43,6 +44,7 @@
opens org.chainoptim.desktop.core.user.controller to javafx.fxml, com.google.guice;
opens org.chainoptim.desktop.core.user.service to com.google.guice;
opens org.chainoptim.desktop.core.user.model to com.fasterxml.jackson.databind;
opens org.chainoptim.desktop.core.user.dto to com.fasterxml.jackson.databind;

// - Organization
opens org.chainoptim.desktop.core.organization.service to com.google.guice;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,9 @@ public NavigationServiceImpl(FXMLLoaderService fxmlLoaderService,

private final Map<String, String> viewMap = Map.ofEntries(
Map.entry("Overview", "/org/chainoptim/desktop/core/main/OverviewView.fxml"),

Map.entry("Organization", "/org/chainoptim/desktop/core/organization/OrganizationView.fxml"),
Map.entry("Add-New-Members", "/org/chainoptim/desktop/core/organization/AddNewMembersView.fxml"),

Map.entry("Products", "/org/chainoptim/desktop/features/product/ProductsView.fxml"),
Map.entry("Product", "/org/chainoptim/desktop/features/product/ProductView.fxml"),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package org.chainoptim.desktop.core.organization.controller;

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.organization.service.OrganizationService;
import org.chainoptim.desktop.shared.fallback.FallbackManager;
import org.chainoptim.desktop.shared.util.resourceloader.FXMLLoaderService;
import com.google.inject.Inject;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.Node;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;

import java.net.URL;
import java.util.ResourceBundle;

public class AddNewMembersController implements Initializable {

private final OrganizationService organizationService;
private final NavigationService navigationService;
private final CurrentSelectionService currentSelectionService;
private final FXMLLoaderService fxmlLoaderService;
private final ControllerFactory controllerFactory;
private final FallbackManager fallbackManager;

private Integer organizationId;

@FXML
private StackPane usersSelectionContainer;
@FXML
private StackPane fallbackContainer;

@Inject
public AddNewMembersController(OrganizationService organizationService,
NavigationService navigationService,
CurrentSelectionService currentSelectionService,
FXMLLoaderService fxmlLoaderService,
ControllerFactory controllerFactory,
FallbackManager fallbackManager) {
this.organizationService = organizationService;
this.navigationService = navigationService;
this.currentSelectionService = currentSelectionService;
this.fxmlLoaderService = fxmlLoaderService;
this.controllerFactory = controllerFactory;
this.fallbackManager = fallbackManager;
}

@Override
public void initialize(URL location, ResourceBundle resourceBundle) {
loadFallbackManager();
loadUsersSearch();
setupListeners();

Integer receivedOrganizationId = currentSelectionService.getSelectedId();
if (receivedOrganizationId != null) {
System.out.println("Organization ID: " + receivedOrganizationId);
this.organizationId = receivedOrganizationId;
} else {
fallbackManager.setErrorMessage("Failed to load organization.");
}
}

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 loadUsersSearch() {
Node usersSearchView = fxmlLoaderService.loadView(
"/org/chainoptim/desktop/core/user/PublicUsersSearchAndSelectionView.fxml",
controllerFactory::createController
);
usersSelectionContainer.getChildren().add(usersSearchView);
}

private void setupListeners() {
fallbackManager.isEmptyProperty().addListener((observable, oldValue, newValue) -> {
usersSelectionContainer.setVisible(newValue);
usersSelectionContainer.setManaged(newValue);
fallbackContainer.setVisible(!newValue);
fallbackContainer.setManaged(!newValue);
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
package org.chainoptim.desktop.core.organization.controller;

import org.chainoptim.desktop.core.organization.model.CustomRole;
import org.chainoptim.desktop.core.organization.model.FeaturePermissions;
import org.chainoptim.desktop.core.user.model.User;
import org.chainoptim.desktop.shared.confirmdialog.controller.GenericConfirmDialogActionListener;
import org.chainoptim.desktop.shared.util.DataReceiver;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.Node;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import javafx.scene.text.Text;
import javafx.scene.text.TextFlow;
import javafx.util.Pair;
import lombok.Setter;

import java.util.List;
import java.util.Objects;

import static org.chainoptim.desktop.core.user.model.User.Role.ADMIN;

public class OrganizationAssignBasicRoleController implements DataReceiver<User> {

// State
private User user;
private User.Role originalSelectedRole;
private User.Role selectedRole;
private boolean hasRenderedWarning;

// Listeners
@Setter
private GenericConfirmDialogActionListener<Pair<String, User.Role>> actionListener; // userId, basic role

// FXML
@FXML
private Label titleLabel;
@FXML
private VBox rolesVBox;
@FXML
private TextFlow messageTextFlowContainer;
@FXML
private VBox permissionsVBox;
@FXML
private Button confirmButton;
@FXML
private Button cancelButton;

@Override
public void setData(User data) {
user = data;
originalSelectedRole = user.getRole();
selectedRole = originalSelectedRole;

initializeUI();
}

private void initializeUI() {
titleLabel.setText("Assign role to " + user.getUsername());

for (User.Role role : User.Role.values()) {
String label = role.toString();
label = label.substring(0, 1).toUpperCase() + label.substring(1).toLowerCase();
Button selectRoleButton = new Button(label);
boolean isSelected = role.equals(selectedRole);
styleSelectButton(selectRoleButton, isSelected);
selectRoleButton.setOnAction(this::selectRole);

rolesVBox.getChildren().add(selectRoleButton);
}
}

private void selectRole(ActionEvent event) {
Button source = (Button) event.getSource();

// Select role, accounting for None button
int roleIndex = rolesVBox.getChildren().indexOf(source);
selectedRole = User.Role.values()[roleIndex];
styleSelectButton(source, true);

// Deselect other roles
for (int i = 0; i < rolesVBox.getChildren().size(); i++) {
if (i != roleIndex) {
Node otherButton = rolesVBox.getChildren().get(i);
if (otherButton instanceof Button button) {
styleSelectButton(button, false);
}
}
}

// Render permissions to be granted
renderPermissionsVBox();

// On first selection, render warning message
if (hasRenderedWarning) return;
String message = "Are you sure you want to assign this role to " + user.getUsername() + "? ";
if (user.getCustomRole() != null) {
message += "This will have no effect as the user already has the custom role " + user.getCustomRole().getName() + ".";
} else {
message += "This will grant them the following permissions:";
}
messageTextFlowContainer.getChildren().clear();
messageTextFlowContainer.getChildren().add(new Text(message));
hasRenderedWarning = true;
}

private void renderPermissionsVBox() {
if (selectedRole == null) return;

permissionsVBox.getChildren().clear();

Label permissionsLabel = switch (selectedRole) {
case ADMIN -> new Label("To Read, Create, Update, Delete all features");
case MEMBER -> new Label("To Read all features");
case NONE -> new Label("No permissions granted");
};

permissionsLabel.getStyleClass().add("general-label");
permissionsVBox.getChildren().add(permissionsLabel);
}

@FXML
private void onConfirmButtonClicked() {
if (selectedRole != null && Objects.equals(selectedRole, originalSelectedRole)) return; // Skip if already assigned

Pair<String, User.Role> data = new Pair<>(user.getId(), selectedRole);
actionListener.onConfirmAction(data);
}

@FXML
private void onCancelButtonClicked() {
actionListener.onCancelAction();
}

private void styleSelectButton(Button selectButton, boolean isSelected) {
if (isSelected) {
styleSelectedButton(selectButton);
} else {
styleUnselectedButton(selectButton);
}
}

private void styleUnselectedButton(Button selectButton) {
selectButton.setMaxWidth(Double.MAX_VALUE);
selectButton.getStyleClass().clear();
selectButton.getStyleClass().add("assign-role-element");
}

private void styleSelectedButton(Button selectButton) {
selectButton.setMaxWidth(Double.MAX_VALUE);
selectButton.getStyleClass().clear();
selectButton.getStyleClass().add("assign-role-selected-element");
}
}
Loading
Loading