import sources from develop/0.1.0

This commit is contained in:
Thomas Peetz
2025-04-29 12:52:55 +02:00
committed by Thomas Peetz
parent c30bdd1cd5
commit 19a5623075
670 changed files with 35977 additions and 0 deletions
@@ -0,0 +1,35 @@
package de.thpeetz.kontor.admin.data;
import de.thpeetz.kontor.common.data.AbstractEntity;
import jakarta.persistence.Entity;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.validation.constraints.NotNull;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@Entity
public class AuthorizationMatrix extends AbstractEntity {
@ManyToOne
@JoinColumn(name = "user_id")
@NotNull
private User user;
@ManyToOne
@JoinColumn(name = "role_id")
@NotNull
private Role role;
@Override
public String toString() {
final StringBuffer sb = new StringBuffer("AuthorizationMatrix{");
sb.append("user=").append(user.getUserName());
sb.append(", role=").append(role.getName());
sb.append('}');
return sb.toString();
}
}
@@ -0,0 +1,69 @@
package de.thpeetz.kontor.admin.data;
import de.thpeetz.kontor.common.data.AbstractEntity;
import jakarta.annotation.Nullable;
import jakarta.persistence.*;
import jakarta.validation.constraints.NotNull;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Entity
@Getter
@Setter
@Table(
indexes = @Index(columnList = "columnName, table_id"),
uniqueConstraints = @UniqueConstraint(columnNames = {"table_id", "columnOrder"})
)
public class MetaDataColumn extends AbstractEntity {
@NotNull
private String columnName;
private String columnSyncName;
private String columnType;
@Nullable
private String columnModifier;
private Integer columnOrder;
private Boolean isShown;
private String columnLabel;
private Boolean showFilter = Boolean.FALSE;
private String filterLabel;
private String refColumn;
@ManyToOne
@JoinColumn(name = "table_id")
@NotNull
private MetaDataTable table;
public String getTableName() {
return table.getTableName();
}
public String updateColumnName(String value) {
if (!this.getColumnName().equals(value)) {
this.setColumnName(value);
log.info("update columnName");
return "updated " + this.getId() + " with " + value + "\n";
}
return "no changes for " + this.getId() + "\n";
}
public String updateColumnSyncName(String value) {
if (!this.getColumnSyncName().equals(value)) {
this.setColumnSyncName(value);
log.info("update columnSyncName");
return "updated " + this.getId() + " with " + value + "\n";
}
return "no changes for " + this.getId() + "\n";
}
}
@@ -0,0 +1,40 @@
package de.thpeetz.kontor.admin.data;
import de.thpeetz.kontor.common.data.AbstractEntity;
import jakarta.persistence.*;
import jakarta.validation.constraints.NotNull;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
@Slf4j
@Entity
@Getter
@Setter
@Table(
indexes = @Index(columnList = "tableName"),
uniqueConstraints = @UniqueConstraint(columnNames = {"tableName"})
)
public class MetaDataTable extends AbstractEntity {
@NotNull
private String tableName;
@OneToMany(fetch = FetchType.EAGER, mappedBy = "table")
private List<MetaDataColumn> tableColumns = new LinkedList<>();
public String updateTableName(String value) {
if (!this.getTableName().equals(value)) {
this.setTableName(value);
log.info("update tableName");
return "updated " + this.getId() + " with " + value;
}
return "no changes for " + this.getId();
}
}
@@ -0,0 +1,25 @@
package de.thpeetz.kontor.admin.data;
import de.thpeetz.kontor.common.data.AbstractEntity;
import jakarta.persistence.Entity;
import jakarta.persistence.Index;
import jakarta.persistence.Table;
import jakarta.persistence.UniqueConstraint;
import jakarta.validation.constraints.NotEmpty;
import lombok.Getter;
import lombok.Setter;
@Entity
@Getter
@Setter
@Table(
indexes = @Index(columnList = "moduleName"),
uniqueConstraints = @UniqueConstraint(columnNames = {"moduleName"})
)
public class ModuleData extends AbstractEntity {
@NotEmpty
private String moduleName;
private Boolean importData;
}
@@ -0,0 +1,30 @@
package de.thpeetz.kontor.admin.data;
import java.util.List;
import de.thpeetz.kontor.common.data.AbstractEntity;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.OneToMany;
import jakarta.validation.constraints.NotEmpty;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;
import javax.annotation.Nullable;
@Slf4j
@Getter
@Setter
@ToString
@Entity
public class Role extends AbstractEntity {
@NotEmpty
private String name;
@OneToMany(fetch = FetchType.EAGER, mappedBy = "role")
@Nullable
private List<AuthorizationMatrix> matrix;
}
@@ -0,0 +1,62 @@
package de.thpeetz.kontor.admin.data;
import de.thpeetz.kontor.common.data.AbstractEntity;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.Index;
import jakarta.persistence.OneToMany;
import jakarta.persistence.Table;
import jakarta.persistence.UniqueConstraint;
import jakarta.validation.constraints.NotEmpty;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;
import javax.annotation.Nullable;
import java.util.LinkedList;
import java.util.List;
@Slf4j
@Getter
@Setter
@ToString
@Entity
@Table(indexes = @Index(columnList = "userName"), uniqueConstraints = @UniqueConstraint(columnNames = {"userName"}))
public class User extends AbstractEntity {
private String firstName;
private String lastName;
@NotEmpty
private String userName;
private String email;
private String password;
private boolean enabled;
@OneToMany(fetch = FetchType.EAGER, mappedBy = "user")
@Nullable
private List<AuthorizationMatrix> matrix = new LinkedList<>();
@OneToMany(fetch = FetchType.EAGER, mappedBy = "user")
@Nullable
private List<Token> tokens = new LinkedList<>();
public String getFullName() {
StringBuilder fullNamBuilder = new StringBuilder();
if (firstName != null) {
fullNamBuilder.append(firstName);
}
if (lastName != null) {
if (fullNamBuilder.length() > 0) {
fullNamBuilder.append(" ");
}
fullNamBuilder.append(lastName);
}
return fullNamBuilder.toString();
}
}
@@ -0,0 +1,15 @@
package de.thpeetz.kontor.admin.repository;
import java.util.List;
import de.thpeetz.kontor.admin.data.AuthorizationMatrix;
import de.thpeetz.kontor.admin.data.Role;
import de.thpeetz.kontor.admin.data.User;
import org.springframework.data.jpa.repository.JpaRepository;
public interface AuthorizationMatrixRepository extends JpaRepository<AuthorizationMatrix, String> {
List<AuthorizationMatrix> findByUser(User user);
List<AuthorizationMatrix> findByRole(Role role);
}
@@ -0,0 +1,18 @@
package de.thpeetz.kontor.admin.repository;
import de.thpeetz.kontor.admin.data.MetaDataColumn;
import de.thpeetz.kontor.admin.data.MetaDataTable;
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 MetaDataColumnRepository extends JpaRepository<MetaDataColumn, String> {
List<MetaDataColumn> findByTable(MetaDataTable table);
@Query("select m from MetaDataColumn m " +
"where lower(m.columnName) like lower(concat('%', :searchTerm, '%')) or lower(m.columnLabel) like lower(concat('%', :searchTerm, '%'))")
List<MetaDataColumn> search(@Param("searchTerm") String searchTerm);
}
@@ -0,0 +1,9 @@
package de.thpeetz.kontor.admin.repository;
import de.thpeetz.kontor.admin.data.MetaDataTable;
import org.springframework.data.jpa.repository.JpaRepository;
public interface MetaDataTableRepository extends JpaRepository<MetaDataTable, String> {
MetaDataTable findByTableName(String tableName);
}
@@ -0,0 +1,16 @@
package de.thpeetz.kontor.admin.repository;
import de.thpeetz.kontor.admin.data.ModuleData;
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 ModuleDataRepository extends JpaRepository<ModuleData, String> {
@Query("select m from ModuleData m where lower(m.moduleName) like lower(concat('%', :searchTerm, '%')) ")
List<ModuleData> search(@Param("searchTerm") String searchTerm);
ModuleData findByModuleName(String moduleName);
}
@@ -0,0 +1,19 @@
package de.thpeetz.kontor.admin.repository;
import java.util.List;
import de.thpeetz.kontor.admin.data.Role;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
public interface RoleRepository extends JpaRepository<Role, String> {
@Query("select r from Role r " +
"where lower(r.name) like lower(concat('%', :searchTerm, '%')) ")
List<Role> search(@Param("searchTerm") String searchTerm);
@Query("select r from Role r " +
"where lower(r.name) like lower(:name) ")
Role findByName(@Param("name") String name);
}
@@ -0,0 +1,17 @@
package de.thpeetz.kontor.admin.repository;
import java.util.List;
import de.thpeetz.kontor.admin.data.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
public interface UserRepository extends JpaRepository<User, String> {
@Query("select u from User u " +
"where lower(u.lastName) like lower(concat('%', :searchTerm, '%')) ")
List<User> search(@Param("searchTerm") String searchTerm);
User findByUserName(String userName);
}
@@ -0,0 +1,243 @@
package de.thpeetz.kontor.admin.services;
import org.springframework.stereotype.Service;
import de.thpeetz.kontor.admin.data.MetaDataColumn;
import de.thpeetz.kontor.admin.repository.MetaDataColumnRepository;
import de.thpeetz.kontor.admin.data.MetaDataTable;
import de.thpeetz.kontor.admin.repository.MetaDataTableRepository;
import lombok.extern.slf4j.Slf4j;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicReference;
@Slf4j
@Service
public class MetaDataService {
private final MetaDataTableRepository metaDataTableRepository;
private final MetaDataColumnRepository metaDataColumnRepository;
public MetaDataService(MetaDataTableRepository metaDataTableRepository, MetaDataColumnRepository metaDataColumnRepository) {
this.metaDataTableRepository = metaDataTableRepository;
this.metaDataColumnRepository = metaDataColumnRepository;
}
public List<MetaDataTable> findAllTables() {
return metaDataTableRepository.findAll();
}
public MetaDataTable getTable(String tableName) {
MetaDataTable table = metaDataTableRepository.findByTableName(tableName);
if (table == null) {
log.info("Metadata for table {} not found, will create it", tableName);
table = new MetaDataTable();
table.setTableName(tableName);
metaDataTableRepository.save(table);
}
return table;
}
private void deleteTable(MetaDataTable metaDataTable) {
List<MetaDataColumn> columns = metaDataTable.getTableColumns();
List<MetaDataColumn> columnsToDelete = new LinkedList<>();
for (MetaDataColumn column: columns) {
try {
columnsToDelete.add(column);
metaDataColumnRepository.delete(column);
} catch (Exception e) {
log.info("Exception {} thrown, just go on", e.getMessage());
}
}
for (MetaDataColumn column: columnsToDelete) {
metaDataTable.getTableColumns().remove(column);
}
try {
metaDataTableRepository.delete(metaDataTable);
} catch (Exception e) {
log.info("could not delete MetaDataTable: {}", e.getMessage());
}
}
public void getColumn(MetaDataTable table, String columnName, String columnSyncName, String columnType, String columnModifier, Integer columnOrder, Boolean isShown, String columnLabel, Boolean showFilter, String filterLabel) {
this.getColumn(table, columnName, columnSyncName, columnType, columnModifier, columnOrder, isShown, columnLabel, showFilter, filterLabel, null);
}
public void getColumn(MetaDataTable table, String columnName, String columnSyncName, String columnType, String columnModifier, Integer columnOrder, Boolean isShown, String columnLabel, Boolean showFilter, String filterLabel, String refColumn) {
if (table.getTableColumns().stream().anyMatch(column -> column.getColumnName().equals(columnName))) {
log.debug("Column {} with name {} of table {} found, check Values", columnOrder, columnName, table.getTableName());
MetaDataColumn column = table.getTableColumns().get(columnOrder.intValue()-1);
if (!column.getColumnName().equals(columnName)) {
log.debug("columnName has to be changed to {}", columnName);
column.setColumnName(columnName);
}
if (!column.getColumnSyncName().equals(columnSyncName)) {
log.debug("columnSyncName has to be changed to {}", columnSyncName);
column.setColumnSyncName(columnSyncName);
}
if (!column.getColumnType().equals(columnType)) {
log.debug("columnType has to be changed to {}", columnType);
column.setColumnType(columnType);
}
if (columnModifier != null && !columnModifier.equals(column.getColumnModifier())) {
log.debug("columnModifier has to be changed to {}", columnModifier);
column.setColumnModifier(columnModifier);
}
if (isShown != null && !isShown.equals(column.getIsShown())) {
log.debug("isShown has to be change to {}}", isShown);
column.setIsShown(isShown);
}
if (columnLabel != null && !columnLabel.equals(column.getColumnLabel())) {
log.debug("columnLabel has to be change to {}}", columnLabel);
column.setColumnLabel(columnLabel);
}
if (showFilter != null &&!showFilter.equals(column.getShowFilter())) {
log.debug("showFilter has to be change to {}}", showFilter);
column.setShowFilter(showFilter);
}
if (filterLabel != null && !filterLabel.equals(column.getFilterLabel())) {
log.debug("filterLabel has to be change to {}}", filterLabel);
column.setFilterLabel(filterLabel);
}
if (refColumn != null && !refColumn.equals(column.getRefColumn())) {
log.debug("refColumn has to be change to {}}", filterLabel);
column.setRefColumn(refColumn);
}
metaDataColumnRepository.save(column);
} else {
log.info("Column {} of table {} not found, will create it", columnName, table.getTableName());
MetaDataColumn column = new MetaDataColumn();
column.setTable(table);
column.setColumnName(columnName);
column.setColumnSyncName(columnSyncName);
column.setColumnType(columnType);
column.setColumnModifier(columnModifier);
column.setColumnOrder(columnOrder);
column.setIsShown(Boolean.FALSE);
metaDataColumnRepository.save(column);
}
}
public List<MetaDataColumn> findAllMetaDataColumns(String stringFilter) {
if (stringFilter == null || stringFilter.isEmpty()) {
log.debug("Found " + metaDataColumnRepository.count()+ " entries");
return metaDataColumnRepository.findAll();
} else {
List<MetaDataColumn> results = metaDataColumnRepository.search(stringFilter);
log.debug("Found " + results.size() + " entries");
return results;
}
}
public void deleteMetaDataColumn(MetaDataColumn metaDataColumn) {
if (metaDataColumn == null) {
log.warn("MetaDataColumn is null, can't delete it");
return;
}
log.debug("deleteMetaDataColumn: MetaDataColumn={}", metaDataColumn);
metaDataColumnRepository.delete(metaDataColumn);
}
public void saveMetaDataColumn(MetaDataColumn metaDataColumn) {
if (metaDataColumn == null) {
log.warn("MetaDataColumn is null, can't save it");
return;
}
log.debug("saveMetaDataColumn: MetaDataColumn={}", metaDataColumn);
metaDataColumnRepository.save(metaDataColumn);
}
public String importTableData(Map<String, String> fields) {
AtomicReference<String> status = new AtomicReference<>("unknown");
String id = fields.get("id");
Optional<MetaDataTable> optional = metaDataTableRepository.findById(id);
if (optional.isEmpty()) {
log.info(" not found: {} with {}", id, fields);
status.set(id + "not found");
MetaDataTable checkExisting = metaDataTableRepository.findByTableName(fields.get("table_name"));
if (checkExisting != null) {
log.info("entry already there with different id ({}), will be deleted", checkExisting.getId());
deleteTable(checkExisting);
}
MetaDataTable metaDataTable = new MetaDataTable();
metaDataTable.setId(id);
metaDataTable.setTableName(fields.get("table_name"));
metaDataTableRepository.save(metaDataTable);
} else {
optional.ifPresent( entry -> {
log.info(" found: {}", entry.getTableName());
String updateStatus = updateTableFields(entry, fields);
metaDataTableRepository.save(entry);
status.set(updateStatus);
});
}
return status.get();
}
public String importColumnData(String tableName, Map<String, String> fields) {
AtomicReference<String> status = new AtomicReference<>("unknown");
String id = fields.get("id");
Optional<MetaDataColumn> optional = metaDataColumnRepository.findById(id);
if (optional.isEmpty()) {
log.info(" not found: {} with {}", id, fields);
status.set(id + "not found");
MetaDataColumn metaDataColumn = new MetaDataColumn();
metaDataColumn.setId(id);
metaDataColumn.setColumnName(fields.get("column_name"));
metaDataColumn.setColumnSyncName(fields.get("column_sync_name"));
metaDataColumn.setColumnType(fields.get("column_type"));
metaDataColumnRepository.save(metaDataColumn);
} else {
optional.ifPresent( entry -> {
log.info(" found: {}", entry.getTableName());
String updateStatus = updateColumnFields(entry, tableName, fields);
metaDataColumnRepository.save(entry);
status.set(updateStatus);
});
}
return status.get();
}
private String updateColumnFields(MetaDataColumn metaDataColumn, String tableName, Map<String, String> fields) {
StringBuilder status = new StringBuilder();
for (Map.Entry<String, String> entry : fields.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
switch (key) {
case "id", "created_date", "last_modified_date", "version":
break;
case "column_name":
status.append(metaDataColumn.updateColumnName(value));
break;
case "column_sync_name":
status.append(metaDataColumn.updateColumnSyncName(value));
break;
default:
log.info("field {} is unknown for table {}", key, tableName);
}
}
return status.toString();
}
private String updateTableFields(MetaDataTable metaDataTable, Map<String, String> fields) {
String status = "";
for (Map.Entry<String, String> entry : fields.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
switch (key) {
case "id", "created_date", "last_modified_date", "version":
break;
case "table_name":
status += metaDataTable.updateTableName(value);
default:
log.info("field {} is unknown for table {}", key, MetaDataTable.class.getName());
}
}
return status;
}
}
@@ -0,0 +1,76 @@
package de.thpeetz.kontor.admin.services;
import de.thpeetz.kontor.admin.data.ModuleData;
import de.thpeetz.kontor.admin.repository.ModuleDataRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.List;
@Slf4j
@Service
public class ModuleService {
private final ModuleDataRepository moduleDataRepository;
public ModuleService(ModuleDataRepository moduleDataRepository) {
this.moduleDataRepository = moduleDataRepository;
}
public List<ModuleData> findAll(String stringFilter) {
if (stringFilter == null || stringFilter.isEmpty()) {
return moduleDataRepository.findAll();
} else {
return moduleDataRepository.search(stringFilter);
}
}
public ModuleData findByName(String moduleName) {
if (moduleName == null || moduleName.isEmpty()) {
return null;
} else {
return moduleDataRepository.findByModuleName(moduleName);
}
}
public boolean importData(String moduleName) {
ModuleData module = moduleDataRepository.findByModuleName(moduleName);
if (module != null) {
return module.getImportData();
} else {
log.info("Module {} not found, should import data", moduleName);
return true;
}
}
public void setDataImported(String moduleName) {
ModuleData module = moduleDataRepository.findByModuleName(moduleName);
if (module == null) {
log.info("Module {} not found, will create it", moduleName);
module = new ModuleData();
module.setModuleName(moduleName);
module.setImportData(false);
moduleDataRepository.save(module);
} else {
log.info("Module {} found, change import data", module);
module.setImportData(false);
moduleDataRepository.save(module);
}
}
public void saveModuleData(ModuleData moduleData) {
if (moduleData == null) {
log.warn("ModuleData is null, can't save it.");
} else {
moduleDataRepository.save(moduleData);
}
}
public void deleteModuleData(ModuleData moduleData) {
if (moduleData == null) {
log.warn("ModuleData is null, can't delete it.");
} else {
moduleDataRepository.delete(moduleData);
}
}
}
@@ -0,0 +1,112 @@
package de.thpeetz.kontor.admin.views;
import java.util.List;
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.admin.data.AuthorizationMatrix;
import de.thpeetz.kontor.admin.data.Role;
import de.thpeetz.kontor.admin.data.User;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class AuthorizationForm extends FormLayout {
ComboBox<User> user = new ComboBox<>("User");
ComboBox<Role> role = new ComboBox<>("Role");
Button save = new Button("Save");
Button delete = new Button("Delete");
Button close = new Button("Cancel");
Binder<AuthorizationMatrix> binder = new BeanValidationBinder<>(AuthorizationMatrix.class);
public AuthorizationForm(List<User> users, List<Role> roles) {
addClassName("authorizationmatrix-form");
binder.bindInstanceFields(this);
user.setItems(users);
user.setItemLabelGenerator(User::getUserName);
role.setItems(roles);
role.setItemLabelGenerator(Role::getName);
add(user, role, 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 DeleteEvent(this, binder.getBean())));
close.addClickListener(event -> fireEvent(new CloseEvent(this)));
binder.addStatusChangeListener(e -> save.setEnabled(binder.isValid()));
return new HorizontalLayout(save, delete, close);
}
private void validateAndSave() {
if (binder.isValid()) {
fireEvent(new SaveEvent(this, binder.getBean()));
}
}
public void setAuthorizationMatrix(AuthorizationMatrix authorizationMatrix) {
binder.setBean(authorizationMatrix);
}
public abstract static class AuthorizationFormEvent extends ComponentEvent<AuthorizationForm> {
private AuthorizationMatrix authorizationMatrix;
protected AuthorizationFormEvent(AuthorizationForm source, AuthorizationMatrix authorizationMatrix) {
super(source, false);
this.authorizationMatrix = authorizationMatrix;
}
public AuthorizationMatrix getAuthorizationMatrix() {
return authorizationMatrix;
}
}
public static class SaveEvent extends AuthorizationFormEvent {
SaveEvent(AuthorizationForm source, AuthorizationMatrix authorizationMatrix) {
super(source, authorizationMatrix);
}
}
public static class DeleteEvent extends AuthorizationFormEvent {
DeleteEvent(AuthorizationForm source, AuthorizationMatrix authorizationMatrix) {
super(source, authorizationMatrix);
}
}
public static class CloseEvent extends AuthorizationFormEvent {
CloseEvent(AuthorizationForm source) {
super(source, null);
}
}
public void addDeleteListener(ComponentEventListener<DeleteEvent> listener) {
addListener(DeleteEvent.class, listener);
}
public void addSaveListener(ComponentEventListener<SaveEvent> listener) {
addListener(SaveEvent.class, listener);
}
public void addCloseListener(ComponentEventListener<CloseEvent> listener) {
addListener(CloseEvent.class, listener);
}
}
@@ -0,0 +1,114 @@
package de.thpeetz.kontor.admin.views;
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;
import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.spring.annotation.SpringComponent;
import de.thpeetz.kontor.admin.AdminConstants;
import de.thpeetz.kontor.admin.data.AuthorizationMatrix;
import de.thpeetz.kontor.admin.services.AdminService;
import de.thpeetz.kontor.common.views.MainLayout;
import jakarta.annotation.security.RolesAllowed;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@SpringComponent
@Scope("prototype")
@RolesAllowed("ROLE_ADMIN")
@Route(value = AdminConstants.AUTHORIZATION_ROUTE, layout = MainLayout.class)
@PageTitle("Authorization | Admin | Kontor")
public class AuthorizationView extends VerticalLayout {
Grid<AuthorizationMatrix> grid = new Grid<>(AuthorizationMatrix.class);
AuthorizationForm form;
AdminService service;
public AuthorizationView(AdminService service) {
this.service = service;
addClassName("authoriaztionmatrix-view");
setSizeFull();
configureGrid();
configureForm();
add(getToolbar(), getContent());
updateList();
}
private void configureGrid() {
grid.addClassName("authorizationmatrix-grid");
grid.setSizeFull();
grid.setColumns("user.userName", "role.name");
grid.getColumns().forEach(col -> col.setAutoWidth(true));
grid.asSingleSelect().addValueChangeListener(event -> editAuthorizationMatrix(event.getValue()));
}
private void configureForm() {
form = new AuthorizationForm(service.findAllUsers(), service.findAllRoles());
form.setWidth("25em");
form.addSaveListener(this::saveAuthorizationMatrix);
form.addDeleteListener(this::deleteAuthorizationMatrix);
form.addCloseListener(e -> closeEditor());
}
private void saveAuthorizationMatrix(AuthorizationForm.SaveEvent event) {
AuthorizationMatrix authorizationMatrix = event.getAuthorizationMatrix();
service.saveAuthorizationMatrix(authorizationMatrix);
updateList();
closeEditor();
}
private void deleteAuthorizationMatrix(AuthorizationForm.DeleteEvent event) {
service.deleteAuthorizationMatrix(event.getAuthorizationMatrix());
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 addAuthorizationMaxtrixButton = new Button("Add permssion", click -> addAuthorizationMatrix());
HorizontalLayout toolbar = new HorizontalLayout(addAuthorizationMaxtrixButton);
toolbar.addClassName("toolbar");
return toolbar;
}
public void editAuthorizationMatrix(AuthorizationMatrix authorizationMatrix) {
if (authorizationMatrix == null) {
closeEditor();
} else {
form.setAuthorizationMatrix(authorizationMatrix);
form.setVisible(true);
addClassName("editing");
}
}
public void closeEditor() {
form.setAuthorizationMatrix(null);
form.setVisible(false);
removeClassName("editing");
}
private void addAuthorizationMatrix() {
grid.asSingleSelect().clear();
editAuthorizationMatrix(new AuthorizationMatrix());
}
private void updateList() {
grid.setItems(service.findAllAuthorizationMatrices());
}
}
@@ -0,0 +1,123 @@
package de.thpeetz.kontor.admin.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.checkbox.Checkbox;
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.component.textfield.IntegerField;
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.admin.data.MetaDataColumn;
import de.thpeetz.kontor.admin.data.MetaDataTable;
import java.util.List;
public class MetaDataForm extends FormLayout {
ComboBox<MetaDataTable> table = new ComboBox<>("Table");
TextField columnName = new TextField("Column Name");
TextField columnSyncName = new TextField("Column Sync Name");
TextField columnModifier = new TextField("Column Modifier");
IntegerField columnOrder = new IntegerField("Column Order");
Checkbox isShown = new Checkbox("Is Shown");
TextField columnLabel = new TextField("Column Label");
Checkbox showFilter = new Checkbox("Show Filter");
TextField filterLabel = new TextField("Filter Label");
TextField refColumn = new TextField("Ref Column");
Button save = new com.vaadin.flow.component.button.Button("Save");
Button delete = new com.vaadin.flow.component.button.Button("Delete");
Button close = new Button("Cancel");
Binder<MetaDataColumn> binder = new BeanValidationBinder<>(MetaDataColumn.class);
public MetaDataForm(List<MetaDataTable> tables) {
addClassName("metaData-form");
binder.bindInstanceFields(this);
table.setItems(tables);
table.setItemLabelGenerator(MetaDataTable::getTableName);
add(table, columnName, columnSyncName, columnModifier, columnOrder);
add(isShown, columnLabel);
isShown.addClickListener(click -> columnLabel.setEnabled(isShown.getValue()));
add(showFilter, filterLabel);
showFilter.addClickListener(click -> filterLabel.setEnabled(showFilter.getValue()));
add(refColumn);
add(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 MetaDataForm.DeleteEvent(this, binder.getBean())));
close.addClickListener(event -> fireEvent(new MetaDataForm.CloseEvent(this)));
binder.addStatusChangeListener(e -> save.setEnabled(binder.isValid()));
return new HorizontalLayout(save, delete, close);
}
private void validateAndSave() {
if (binder.isValid()) {
fireEvent(new MetaDataForm.SaveEvent(this, binder.getBean()));
}
}
public void setMetaDataColumn(MetaDataColumn metaDataColumn) {
binder.setBean(metaDataColumn);
}
public abstract static class MetaDataFormEvent extends ComponentEvent<MetaDataForm> {
private MetaDataColumn metaDataColumn;
protected MetaDataFormEvent(MetaDataForm source, MetaDataColumn metaDataColumn) {
super(source, false);
this.metaDataColumn = metaDataColumn;
}
public MetaDataColumn getMetaDataColumn() {
return metaDataColumn;
}
}
public static class SaveEvent extends MetaDataForm.MetaDataFormEvent {
SaveEvent(MetaDataForm source, MetaDataColumn metaDataColumn) {
super(source, metaDataColumn);
}
}
public static class DeleteEvent extends MetaDataForm.MetaDataFormEvent {
DeleteEvent(MetaDataForm source, MetaDataColumn metaDataColumn) {
super(source, metaDataColumn);
}
}
public static class CloseEvent extends MetaDataForm.MetaDataFormEvent {
CloseEvent(MetaDataForm source) {
super(source, null);
}
}
public void addDeleteListener(ComponentEventListener<MetaDataForm.DeleteEvent> listener) {
addListener(MetaDataForm.DeleteEvent.class, listener);
}
public void addSaveListener(ComponentEventListener<MetaDataForm.SaveEvent> listener) {
addListener(MetaDataForm.SaveEvent.class, listener);
}
public void addCloseListener(ComponentEventListener<MetaDataForm.CloseEvent> listener) {
addListener(MetaDataForm.CloseEvent.class, listener);
}
}
@@ -0,0 +1,193 @@
package de.thpeetz.kontor.admin.views;
import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.button.ButtonVariant;
import com.vaadin.flow.component.contextmenu.ContextMenu;
import com.vaadin.flow.component.contextmenu.MenuItem;
import com.vaadin.flow.component.grid.Grid;
import com.vaadin.flow.component.grid.GridSortOrder;
import com.vaadin.flow.component.icon.Icon;
import com.vaadin.flow.component.icon.VaadinIcon;
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.provider.SortDirection;
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.admin.AdminConstants;
import de.thpeetz.kontor.admin.data.MetaDataColumn;
import de.thpeetz.kontor.admin.services.MetaDataService;
import de.thpeetz.kontor.common.views.MainLayout;
import de.thpeetz.kontor.common.views.ColumnToggleContextMenu;
import de.thpeetz.kontor.common.views.StatusIcon;
import jakarta.annotation.security.RolesAllowed;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Scope;
import java.util.ArrayList;
import java.util.List;
@Slf4j
@SpringComponent
@Scope("prototype")
@RolesAllowed("ROLE_ADMIN")
@Route(value = AdminConstants.METADATA_ROUTE, layout = MainLayout.class)
@PageTitle("Meta Data | Admin | Kontor")
public class MetaDataView extends VerticalLayout {
Grid<MetaDataColumn> grid = new Grid<>(MetaDataColumn.class, false);
Grid.Column<MetaDataColumn> idColumn = grid.addColumn(MetaDataColumn::getId)
.setHeader("ID").setResizable(true).setSortable(true);
Grid.Column<MetaDataColumn> createdColumn = grid.addColumn(MetaDataColumn::getCreatedDate)
.setHeader("Erstellt").setResizable(true).setSortable(true);
Grid.Column<MetaDataColumn> modifiedColumn = grid.addColumn(MetaDataColumn::getLastModifiedDate)
.setHeader("Geändert").setResizable(true).setSortable(true);
Grid.Column<MetaDataColumn> versionColumn = grid.addColumn(MetaDataColumn::getVersion)
.setHeader("Version").setResizable(true).setSortable(true);
Grid.Column<MetaDataColumn> tableColumn = grid.addColumn(MetaDataColumn::getTableName)
.setHeader("Table").setResizable(true).setSortable(true);
Grid.Column<MetaDataColumn> columnNameColumn = grid.addColumn(MetaDataColumn::getColumnName)
.setHeader("Column Name").setResizable(true).setSortable(true);
Grid.Column<MetaDataColumn> columnSyncNameColumn = grid.addColumn(MetaDataColumn::getColumnSyncName)
.setHeader("Column Sync Name").setResizable(true).setSortable(true);
Grid.Column<MetaDataColumn> columnTypeColumn = grid.addColumn(MetaDataColumn::getColumnType)
.setHeader("Column Type").setResizable(true).setSortable(true);
Grid.Column<MetaDataColumn> columnModifierColumn = grid.addColumn(MetaDataColumn::getColumnModifier)
.setHeader("Column Modifier").setResizable(true).setSortable(true);
Grid.Column<MetaDataColumn> columnOrderColumn = grid.addColumn(MetaDataColumn::getColumnOrder)
.setHeader("Column Order").setResizable(true).setSortable(true);
Grid.Column<MetaDataColumn> isShownColumn = grid.addComponentColumn(metaDataColumn -> StatusIcon.create(metaDataColumn.getIsShown())).
setHeader("Anzeige?").setWidth("6rem").setSortable(true);
Grid.Column<MetaDataColumn> columnLabelColumn = grid.addColumn(MetaDataColumn::getColumnLabel)
.setHeader("Spaltenname").setResizable(true).setSortable(true);
Grid.Column<MetaDataColumn> showFilterColumn = grid.addComponentColumn(metaDataColumn -> StatusIcon.create(metaDataColumn.getShowFilter())).
setHeader("Zeige Filter").setWidth("6rem").setSortable(true);
Grid.Column<MetaDataColumn> filterLabelColumn = grid.addColumn(MetaDataColumn::getFilterLabel)
.setHeader("Filter Name").setResizable(true).setSortable(true);
Grid.Column<MetaDataColumn> refColumnColumn = grid.addColumn(MetaDataColumn::getRefColumn)
.setHeader("Ref Column Name").setResizable(true).setSortable(true);
TextField searchField = new TextField();
@Getter
MetaDataForm form;
MetaDataService service;
public MetaDataView(MetaDataService service) {
this.service = service;
addClassName("metadata-view");
setSizeFull();
configureGrid();
configureForm();
add(getToolbar(), getContent());
updateList();
}
private void configureGrid() {
grid.addClassName("metadata-grid");
grid.setSizeFull();
grid.getColumns().forEach(col -> col.setAutoWidth(true));
idColumn.setVisible(false);
createdColumn.setVisible(false);
modifiedColumn.setVisible(false);
versionColumn.setVisible(false);
grid.setMultiSort(true);
List<GridSortOrder<MetaDataColumn>> sortOrder = new ArrayList<>();
sortOrder.add(new GridSortOrder<MetaDataColumn>(tableColumn, SortDirection.ASCENDING));
sortOrder.add(new GridSortOrder<MetaDataColumn>(columnOrderColumn, SortDirection.ASCENDING));
grid.sort(sortOrder);
grid.asSingleSelect().addValueChangeListener(event -> editMetaData(event.getValue()));
}
private void configureForm() {
form = new MetaDataForm(service.findAllTables());
form.setWidth("25em");
form.setVisible(false);
form.addSaveListener(this::saveMetaData);
form.addDeleteListener(this::deleteMetaData);
form.addCloseListener(e -> 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() {
searchField.setPlaceholder("Search");
searchField.setClearButtonVisible(true);
searchField.setPrefixComponent(new Icon(VaadinIcon.SEARCH));
searchField.setValueChangeMode(ValueChangeMode.EAGER);
searchField.addValueChangeListener(e -> updateList());
Button addMetaDataButton = new Button("Add Meta Data");
addMetaDataButton.addClickListener(click -> addMetaDataColumn());
Button menuButton = new Button("Show/Hide Columns");
menuButton.addThemeVariants(ButtonVariant.LUMO_TERTIARY);
ColumnToggleContextMenu<MetaDataColumn> columnToggleContextMenu = new ColumnToggleContextMenu<>(menuButton);
columnToggleContextMenu.addColumnToggleItem(idColumn);
columnToggleContextMenu.addColumnToggleItem(createdColumn);
columnToggleContextMenu.addColumnToggleItem(modifiedColumn);
columnToggleContextMenu.addColumnToggleItem(versionColumn);
columnToggleContextMenu.addColumnToggleItem(tableColumn);
columnToggleContextMenu.addColumnToggleItem(columnNameColumn);
columnToggleContextMenu.addColumnToggleItem(columnSyncNameColumn);
columnToggleContextMenu.addColumnToggleItem(columnTypeColumn);
columnToggleContextMenu.addColumnToggleItem(columnModifierColumn);
columnToggleContextMenu.addColumnToggleItem(columnOrderColumn);
columnToggleContextMenu.addColumnToggleItem(isShownColumn);
columnToggleContextMenu.addColumnToggleItem(columnLabelColumn);
columnToggleContextMenu.addColumnToggleItem(showFilterColumn);
columnToggleContextMenu.addColumnToggleItem(filterLabelColumn);
columnToggleContextMenu.addColumnToggleItem(refColumnColumn);
HorizontalLayout toolbar = new HorizontalLayout(searchField, addMetaDataButton, menuButton);
toolbar.addClassName("toolbar");
return toolbar;
}
private void saveMetaData(MetaDataForm.SaveEvent event) {
MetaDataColumn metaDataColumn = event.getMetaDataColumn();
service.saveMetaDataColumn(metaDataColumn);
updateList();
closeEditor();
}
private void deleteMetaData(MetaDataForm.DeleteEvent event) {
service.deleteMetaDataColumn(event.getMetaDataColumn());
updateList();
closeEditor();
}
public void editMetaData(MetaDataColumn metaDataColumn) {
if (metaDataColumn == null) {
closeEditor();
} else {
form.setMetaDataColumn(metaDataColumn);
form.setVisible(true);
addClassName("editing");
}
}
public void closeEditor() {
form.setMetaDataColumn(null);
form.setVisible(false);
removeClassName("editing");
}
private void addMetaDataColumn() {
grid.asSingleSelect().clear();
editMetaData(new MetaDataColumn());
}
private void updateList() {
grid.setItems(service.findAllMetaDataColumns(searchField.getValue()));
}
}
@@ -0,0 +1,100 @@
package de.thpeetz.kontor.admin.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.checkbox.Checkbox;
import com.vaadin.flow.component.formlayout.FormLayout;
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.admin.data.ModuleData;
public class ModuleDataForm extends FormLayout {
TextField moduleName = new TextField("Module Name");
Checkbox importData = new Checkbox("Import Data");
Button save = new com.vaadin.flow.component.button.Button("Save");
Button delete = new com.vaadin.flow.component.button.Button("Delete");
Button close = new Button("Cancel");
Binder<ModuleData> binder = new BeanValidationBinder<>(ModuleData.class);
public ModuleDataForm() {
addClassName("moduleData-form");
binder.bindInstanceFields(this);
add(moduleName, importData, 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 ModuleDataForm.DeleteEvent(this, binder.getBean())));
close.addClickListener(event -> fireEvent(new ModuleDataForm.CloseEvent(this)));
binder.addStatusChangeListener(e -> save.setEnabled(binder.isValid()));
return new HorizontalLayout(save, delete, close);
}
private void validateAndSave() {
if (binder.isValid()) {
fireEvent(new ModuleDataForm.SaveEvent(this, binder.getBean()));
}
}
public void setModuleData(ModuleData moduleData) {
binder.setBean(moduleData);
}
public abstract static class ModuleDataFormEvent extends ComponentEvent<ModuleDataForm> {
private ModuleData moduleData;
protected ModuleDataFormEvent(ModuleDataForm source, ModuleData moduleData) {
super(source, false);
this.moduleData = moduleData;
}
public ModuleData getModuleData() {
return moduleData;
}
}
public static class SaveEvent extends ModuleDataForm.ModuleDataFormEvent {
SaveEvent(ModuleDataForm source, ModuleData moduleData) {
super(source, moduleData);
}
}
public static class DeleteEvent extends ModuleDataForm.ModuleDataFormEvent {
DeleteEvent(ModuleDataForm source, ModuleData moduleData) {
super(source, moduleData);
}
}
public static class CloseEvent extends ModuleDataForm.ModuleDataFormEvent {
CloseEvent(ModuleDataForm source) {
super(source, null);
}
}
public void addDeleteListener(ComponentEventListener<ModuleDataForm.DeleteEvent> listener) {
addListener(ModuleDataForm.DeleteEvent.class, listener);
}
public void addSaveListener(ComponentEventListener<ModuleDataForm.SaveEvent> listener) {
addListener(ModuleDataForm.SaveEvent.class, listener);
}
public void addCloseListener(ComponentEventListener<ModuleDataForm.CloseEvent> listener) {
addListener(ModuleDataForm.CloseEvent.class, listener);
}
}
@@ -0,0 +1,140 @@
package de.thpeetz.kontor.admin.views;
import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.button.ButtonVariant;
import com.vaadin.flow.component.contextmenu.ContextMenu;
import com.vaadin.flow.component.contextmenu.MenuItem;
import com.vaadin.flow.component.grid.Grid;
import com.vaadin.flow.component.icon.Icon;
import com.vaadin.flow.component.icon.VaadinIcon;
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.admin.data.ModuleData;
import de.thpeetz.kontor.admin.services.ModuleService;
import de.thpeetz.kontor.common.views.MainLayout;
import de.thpeetz.kontor.common.views.ColumnToggleContextMenu;
import de.thpeetz.kontor.common.views.StatusIcon;
import jakarta.annotation.security.RolesAllowed;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Scope;
@Slf4j
@SpringComponent
@Scope("prototype")
@RolesAllowed("ROLE_ADMIN")
@Route(value = "admin/module", layout = MainLayout.class)
@PageTitle("Module Data | Admin | Kontor")
public class ModuleDataView extends VerticalLayout {
Grid<ModuleData> grid = new Grid<>(ModuleData.class, false);
Grid.Column<ModuleData> idColumn = grid.addColumn(ModuleData::getId)
.setHeader("ID").setResizable(true).setSortable(true);
Grid.Column<ModuleData> nameColumn = grid.addColumn(ModuleData::getModuleName)
.setHeader("Name").setResizable(true).setSortable(true);
Grid.Column<ModuleData> importColumn = grid.addComponentColumn(moduleData -> StatusIcon.create(moduleData.getImportData()))
.setHeader("Import Data").setWidth("6rem").setSortable(true);
TextField filterText = new TextField();
@Getter
ModuleDataForm form;
ModuleService service;
public ModuleDataView(ModuleService service) {
this.service = service;
addClassName("moduleData-view");
setSizeFull();
configureGrid();
configureForm();
add(getToolbar(), getContent());
updateList();
}
private void configureGrid() {
grid.addClassName("moduleData-grid");
grid.setSizeFull();
grid.getColumns().forEach(col -> col.setAutoWidth(true));
grid.asSingleSelect().addValueChangeListener(event -> editModuleData(event.getValue()));
}
private void configureForm() {
form = new ModuleDataForm();
form.setWidth("25em");
form.setVisible(false);
form.addSaveListener(this::saveModuleData);
form.addDeleteListener(this::deleteModuleData);
form.addCloseListener(e -> closeEditor());
}
private void saveModuleData(ModuleDataForm.SaveEvent event) {
ModuleData moduleData = event.getModuleData();
service.saveModuleData(moduleData);
updateList();
closeEditor();
}
private void deleteModuleData(ModuleDataForm.DeleteEvent event) {
service.deleteModuleData(event.getModuleData());
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 module name...");
filterText.setClearButtonVisible(true);
filterText.setValueChangeMode(ValueChangeMode.LAZY);
filterText.addValueChangeListener(e -> updateList());
Button addModuleDataButton = new Button("Add module", click -> addModuleData());
Button menuButton = new Button("Show/Hide Columns");
menuButton.addThemeVariants(ButtonVariant.LUMO_TERTIARY);
ColumnToggleContextMenu<ModuleData> columnToggleContextMenu = new ColumnToggleContextMenu<>(menuButton);
columnToggleContextMenu.addColumnToggleItem(idColumn);
columnToggleContextMenu.addColumnToggleItem(nameColumn);
columnToggleContextMenu.addColumnToggleItem(importColumn);
HorizontalLayout toolbar = new HorizontalLayout(filterText, addModuleDataButton, menuButton);
toolbar.addClassName("toolbar");
return toolbar;
}
public void editModuleData(ModuleData moduleData) {
if (moduleData == null) {
closeEditor();
} else {
form.setModuleData(moduleData);
form.setVisible(true);
addClassName("editing");
}
}
public void closeEditor() {
form.setModuleData(null);
form.setVisible(false);
removeClassName("editing");
}
private void addModuleData() {
grid.asSingleSelect().clear();
editModuleData(new ModuleData());
}
private void updateList() {
grid.setItems(service.findAll(filterText.getValue()));
}
}
@@ -0,0 +1,102 @@
package de.thpeetz.kontor.admin.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.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.admin.data.Role;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class RoleForm extends FormLayout {
TextField name = new TextField("Role name");
Button save = new Button("Save");
Button delete = new Button("Delete");
Button close = new Button("Cancel");
Binder<Role> binder = new BeanValidationBinder<>(Role.class);
public RoleForm() {
addClassName("role-form");
binder.bindInstanceFields(this);
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 DeleteEvent(this, binder.getBean())));
close.addClickListener(event -> fireEvent(new CloseEvent(this)));
binder.addStatusChangeListener(e -> save.setEnabled(binder.isValid()));
return new HorizontalLayout(save, delete, close);
}
private void validateAndSave() {
if (binder.isValid()) {
fireEvent(new SaveEvent(this, binder.getBean()));
}
}
public void setRole(Role role) {
binder.setBean(role);
}
public abstract static class RoleFormEvent extends ComponentEvent<RoleForm> {
private Role role;
protected RoleFormEvent(RoleForm source, Role role) {
super(source, false);
this.role = role;
}
public Role getRole() {
return role;
}
}
public static class SaveEvent extends RoleFormEvent {
SaveEvent(RoleForm source, Role role) {
super(source, role);
}
}
public static class DeleteEvent extends RoleFormEvent {
DeleteEvent(RoleForm source, Role role) {
super(source, role);
}
}
public static class CloseEvent extends RoleFormEvent {
CloseEvent(RoleForm source) {
super(source, null);
}
}
public void addDeleteListener(ComponentEventListener<DeleteEvent> listener) {
addListener(DeleteEvent.class, listener);
}
public void addSaveListener(ComponentEventListener<SaveEvent> listener) {
addListener(SaveEvent.class, listener);
}
public void addCloseListener(ComponentEventListener<CloseEvent> listener) {
addListener(CloseEvent.class, listener);
}
}
@@ -0,0 +1,118 @@
package de.thpeetz.kontor.admin.views;
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;
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.admin.AdminConstants;
import de.thpeetz.kontor.admin.data.Role;
import de.thpeetz.kontor.admin.services.AdminService;
import de.thpeetz.kontor.common.views.MainLayout;
import jakarta.annotation.security.RolesAllowed;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@SpringComponent
@Scope("prototype")
@RolesAllowed("ROLE_ADMIN")
@Route(value = AdminConstants.ROLE_ROUTE, layout = MainLayout.class)
@PageTitle("Rollen | Admin | Kontor")
public class RoleView extends VerticalLayout {
Grid<Role> grid = new Grid<>(Role.class);
TextField filterText = new TextField();
RoleForm form;
AdminService service;
public RoleView(AdminService service) {
this.service = service;
addClassName("user-view");
setSizeFull();
configureGrid();
configureForm();
add(getToolbar(), getContent());
updateList();
}
private void configureGrid() {
grid.addClassName("user-grid");
grid.setSizeFull();
grid.setColumns("name");
grid.getColumns().forEach(col -> col.setAutoWidth(true));
grid.asSingleSelect().addValueChangeListener(event -> editRole(event.getValue()));
}
private void configureForm() {
form = new RoleForm();
form.setWidth("25em");
form.addSaveListener(this::saveRole);
form.addDeleteListener(this::deleteRole);
form.addCloseListener(e -> closeEditor());
}
private void saveRole(RoleForm.SaveEvent event) {
service.saveRole(event.getRole());
updateList();
closeEditor();
}
private void deleteRole(RoleForm.DeleteEvent event) {
service.deleteRole(event.getRole());
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 user name...");
filterText.setClearButtonVisible(true);
filterText.setValueChangeMode(ValueChangeMode.LAZY);
filterText.addValueChangeListener(e -> updateList());
Button addUserButton = new Button("Add user", click -> addUser());
HorizontalLayout toolbar = new HorizontalLayout(filterText, addUserButton);
toolbar.addClassName("toolbar");
return toolbar;
}
public void editRole(Role role) {
if (role == null) {
closeEditor();
} else {
form.setRole(role);
form.setVisible(true);
addClassName("editing");
}
}
public void closeEditor() {
form.setRole(null);
form.setVisible(false);
removeClassName("editing");
}
private void addUser() {
grid.asSingleSelect().clear();
editRole(new Role());
}
private void updateList() {
grid.setItems(service.findAllRoles(filterText.getValue()));
}
}
@@ -0,0 +1,143 @@
package de.thpeetz.kontor.admin.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.checkbox.Checkbox;
import com.vaadin.flow.component.checkbox.CheckboxGroup;
import com.vaadin.flow.component.checkbox.CheckboxGroupVariant;
import com.vaadin.flow.component.formlayout.FormLayout;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.textfield.EmailField;
import com.vaadin.flow.component.textfield.PasswordField;
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.admin.data.Role;
import de.thpeetz.kontor.admin.data.User;
import lombok.extern.slf4j.Slf4j;
import java.util.List;
@Slf4j
public class UserForm extends FormLayout {
TextField userName = new TextField("User name");
PasswordField password = new PasswordField("Password");
EmailField email = new EmailField("Email");
TextField firstName = new TextField("First name");
TextField lastName = new TextField("Last name");
Checkbox enabled = new Checkbox("Enabled");
String originalPassword;
CheckboxGroup<Role> permissions = new CheckboxGroup<>("Permissions");
Button save = new Button("Save");
Button delete = new Button("Delete");
Button close = new Button("Cancel");
Binder<User> binder = new BeanValidationBinder<>(User.class);
public UserForm() {
addClassName("user-form");
binder.bindInstanceFields(this);
add(userName, password, email, firstName, lastName, enabled, configurePermissionsGroup(), createButtonsLayout());
}
private CheckboxGroup<Role> configurePermissionsGroup() {
permissions.addThemeVariants(CheckboxGroupVariant.LUMO_VERTICAL);
permissions.setItemLabelGenerator(Role::getName);
permissions.addValueChangeListener(event -> {
log.debug("permissions changed: {}", event);
});
return permissions;
}
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 DeleteEvent(this, binder.getBean())));
close.addClickListener(event -> fireEvent(new CloseEvent(this)));
binder.addStatusChangeListener(e -> save.setEnabled(binder.isValid()));
return new HorizontalLayout(save, delete, close);
}
private void validateAndSave() {
if (binder.isValid()) {
fireEvent(new SaveEvent(this, binder.getBean()));
}
}
public void setUser(User user) {
binder.setBean(user);
//log.debug("UserForm.setUser: {}", user);
if (user != null) {
this.originalPassword = user.getPassword();
} else {
this.originalPassword = null;
}
}
public void setRoles(List<Role> roles, User user) {
permissions.setItems(roles);
user.getMatrix().stream().forEach(authorizationMatrix -> {
permissions.select(authorizationMatrix.getRole());
});
}
public boolean hasPasswordChanged(User user) {
return !originalPassword.equals(user.getPassword());
}
public abstract static class UserFormEvent extends ComponentEvent<UserForm> {
private User user;
protected UserFormEvent(UserForm source, User user) {
super(source, false);
this.user = user;
}
public User getUser() {
return user;
}
}
public static class SaveEvent extends UserFormEvent {
SaveEvent(UserForm source, User user) {
super(source, user);
}
}
public static class DeleteEvent extends UserFormEvent {
DeleteEvent(UserForm source, User user) {
super(source, user);
}
}
public static class CloseEvent extends UserFormEvent {
CloseEvent(UserForm source) {
super(source, null);
}
}
public void addDeleteListener(ComponentEventListener<DeleteEvent> listener) {
addListener(DeleteEvent.class, listener);
}
public void addSaveListener(ComponentEventListener<SaveEvent> listener) {
addListener(SaveEvent.class, listener);
}
public void addCloseListener(ComponentEventListener<CloseEvent> listener) {
addListener(CloseEvent.class, listener);
}
}
@@ -0,0 +1,135 @@
package de.thpeetz.kontor.admin.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.admin.data.Role;
import de.thpeetz.kontor.admin.data.User;
import de.thpeetz.kontor.admin.services.KontorUserDetailsService;
import de.thpeetz.kontor.common.views.MainLayout;
import jakarta.annotation.security.RolesAllowed;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.security.crypto.password.PasswordEncoder;
import java.util.List;
import java.util.stream.Collectors;
@Slf4j
@SpringComponent
@Scope("prototype")
@RolesAllowed("ROLE_ADMIN")
@Route(value = "admin/user", layout = MainLayout.class)
@PageTitle("User | Admin | Kontor")
public class UserView extends VerticalLayout {
Grid<User> grid = new Grid<>(User.class);
TextField filterText = new TextField();
UserForm form;
KontorUserDetailsService service;
@Autowired
PasswordEncoder passwordEncoder;
public UserView(KontorUserDetailsService service) {
this.service = service;
addClassName("user-view");
setSizeFull();
configureGrid();
configureForm();
add(getToolbar(), getContent());
updateList();
}
private void configureGrid() {
grid.addClassName("user-grid");
grid.setSizeFull();
grid.setColumns("userName", "email", "firstName", "lastName", "enabled");
grid.getColumns().forEach(col -> col.setAutoWidth(true));
grid.asSingleSelect().addValueChangeListener(event -> editUser(event.getValue()));
}
private void configureForm() {
form = new UserForm();
form.setWidth("25em");
form.setVisible(false);
form.addSaveListener(this::saveUser);
form.addDeleteListener(this::deleteUser);
form.addCloseListener(e -> closeEditor());
}
private void saveUser(UserForm.SaveEvent event) {
User user = event.getUser();
log.debug("UserView.saveUser: {}", user);
List<Role> permissions = form.permissions.getSelectedItems().stream().collect(Collectors.toList());
log.info("selected permissions: {}", permissions);
if (form.hasPasswordChanged(user)) {
user.setPassword(passwordEncoder.encode(user.getPassword()));
log.debug("password changed for user {}", user);
}
service.saveUser(user, permissions);
updateList();
closeEditor();
}
private void deleteUser(UserForm.DeleteEvent event) {
service.deleteUser(event.getUser());
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 user name...");
filterText.setClearButtonVisible(true);
filterText.setValueChangeMode(ValueChangeMode.LAZY);
filterText.addValueChangeListener(e -> updateList());
Button addUserButton = new Button("Add user", click -> addUser());
HorizontalLayout toolbar = new HorizontalLayout(filterText, addUserButton);
toolbar.addClassName("toolbar");
return toolbar;
}
public void editUser(User user) {
if (user == null) {
closeEditor();
} else {
form.setUser(user);
form.setRoles(service.findAllRoles(), user);
form.setVisible(true);
addClassName("editing");
}
}
public void closeEditor() {
form.setUser(null);
form.setVisible(false);
removeClassName("editing");
}
private void addUser() {
grid.asSingleSelect().clear();
editUser(new User());
}
private void updateList() {
grid.setItems(service.findAllUsers(filterText.getValue()));
}
}
@@ -0,0 +1,17 @@
package de.thpeetz.kontor.comics.data;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
public interface ArtistRepository extends JpaRepository<Artist, String> {
@Query("select a from Artist a " +
"where lower(a.name) like lower(concat('%', :searchTerm, '%')) ")
List<Artist> search(@Param("searchTerm") String searchTerm);
List<Artist> findByNameIgnoreCase(String name);
Artist findByName(String name);
}
@@ -0,0 +1,19 @@
package de.thpeetz.kontor.comics.data;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
public interface ComicRepository extends JpaRepository<Comic, String> {
@Query("select c from Comic c " +
"where lower(c.title) like lower(concat('%', :searchTerm, '%')) ")
List<Comic> search(@Param("searchTerm") String searchTerm);
Comic findByTitleAndPublisher(String title, Publisher publisher);
List<Comic> findByTitle(String title);
List<Comic> findByTitleIgnoreCase(String title);
}
@@ -0,0 +1,15 @@
package de.thpeetz.kontor.comics.data;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
public interface ComicWorkRepository extends JpaRepository<ComicWork, String> {
@Query("SELECT c from ComicWork c where c.comic = ?1 and c.artist = ?2 and c.workType = ?3")
ComicWork findbyComicAndArtistAndWorktype(Comic comic, Artist artist, Worktype worktype);
@Query("select c from ComicWork c where c.comic = ?1")
List<ComicWork> findByComic(Comic comic);
}
@@ -0,0 +1,17 @@
package de.thpeetz.kontor.comics.data;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
public interface IssueRepository extends JpaRepository<Issue, String> {
@Query("select i from Issue i " +
"where lower(i.issueNumber) like lower(concat('%', :searchTerm, '%')) ")
List<Issue> search(@Param("searchTerm") String searchTerm);
List<Issue> findByComic(Comic comic);
Issue findByComicAndIssueNumber(Comic comic, String issueNumber);
}
@@ -0,0 +1,17 @@
package de.thpeetz.kontor.comics.data;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
public interface PublisherRepository extends JpaRepository<Publisher, String> {
@Query("select p from Publisher p " +
"where lower(p.name) like lower(concat('%', :searchTerm, '%')) ")
List<Publisher> search(@Param("searchTerm") String searchTerm);
Publisher findByName(String name);
List<Publisher> findByNameIgnoreCase(String name);
}
@@ -0,0 +1,17 @@
package de.thpeetz.kontor.comics.data;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
public interface StoryArcRepository extends JpaRepository<StoryArc, String> {
@Query("select s from StoryArc s " +
"where lower(s.name) like lower(concat('%', :searchTerm, '%')) ")
List<StoryArc> search(@Param("searchTerm") String searchTerm);
StoryArc findByNameAndComic(String name, Comic comic);
List<StoryArc> findByComic(Comic comic);
}
@@ -0,0 +1,20 @@
package de.thpeetz.kontor.comics.data;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
public interface TradePaperbackRepository extends JpaRepository<TradePaperback, String> {
@Query("select t from TradePaperback t " +
"where lower(t.name) like lower(concat('%', :searchTerm, '%')) ")
List<TradePaperback> search(@Param("searchTerm") String searchTerm);
List<TradePaperback> findByComic(Comic comic);
List<TradePaperback> findByNameAndComic(String name, Comic comic);
@Query("select t from TradePaperback t where t.name = ?1 and t.comic = ?2 and t.issueStart = ?3 and t.issueEnd = ?4")
TradePaperback findByFields(String name, Comic comic, int start, int end);
}
@@ -0,0 +1,13 @@
package de.thpeetz.kontor.comics.data;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
public interface VolumeRepository extends JpaRepository<Volume, String> {
List<Volume> findByName(String name);
List<Volume> findByComic(Comic comic);
}
@@ -0,0 +1,18 @@
package de.thpeetz.kontor.comics.data;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
public interface WorktypeRepository extends JpaRepository<Worktype, String> {
@Query("select w from Worktype w " +
"where lower(w.name) like lower(concat('%', :searchTerm, '%')) ")
List<Worktype> search(@Param("searchTerm") String searchTerm);
Worktype findByName(String name);
List<Worktype> findByNameIgnoreCase(String name);
}
@@ -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);
}
@@ -0,0 +1,13 @@
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 MediaArticleRepository extends JpaRepository<MediaArticle, String> {
@Query("select m from MediaArticle m " +
"where lower(m.url) like lower(concat('%', :searchTerm, '%')) or lower(m.title) like lower(concat('%', :searchTerm, '%'))")
List<MediaArticle> search(@Param("searchTerm") String searchTerm);
}
@@ -0,0 +1,14 @@
package de.thpeetz.kontor.media.data;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
public interface MediaFileRepository extends JpaRepository<MediaFile, String> {
@Query("select m from MediaFile m " +
"where lower(m.url) like lower(concat('%', :searchTerm, '%')) or lower(m.title) like lower(concat('%', :searchTerm, '%'))")
List<MediaFile> search(@Param("searchTerm") String searchTerm);
}
@@ -0,0 +1,15 @@
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 MediaVideoRepository extends JpaRepository<MediaVideo, String> {
@Query("select m from MediaVideo m " +
"where lower(m.url) like lower(concat('%', :searchTerm, '%')) or lower(m.title) like lower(concat('%', :searchTerm, '%'))")
List<MediaVideo> search(@Param("searchTerm") String searchTerm);
}
@@ -0,0 +1,73 @@
package de.thpeetz.kontor.comics.data;
import static org.junit.jupiter.api.Assertions.*;
import java.util.List;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.MethodOrderer.OrderAnnotation;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
@TestMethodOrder(OrderAnnotation.class)
class ArtistRepositoryTest {
private Artist stanLee;
private static final String ARTISTNAME = "Lee, Stan";
@Autowired
ArtistRepository artistRepository;
@BeforeEach
void setupData() {
stanLee = new Artist();
stanLee.setName(ARTISTNAME);
}
@Test
@Order(1)
void checkInitialLoad() {
int count = artistRepository.findAll().size();
assertEquals(5, count);
}
@Test
@Order(2)
void saveArtist() {
int count = artistRepository.findAll().size();
artistRepository.save(stanLee);
assertEquals(count+1, artistRepository.findAll().size());
}
@Test
@Order(3)
void findArtist() {
List<Artist> artists = artistRepository.findByNameIgnoreCase("lEE, sTAN");
assertTrue(artists.size() > 0);
assertEquals(artists.get(0).getName(), stanLee.getName());
}
@Test
@Order(4)
void searchArtist() {
List<Artist> artists = artistRepository.search("Lee");
assertEquals(1, artists.size());
assertEquals(ARTISTNAME, artists.get(0).getName());
List<Artist> artists2 = artistRepository.search("Stan");
assertEquals(1, artists2.size());
assertEquals(ARTISTNAME, artists2.get(0).getName());
}
@Test
@Order(5)
void deleteArtist() {
int count = artistRepository.findAll().size();
Artist artist = artistRepository.findByName(ARTISTNAME);
artistRepository.delete(artist);
assertEquals(count-1, artistRepository.findAll().size());
}
}
@@ -0,0 +1,53 @@
package de.thpeetz.kontor.comics.data;
import static org.junit.jupiter.api.Assertions.*;
import java.util.List;
import java.util.stream.Collectors;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class ComicRepositoryTest {
@Autowired
private ComicRepository comicRepository;
@Autowired
private PublisherRepository publisherRepository;
@Test
void testFindByTitle() {
List<Comic> comics = comicRepository.findByTitle("Emma Frost");
assertEquals(1, comics.size());
assertEquals("Emma Frost", comics.get(0).getTitle());
Publisher publisher = comics.get(0).getPublisher();
assertEquals("Marvel", publisher.getName());
}
@Test
void testFindByTitleIgnoreCase() {
List<Comic> comics = comicRepository.findByTitleIgnoreCase("x-men");
assertEquals(1, comics.size());
assertEquals("X-Men", comics.get(0).getTitle());
}
@Test
void testFindByTitleAndPublisher() {
Publisher publisher = publisherRepository.findByName("Marvel");
assertNotNull(publisher);
Comic found = comicRepository.findByTitleAndPublisher("Emma Frost", publisher);
assertNotNull(found);
assertEquals("Emma Frost", found.getTitle());
assertEquals("Marvel", found.getPublisher().getName());
}
@Test
void testSearch() {
List<Comic> comics = comicRepository.search("X-men");
assertEquals(11, comics.size());
assertTrue(comics.stream().map(comic -> comic.getTitle()).collect(Collectors.toList()).contains("Astonishing X-Men"));
}
}
@@ -0,0 +1,83 @@
package de.thpeetz.kontor.comics.data;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.MethodOrderer.OrderAnnotation;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import de.thpeetz.kontor.comics.services.ComicService;
@SpringBootTest
@TestMethodOrder(OrderAnnotation.class)
class ComicWorkRepositoryTest {
@Autowired
private ComicWorkRepository comicWorkRepository;
@Autowired
private ComicRepository comicRepository;
@Autowired
private WorktypeRepository worktypeRepository;
@Autowired
private ArtistRepository artistRepository;
@Autowired
private ComicService comicService;
@Test
@Order(1)
void checkInitialLoad() {
int count = comicWorkRepository.findAll().size();
assertEquals(18, count);
}
@Test
@Order(2)
void saveComicWork() {
int count = comicWorkRepository.findAll().size();
Artist artist = artistRepository.findByName("Turner, Michael");
Worktype worktype = worktypeRepository.findByName("Writer");
Comic comic = comicRepository.findByTitle("Emma Frost").get(0);
ComicWork comicWork = new ComicWork();
comicWork.setArtist(artist);
comicWork.setComic(comic);
comicWork.setWorkType(worktype);
comicWorkRepository.save(comicWork);
assertEquals(count + 1, comicWorkRepository.findAll().size());
}
@Test
@Order(3)
void findByComicAndArtistAndComicWork() {
assertEquals(19, comicWorkRepository.count());
Artist artist = artistRepository.findByName("Turner, Michael");
Worktype worktype = worktypeRepository.findByName("Writer");
Comic comic = comicRepository.findByTitle("Emma Frost").get(0);
ComicWork comicWork = comicWorkRepository.findbyComicAndArtistAndWorktype(comic, artist, worktype);
assertNotNull(comicWork);
assertEquals(comicWork.getArtist().getName(), artist.getName());
assertEquals(comicWork.getComic().getTitle(), comic.getTitle());
assertEquals(comicWork.getWorkType().getName(), worktype.getName());
ComicWork notFound = comicWorkRepository.findbyComicAndArtistAndWorktype(comic, artist, null);
assertNull(notFound);
}
@Test
@Order(4)
void deleteComicWork() {
long count = comicWorkRepository.count();
Artist artist = artistRepository.findByName("Turner, Michael");
Worktype worktype = worktypeRepository.findByName("Writer");
Comic comic = comicRepository.findByTitle("Emma Frost").get(0);
ComicWork comicWork = comicWorkRepository.findbyComicAndArtistAndWorktype(comic, artist, worktype);
assertNotNull(comicWork);
comicService.deleteComicWork(comicWork);
assertEquals(count - 1, comicWorkRepository.count());
}
}
@@ -0,0 +1,45 @@
package de.thpeetz.kontor.comics.data;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import java.util.List;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import de.thpeetz.kontor.comics.TestConstants;
import de.thpeetz.kontor.comics.services.ComicService;
@SpringBootTest
class IssueRepositoryTest {
@Autowired
private IssueRepository issueRepository;
@Autowired
private ComicService comicService;
@Test
void testFindByComic() {
Comic comic = TestConstants.getComicWithIssues(comicService);
List<Issue> issues = issueRepository.findByComic(comic);
assertEquals(TestConstants.BATTLE_POPE_ISSUE_COUNT, issues.size());
}
@Test
void testFindByComicAndIssueNumber() {
Comic comic = TestConstants.getComicWithIssues(comicService);
Issue issue = issueRepository.findByComicAndIssueNumber(comic, "12");
assertNotNull(issue);
assertFalse(issue.getIsRead());
}
@Test
void testSearch() {
List<Issue> issues = issueRepository.search("2");
assertEquals(187, issues.size());
}
}
@@ -0,0 +1,68 @@
package de.thpeetz.kontor.comics.data;
import static org.junit.jupiter.api.Assertions.*;
import java.util.List;
import org.junit.jupiter.api.MethodOrderer.OrderAnnotation;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import de.thpeetz.kontor.comics.TestConstants;
@SpringBootTest
@TestMethodOrder(OrderAnnotation.class)
class PublisherRepositoryTest {
@Autowired
private PublisherRepository publisherRepository;
@Test
@Order(1)
void checkInitialLoad() {
assertEquals(TestConstants.PUBLISHER_COUNT, publisherRepository.findAll().size());
}
@Test
@Order(2)
void savePublisher() {
Publisher publisher = new Publisher();
publisher.setName(TestConstants.PUBLISHER_NAME);
publisherRepository.save(publisher);
assertEquals(TestConstants.PUBLISHER_COUNT + 1, publisherRepository.findAll().size());
}
@Test
@Order(3)
void findPublisherByName() {
Publisher publisher = publisherRepository.findByName(TestConstants.PUBLISHER_NAME);
assertNotNull(publisher);
assertEquals(TestConstants.PUBLISHER_NAME, publisher.getName());
Publisher notFound = publisherRepository.findByName("Cow");
assertNull(notFound);
List<Publisher> publishers = publisherRepository
.findByNameIgnoreCase(TestConstants.PUBLISHER_NAME.toLowerCase());
assertEquals(1, publishers.size());
assertEquals(TestConstants.PUBLISHER_NAME, publishers.get(0).getName());
}
@Test
@Order(4)
void searchPublisher() {
List<Publisher> publishers = publisherRepository.search("Cow");
assertEquals(1, publishers.size());
assertEquals("Top Cow Productions", publishers.get(0).getName());
}
@Test
@Order(5)
void deletePublisher() {
Publisher publisher = publisherRepository.findByName(TestConstants.PUBLISHER_NAME);
assertNotNull(publisher);
publisherRepository.delete(publisher);
assertEquals(TestConstants.PUBLISHER_COUNT, publisherRepository.findAll().size());
}
}
@@ -0,0 +1,45 @@
package de.thpeetz.kontor.comics.data;
import static org.junit.jupiter.api.Assertions.*;
import java.util.List;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import de.thpeetz.kontor.comics.TestConstants;
import de.thpeetz.kontor.comics.services.ComicService;
@SpringBootTest
class StoryArcRepositoryTest {
@Autowired
private StoryArcRepository storyArcRepository;
@Autowired
private ComicService comicService;
@Test
void testSearch() {
List<StoryArc> storyArcs = storyArcRepository.search("Learn");
assertNotNull(storyArcs);
assertEquals(1, storyArcs.size());
}
@Test
void findByComic() {
Comic comic = TestConstants.getComicWithStoryArcs(comicService);
List<StoryArc> storyArcs = storyArcRepository.findByComic(comic);
assertNotNull(storyArcs);
assertEquals(3, storyArcs.size());
}
@Test
void findByNameAndComic() {
Comic comic = TestConstants.getComicWithStoryArcs(comicService);
StoryArc storyArc = storyArcRepository.findByNameAndComic("Higher Learning", comic);
assertNotNull(storyArc);
assertEquals("Emma Frost", storyArc.getComic().getTitle());
}
}
@@ -0,0 +1,59 @@
package de.thpeetz.kontor.comics.data;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.util.List;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import de.thpeetz.kontor.comics.TestConstants;
import de.thpeetz.kontor.comics.services.ComicService;
@SpringBootTest
class TradePaperbackRepositoryTest {
@Autowired
private TradePaperbackRepository tradePaperbackRepository;
@Autowired
private ComicService comicService;
@Test
void testSearch() {
List<TradePaperback> tradePaperbacks = tradePaperbackRepository.search("Dragon");
assertNotNull(tradePaperbacks);
assertEquals(1, tradePaperbacks.size());
}
@Test
void testFindByComic() {
Comic comic = TestConstants.getComicWithTradePaperbacks(comicService);
List<TradePaperback> tradePaperbacks = tradePaperbackRepository.findByComic(comic);
assertNotNull(tradePaperbacks);
assertEquals(TestConstants.SOJOURN_TPB_COUNT, tradePaperbacks.size());
}
@Test
void testFindByNameAndComic() {
Comic comic = TestConstants.getComicWithTradePaperbacks(comicService);
List<TradePaperback> tradePaperbacks = tradePaperbackRepository
.findByNameAndComic(TestConstants.SOJOURN_TPB_NAME, comic);
assertNotNull(tradePaperbacks);
assertTrue(tradePaperbacks.size() > 0);
assertEquals(TestConstants.SOJOURN_TPB_COMIC_TITLE, tradePaperbacks.get(0).getComic().getTitle());
}
@Test
void testFindByFields() {
Comic comic = TestConstants.getComicWithTradePaperbacks(comicService);
TradePaperback tradePaperback = tradePaperbackRepository.findByFields(TestConstants.SOJOURN_TPB_NAME,
comic, TestConstants.SOJOURN_TPB_START, TestConstants.SOJOURN_TPB_END);
assertNotNull(tradePaperback);
assertEquals(TestConstants.SOJOURN_TPB_COMIC_TITLE, tradePaperback.getComic().getTitle());
assertEquals(TestConstants.SOJOURN_TPB_END, tradePaperback.getIssueEnd());
}
}
@@ -0,0 +1,61 @@
package de.thpeetz.kontor.comics.data;
import static org.junit.jupiter.api.Assertions.*;
import java.util.List;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import de.thpeetz.kontor.comics.TestConstants;
import de.thpeetz.kontor.comics.services.ComicService;
@SpringBootTest
class VolumeRepositoryTest {
@Autowired
private VolumeRepository volumeRepository;
@Autowired
private ComicRepository comicRepository;
@Autowired
private ComicService comicService;
@Test
void testFindByComic() {
Comic comic = TestConstants.getComicWithoutReferences(comicService);
assertEquals(0, comic.getVolumes().size());
Volume volume = new Volume();
volume.setName(TestConstants.VOLUME_NAME);
volume.setComic(comic);
Volume savedInstance = volumeRepository.save(volume);
assertNotNull(savedInstance);
List<Volume> found = volumeRepository.findByComic(comic);
assertEquals(1, found.size());
comicService.deleteVolume(found.get(0));
assertEquals(0, comic.getVolumes().size());
assertEquals(TestConstants.VOLUME_COUNT, volumeRepository.count());
}
@Test
void testFindByName() {
Comic comic = TestConstants.getComicWithoutReferences(comicService);
assertEquals(0, comic.getVolumes().size());
Volume volume = new Volume();
volume.setName(TestConstants.VOLUME_NAME);
volume.setComic(comic);
Volume savedInstance = volumeRepository.save(volume);
assertNotNull(savedInstance);
List<Volume> found = volumeRepository.findByName(TestConstants.VOLUME_NAME);
assertEquals(1, found.size());
comicService.deleteVolume(found.get(0));
assertEquals(0, comic.getVolumes().size());
assertEquals(TestConstants.VOLUME_COUNT, volumeRepository.count());
}
}
@@ -0,0 +1,46 @@
package de.thpeetz.kontor.comics.data;
import static org.junit.jupiter.api.Assertions.*;
import java.util.List;
import java.util.stream.Collectors;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.MethodOrderer.OrderAnnotation;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import de.thpeetz.kontor.comics.TestConstants;
@SpringBootTest
class WorktypeRepositoryTest {
@Autowired
private WorktypeRepository worktypeRepository;
@Test
void findWorktypeByName() {
Worktype found = worktypeRepository.findByName("Writer");
assertNotNull(found);
Worktype notFound = worktypeRepository.findByName("er");
assertNull(notFound);
}
@Test
void findWorktypeByNameIgnoreCase() {
List<Worktype> worktypes = worktypeRepository.findByNameIgnoreCase("Writer".toLowerCase());
assertNotNull(worktypes);
assertEquals(1, worktypes.size());
assertEquals("Writer", worktypes.get(0).getName());
}
@Test
void searchWorktype() {
List<Worktype> worktypes = worktypeRepository.search("er");
assertEquals(3, worktypes.size());
assertTrue(worktypes.stream().map(worktype -> worktype.getName()).collect(Collectors.toList()).contains("Writer"));
}
}