diff --git a/src/main/java/tech/ailef/dbadmin/controller/DefaultDbAdminController.java b/src/main/java/tech/ailef/dbadmin/controller/DefaultDbAdminController.java index c4bc1ed..f002e35 100644 --- a/src/main/java/tech/ailef/dbadmin/controller/DefaultDbAdminController.java +++ b/src/main/java/tech/ailef/dbadmin/controller/DefaultDbAdminController.java @@ -2,7 +2,6 @@ package tech.ailef.dbadmin.controller; import java.util.ArrayList; import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Optional; @@ -25,16 +24,15 @@ import org.springframework.web.multipart.MultipartFile; import org.springframework.web.server.ResponseStatusException; import org.springframework.web.servlet.mvc.support.RedirectAttributes; -import ch.qos.logback.core.joran.action.ParamAction; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import tech.ailef.dbadmin.DbAdmin; import tech.ailef.dbadmin.dbmapping.DbAdminRepository; import tech.ailef.dbadmin.dbmapping.DbObject; import tech.ailef.dbadmin.dbmapping.DbObjectSchema; +import tech.ailef.dbadmin.dto.CompareOperator; import tech.ailef.dbadmin.dto.PaginatedResult; import tech.ailef.dbadmin.dto.QueryFilter; -import tech.ailef.dbadmin.exceptions.DbAdminException; import tech.ailef.dbadmin.exceptions.InvalidPageException; import tech.ailef.dbadmin.misc.Utils; @@ -113,7 +111,11 @@ public class DefaultDbAdminController { for (int i = 0; i < fields.size(); i++) { QueryFilter toRemove = - new QueryFilter(fields.get(i), otherParams.get("remove_op").get(i), otherParams.get("remove_value").get(i)); + new QueryFilter( + fields.get(i), + CompareOperator.valueOf(otherParams.get("remove_op").get(i).toUpperCase()), + otherParams.get("remove_value").get(i) + ); queryFilters.removeIf(f -> f.equals(toRemove)); } diff --git a/src/main/java/tech/ailef/dbadmin/dbmapping/AdvancedJpaRepository.java b/src/main/java/tech/ailef/dbadmin/dbmapping/AdvancedJpaRepository.java index 185e8bd..91011d5 100644 --- a/src/main/java/tech/ailef/dbadmin/dbmapping/AdvancedJpaRepository.java +++ b/src/main/java/tech/ailef/dbadmin/dbmapping/AdvancedJpaRepository.java @@ -1,6 +1,9 @@ package tech.ailef.dbadmin.dbmapping; +import java.time.LocalDate; +import java.time.LocalDateTime; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.stream.Collectors; @@ -13,6 +16,7 @@ import jakarta.persistence.criteria.CriteriaQuery; import jakarta.persistence.criteria.Path; import jakarta.persistence.criteria.Predicate; import jakarta.persistence.criteria.Root; +import tech.ailef.dbadmin.dto.CompareOperator; import tech.ailef.dbadmin.dto.QueryFilter; @SuppressWarnings("rawtypes") @@ -89,29 +93,54 @@ public class AdvancedJpaRepository extends SimpleJpaRepository { finalPredicates.add(queryPredicate); } + + if (queryFilters == null) queryFilters = new HashSet<>(); for (QueryFilter filter : queryFilters) { - String op = filter.getOp(); + CompareOperator op = filter.getOp(); String field = filter.getField(); - String value = filter.getValue(); - - if (op.equalsIgnoreCase("equals")) { - finalPredicates.add(cb.equal(cb.lower(cb.toString(root.get(field))), value.toLowerCase())); - } else if (op.equalsIgnoreCase("contains")) { + String v = filter.getValue(); + + DbField dbField = schema.getFieldByJavaName(field); + Object value = dbField.getType().parseValue(v); + + if (op == CompareOperator.STRING_EQ) { + finalPredicates.add(cb.equal(cb.lower(cb.toString(root.get(field))), value.toString().toLowerCase())); + } else if (op == CompareOperator.CONTAINS) { finalPredicates.add( - cb.like(cb.lower(cb.toString(root.get(field))), "%" + value.toLowerCase() + "%") + cb.like(cb.lower(cb.toString(root.get(field))), "%" + value.toString().toLowerCase() + "%") ); - } else if (op.equalsIgnoreCase("eq")) { + } else if (op == CompareOperator.EQ) { finalPredicates.add( cb.equal(root.get(field), value) ); - } else if (op.equalsIgnoreCase("gt")) { + } else if (op == CompareOperator.GT) { finalPredicates.add( - cb.greaterThan(root.get(field), value) + cb.greaterThan(root.get(field), value.toString()) ); - } else if (op.equalsIgnoreCase("lt")) { + } else if (op == CompareOperator.LT) { finalPredicates.add( - cb.lessThan(root.get(field), value) + cb.lessThan(root.get(field), value.toString()) ); + } else if (op == CompareOperator.AFTER) { + if (value instanceof LocalDate) + finalPredicates.add( + cb.greaterThan(root.get(field), (LocalDate)value) + ); + else if (value instanceof LocalDateTime) + finalPredicates.add( + cb.greaterThan(root.get(field), (LocalDateTime)value) + ); + + } else if (op == CompareOperator.BEFORE) { + if (value instanceof LocalDate) + finalPredicates.add( + cb.lessThan(root.get(field), (LocalDate)value) + ); + else if (value instanceof LocalDateTime) + finalPredicates.add( + cb.lessThan(root.get(field), (LocalDateTime)value) + ); + } } return finalPredicates; diff --git a/src/main/java/tech/ailef/dbadmin/dbmapping/DbAdminRepository.java b/src/main/java/tech/ailef/dbadmin/dbmapping/DbAdminRepository.java index aa01777..7f04f97 100644 --- a/src/main/java/tech/ailef/dbadmin/dbmapping/DbAdminRepository.java +++ b/src/main/java/tech/ailef/dbadmin/dbmapping/DbAdminRepository.java @@ -119,7 +119,7 @@ public class DbAdminRepository { return new PaginatedResult( - new PaginationInfo(page, maxPage, pageSize, maxElement, null, new HashSet<>()), + new PaginationInfo(page, maxPage, pageSize, maxElement, null, sortKey, sortOrder, new HashSet<>()), results ); } @@ -239,7 +239,7 @@ public class DbAdminRepository { } return new PaginatedResult( - new PaginationInfo(page, maxPage, pageSize, maxElement, query, queryFilters), + new PaginationInfo(page, maxPage, pageSize, maxElement, query, sortKey, sortOrder, queryFilters), jpaRepository.search(query, page, pageSize, sortKey, sortOrder, queryFilters).stream() .map(o -> new DbObject(o, schema)) .toList() diff --git a/src/main/java/tech/ailef/dbadmin/dbmapping/DbFieldType.java b/src/main/java/tech/ailef/dbadmin/dbmapping/DbFieldType.java index ececf23..389b5a2 100644 --- a/src/main/java/tech/ailef/dbadmin/dbmapping/DbFieldType.java +++ b/src/main/java/tech/ailef/dbadmin/dbmapping/DbFieldType.java @@ -11,6 +11,7 @@ import org.springframework.web.multipart.MultipartFile; import jakarta.persistence.ManyToMany; import jakarta.persistence.OneToMany; import jakarta.persistence.OneToOne; +import tech.ailef.dbadmin.dto.CompareOperator; import tech.ailef.dbadmin.exceptions.DbAdminException; public enum DbFieldType { @@ -32,8 +33,8 @@ public enum DbFieldType { } @Override - public List getCompareOperators() { - return List.of("gt", "eq", "lt"); + public List getCompareOperators() { + return List.of(CompareOperator.GT, CompareOperator.EQ, CompareOperator.LT); } }, DOUBLE { @@ -53,8 +54,8 @@ public enum DbFieldType { } @Override - public List getCompareOperators() { - return List.of("gt", "eq", "lt"); + public List getCompareOperators() { + return List.of(CompareOperator.GT, CompareOperator.EQ, CompareOperator.LT); } }, LONG { @@ -74,8 +75,8 @@ public enum DbFieldType { } @Override - public List getCompareOperators() { - return List.of("gt", "eq", "lt"); + public List getCompareOperators() { + return List.of(CompareOperator.GT, CompareOperator.EQ, CompareOperator.LT); } }, FLOAT { @@ -95,8 +96,8 @@ public enum DbFieldType { } @Override - public List getCompareOperators() { - return List.of("gt", "eq", "lt"); + public List getCompareOperators() { + return List.of(CompareOperator.GT, CompareOperator.EQ, CompareOperator.LT); } }, LOCAL_DATE { @@ -116,8 +117,8 @@ public enum DbFieldType { } @Override - public List getCompareOperators() { - return List.of("After", "Equals", "Before"); + public List getCompareOperators() { + return List.of(CompareOperator.AFTER, CompareOperator.STRING_EQ, CompareOperator.BEFORE); } }, LOCAL_DATE_TIME { @@ -137,8 +138,8 @@ public enum DbFieldType { } @Override - public List getCompareOperators() { - return List.of("After", "Equals", "Before"); + public List getCompareOperators() { + return List.of(CompareOperator.AFTER, CompareOperator.STRING_EQ, CompareOperator.BEFORE); } }, STRING { @@ -158,8 +159,8 @@ public enum DbFieldType { } @Override - public List getCompareOperators() { - return List.of("Equals", "Contains"); + public List getCompareOperators() { + return List.of(CompareOperator.CONTAINS, CompareOperator.STRING_EQ); } }, BOOLEAN { @@ -179,8 +180,8 @@ public enum DbFieldType { } @Override - public List getCompareOperators() { - return List.of("Equals"); + public List getCompareOperators() { + return List.of(CompareOperator.EQ); } }, BIG_DECIMAL { @@ -200,8 +201,8 @@ public enum DbFieldType { } @Override - public List getCompareOperators() { - return List.of("gt", "eq", "lt"); + public List getCompareOperators() { + return List.of(CompareOperator.GT, CompareOperator.EQ, CompareOperator.LT); } }, BYTE_ARRAY { @@ -225,8 +226,8 @@ public enum DbFieldType { } @Override - public List getCompareOperators() { - return List.of("Equals"); + public List getCompareOperators() { + throw new DbAdminException("Binary fields are not comparable"); } }, ONE_TO_MANY { @@ -256,7 +257,7 @@ public enum DbFieldType { } @Override - public List getCompareOperators() { + public List getCompareOperators() { throw new DbAdminException(); } }, @@ -287,7 +288,7 @@ public enum DbFieldType { } @Override - public List getCompareOperators() { + public List getCompareOperators() { throw new DbAdminException(); } }, @@ -318,7 +319,7 @@ public enum DbFieldType { } @Override - public List getCompareOperators() { + public List getCompareOperators() { throw new DbAdminException(); } }, @@ -339,7 +340,7 @@ public enum DbFieldType { } @Override - public List getCompareOperators() { + public List getCompareOperators() { throw new DbAdminException(); } }; @@ -350,7 +351,7 @@ public enum DbFieldType { public abstract Class getJavaClass(); - public abstract List getCompareOperators(); + public abstract List getCompareOperators(); public boolean isRelationship() { return false; diff --git a/src/main/java/tech/ailef/dbadmin/dbmapping/DbObjectSchema.java b/src/main/java/tech/ailef/dbadmin/dbmapping/DbObjectSchema.java index a2705a4..31242c8 100644 --- a/src/main/java/tech/ailef/dbadmin/dbmapping/DbObjectSchema.java +++ b/src/main/java/tech/ailef/dbadmin/dbmapping/DbObjectSchema.java @@ -1,7 +1,6 @@ package tech.ailef.dbadmin.dbmapping; import java.lang.reflect.Method; - import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; diff --git a/src/main/java/tech/ailef/dbadmin/dto/CompareOperator.java b/src/main/java/tech/ailef/dbadmin/dto/CompareOperator.java new file mode 100644 index 0000000..6f850e7 --- /dev/null +++ b/src/main/java/tech/ailef/dbadmin/dto/CompareOperator.java @@ -0,0 +1,52 @@ +package tech.ailef.dbadmin.dto; + +public enum CompareOperator { + GT { + @Override + public String getDisplayName() { + return "Greater than"; + } + }, + LT { + @Override + public String getDisplayName() { + return "Less than"; + } + }, + EQ { + @Override + public String getDisplayName() { + return "Equals"; + } + }, + STRING_EQ { + @Override + public String getDisplayName() { + return "Equals"; + } + }, + BEFORE { + @Override + public String getDisplayName() { + return "Before"; + } + }, + AFTER { + @Override + public String getDisplayName() { + return "After"; + } + }, + CONTAINS { + @Override + public String getDisplayName() { + return "Contains"; + } + }; + + public abstract String getDisplayName(); + + public String toString() { + return this.name().toLowerCase(); + } +} diff --git a/src/main/java/tech/ailef/dbadmin/dto/PaginationInfo.java b/src/main/java/tech/ailef/dbadmin/dto/PaginationInfo.java index 58db91f..dd69835 100644 --- a/src/main/java/tech/ailef/dbadmin/dto/PaginationInfo.java +++ b/src/main/java/tech/ailef/dbadmin/dto/PaginationInfo.java @@ -40,14 +40,21 @@ public class PaginationInfo { private Set queryFilters; private String query; + + private String sortKey; + + private String sortOrder; - public PaginationInfo(int currentPage, int maxPage, int pageSize, long maxElement, String query, Set queryFilters) { + public PaginationInfo(int currentPage, int maxPage, int pageSize, long maxElement, String query, + String sortKey, String sortOrder, Set queryFilters) { this.currentPage = currentPage; this.maxPage = maxPage; this.pageSize = pageSize; this.query = query; this.maxElement = maxElement; this.queryFilters = queryFilters; + this.sortKey = sortKey; + this.sortOrder = sortOrder; } public int getCurrentPage() { @@ -78,6 +85,22 @@ public class PaginationInfo { return maxElement; } + public String getSortedPageLink(String sortKey, String sortOrder) { + MultiValueMap params = Utils.computeParams(queryFilters); + + if (query != null) { + params.put("query", new ArrayList<>()); + params.get("query").add(query); + } + + params.add("pageSize", "" + pageSize); + params.add("page", "" + currentPage); + params.add("sortKey", sortKey); + params.add("sortOrder", sortOrder); + + return Utils.getQueryString(params); + } + public String getLink(int page) { MultiValueMap params = Utils.computeParams(queryFilters); diff --git a/src/main/java/tech/ailef/dbadmin/dto/QueryFilter.java b/src/main/java/tech/ailef/dbadmin/dto/QueryFilter.java index 166feed..2d52b3c 100644 --- a/src/main/java/tech/ailef/dbadmin/dto/QueryFilter.java +++ b/src/main/java/tech/ailef/dbadmin/dto/QueryFilter.java @@ -5,11 +5,11 @@ import java.util.Objects; public class QueryFilter { private String field; - private String op; + private CompareOperator op; private String value; - public QueryFilter(String field, String op, String value) { + public QueryFilter(String field, CompareOperator op, String value) { this.field = field; this.op = op; this.value = value; @@ -19,7 +19,7 @@ public class QueryFilter { return field; } - public String getOp() { + public CompareOperator getOp() { return op; } @@ -34,7 +34,11 @@ public class QueryFilter { @Override public String toString() { - return field + " " + op + " '" + value + "'"; + String displayValue = value; + if (value.length() > 10) { + displayValue = value.substring(0, 4) + "..." + value.substring(value.length() - 4); + } + return "'" + field + "' " + op.getDisplayName() + " '" + displayValue + "'"; } @Override diff --git a/src/main/java/tech/ailef/dbadmin/misc/Utils.java b/src/main/java/tech/ailef/dbadmin/misc/Utils.java index b6230ef..06f3632 100644 --- a/src/main/java/tech/ailef/dbadmin/misc/Utils.java +++ b/src/main/java/tech/ailef/dbadmin/misc/Utils.java @@ -8,6 +8,7 @@ import java.util.Set; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; +import tech.ailef.dbadmin.dto.CompareOperator; import tech.ailef.dbadmin.dto.QueryFilter; import tech.ailef.dbadmin.exceptions.DbAdminException; @@ -30,7 +31,7 @@ public interface Utils { for (QueryFilter filter : filters) { r.get("filter_field").add(filter.getField()); - r.get("filter_op").add(filter.getOp()); + r.get("filter_op").add(filter.getOp().toString()); r.get("filter_value").add(filter.getValue()); } @@ -59,7 +60,7 @@ public interface Utils { String field = fields.get(i); String value = values.get(i); - QueryFilter queryFilter = new QueryFilter(field, op, value); + QueryFilter queryFilter = new QueryFilter(field, CompareOperator.valueOf(op.toUpperCase()), value); filters.add(queryFilter); } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 2267faf..13b71fa 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,9 +1,7 @@ -spring.datasource.url=jdbc:h2:file:./dbadmin -spring.datasource.username=sa -spring.datasource.password=password +#spring.datasource.url=jdbc:h2:file:./database +#spring.datasource.username=sa +#spring.datasource.password=password #spring.h2.console.enabled=true -spring.jpa.show-sql=true - -server.tomcat.relaxed-path-chars=[,] \ No newline at end of file +#spring.jpa.show-sql=true diff --git a/src/main/resources/templates/fragments/forms.html b/src/main/resources/templates/fragments/forms.html index e5ec680..110203a 100644 --- a/src/main/resources/templates/fragments/forms.html +++ b/src/main/resources/templates/fragments/forms.html @@ -50,31 +50,40 @@
- + +
-
+ + + Equals + +
+ + +
+
- + -
- -
- + -
@@ -84,7 +93,7 @@ - +
diff --git a/src/main/resources/templates/fragments/table_selectable.html b/src/main/resources/templates/fragments/table_selectable.html index 26f18fc..8bd5262 100644 --- a/src/main/resources/templates/fragments/table_selectable.html +++ b/src/main/resources/templates/fragments/table_selectable.html @@ -27,21 +27,18 @@

- - + + - + + th:href="@{|/dbadmin/model/${schema.getClassName()}${page.getPagination().getSortedPageLink(field.getJavaName(), 'ASC')}|}"> + th:href="@{|/dbadmin/model/${schema.getClassName()}${page.getPagination().getSortedPageLink(field.getJavaName(), 'DESC')}|}"> diff --git a/src/main/resources/templates/model/list.html b/src/main/resources/templates/model/list.html index ab0dc2d..d178812 100644 --- a/src/main/resources/templates/model/list.html +++ b/src/main/resources/templates/model/list.html @@ -47,7 +47,7 @@ + th:value="${page.getPagination().getPageSize()}">