add MediaActor
This commit is contained in:
@@ -25,10 +25,10 @@ import jakarta.annotation.security.PermitAll;
|
||||
@PageTitle("Artist | Comics | Kontor")
|
||||
public class ArtistView extends VerticalLayout {
|
||||
|
||||
Grid<Artist> grid = new Grid<>(Artist.class);
|
||||
TextField filterText = new TextField();
|
||||
ArtistForm form;
|
||||
ComicService service;
|
||||
Grid<Artist> grid = new Grid<>(Artist.class);
|
||||
TextField filterText = new TextField();
|
||||
ArtistForm form;
|
||||
ComicService service;
|
||||
|
||||
public ArtistView(ComicService service) {
|
||||
this.service = service;
|
||||
|
||||
@@ -2,6 +2,7 @@ package de.thpeetz.kontor.media;
|
||||
|
||||
import com.vaadin.flow.component.icon.VaadinIcon;
|
||||
import com.vaadin.flow.component.sidenav.SideNavItem;
|
||||
import de.thpeetz.kontor.media.views.MediaActorView;
|
||||
import de.thpeetz.kontor.media.views.MediaArticleView;
|
||||
import de.thpeetz.kontor.media.views.MediaFileView;
|
||||
import de.thpeetz.kontor.media.views.MediaVideoView;
|
||||
@@ -15,9 +16,11 @@ public class MediaConstants {
|
||||
public static final String MEDIAVIDEO_ROUTE = "media/mediavideo";
|
||||
public static final String MEDIAARTICLE_ROUTE = "media/mediaarticle";
|
||||
public static final String MEDIA_ROLE = "ROLE_MEDIA";
|
||||
public static final String MEDIAACTOR_ROUTE = "media/mediaactor";
|
||||
private static final String MEDIAFILE = "Media Files";
|
||||
private static final String MEDIAVIDEO = "Media Videos";
|
||||
private static final String MEDIAARTICLE = "Media Article";
|
||||
private static final String MEDIAACTOR = "Media Actor";
|
||||
|
||||
public static SideNavItem getMediaNavigation(ArrayList<String> roles) {
|
||||
SideNavItem media = new SideNavItem(MEDIA, MEDIAFILE_ROUTE, VaadinIcon.VIMEO.create());
|
||||
@@ -25,6 +28,7 @@ public class MediaConstants {
|
||||
media.addItem(new SideNavItem(MEDIAARTICLE, MediaArticleView.class));
|
||||
if (roles.contains(MEDIA_ROLE)) {
|
||||
media.addItem(new SideNavItem(MEDIAFILE, MediaFileView.class));
|
||||
media.addItem(new SideNavItem(MEDIAACTOR, MediaActorView.class));
|
||||
}
|
||||
return media;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package de.thpeetz.kontor.media.data;
|
||||
|
||||
import de.thpeetz.kontor.common.data.AbstractEntity;
|
||||
import jakarta.annotation.Nullable;
|
||||
import jakarta.persistence.*;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Slf4j
|
||||
@Entity
|
||||
public class MediaActor extends AbstractEntity {
|
||||
|
||||
@NotEmpty
|
||||
@Column(unique = true)
|
||||
private String name;
|
||||
|
||||
@OneToMany(fetch = FetchType.EAGER, mappedBy = "media_actor", cascade = CascadeType.REFRESH, orphanRemoval = true)
|
||||
@Nullable
|
||||
List<MediaActorFile> mediaActorFiles;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package de.thpeetz.kontor.media.data;
|
||||
|
||||
import de.thpeetz.kontor.comics.data.Artist;
|
||||
import de.thpeetz.kontor.comics.data.Comic;
|
||||
import de.thpeetz.kontor.common.data.AbstractEntity;
|
||||
import jakarta.persistence.*;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
@Entity
|
||||
@Table(indexes = {@Index(columnList = "media_file_id, media_actor_id") },
|
||||
uniqueConstraints = @UniqueConstraint(columnNames = {"media_file_id", "media_actor_id" })
|
||||
)
|
||||
public class MediaActorFile extends AbstractEntity {
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "media_file_id")
|
||||
@NotNull
|
||||
private MediaFile media_file;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "media_actor_id")
|
||||
@NotNull
|
||||
private MediaActor media_actor;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package de.thpeetz.kontor.media.data;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
public interface MediaActorFileRepository extends JpaRepository<MediaActorFile, String> {
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package de.thpeetz.kontor.media.data;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface MediaActorRepository extends JpaRepository<MediaActor, String> {
|
||||
@Query("select m from MediaActor m " +
|
||||
"where lower(m.name) like lower(concat('%', :searchTerm, '%')) ")
|
||||
List<MediaActor> search(@Param("searchTerm") String searchTerm);
|
||||
|
||||
List<MediaActor> findByNameIgnoreCase(String name);
|
||||
|
||||
MediaActor findByName(String name);
|
||||
}
|
||||
@@ -2,14 +2,14 @@ package de.thpeetz.kontor.media.data;
|
||||
|
||||
import de.thpeetz.kontor.common.data.AbstractEntity;
|
||||
import jakarta.annotation.Nullable;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.persistence.UniqueConstraint;
|
||||
import jakarta.persistence.*;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@Getter
|
||||
@Setter
|
||||
@@ -37,4 +37,7 @@ public class MediaFile extends AbstractEntity {
|
||||
@Nullable
|
||||
private String path;
|
||||
|
||||
@OneToMany(fetch = FetchType.EAGER, mappedBy = "media_file", cascade = CascadeType.REFRESH, orphanRemoval = true)
|
||||
@Nullable
|
||||
List<MediaActorFile> mediaActorFiles;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package de.thpeetz.kontor.media.services;
|
||||
|
||||
import de.thpeetz.kontor.media.data.MediaFile;
|
||||
import de.thpeetz.kontor.media.data.MediaFileRepository;
|
||||
import de.thpeetz.kontor.media.data.*;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@@ -13,19 +12,22 @@ public class MediaFileService {
|
||||
|
||||
private final MediaFileRepository mediaFileRepository;
|
||||
|
||||
public MediaFileService(MediaFileRepository mediaFileRepository) {
|
||||
private final MediaActorRepository mediaActorRepository;
|
||||
|
||||
public MediaFileService(MediaFileRepository mediaFileRepository, MediaActorRepository mediaActorRepository) {
|
||||
this.mediaFileRepository = mediaFileRepository;
|
||||
this.mediaActorRepository = mediaActorRepository;
|
||||
}
|
||||
|
||||
public List<MediaFile> findAllMediaFiles(String stringFilter) {
|
||||
List<MediaFile> results;
|
||||
if (stringFilter == null || stringFilter.isEmpty()) {
|
||||
log.debug("Found " + mediaFileRepository.count()+ " entries");
|
||||
return mediaFileRepository.findAll();
|
||||
results = mediaFileRepository.findAll();
|
||||
} else {
|
||||
List<MediaFile> results = mediaFileRepository.search(stringFilter);
|
||||
log.debug("Found " + results.size() + " entries");
|
||||
return results;
|
||||
results = mediaFileRepository.search(stringFilter);
|
||||
}
|
||||
log.debug("Found " + results.size() + " entries");
|
||||
return results;
|
||||
}
|
||||
|
||||
public void saveMediaFile(MediaFile mediaFile) {
|
||||
@@ -39,4 +41,27 @@ public class MediaFileService {
|
||||
public void deleteMediaFile(MediaFile mediaFile) {
|
||||
mediaFileRepository.delete(mediaFile);
|
||||
}
|
||||
|
||||
public List<MediaActor> findAllMediaActors(String stringFilter) {
|
||||
List<MediaActor> results;
|
||||
if (stringFilter == null || stringFilter.isEmpty()) {
|
||||
results = mediaActorRepository.findAll();
|
||||
} else {
|
||||
results = mediaActorRepository.search(stringFilter);
|
||||
}
|
||||
log.debug("Found " + results.size() + " entries");
|
||||
return results;
|
||||
}
|
||||
|
||||
public void saveMediaActor(MediaActor mediaActor) {
|
||||
if (mediaActor == null) {
|
||||
log.warn("MediaActor is null. Are you sure you have connected your form to the application?");
|
||||
return;
|
||||
}
|
||||
mediaActorRepository.save(mediaActor);
|
||||
}
|
||||
|
||||
public void deleteMediaActor(MediaActor mediaActor) {
|
||||
mediaActorRepository.delete(mediaActor);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
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.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.MediaActor;
|
||||
import de.thpeetz.kontor.media.data.MediaActorFile;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
public class MediaActorForm extends FormLayout {
|
||||
|
||||
TextField name = new TextField("Name");
|
||||
// Grid<MediaActorFile> mediaActorFiles = new Grid<>(MediaActorFile.class);
|
||||
|
||||
Button save = new Button("Save");
|
||||
Button delete = new Button("Delete");
|
||||
Button close = new Button("Cancel");
|
||||
|
||||
Binder<MediaActor> binder = new BeanValidationBinder<>(MediaActor.class);
|
||||
|
||||
public MediaActorForm() {
|
||||
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());
|
||||
}
|
||||
|
||||
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 MediaActorForm.DeleteEvent(this, binder.getBean())));
|
||||
close.addClickListener(event -> fireEvent(new MediaActorForm.CloseEvent(this)));
|
||||
|
||||
binder.addStatusChangeListener(e -> save.setEnabled(binder.isValid()));
|
||||
return new HorizontalLayout(save, delete, close);
|
||||
}
|
||||
|
||||
private void validateAndSave() {
|
||||
if (binder.isValid()) {
|
||||
fireEvent(new MediaActorForm.SaveEvent(this, binder.getBean()));
|
||||
}
|
||||
}
|
||||
|
||||
public void setMediaActor(MediaActor mediaActor) {
|
||||
binder.setBean(mediaActor);
|
||||
}
|
||||
|
||||
public void setMediaActorFiles(List<MediaActorFile> mediaActorFiles) {
|
||||
log.info("Setting comic works: {}", mediaActorFiles);
|
||||
// this.mediaActorFiles.setItems(mediaActorFiles);
|
||||
}
|
||||
|
||||
public abstract static class MediaActorFormEvent extends ComponentEvent<MediaActorForm> {
|
||||
private MediaActor mediaActor;
|
||||
|
||||
protected MediaActorFormEvent(MediaActorForm source, MediaActor mediaActor) {
|
||||
super(source, false);
|
||||
this.mediaActor = mediaActor;
|
||||
}
|
||||
|
||||
public MediaActor getMediaActor() {
|
||||
return mediaActor;
|
||||
}
|
||||
}
|
||||
|
||||
public static class SaveEvent extends MediaActorForm.MediaActorFormEvent {
|
||||
SaveEvent(MediaActorForm source, MediaActor mediaActor) {
|
||||
super(source, mediaActor);
|
||||
}
|
||||
}
|
||||
|
||||
public static class DeleteEvent extends MediaActorForm.MediaActorFormEvent {
|
||||
DeleteEvent(MediaActorForm source, MediaActor mediaActor) {
|
||||
super(source, mediaActor);
|
||||
}
|
||||
}
|
||||
|
||||
public static class CloseEvent extends MediaActorForm.MediaActorFormEvent {
|
||||
CloseEvent(MediaActorForm source) {
|
||||
super(source, null);
|
||||
}
|
||||
}
|
||||
|
||||
public void addDeleteListener(ComponentEventListener<MediaActorForm.DeleteEvent> listener) {
|
||||
addListener(MediaActorForm.DeleteEvent.class, listener);
|
||||
}
|
||||
|
||||
public void addSaveListener(ComponentEventListener<MediaActorForm.SaveEvent> listener) {
|
||||
addListener(MediaActorForm.SaveEvent.class, listener);
|
||||
}
|
||||
|
||||
public void addCloseListener(ComponentEventListener<MediaActorForm.CloseEvent> listener) {
|
||||
addListener(MediaActorForm.CloseEvent.class, listener);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
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.component.textfield.TextField;
|
||||
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;
|
||||
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.MEDIAACTOR_ROUTE, layout = MainLayout.class)
|
||||
@PageTitle("Actor | Media | Kontor")
|
||||
public class MediaActorView extends VerticalLayout {
|
||||
|
||||
@Getter
|
||||
Grid<MediaActor> grid = new Grid<>(MediaActor.class);
|
||||
TextField filterText = new TextField();
|
||||
@Getter
|
||||
MediaActorForm form;
|
||||
MediaFileService service;
|
||||
|
||||
public MediaActorView(MediaFileService service) {
|
||||
this.service = service;
|
||||
addClassName("media-actor-view");
|
||||
setSizeFull();
|
||||
configureGrid();
|
||||
configureForm();
|
||||
|
||||
add(getToolbar(), getContent());
|
||||
updateList();
|
||||
}
|
||||
|
||||
private void configureGrid() {
|
||||
grid.addClassName("artist-grid");
|
||||
grid.setSizeFull();
|
||||
grid.setColumns("name");
|
||||
grid.getColumns().forEach(col -> col.setAutoWidth(true));
|
||||
grid.asSingleSelect().addValueChangeListener(event -> editMediaActor(event.getValue()));
|
||||
}
|
||||
|
||||
private void configureForm() {
|
||||
form = new MediaActorForm();
|
||||
form.setWidth("25em");
|
||||
form.setVisible(false);
|
||||
form.addSaveListener(this::saveMediaActor);
|
||||
form.addDeleteListener(this::deleteMediaActor);
|
||||
form.addCloseListener(e -> closeEditor());
|
||||
}
|
||||
|
||||
private void saveMediaActor(MediaActorForm.SaveEvent event) {
|
||||
service.saveMediaActor(event.getMediaActor());
|
||||
updateList();
|
||||
closeEditor();
|
||||
}
|
||||
|
||||
private void deleteMediaActor(MediaActorForm.DeleteEvent event) {
|
||||
service.deleteMediaActor(event.getMediaActor());
|
||||
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() {
|
||||
filterText.setPlaceholder("Filter by name...");
|
||||
filterText.setClearButtonVisible(true);
|
||||
filterText.setValueChangeMode(ValueChangeMode.LAZY);
|
||||
filterText.addValueChangeListener(e -> updateList());
|
||||
|
||||
Button addMediaActorButton = new Button("Add actor");
|
||||
addMediaActorButton.addClickListener(click -> addMediaActor());
|
||||
|
||||
HorizontalLayout toolbar = new HorizontalLayout(filterText, addMediaActorButton);
|
||||
toolbar.addClassName("toolbar");
|
||||
return toolbar;
|
||||
}
|
||||
|
||||
public void editMediaActor(MediaActor mediaActor) {
|
||||
if (mediaActor == null) {
|
||||
closeEditor();
|
||||
} else {
|
||||
form.setMediaActor(mediaActor);
|
||||
form.setMediaActorFiles(mediaActor.getMediaActorFiles());
|
||||
form.setVisible(true);
|
||||
addClassName("editing");
|
||||
}
|
||||
}
|
||||
|
||||
private void closeEditor() {
|
||||
form.setMediaActor(null);
|
||||
form.setVisible(false);
|
||||
removeClassName("editing");
|
||||
}
|
||||
|
||||
private void addMediaActor() {
|
||||
grid.asSingleSelect().clear();
|
||||
editMediaActor(new MediaActor());
|
||||
}
|
||||
|
||||
public void updateList() {
|
||||
grid.setItems(service.findAllMediaActors(filterText.getValue()));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user