From 41d513e402852ad363dcea60faf35d07d4527a5c Mon Sep 17 00:00:00 2001 From: Thomas Peetz Date: Tue, 13 May 2025 21:40:29 +0200 Subject: [PATCH] add reference from Volume to Issue and Comic --- kontor-api/src/db/models/comic.py | 7 +++- .../src/templates/comic/comic_detail.html | 32 +++++++++++++------ .../de/thpeetz/kontor/comics/data/Issue.java | 13 ++++++++ .../thpeetz/kontor/comics/data/StoryArc.java | 19 +++++++++-- .../de/thpeetz/kontor/comics/data/Volume.java | 6 +++- .../kontor/comics/views/IssueForm.java | 17 +++++----- .../kontor/comics/views/IssueView.java | 5 ++- 7 files changed, 76 insertions(+), 23 deletions(-) diff --git a/kontor-api/src/db/models/comic.py b/kontor-api/src/db/models/comic.py index 460421b..f59da22 100644 --- a/kontor-api/src/db/models/comic.py +++ b/kontor-api/src/db/models/comic.py @@ -68,6 +68,7 @@ class Volume(Base, BaseMixin): name = Column(String, nullable=False) comic_id = Column(String, ForeignKey("comic.id"), nullable=False) comic = relationship("Comic", back_populates="volumes") + story_arcs = relationship("StoryArc") issues = relationship("Issue") @@ -85,6 +86,9 @@ class StoryArc(Base, BaseMixin): name = Column(String, nullable=False) comic_id = Column(String, ForeignKey("comic.id"), nullable=False) comic = relationship("Comic", back_populates="story_arcs") + volume_id = Column(String, ForeignKey("volume.id"), nullable=True) + volume = relationship("Volume", back_populates="story_arcs") + issues = relationship("Issue") class Issue(Base, BaseMixin): @@ -96,7 +100,8 @@ class Issue(Base, BaseMixin): comic = relationship("Comic", back_populates="issues") volume_id = Column(String, ForeignKey("volume.id"), nullable=True) volume = relationship("Volume", back_populates="issues") - + story_arc_id = Column(String, ForeignKey("story_arc.id"), nullable=True) + story_arc = relationship("StoryArc", back_populates="issues") class Artist(Base, BaseMixin): __tablename__ = "artist" diff --git a/kontor-api/src/templates/comic/comic_detail.html b/kontor-api/src/templates/comic/comic_detail.html index aa004fc..f769844 100644 --- a/kontor-api/src/templates/comic/comic_detail.html +++ b/kontor-api/src/templates/comic/comic_detail.html @@ -46,6 +46,28 @@ {% endfor %} + {% if comic.volumes|length > 0 %} + + Volumes + + + + + {% endif %} + + Issues + + + + Data Created {{comic.created_date}} @@ -58,16 +80,6 @@ Data Version {{comic.version}} - - Issues - - - - diff --git a/kontor-spring/src/main/java/de/thpeetz/kontor/comics/data/Issue.java b/kontor-spring/src/main/java/de/thpeetz/kontor/comics/data/Issue.java index d63f924..02392e2 100644 --- a/kontor-spring/src/main/java/de/thpeetz/kontor/comics/data/Issue.java +++ b/kontor-spring/src/main/java/de/thpeetz/kontor/comics/data/Issue.java @@ -33,6 +33,12 @@ public class Issue extends AbstractEntity { @Nullable private Volume volume; + @ManyToOne + @JoinColumn(name = "storyArc_id") + @JsonIgnoreProperties({ "issues" }) + @Nullable + private StoryArc storyArc; + @NotEmpty private String issueNumber; @@ -43,4 +49,11 @@ public class Issue extends AbstractEntity { public String getComicTitle() { return comic.getTitle(); } + + public String getVolumeName() { + if (volume != null) { + return volume.getName(); + } + return null; + } } diff --git a/kontor-spring/src/main/java/de/thpeetz/kontor/comics/data/StoryArc.java b/kontor-spring/src/main/java/de/thpeetz/kontor/comics/data/StoryArc.java index 34f2188..11d328c 100644 --- a/kontor-spring/src/main/java/de/thpeetz/kontor/comics/data/StoryArc.java +++ b/kontor-spring/src/main/java/de/thpeetz/kontor/comics/data/StoryArc.java @@ -1,11 +1,14 @@ package de.thpeetz.kontor.comics.data; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; - +import jakarta.annotation.Nullable; import de.thpeetz.kontor.common.data.AbstractEntity; +import jakarta.persistence.CascadeType; import jakarta.persistence.Entity; -import jakarta.persistence.JoinColumn; +import jakarta.persistence.FetchType; import jakarta.persistence.ManyToOne; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.OneToMany; import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; import lombok.EqualsAndHashCode; @@ -13,6 +16,8 @@ import lombok.Getter; import lombok.Setter; import lombok.ToString; +import java.util.*; + @Getter @Setter @ToString @@ -28,4 +33,14 @@ public class StoryArc extends AbstractEntity { @NotNull @JsonIgnoreProperties({ "storyArcs" }) private Comic comic; + + @ManyToOne + @JoinColumn(name = "volume_id") + @JsonIgnoreProperties({ "storyArcs" }) + @Nullable + private Volume volume; + + @OneToMany(fetch = FetchType.EAGER, mappedBy = "storyArc", cascade = CascadeType.REMOVE, orphanRemoval = true) + @Nullable + private List issues = new LinkedList<>(); } diff --git a/kontor-spring/src/main/java/de/thpeetz/kontor/comics/data/Volume.java b/kontor-spring/src/main/java/de/thpeetz/kontor/comics/data/Volume.java index c8e1eb0..67a6d8a 100644 --- a/kontor-spring/src/main/java/de/thpeetz/kontor/comics/data/Volume.java +++ b/kontor-spring/src/main/java/de/thpeetz/kontor/comics/data/Volume.java @@ -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.*; import jakarta.persistence.CascadeType; import jakarta.persistence.Entity; import jakarta.persistence.FetchType; @@ -36,6 +36,10 @@ public class Volume extends AbstractEntity { @JsonIgnoreProperties({ "volumes" }) private Comic comic; + @OneToMany(fetch = FetchType.EAGER, mappedBy = "volume", cascade = CascadeType.REMOVE, orphanRemoval = true) + @Nullable + private List storyArcs = new LinkedList<>(); + @OneToMany(fetch = FetchType.EAGER, mappedBy = "volume", cascade = CascadeType.REMOVE, orphanRemoval = true) @Nullable private List issues = new LinkedList<>(); diff --git a/kontor-spring/src/main/java/de/thpeetz/kontor/comics/views/IssueForm.java b/kontor-spring/src/main/java/de/thpeetz/kontor/comics/views/IssueForm.java index d537210..5bb117f 100644 --- a/kontor-spring/src/main/java/de/thpeetz/kontor/comics/views/IssueForm.java +++ b/kontor-spring/src/main/java/de/thpeetz/kontor/comics/views/IssueForm.java @@ -15,14 +15,14 @@ import com.vaadin.flow.component.textfield.TextField; import com.vaadin.flow.data.binder.BeanValidationBinder; import com.vaadin.flow.data.binder.Binder; -import de.thpeetz.kontor.comics.data.Comic; -import de.thpeetz.kontor.comics.data.Issue; +import de.thpeetz.kontor.comics.data.*; import lombok.extern.slf4j.Slf4j; @Slf4j public class IssueForm extends FormLayout { ComboBox comic = new ComboBox<>("Comic"); + ComboBox volume = new ComboBox<>("Volume"); TextField issueNumber = new TextField("Issue number"); Checkbox isRead = new Checkbox("Read"); Checkbox inStock = new Checkbox("In stock"); @@ -39,7 +39,7 @@ public class IssueForm extends FormLayout { comic.setItems(comics); comic.setItemLabelGenerator(Comic::getTitle); - add(comic, issueNumber, isRead, inStock, createButtonsLayout()); + add(comic, volume, issueNumber, isRead, inStock, createButtonsLayout()); } private HorizontalLayout createButtonsLayout() { @@ -66,19 +66,20 @@ public class IssueForm extends FormLayout { public void setIssue(Issue issue) { binder.setBean(issue); + if (issue != null) { + volume.setItems(issue.getComic().getVolumes()); + volume.setItemLabelGenerator(Volume::getName); + } } public abstract static class IssueFormEvent extends ComponentEvent { - private Issue issue; + @lombok.Getter + private final Issue issue; protected IssueFormEvent(IssueForm source, Issue issue) { super(source, false); this.issue = issue; } - - public Issue getIssue() { - return issue; - } } public static class SaveEvent extends IssueFormEvent { diff --git a/kontor-spring/src/main/java/de/thpeetz/kontor/comics/views/IssueView.java b/kontor-spring/src/main/java/de/thpeetz/kontor/comics/views/IssueView.java index 4a8e15e..64d7634 100644 --- a/kontor-spring/src/main/java/de/thpeetz/kontor/comics/views/IssueView.java +++ b/kontor-spring/src/main/java/de/thpeetz/kontor/comics/views/IssueView.java @@ -49,6 +49,8 @@ public class IssueView extends VerticalLayout { .setHeader("Version").setResizable(true).setSortable(true); Grid.Column titleColumn = grid.addColumn(Issue::getComicTitle) .setHeader("Comic").setResizable(true).setSortable(true); + Grid.Column volumeColumn = grid.addColumn(Issue::getVolumeName) + .setHeader("Volume").setResizable(true).setSortable(true); Grid.Column issueNumberColumn = grid.addColumn(Issue::getIssueNumber) .setHeader("Heft Nummer").setResizable(true).setSortable(true); Grid.Column isReadColumn = grid.addComponentColumn(issueColumn -> StatusIcon.create(issueColumn.getIsRead())) @@ -118,10 +120,11 @@ public class IssueView extends VerticalLayout { menuButton.addThemeVariants(ButtonVariant.LUMO_TERTIARY); ColumnToggleContextMenu columnToggleContextMenu = new ColumnToggleContextMenu<>(menuButton); columnToggleContextMenu.addColumnToggleItem(idColumn); - columnToggleContextMenu.addColumnToggleItem(createdColumn); + columnToggleContextMenu.addColumnToggleItem(createdColumn); columnToggleContextMenu.addColumnToggleItem(modifiedColumn); columnToggleContextMenu.addColumnToggleItem(versionColumn); columnToggleContextMenu.addColumnToggleItem(titleColumn); + columnToggleContextMenu.addColumnToggleItem(volumeColumn); columnToggleContextMenu.addColumnToggleItem(issueNumberColumn); columnToggleContextMenu.addColumnToggleItem(isReadColumn); columnToggleContextMenu.addColumnToggleItem(inStockColumn);