Skip to content

Commit

Permalink
Merge pull request #26 from penguineer/accounting
Browse files Browse the repository at this point in the history
Add an Accounting area
  • Loading branch information
penguineer authored Aug 2, 2024
2 parents 096bc59 + da7a1da commit aba6b72
Show file tree
Hide file tree
Showing 10 changed files with 164 additions and 76 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,10 @@
import com.vaadin.flow.component.contextmenu.MenuItem;
import com.vaadin.flow.component.contextmenu.SubMenu;
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.component.icon.Icon;
import com.vaadin.flow.component.icon.IconFactory;
import com.vaadin.flow.component.icon.VaadinIcon;
import com.vaadin.flow.component.menubar.MenuBar;
import com.vaadin.flow.component.menubar.MenuBarVariant;
import com.vaadin.flow.component.orderedlayout.FlexComponent;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -71,6 +69,9 @@ public LoggedUserView(Supplier<UserDTO> currentUser) {
subMenu.addItem(createMenuItemWithIcon("Dashboard", VaadinIcon.HOME),
e -> navigateTo("/"));

subMenu.addItem(createMenuItemWithIcon("Buchhaltung", VaadinIcon.PIGGY_BANK_COIN),
e -> navigateTo("/accounting"));

subMenu.addSeparator();

if (isAdmin) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package com.penguineering.gartenplus.ui.appframe;

import com.penguineering.gartenplus.auth.SecurityUtils;
import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.HasElement;
import com.vaadin.flow.component.UI;
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.tabs.Tab;
import com.vaadin.flow.component.tabs.Tabs;
import com.vaadin.flow.router.BeforeEnterEvent;
import com.vaadin.flow.router.BeforeEnterObserver;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.router.RouterLayout;

import java.util.Map;
import java.util.Optional;
import java.util.Set;

public abstract class TabbedLayoutBase extends VerticalLayout implements RouterLayout, BeforeEnterObserver {
private final Map<String, Class<? extends Component>> targets;

private final Div content;
private final Tabs menu;

public TabbedLayoutBase(Map<String, Class<? extends Component>> targets) {
super();
this.targets = targets;

Set<String> userRoles = SecurityUtils.getCurrentUserRoles();

menu = new Tabs();
targets.entrySet().stream()
.filter(e -> SecurityUtils.isUserAuthorizedForComponent(e.getValue(), userRoles))
.map(Map.Entry::getKey)
.map(Tab::new)
.forEach(menu::add);
menu.addSelectedChangeListener(this::navigateToTab);
add(menu);

content = new Div();
content.setSizeFull();
content.getStyle()
.set("margin", "0")
.set("padding", "0");
add(content);
}

private void navigateToTab(Tabs.SelectedChangeEvent event) {
Optional.of(event.getSelectedTab())
.map(Tab::getLabel)
.map(targets::get)
.ifPresent(target -> UI.getCurrent().navigate(target));
}

@Override
public void beforeEnter(BeforeEnterEvent event) {
String currentPath = event.getLocation().getPath();
targets.forEach((label, target) -> {
Route route = target.getAnnotation(Route.class);
if (route != null && currentPath.contains(route.value())) {
menu.setSelectedTab(menu.getChildren()
.filter(component -> component instanceof Tab)
.map(component -> (Tab) component)
.filter(tab -> tab.getLabel().equals(label))
.findFirst()
.orElse(null));
}
});
}

@Override
public void showRouterLayoutContent(HasElement newContent) {
// Previous content is automatically removed

newContent.getElement()
.getComponent()
.ifPresent(content::add);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.penguineering.gartenplus.ui.content.accounting;


import com.penguineering.gartenplus.ui.appframe.AppFrameLayout;
import com.penguineering.gartenplus.ui.appframe.TabbedLayoutBase;
import com.penguineering.gartenplus.ui.content.accounting.ledgers.LedgersSettingsPage;
import com.penguineering.gartenplus.ui.content.accounting.myfinances.MyFinancesPage;
import com.vaadin.flow.component.Component;
import com.vaadin.flow.router.ParentLayout;
import com.vaadin.flow.router.RoutePrefix;

import java.util.LinkedHashMap;
import java.util.Map;

@ParentLayout(AppFrameLayout.class)
@RoutePrefix(value = "accounting")
public class AccountingLayout extends TabbedLayoutBase {
private static final Map<String, Class<? extends Component>> targets = new LinkedHashMap<>();

static {
targets.put("Meine Finanzen", MyFinancesPage.class);
targets.put("Hauptbücher", LedgersSettingsPage.class);
}

public AccountingLayout() {
super(targets);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.penguineering.gartenplus.ui.content.accounting;

import com.penguineering.gartenplus.ui.appframe.GartenplusPage;
import com.penguineering.gartenplus.ui.content.accounting.myfinances.MyFinancesPage;
import com.vaadin.flow.router.BeforeEnterEvent;
import com.vaadin.flow.router.BeforeEnterObserver;
import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route;
import jakarta.annotation.security.PermitAll;

@Route(value = "", layout = AccountingLayout.class)
@PermitAll
@PageTitle("GartenPlus | Buchhaltung")
public class AccountingPage extends GartenplusPage implements BeforeEnterObserver {
@Override
public void beforeEnter(BeforeEnterEvent event) {

event.getUI().navigate(MyFinancesPage.class);
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.penguineering.gartenplus.ui.content.admin.settings.ledgers;
package com.penguineering.gartenplus.ui.content.accounting.ledgers;

import com.penguineering.gartenplus.accounting.model.ledger.LedgerDTO;
import com.vaadin.flow.component.button.Button;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.penguineering.gartenplus.ui.content.admin.settings.ledgers;
package com.penguineering.gartenplus.ui.content.accounting.ledgers;

import com.penguineering.gartenplus.accounting.model.ledger.LedgerDTO;
import com.vaadin.flow.component.button.Button;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package com.penguineering.gartenplus.ui.content.admin.settings.ledgers;
package com.penguineering.gartenplus.ui.content.accounting.ledgers;

import com.penguineering.gartenplus.accounting.model.ledger.LedgerDTO;
import com.penguineering.gartenplus.accounting.model.ledger.LedgerEntityService;
import com.penguineering.gartenplus.ui.appframe.GartenplusPage;
import com.penguineering.gartenplus.ui.content.admin.settings.SettingsLayout;
import com.penguineering.gartenplus.ui.content.accounting.AccountingLayout;
import com.vaadin.flow.component.confirmdialog.ConfirmDialog;
import com.vaadin.flow.component.html.H3;
import com.vaadin.flow.router.PageTitle;
Expand All @@ -13,9 +13,9 @@
import java.util.Optional;
import java.util.UUID;

@Route(value = "ledgers", layout = SettingsLayout.class)
@Route(value = "ledgers", layout = AccountingLayout.class)
@RolesAllowed({"ADMINISTRATOR", "TREASURER"})
@PageTitle("GartenPlus | Einstellungen | Ledger")
@PageTitle("GartenPlus | Buchhaltung | Ledger")
public class LedgersSettingsPage extends GartenplusPage {
private final LedgerEntityService ledgerService;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.penguineering.gartenplus.ui.content.accounting.myfinances;

import com.penguineering.gartenplus.ui.appframe.GartenplusPage;
import com.penguineering.gartenplus.ui.content.accounting.AccountingLayout;
import com.vaadin.flow.component.html.Paragraph;
import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route;
import jakarta.annotation.security.PermitAll;
import jakarta.annotation.security.RolesAllowed;

@Route(value = "myfinances", layout = AccountingLayout.class)
@PermitAll
@PageTitle("GartenPlus | Buchhaltung | Meine Finanzen")
public class MyFinancesPage extends GartenplusPage {
public MyFinancesPage() {
add(new Paragraph("Diese Seite wächst noch."));
}
}
Original file line number Diff line number Diff line change
@@ -1,89 +1,28 @@
package com.penguineering.gartenplus.ui.content.admin.settings;

import com.penguineering.gartenplus.auth.SecurityUtils;
import com.penguineering.gartenplus.ui.appframe.TabbedLayoutBase;
import com.penguineering.gartenplus.ui.content.accounting.ledgers.LedgersSettingsPage;
import com.penguineering.gartenplus.ui.content.admin.AdminLayout;
import com.penguineering.gartenplus.ui.content.admin.settings.groups.GroupSettingsPage;
import com.penguineering.gartenplus.ui.content.admin.settings.ledgers.LedgersSettingsPage;
import com.penguineering.gartenplus.ui.content.admin.settings.users.UsersSettingsPage;
import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.HasElement;
import com.vaadin.flow.component.UI;
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.tabs.Tab;
import com.vaadin.flow.component.tabs.Tabs;
import com.vaadin.flow.router.*;
import com.vaadin.flow.router.ParentLayout;
import com.vaadin.flow.router.RoutePrefix;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Optional;
import java.util.Set;

@ParentLayout(AdminLayout.class)
@RoutePrefix(value = "settings")
public class SettingsLayout extends VerticalLayout implements RouterLayout, BeforeEnterObserver {
public class SettingsLayout extends TabbedLayoutBase {
private static final Map<String, Class<? extends Component>> targets = new LinkedHashMap<>();

static {
targets.put("Benutzer", UsersSettingsPage.class);
targets.put("Gruppen", GroupSettingsPage.class);
targets.put("Hauptbücher", LedgersSettingsPage.class);
}

private final Div content;
private final Tabs menu;

public SettingsLayout() {
super();

Set<String> userRoles = SecurityUtils.getCurrentUserRoles();

menu = new Tabs();
targets.entrySet().stream()
.filter(e -> SecurityUtils.isUserAuthorizedForComponent(e.getValue(), userRoles))
.map(Map.Entry::getKey)
.map(Tab::new)
.forEach(menu::add);
menu.addSelectedChangeListener(this::navigateToTab);
add(menu);

content = new Div();
content.setSizeFull();
content.getStyle()
.set("margin", "0")
.set("padding", "0");
add(content);
}

private void navigateToTab(Tabs.SelectedChangeEvent event) {
Optional.of(event.getSelectedTab())
.map(Tab::getLabel)
.map(targets::get)
.ifPresent(target -> UI.getCurrent().navigate(target));
}

@Override
public void beforeEnter(BeforeEnterEvent event) {
String currentPath = event.getLocation().getPath();
targets.forEach((label, target) -> {
Route route = target.getAnnotation(Route.class);
if (route != null && currentPath.contains(route.value())) {
menu.setSelectedTab(menu.getChildren()
.filter(component -> component instanceof Tab)
.map(component -> (Tab) component)
.filter(tab -> tab.getLabel().equals(label))
.findFirst()
.orElse(null));
}
});
}

@Override
public void showRouterLayoutContent(HasElement newContent) {
// Previous content is automatically removed

newContent.getElement()
.getComponent()
.ifPresent(content::add);
super(targets);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.penguineering.gartenplus.ui.content.admin.settings;

import com.penguineering.gartenplus.ui.appframe.GartenplusPage;
import com.penguineering.gartenplus.ui.content.admin.settings.users.UsersSettingsPage;
import com.vaadin.flow.router.BeforeEnterEvent;
import com.vaadin.flow.router.BeforeEnterObserver;
import com.vaadin.flow.router.PageTitle;
Expand All @@ -13,6 +14,7 @@
public class SettingsPage extends GartenplusPage implements BeforeEnterObserver {
@Override
public void beforeEnter(BeforeEnterEvent event) {
event.getUI().navigate(event.getLocation().getPath() + "/users");

event.getUI().navigate(UsersSettingsPage.class);
}
}

0 comments on commit aba6b72

Please sign in to comment.