diff --git a/springboot/src/main/java/de/thpeetz/kontor/admin/AdminConstants.java b/springboot/src/main/java/de/thpeetz/kontor/admin/AdminConstants.java index 63f11b1..ce0e33b 100644 --- a/springboot/src/main/java/de/thpeetz/kontor/admin/AdminConstants.java +++ b/springboot/src/main/java/de/thpeetz/kontor/admin/AdminConstants.java @@ -6,6 +6,8 @@ import com.vaadin.flow.router.RouterLink; import de.thpeetz.kontor.admin.views.*; import de.thpeetz.kontor.comics.ComicConstants; import de.thpeetz.kontor.comics.views.ComicWorkView; +import de.thpeetz.kontor.media.MediaConstants; +import de.thpeetz.kontor.media.views.MediaActorFileView; public class AdminConstants { @@ -44,6 +46,7 @@ public class AdminConstants { administration.addItem(new SideNavItem(ROLE, RoleView.class)); SideNavItem data = new SideNavItem(DATA, AUTHORIZATION_ROUTE, VaadinIcon.DATABASE.create()); data.addItem(new SideNavItem(ComicConstants.COMICWORK, ComicWorkView.class)); + data.addItem(new SideNavItem(MediaConstants.MEDIAACTORFILE, MediaActorFileView.class)); data.addItem(new SideNavItem(AUTHORIZATION, AuthorizationView.class)); data.addItem(new SideNavItem("Data Import", ModuleDataView.class)); data.addItem(new SideNavItem("Meta Data", MetaDataView.class)); diff --git a/springboot/src/main/java/de/thpeetz/kontor/admin/SetupModuleAdmin.java b/springboot/src/main/java/de/thpeetz/kontor/admin/SetupModuleAdmin.java index 5350f69..a819bb2 100644 --- a/springboot/src/main/java/de/thpeetz/kontor/admin/SetupModuleAdmin.java +++ b/springboot/src/main/java/de/thpeetz/kontor/admin/SetupModuleAdmin.java @@ -1,5 +1,6 @@ package de.thpeetz.kontor.admin; +import com.vaadin.flow.component.page.Meta; import de.thpeetz.kontor.admin.data.*; import de.thpeetz.kontor.admin.services.AdminService; import de.thpeetz.kontor.admin.services.MetaDataService; @@ -159,6 +160,19 @@ public class SetupModuleAdmin implements ApplicationListener findAllMediaFiles(String stringFilter) { @@ -64,4 +65,26 @@ public class MediaFileService { public void deleteMediaActor(MediaActor mediaActor) { mediaActorRepository.delete(mediaActor); } + + public List findAllMediaActorFiles() { + return mediaActorFileRepository.findAll(); + } + + public void saveMediaActorFile(MediaActorFile mediaActorFile) { + if (mediaActorFile == null){ + log.warn("MediaActorFile is null. Are you sure you have connected your form to the application?"); + return; + } + mediaActorFileRepository.save(mediaActorFile); + } + + public void deleteMediaActorFile(MediaActorFile mediaActorFile) { + MediaFile mediaFile = mediaActorFile.getMedia_file(); + mediaFile.getMediaActorFiles().remove(mediaActorFile); + mediaFileRepository.save(mediaFile); + MediaActor mediaActor = mediaActorFile.getMedia_actor(); + mediaActor.getMediaActorFiles().remove(mediaActorFile); + mediaActorRepository.save(mediaActor); + mediaActorFileRepository.delete(mediaActorFile); + } } diff --git a/springboot/src/main/java/de/thpeetz/kontor/media/views/MediaActorFileForm.java b/springboot/src/main/java/de/thpeetz/kontor/media/views/MediaActorFileForm.java new file mode 100644 index 0000000..ac3acb1 --- /dev/null +++ b/springboot/src/main/java/de/thpeetz/kontor/media/views/MediaActorFileForm.java @@ -0,0 +1,106 @@ +package de.thpeetz.kontor.media.views; + +import com.vaadin.flow.component.ComponentEvent; +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.ComboBox; +import com.vaadin.flow.component.formlayout.FormLayout; +import com.vaadin.flow.component.orderedlayout.HorizontalLayout; +import com.vaadin.flow.data.binder.BeanValidationBinder; +import com.vaadin.flow.data.binder.Binder; +import de.thpeetz.kontor.media.data.MediaActor; +import de.thpeetz.kontor.media.data.MediaActorFile; +import de.thpeetz.kontor.media.data.MediaFile; +import lombok.Getter; + +import java.util.List; + +public class MediaActorFileForm extends FormLayout { + ComboBox mediaFile = new ComboBox<>("Media File"); + ComboBox mediaActor = new ComboBox<>("Actor"); + + Button save = new Button("Save"); + Button delete = new Button("Delete"); + Button close = new Button("Cancel"); + + Binder binder = new BeanValidationBinder<>(MediaActorFile.class); + + public MediaActorFileForm(List mediaFiles, List actors) { + addClassName("mediaactorfile-form"); + binder.bindInstanceFields(this); + + mediaFile.setItems(mediaFiles); + mediaFile.setItemLabelGenerator(MediaFile::getTitle); + mediaActor.setItems(actors); + mediaActor.setItemLabelGenerator(MediaActor::getName); + add(mediaFile, mediaActor, createButtonsLayout()); + } + + private HorizontalLayout createButtonsLayout() { + save.addThemeVariants(ButtonVariant.LUMO_PRIMARY); + delete.addThemeVariants(ButtonVariant.LUMO_ERROR); + close.addThemeVariants(ButtonVariant.LUMO_TERTIARY); + + save.addClickShortcut(Key.ENTER); + close.addClickShortcut(Key.ESCAPE); + + save.addClickListener(event -> validateAndSave()); + delete.addClickListener(event -> fireEvent(new MediaActorFileForm.DeleteEvent(this, binder.getBean()))); + close.addClickListener(event -> fireEvent(new MediaActorFileForm.CloseEvent(this))); + + binder.addStatusChangeListener(e -> save.setEnabled(binder.isValid())); + return new HorizontalLayout(save, delete, close); + } + + private void validateAndSave() { + if (binder.isValid()) { + fireEvent(new MediaActorFileForm.SaveEvent(this, binder.getBean())); + } + } + + public void setMediaActorFile(MediaActorFile mediaActorFile) { + binder.setBean(mediaActorFile); + } + + public abstract static class MediaActorFileFormEvent extends ComponentEvent { + @Getter + private MediaActorFile mediaActorFile; + + protected MediaActorFileFormEvent(MediaActorFileForm source, MediaActorFile mediaActorFile) { + super(source, false); + this.mediaActorFile = mediaActorFile; + } + } + + public static class SaveEvent extends MediaActorFileForm.MediaActorFileFormEvent { + SaveEvent(MediaActorFileForm source, MediaActorFile mediaActorFile) { + super(source, mediaActorFile); + } + } + + public static class DeleteEvent extends MediaActorFileForm.MediaActorFileFormEvent { + DeleteEvent(MediaActorFileForm source, MediaActorFile mediaActorFile) { + super(source, mediaActorFile); + } + } + + public static class CloseEvent extends MediaActorFileForm.MediaActorFileFormEvent { + CloseEvent(MediaActorFileForm source) { + super(source, null); + } + } + + public void addDeleteListener(ComponentEventListener listener) { + addListener(MediaActorFileForm.DeleteEvent.class, listener); + } + + public void addSaveListener(ComponentEventListener listener) { + addListener(MediaActorFileForm.SaveEvent.class, listener); + } + + public void addCloseListener(ComponentEventListener listener) { + addListener(MediaActorFileForm.CloseEvent.class, listener); + } +} diff --git a/springboot/src/main/java/de/thpeetz/kontor/media/views/MediaActorFileView.java b/springboot/src/main/java/de/thpeetz/kontor/media/views/MediaActorFileView.java new file mode 100644 index 0000000..f1462b6 --- /dev/null +++ b/springboot/src/main/java/de/thpeetz/kontor/media/views/MediaActorFileView.java @@ -0,0 +1,114 @@ +package de.thpeetz.kontor.media.views; + +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; +import com.vaadin.flow.router.PageTitle; +import com.vaadin.flow.router.Route; +import com.vaadin.flow.spring.annotation.SpringComponent; +import de.thpeetz.kontor.common.views.MainLayout; +import de.thpeetz.kontor.media.MediaConstants; +import de.thpeetz.kontor.media.data.MediaActorFile; +import de.thpeetz.kontor.media.services.MediaFileService; +import jakarta.annotation.security.PermitAll; +import lombok.Getter; +import org.springframework.context.annotation.Scope; + +@SpringComponent +@Scope("prototype") +@PermitAll +@Route(value = MediaConstants.MEDIAACTORFILE_ROUTE, layout = MainLayout.class) +@PageTitle("MediaActorFile | Media | Kontor") +public class MediaActorFileView extends VerticalLayout { + + @Getter + Grid grid = new Grid<>(MediaActorFile.class); + @Getter + MediaActorFileForm form; + MediaFileService service; + + public MediaActorFileView(MediaFileService service) { + this.service = service; + addClassName("mediaactorfile-view"); + setSizeFull(); + configureGrid(); + configureForm(); + + add(getToolbar(), getContent()); + updateList(); + } + + private void configureGrid() { + grid.addClassName("mediaactorfile-grid"); + grid.setSizeFull(); + grid.setColumns("id", "media_actor.name", "media_file.title"); + grid.getColumns().forEach(col -> col.setAutoWidth(true)); + grid.asSingleSelect().addValueChangeListener(event -> editMediaActorFile(event.getValue())); + } + + private void configureForm() { + form = new MediaActorFileForm(service.findAllMediaFiles(null), service.findAllMediaActors(null)); + form.setWidth("25em"); + form.setVisible(false); + form.addSaveListener(this::saveMediaActorFile); + form.addDeleteListener(this::deleteMediaActorFile); + form.addCloseListener(e -> closeEditor()); + } + + private void saveMediaActorFile(MediaActorFileForm.SaveEvent event) { + service.saveMediaActorFile(event.getMediaActorFile()); + updateList(); + closeEditor(); + } + + private void deleteMediaActorFile(MediaActorFileForm.DeleteEvent event) { + service.deleteMediaActorFile(event.getMediaActorFile()); + updateList(); + closeEditor(); + } + + private Component getContent() { + HorizontalLayout content = new HorizontalLayout(grid, form); + content.setFlexGrow(2, grid); + content.setFlexGrow(1, form); + content.addClassName("content"); + content.setSizeFull(); + return content; + } + + private HorizontalLayout getToolbar() { + Button addMediaActorFileButton = new Button("Add MediaActorFile"); + addMediaActorFileButton.addClickListener(click -> addMediaActorFile()); + + HorizontalLayout toolbar = new HorizontalLayout(addMediaActorFileButton); + toolbar.addClassName("toolbar"); + return toolbar; + } + + public void editMediaActorFile(MediaActorFile mediaActorFile) { + if (mediaActorFile == null) { + closeEditor(); + } else { + form.setMediaActorFile(mediaActorFile); + form.setVisible(true); + addClassName("editing"); + } + } + + private void closeEditor() { + form.setMediaActorFile(null); + form.setVisible(false); + removeClassName("editing"); + } + + private void addMediaActorFile() { + grid.asSingleSelect().clear(); + editMediaActorFile(new MediaActorFile()); + } + + public void updateList() { + grid.setItems(service.findAllMediaActorFiles()); + } +} diff --git a/springboot/src/main/java/de/thpeetz/kontor/media/views/MediaActorForm.java b/springboot/src/main/java/de/thpeetz/kontor/media/views/MediaActorForm.java index e7cab60..e011fb7 100644 --- a/springboot/src/main/java/de/thpeetz/kontor/media/views/MediaActorForm.java +++ b/springboot/src/main/java/de/thpeetz/kontor/media/views/MediaActorForm.java @@ -7,6 +7,7 @@ import com.vaadin.flow.component.button.Button; import com.vaadin.flow.component.button.ButtonVariant; import com.vaadin.flow.component.formlayout.FormLayout; import com.vaadin.flow.component.grid.Grid; +import com.vaadin.flow.component.listbox.MultiSelectListBox; import com.vaadin.flow.component.orderedlayout.HorizontalLayout; import com.vaadin.flow.component.textfield.TextField; import com.vaadin.flow.data.binder.BeanValidationBinder; @@ -21,7 +22,7 @@ import java.util.List; public class MediaActorForm extends FormLayout { TextField name = new TextField("Name"); - // Grid mediaActorFiles = new Grid<>(MediaActorFile.class); + Grid mediaActorFiles = new Grid<>(MediaActorFile.class); Button save = new Button("Save"); Button delete = new Button("Delete"); @@ -33,11 +34,11 @@ public class MediaActorForm extends FormLayout { addClassName("media-actor-form"); binder.bindInstanceFields(this); - // mediaActorFiles.setColumns("media_file.title"); - // mediaActorFiles.getColumnByKey("mediaFile.title").setHeader("MediaFile"); - // mediaActorFiles.getColumns().forEach(col -> col.setAutoWidth(true)); - // add(name, mediaActorFiles, createButtonsLayout()); - add(name, createButtonsLayout()); + mediaActorFiles.setColumns("media_file.title"); + mediaActorFiles.getColumnByKey("media_file.title").setHeader("File Title"); + add(name, 2); + add(mediaActorFiles, 2); + add(createButtonsLayout()); } private HorizontalLayout createButtonsLayout() { @@ -67,8 +68,8 @@ public class MediaActorForm extends FormLayout { } public void setMediaActorFiles(List mediaActorFiles) { - log.info("Setting comic works: {}", mediaActorFiles); - // this.mediaActorFiles.setItems(mediaActorFiles); + log.info("Setting mediaActorFiles: {}", mediaActorFiles); + this.mediaActorFiles.setItems(mediaActorFiles); } public abstract static class MediaActorFormEvent extends ComponentEvent { diff --git a/springboot/src/main/java/de/thpeetz/kontor/media/views/MediaActorView.java b/springboot/src/main/java/de/thpeetz/kontor/media/views/MediaActorView.java index 40727cb..0f885b8 100644 --- a/springboot/src/main/java/de/thpeetz/kontor/media/views/MediaActorView.java +++ b/springboot/src/main/java/de/thpeetz/kontor/media/views/MediaActorView.java @@ -10,8 +10,6 @@ import com.vaadin.flow.data.value.ValueChangeMode; import com.vaadin.flow.router.PageTitle; import com.vaadin.flow.router.Route; import com.vaadin.flow.spring.annotation.SpringComponent; -import de.thpeetz.kontor.comics.data.Artist; -import de.thpeetz.kontor.comics.views.ArtistForm; import de.thpeetz.kontor.common.views.MainLayout; import de.thpeetz.kontor.media.MediaConstants; import de.thpeetz.kontor.media.data.MediaActor; @@ -55,7 +53,7 @@ public class MediaActorView extends VerticalLayout { private void configureForm() { form = new MediaActorForm(); - form.setWidth("25em"); + form.setWidth("75em"); form.setVisible(false); form.addSaveListener(this::saveMediaActor); form.addDeleteListener(this::deleteMediaActor); diff --git a/springboot/src/main/java/de/thpeetz/kontor/media/views/MediaFileForm.java b/springboot/src/main/java/de/thpeetz/kontor/media/views/MediaFileForm.java index b1042fa..4b4b469 100644 --- a/springboot/src/main/java/de/thpeetz/kontor/media/views/MediaFileForm.java +++ b/springboot/src/main/java/de/thpeetz/kontor/media/views/MediaFileForm.java @@ -7,14 +7,18 @@ import com.vaadin.flow.component.button.Button; import com.vaadin.flow.component.button.ButtonVariant; import com.vaadin.flow.component.checkbox.Checkbox; import com.vaadin.flow.component.formlayout.FormLayout; +import com.vaadin.flow.component.grid.Grid; import com.vaadin.flow.component.orderedlayout.HorizontalLayout; 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.media.data.MediaActorFile; import de.thpeetz.kontor.media.data.MediaFile; import lombok.Getter; import lombok.extern.slf4j.Slf4j; +import java.util.List; + @Slf4j public class MediaFileForm extends FormLayout { @@ -25,6 +29,7 @@ public class MediaFileForm extends FormLayout { TextField cloudLink = new TextField("Cloud Link"); Checkbox review = new Checkbox("Review"); Checkbox shouldDownload = new Checkbox("Download"); + Grid mediaActorFiles = new Grid<>(MediaActorFile.class); Button save = new Button("Save"); Button delete = new Button("Delete"); @@ -36,12 +41,18 @@ public class MediaFileForm extends FormLayout { addClassName("mediafile-form"); binder.bindInstanceFields(this); id.setReadOnly(true); + + mediaActorFiles.setColumns("media_actor.name"); + mediaActorFiles.getColumnByKey("media_actor.name").setHeader("Actor"); + add(id, 2); add(url, 2); add(title, 2); add(fileName, 2); add(cloudLink, 2); - add(review, shouldDownload, createButtonsLayout()); + add(review, shouldDownload); + add(mediaActorFiles, 2); + add(createButtonsLayout()); } private HorizontalLayout createButtonsLayout() { @@ -70,6 +81,10 @@ public class MediaFileForm extends FormLayout { binder.setBean(mediaFile); } + public void setMediaActorFiles(List actorFiles) { + mediaActorFiles.setItems(actorFiles); + } + @Getter public abstract static class MediaFileFormEvent extends ComponentEvent { private final MediaFile mediaFile; diff --git a/springboot/src/main/java/de/thpeetz/kontor/media/views/MediaFileView.java b/springboot/src/main/java/de/thpeetz/kontor/media/views/MediaFileView.java index 0784b8d..3793a38 100644 --- a/springboot/src/main/java/de/thpeetz/kontor/media/views/MediaFileView.java +++ b/springboot/src/main/java/de/thpeetz/kontor/media/views/MediaFileView.java @@ -20,8 +20,10 @@ import de.thpeetz.kontor.media.data.MediaFile; import de.thpeetz.kontor.media.services.MediaFileService; import jakarta.annotation.security.RolesAllowed; import lombok.Getter; +import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Scope; +@Slf4j @SpringComponent @Scope("prototype") @RolesAllowed("MEDIA") @@ -164,6 +166,12 @@ public class MediaFileView extends VerticalLayout { closeEditor(); } else { form.setMediaFile(mediaFile); + if (mediaFile.getMediaActorFiles() == null) { + log.info("no MediaActorFiles"); + } else { + log.info("MediaActorFiles size: {}", mediaFile.getMediaActorFiles().size()); + } + form.setMediaActorFiles(mediaFile.getMediaActorFiles()); form.setVisible(true); addClassName("editing"); }