add CRUD for WorkType

This commit is contained in:
Thomas Peetz
2025-05-13 00:42:41 +02:00
parent 06a48a03ac
commit 3537642df9
49 changed files with 514 additions and 215 deletions
@@ -84,6 +84,7 @@ public class ComicConstants {
comics.addItem(new SideNavItem(TPB, TradePaperbackView.class));
comics.addItem(new SideNavItem(STORYARC, StoryArcView.class));
comics.addItem(new SideNavItem(VOLUME, VolumeView.class));
comics.addItem(new SideNavItem(WORKTYPE, WorktypeView.class));
return comics;
}
@@ -124,7 +124,6 @@ public class SetupModuleComics implements ApplicationListener<ContextRefreshedEv
Comic brath = createComicIfNotFound(crossgen, "Brath", false, false);
Comic catwomanrome = createComicIfNotFound(dc, "Catwoman When In Rome", false, false);
Comic crimson = createComicIfNotFound(wildstorm, "Crimson", false, false);
Comic crossgencomic = createComicIfNotFound(crossgen, "Crossgen", false, false);
Comic dangergirl = createComicIfNotFound(cliffhanger, "Danger Girl", false, false);
Comic dangergirlbackinblack = createComicIfNotFound(wildstorm, "Danger Girl Back in Black", false, false);
Comic daringescapes = createComicIfNotFound(image, "Daring Escapes", false, true);
@@ -275,23 +274,10 @@ public class SetupModuleComics implements ApplicationListener<ContextRefreshedEv
createComicIfNotFound(darkhorse, "Star Wars: Knights of the Old Republic", false, false);
createComicIfNotFound(darkhorse, "Star Wars: Legacy", false, false);
createComicIfNotFound(darkhorse, "Star Wars: Dark Times", false, false);
createComicWorkIfNotFound(crossgencomic, michaelturner, writer);
createComicWorkIfNotFound(dangergirl, michaelturner, writer);
createComicWorkIfNotFound(ultimatefantasticfour, michaelturner, writer);
createComicWorkIfNotFound(ultimatespidermanannual, michaelturner, writer);
createComicWorkIfNotFound(ultimatefantasticfour, brianbendis, writer);
createComicWorkIfNotFound(ultimatespidermanannual, brianbendis, writer);
createComicWorkIfNotFound(uncannyxmen, michaelturner, writer);
createComicWorkIfNotFound(starwars, michaelturner, writer);
createComicWorkIfNotFound(shehulk, michaelturner, writer);
createComicWorkIfNotFound(shehulk2, michaelturner, writer);
createComicWorkIfNotFound(scion, michaelturner, writer);
createComicWorkIfNotFound(newavengers, michaelturner, writer);
createComicWorkIfNotFound(newmutants, michaelturner, writer);
createComicWorkIfNotFound(midnightnation, michaelturner, writer);
createComicWorkIfNotFound(monsterwar, michaelturner, writer);
createComicWorkIfNotFound(monsterwar2005, michaelturner, writer);
createComicWorkIfNotFound(mystic, michaelturner, writer);
createComicWorkIfNotFound(holidayspecial2004, michaelturner, writer);
createComicWorkIfNotFound(hackslashgirlsgonedead, michaelturner, writer);
createComicWorkIfNotFound(newavengers, brianbendis, writer);
createComicWorkIfNotFound(uncannyxmen, brianbendis, writer);
createStoryArcIfNotFound("Higher Learning", emmafrost);
createStoryArcIfNotFound("Mind Games", emmafrost);
@@ -31,6 +31,8 @@ public class Artist extends AbstractEntity {
@Column(unique = true)
private String name;
private String weblink;
@OneToMany(fetch = FetchType.EAGER, mappedBy = "artist", cascade = CascadeType.REFRESH, orphanRemoval = true)
@Nullable
List<ComicWork> comicWorks = new LinkedList<>();
@@ -6,7 +6,7 @@ import java.util.List;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import de.thpeetz.kontor.common.data.AbstractEntity;
import io.micrometer.common.lang.Nullable;
import jakarta.annotation.Nullable;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
@@ -19,7 +19,6 @@ import jakarta.validation.constraints.NotNull;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
/**
* Represents a comic entity.
@@ -44,6 +43,9 @@ public class Comic extends AbstractEntity {
private Boolean completed = false;
@Nullable
private String weblink;
@OneToMany(fetch = FetchType.EAGER, mappedBy = "comic", cascade = CascadeType.REFRESH, orphanRemoval = true)
@Nullable
List<ComicWork> comicWorks;
@@ -3,18 +3,21 @@ package de.thpeetz.kontor.comics.data;
import java.util.LinkedList;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import de.thpeetz.kontor.common.data.AbstractEntity;
import jakarta.annotation.Nullable;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.Column;
import jakarta.persistence.OneToMany;
import jakarta.validation.constraints.NotEmpty;
import jakarta.persistence.ManyToOne;
import jakarta.validation.constraints.*;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@@ -26,10 +29,30 @@ public class Publisher extends AbstractEntity {
@Column(unique = true)
private String name;
private String weblink;
@JsonBackReference
@ManyToOne
@JoinColumn(name = "parent_publisher_id")
@Nullable
@JsonIgnoreProperties({ "comics" })
private Publisher parentCompany;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "parentCompany", cascade = CascadeType.ALL, orphanRemoval = true)
@Nullable
private List<Publisher> imprints = new LinkedList<>();
@OneToMany(fetch = FetchType.EAGER, mappedBy = "publisher", cascade = CascadeType.ALL, orphanRemoval = true)
@Nullable
private List<Comic> comics = new LinkedList<>();
public String getParentCompanyName() {
if (parentCompany != null) {
return parentCompany.name;
}
return null;
}
@Override
public String toString() {
final StringBuffer sb = new StringBuffer("Publisher{");
@@ -16,12 +16,14 @@ import com.vaadin.flow.data.binder.Binder;
import de.thpeetz.kontor.comics.data.Artist;
import de.thpeetz.kontor.comics.data.ComicWork;
import lombok.*;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class ArtistForm extends FormLayout {
TextField name = new TextField("Name");
TextField weblink = new TextField("Link");
Grid<ComicWork> comicWorks = new Grid<>(ComicWork.class);
Button save = new Button("Save");
@@ -38,7 +40,7 @@ public class ArtistForm extends FormLayout {
comicWorks.getColumnByKey("workType.name").setHeader("Work type");
comicWorks.getColumnByKey("comic.title").setHeader("Comic");
comicWorks.getColumns().forEach(col -> col.setAutoWidth(true));
add(name, comicWorks, createButtonsLayout());
add(name, weblink, comicWorks, createButtonsLayout());
}
private HorizontalLayout createButtonsLayout() {
@@ -72,17 +74,15 @@ public class ArtistForm extends FormLayout {
this.comicWorks.setItems(works);
}
@Getter
public abstract static class ArtistFormEvent extends ComponentEvent<ArtistForm> {
private Artist artist;
private final Artist artist;
protected ArtistFormEvent(ArtistForm source, Artist artist) {
super(source, false);
this.artist = artist;
}
public Artist getArtist() {
return artist;
}
}
public static class SaveEvent extends ArtistFormEvent {
@@ -2,6 +2,7 @@ package de.thpeetz.kontor.comics.views;
import java.util.List;
import lombok.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -29,6 +30,7 @@ public class ComicForm extends FormLayout {
TextField title = new TextField("Title");
ComboBox<Publisher> publisher = new ComboBox<>("Publisher");
TextField weblink = new TextField("Link");
Checkbox currentOrder = new Checkbox("Current order");
Checkbox completed = new Checkbox("Completed");
Grid<ComicWork> comicWorks = new Grid<>(ComicWork.class);
@@ -51,7 +53,7 @@ public class ComicForm extends FormLayout {
comicWorks.getColumnByKey("workType.name").setHeader("Work type");
comicWorks.getColumnByKey("artist.name").setHeader("Artist");
comicWorks.getColumns().forEach(col -> col.setAutoWidth(true));
add(title, publisher, currentOrder, completed, comicWorks, createButtonsLayout());
add(title, publisher, weblink, currentOrder, completed, comicWorks, createButtonsLayout());
}
private HorizontalLayout createButtonsLayout() {
@@ -85,17 +87,15 @@ public class ComicForm extends FormLayout {
comicWorks.setItems(works);
}
@Getter
public abstract static class ComicFormEvent extends ComponentEvent<ComicForm> {
private Comic comic;
private final Comic comic;
protected ComicFormEvent(ComicForm source, Comic comic) {
super(source, false);
this.comic = comic;
}
public Comic getComic() {
return comic;
}
}
public static class SaveEvent extends ComicFormEvent {
@@ -50,6 +50,8 @@ public class ComicView extends VerticalLayout {
.setHeader("Bestellung").setWidth("6rem").setSortable(true);
Grid.Column<Comic> completedColumn = grid.addComponentColumn(comic -> StatusIcon.create(comic.getCompleted()))
.setHeader("Abgeschlossen").setWidth("6rem").setSortable(true);
Grid.Column<Comic> weblinkColumn = grid.addColumn(Comic::getWeblink)
.setHeader("Link").setResizable(true).setSortable(true);
TextField filterText = new TextField();
@Getter
ComicForm form;
@@ -123,6 +125,7 @@ public class ComicView extends VerticalLayout {
columnToggleContextMenu.addColumnToggleItem(publisherColumn);
columnToggleContextMenu.addColumnToggleItem(currentOrderColumn);
columnToggleContextMenu.addColumnToggleItem(completedColumn);
columnToggleContextMenu.addColumnToggleItem(weblinkColumn);
HorizontalLayout toolbar = new HorizontalLayout(filterText, addComicButton, menuButton);
toolbar.addClassName("toolbar");
return toolbar;
@@ -5,6 +5,7 @@ import com.vaadin.flow.component.ComponentEventListener;
import com.vaadin.flow.component.Key;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.button.ButtonVariant;
import com.vaadin.flow.component.combobox.*;
import com.vaadin.flow.component.formlayout.FormLayout;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.textfield.TextField;
@@ -12,9 +13,14 @@ import com.vaadin.flow.data.binder.BeanValidationBinder;
import com.vaadin.flow.data.binder.Binder;
import de.thpeetz.kontor.comics.data.Publisher;
import lombok.*;
import java.util.*;
public class PublisherForm extends FormLayout {
public TextField name = new TextField("Name");
public TextField weblink = new TextField("Link");
ComboBox<Publisher> parentCompany = new ComboBox<>("Parent Company");
Button save = new Button("Save");
Button delete = new Button("Delete");
@@ -22,11 +28,13 @@ public class PublisherForm extends FormLayout {
Binder<Publisher> binder = new BeanValidationBinder<>(Publisher.class);
public PublisherForm() {
public PublisherForm(List<Publisher> publishers) {
addClassName("publisher-form");
binder.bindInstanceFields(this);
add(name, createButtonsLayout());
parentCompany.setItems(publishers);
parentCompany.setItemLabelGenerator(Publisher::getName);
add(name, weblink, parentCompany, createButtonsLayout());
}
private HorizontalLayout createButtonsLayout() {
@@ -55,17 +63,15 @@ public class PublisherForm extends FormLayout {
binder.setBean(publisher);
}
@Getter
public abstract static class PublisherFormEvent extends ComponentEvent<PublisherForm> {
private Publisher publisher;
private final Publisher publisher;
protected PublisherFormEvent(PublisherForm source, Publisher publisher) {
super(source, false);
this.publisher = publisher;
}
public Publisher getPublisher() {
return publisher;
}
}
public static class SaveEvent extends PublisherFormEvent {
@@ -1,9 +1,12 @@
package de.thpeetz.kontor.comics.views;
import com.vaadin.flow.component.button.*;
import de.thpeetz.kontor.comics.data.*;
import de.thpeetz.kontor.common.views.*;
import lombok.*;
import org.springframework.context.annotation.Scope;
import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.grid.Grid;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
@@ -14,9 +17,7 @@ import com.vaadin.flow.router.Route;
import com.vaadin.flow.spring.annotation.SpringComponent;
import de.thpeetz.kontor.comics.ComicConstants;
import de.thpeetz.kontor.comics.data.Publisher;
import de.thpeetz.kontor.comics.services.ComicService;
import de.thpeetz.kontor.common.views.MainLayout;
import jakarta.annotation.security.PermitAll;
@SpringComponent
@@ -26,8 +27,24 @@ import jakarta.annotation.security.PermitAll;
@PageTitle("Publisher | Comics | Kontor")
public class PublisherView extends VerticalLayout {
Grid<Publisher> grid = new Grid<>(Publisher.class);
@Getter
Grid<Publisher> grid = new Grid<>(Publisher.class, false);
Grid.Column<Publisher> idColumn = grid.addColumn(Publisher::getId)
.setHeader("ID").setResizable(true).setSortable(true);
Grid.Column<Publisher> createdColumn = grid.addColumn(Publisher::getCreatedDate)
.setHeader("Erstellt").setResizable(true).setSortable(true);
Grid.Column<Publisher> modifiedColumn = grid.addColumn(Publisher::getLastModifiedDate)
.setHeader("Geändert").setResizable(true).setSortable(true);
Grid.Column<Publisher> nameColumn = grid.addColumn(Publisher::getName)
.setHeader("Titel").setResizable(true).setSortable(true);
Grid.Column<Publisher> parentCompanyColumn = grid.addColumn(Publisher::getParentCompanyName)
.setHeader("Parent Company").setResizable(true).setSortable(true);
Grid.Column<Publisher> imprintColumn = grid.addComponentColumn(publisher -> StatusIcon.create(publisher.getParentCompany() != null))
.setHeader("Imprint").setWidth("6rem").setSortable(true);
Grid.Column<Publisher> weblinkColumn = grid.addColumn(Publisher::getWeblink)
.setHeader("Link").setResizable(true).setSortable(true);
TextField filterText = new TextField();
@Getter
PublisherForm form;
ComicService service;
@@ -46,13 +63,12 @@ public class PublisherView extends VerticalLayout {
private void configureGrid() {
grid.addClassName("publisher-grid");
grid.setSizeFull();
grid.setColumns("name");
grid.getColumns().forEach(col -> col.setAutoWidth(true));
grid.asSingleSelect().addValueChangeListener(event -> editPublisher(event.getValue()));
}
private void configureForm() {
form = new PublisherForm();
form = new PublisherForm(service.findAllPublishers(null));
form.setWidth("25em");
form.setVisible(false);
form.addSaveListener(this::savePublisher);
@@ -72,14 +88,6 @@ public class PublisherView extends VerticalLayout {
closeEditor();
}
public Grid<Publisher> getGrid() {
return grid;
}
public PublisherForm getForm() {
return form;
}
private Component getContent() {
HorizontalLayout content = new HorizontalLayout(grid, form);
content.setFlexGrow(2, grid);
@@ -98,7 +106,17 @@ public class PublisherView extends VerticalLayout {
Button addPublisherButton = new Button("Add publisher");
addPublisherButton.addClickListener(click -> addPublisher());
HorizontalLayout toolbar = new HorizontalLayout(filterText, addPublisherButton);
Button menuButton = new Button("Show/Hide Columns");
menuButton.addThemeVariants(ButtonVariant.LUMO_TERTIARY);
ColumnToggleContextMenu<Publisher> columnToggleContextMenu = new ColumnToggleContextMenu<>(menuButton);
columnToggleContextMenu.addColumnToggleItem(idColumn);
columnToggleContextMenu.addColumnToggleItem(createdColumn);
columnToggleContextMenu.addColumnToggleItem(modifiedColumn);
columnToggleContextMenu.addColumnToggleItem(nameColumn);
columnToggleContextMenu.addColumnToggleItem(parentCompanyColumn);
columnToggleContextMenu.addColumnToggleItem(imprintColumn);
columnToggleContextMenu.addColumnToggleItem(weblinkColumn);
HorizontalLayout toolbar = new HorizontalLayout(filterText, addPublisherButton, menuButton);
toolbar.addClassName("toolbar");
return toolbar;
}
@@ -1,5 +1,6 @@
package de.thpeetz.kontor.comics.views;
import lombok.*;
import org.springframework.context.annotation.Scope;
import com.vaadin.flow.component.Component;
@@ -26,8 +27,10 @@ import jakarta.annotation.security.PermitAll;
@PageTitle("Worktype | Comics | Kontor")
public class WorktypeView extends VerticalLayout {
@Getter
Grid<Worktype> grid = new Grid<>(Worktype.class);
TextField filterText = new TextField();
@Getter
WorktypeForm form;
ComicService service;
@@ -42,10 +45,6 @@ public class WorktypeView extends VerticalLayout {
updateList();
}
public Grid<Worktype> getGrid() {
return grid;
}
private void configureGrid() {
grid.addClassName("worktype-grid");
grid.setSizeFull();
@@ -54,13 +53,9 @@ public class WorktypeView extends VerticalLayout {
grid.asSingleSelect().addValueChangeListener(event -> editWorktype(event.getValue()));
}
public WorktypeForm getForm() {
return form;
}
private void configureForm() {
form = new WorktypeForm();
form.setWidth("25em");
form.setWidth("45em");
form.setVisible(false);
form.addSaveListener(this::saveWorktype);
form.addDeleteListener(this::deleteWorktype);
@@ -19,17 +19,19 @@ import de.thpeetz.kontor.bookshelf.BookshelfConstants;
import de.thpeetz.kontor.comics.ComicConstants;
import de.thpeetz.kontor.security.SecurityService;
import de.thpeetz.kontor.tysc.TyscConstants;
import lombok.*;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class KontorLayoutUtil {
private final AppLayout appLayout;
@Setter
private HorizontalLayout secondaryNavigation;
private AdminService adminService;
private final AdminService adminService;
private SecurityService securityService;
private final SecurityService securityService;
public KontorLayoutUtil(AppLayout layout, AdminService adminService, SecurityService securityService) {
this.adminService = adminService;
@@ -37,10 +39,6 @@ public class KontorLayoutUtil {
this.appLayout = layout;
}
public void setSecondaryNavigation(HorizontalLayout secondaryNavigation) {
this.secondaryNavigation = secondaryNavigation;
}
public void createHeader(String titleName) {
appLayout.addToDrawer(createTitle(), getScroller());
appLayout.addToNavbar(getHeader(titleName));
@@ -9,13 +9,7 @@ import de.thpeetz.kontor.security.SecurityService;
public class SeparateMainLayout extends AppLayout {
private final AdminService adminService;
private final SecurityService securityService;
public SeparateMainLayout(AdminService adminService, SecurityService securityService) {
this.adminService = adminService;
this.securityService = securityService;
KontorLayoutUtil layout = new KontorLayoutUtil(this, adminService, securityService);
layout.setSecondaryNavigation(getSecondaryNavigation());