This commit is contained in:
Francesco 2023-09-26 20:01:20 +02:00
parent 07ffca3ff2
commit 9091ba365a
7 changed files with 64 additions and 39 deletions

View File

@ -123,17 +123,20 @@ public class DefaultDbAdminController {
if (page == null) page = 1; if (page == null) page = 1;
if (pageSize == null) pageSize = 50; if (pageSize == null) pageSize = 50;
Set<QueryFilter> queryFilters = Utils.computeFilters(otherParams); DbObjectSchema schema = dbAdmin.findSchemaByClassName(className);
Set<QueryFilter> queryFilters = Utils.computeFilters(schema, otherParams);
if (otherParams.containsKey("remove_field")) { if (otherParams.containsKey("remove_field")) {
List<String> fields = otherParams.get("remove_field"); List<String> fields = otherParams.get("remove_field");
for (int i = 0; i < fields.size(); i++) { for (int i = 0; i < fields.size(); i++) {
QueryFilter toRemove = QueryFilter toRemove =
new QueryFilter( new QueryFilter(
fields.get(i), schema.getFieldByJavaName(fields.get(i)),
CompareOperator.valueOf(otherParams.get("remove_op").get(i).toUpperCase()), CompareOperator.valueOf(otherParams.get("remove_op").get(i).toUpperCase()),
otherParams.get("remove_value").get(i) otherParams.get("remove_value").get(i)
); );
System.out.println("TOREMOVE = " + toRemove);
queryFilters.removeIf(f -> f.equals(toRemove)); queryFilters.removeIf(f -> f.equals(toRemove));
} }
@ -159,8 +162,6 @@ public class DefaultDbAdminController {
return "redirect:" + redirectUrl.trim(); return "redirect:" + redirectUrl.trim();
} }
DbObjectSchema schema = dbAdmin.findSchemaByClassName(className);
try { try {
PaginatedResult<DbObject> result = null; PaginatedResult<DbObject> result = null;
if (query != null || !otherParams.isEmpty()) { if (query != null || !otherParams.isEmpty()) {

View File

@ -104,48 +104,51 @@ public class AdvancedJpaRepository extends SimpleJpaRepository {
if (queryFilters == null) queryFilters = new HashSet<>(); if (queryFilters == null) queryFilters = new HashSet<>();
for (QueryFilter filter : queryFilters) { for (QueryFilter filter : queryFilters) {
CompareOperator op = filter.getOp(); CompareOperator op = filter.getOp();
String field = filter.getField(); DbField dbField = filter.getField();
String fieldName = dbField.getJavaName();
String v = filter.getValue(); String v = filter.getValue();
DbField dbField = schema.getFieldByJavaName(field);
Object value = dbField.getType().parseValue(v); Object value = dbField.getType().parseValue(v);
if (op == CompareOperator.STRING_EQ) { if (op == CompareOperator.STRING_EQ) {
finalPredicates.add(cb.equal(cb.lower(cb.toString(root.get(field))), value.toString().toLowerCase())); if (value == null)
finalPredicates.add(cb.isNull(root.get(fieldName)));
else
finalPredicates.add(cb.equal(cb.lower(cb.toString(root.get(fieldName))), value.toString().toLowerCase()));
} else if (op == CompareOperator.CONTAINS) { } else if (op == CompareOperator.CONTAINS) {
finalPredicates.add( finalPredicates.add(
cb.like(cb.lower(cb.toString(root.get(field))), "%" + value.toString().toLowerCase() + "%") cb.like(cb.lower(cb.toString(root.get(fieldName))), "%" + value.toString().toLowerCase() + "%")
); );
} else if (op == CompareOperator.EQ) { } else if (op == CompareOperator.EQ) {
finalPredicates.add( finalPredicates.add(
cb.equal(root.get(field), Double.parseDouble(value.toString())) cb.equal(root.get(fieldName), value)
); );
} else if (op == CompareOperator.GT) { } else if (op == CompareOperator.GT) {
finalPredicates.add( finalPredicates.add(
cb.greaterThan(root.get(field), Double.parseDouble(value.toString())) cb.greaterThan(root.get(fieldName), value.toString())
); );
} else if (op == CompareOperator.LT) { } else if (op == CompareOperator.LT) {
finalPredicates.add( finalPredicates.add(
cb.lessThan(root.get(field), Double.parseDouble(value.toString())) cb.lessThan(root.get(fieldName), value.toString())
); );
} else if (op == CompareOperator.AFTER) { } else if (op == CompareOperator.AFTER) {
if (value instanceof LocalDate) if (value instanceof LocalDate)
finalPredicates.add( finalPredicates.add(
cb.greaterThan(root.get(field), (LocalDate)value) cb.greaterThan(root.get(fieldName), (LocalDate)value)
); );
else if (value instanceof LocalDateTime) else if (value instanceof LocalDateTime)
finalPredicates.add( finalPredicates.add(
cb.greaterThan(root.get(field), (LocalDateTime)value) cb.greaterThan(root.get(fieldName), (LocalDateTime)value)
); );
} else if (op == CompareOperator.BEFORE) { } else if (op == CompareOperator.BEFORE) {
if (value instanceof LocalDate) if (value instanceof LocalDate)
finalPredicates.add( finalPredicates.add(
cb.lessThan(root.get(field), (LocalDate)value) cb.lessThan(root.get(fieldName), (LocalDate)value)
); );
else if (value instanceof LocalDateTime) else if (value instanceof LocalDateTime)
finalPredicates.add( finalPredicates.add(
cb.lessThan(root.get(field), (LocalDateTime)value) cb.lessThan(root.get(fieldName), (LocalDateTime)value)
); );
} }

View File

@ -108,6 +108,7 @@ public enum DbFieldType {
@Override @Override
public Object parseValue(Object value) { public Object parseValue(Object value) {
if (value == null) return null;
return LocalDate.parse(value.toString()); return LocalDate.parse(value.toString());
} }
@ -129,6 +130,7 @@ public enum DbFieldType {
@Override @Override
public Object parseValue(Object value) { public Object parseValue(Object value) {
if (value == null || value.toString().isBlank()) return null;
return LocalDateTime.parse(value.toString()); return LocalDateTime.parse(value.toString());
} }

View File

@ -2,20 +2,22 @@ package tech.ailef.dbadmin.external.dto;
import java.util.Objects; import java.util.Objects;
import tech.ailef.dbadmin.external.dbmapping.DbField;
public class QueryFilter { public class QueryFilter {
private String field; private DbField field;
private CompareOperator op; private CompareOperator op;
private String value; private String value;
public QueryFilter(String field, CompareOperator op, String value) { public QueryFilter(DbField field, CompareOperator op, String value) {
this.field = field; this.field = field;
this.op = op; this.op = op;
this.value = value; this.value = value;
} }
public String getField() { public DbField getField() {
return field; return field;
} }
@ -28,17 +30,25 @@ public class QueryFilter {
} }
@Override @Override
public int hashCode() { public String toString() {
return Objects.hash(field, op, value); if (value != null && !value.toString().isBlank()) {
String displayValue = value;
if (value.length() > 10) {
displayValue = value.substring(0, 4) + "..." + value.substring(value.length() - 4);
}
return "'" + field.getName() + "' " + op.getDisplayName() + " '" + displayValue + "'";
} else {
if (op != CompareOperator.STRING_EQ && op != CompareOperator.EQ) {
return "'" + field.getName() + "' " + op.getDisplayName() + " NULL";
} else {
return "'" + field.getName() + "' IS NULL";
}
}
} }
@Override @Override
public String toString() { public int hashCode() {
String displayValue = value; return Objects.hash(field, op, value);
if (value.length() > 10) {
displayValue = value.substring(0, 4) + "..." + value.substring(value.length() - 4);
}
return "'" + field + "' " + op.getDisplayName() + " '" + displayValue + "'";
} }
@Override @Override
@ -50,7 +60,7 @@ public class QueryFilter {
if (getClass() != obj.getClass()) if (getClass() != obj.getClass())
return false; return false;
QueryFilter other = (QueryFilter) obj; QueryFilter other = (QueryFilter) obj;
return Objects.equals(field, other.field) && Objects.equals(op, other.op) && Objects.equals(value, other.value); return Objects.equals(field, other.field) && op == other.op && Objects.equals(value, other.value);
} }

View File

@ -8,6 +8,7 @@ import java.util.Set;
import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap; import org.springframework.util.MultiValueMap;
import tech.ailef.dbadmin.external.dbmapping.DbObjectSchema;
import tech.ailef.dbadmin.external.dto.CompareOperator; import tech.ailef.dbadmin.external.dto.CompareOperator;
import tech.ailef.dbadmin.external.dto.QueryFilter; import tech.ailef.dbadmin.external.dto.QueryFilter;
import tech.ailef.dbadmin.external.exceptions.DbAdminException; import tech.ailef.dbadmin.external.exceptions.DbAdminException;
@ -32,7 +33,7 @@ public interface Utils {
r.put("filter_value", new ArrayList<>()); r.put("filter_value", new ArrayList<>());
for (QueryFilter filter : filters) { for (QueryFilter filter : filters) {
r.get("filter_field").add(filter.getField()); r.get("filter_field").add(filter.getField().getJavaName());
r.get("filter_op").add(filter.getOp().toString()); r.get("filter_op").add(filter.getOp().toString());
r.get("filter_value").add(filter.getValue()); r.get("filter_value").add(filter.getValue());
} }
@ -40,7 +41,7 @@ public interface Utils {
return r; return r;
} }
public static Set<QueryFilter> computeFilters(MultiValueMap<String, String> params) { public static Set<QueryFilter> computeFilters(DbObjectSchema schema, MultiValueMap<String, String> params) {
if (params == null) if (params == null)
return new HashSet<>(); return new HashSet<>();
@ -62,7 +63,7 @@ public interface Utils {
String field = fields.get(i); String field = fields.get(i);
String value = values.get(i); String value = values.get(i);
QueryFilter queryFilter = new QueryFilter(field, CompareOperator.valueOf(op.toUpperCase()), value); QueryFilter queryFilter = new QueryFilter(schema.getFieldByJavaName(field), CompareOperator.valueOf(op.toUpperCase()), value);
filters.add(queryFilter); filters.add(queryFilter);
} }

View File

@ -46,15 +46,16 @@
<span class="fw-bold align-middle" th:text="${field.getName()}"></span> <span class="fw-bold align-middle" th:text="${field.getName()}"></span>
</div> </div>
<div class="card-body"> <div class="card-body">
<!--/*--> Propagate queryParams containing other filters with hidden fields <!--*/-->
<th:block th:each="p : ${queryParams.keySet()}">
<input th:each="v : ${queryParams.get(p)}"
th:name="${p}" th:value="${v}" type="hidden"
th:if="${p.startsWith('filter_')}">
</th:block>
<!--/*--> Handle non categorical filter <!--*/--> <!--/*--> Handle non categorical filter <!--*/-->
<th:block th:if="${!field.isFilterableCategorical()}"> <th:block th:if="${!field.isFilterableCategorical()}">
<form action="" method="GET"> <form action="" method="GET">
<!--/*--> Propagate queryParams containing other filters with hidden fields <!--*/-->
<th:block th:each="p : ${queryParams.keySet()}">
<input th:each="v : ${queryParams.get(p)}"
th:name="${p}" th:value="${v}" type="hidden"
th:if="${p.startsWith('filter_')}">
</th:block>
<div class="input-group pe-2"> <div class="input-group pe-2">
<!-- Reset page when applying filter to start back at page 1 --> <!-- Reset page when applying filter to start back at page 1 -->
<input type="hidden" name="page" value="1"> <input type="hidden" name="page" value="1">
@ -102,6 +103,13 @@
<ul class="categorical-select"> <ul class="categorical-select">
<li th:each="categoricalValue : ${field.getConnectedSchema().findAll()}"> <li th:each="categoricalValue : ${field.getConnectedSchema().findAll()}">
<form action="" method="GET"> <form action="" method="GET">
<!--/*--> Propagate queryParams containing other filters with hidden fields <!--*/-->
<th:block th:each="p : ${queryParams.keySet()}">
<input th:each="v : ${queryParams.get(p)}"
th:name="${p}" th:value="${v}" type="hidden"
th:if="${p.startsWith('filter_')}">
</th:block>
<!-- Reset page when applying filter to start back at page 1 --> <!-- Reset page when applying filter to start back at page 1 -->
<input type="hidden" name="page" value="1"> <input type="hidden" name="page" value="1">
<input type="hidden" name="pageSize" th:value="${page.getPagination().getPageSize()}"> <input type="hidden" name="pageSize" th:value="${page.getPagination().getPageSize()}">

View File

@ -88,7 +88,7 @@
<th:block th:each="p : ${queryParams.keySet()}"> <th:block th:each="p : ${queryParams.keySet()}">
<input th:each="v : ${queryParams.get(p)}" th:name="${p}" th:value="${v}" type="hidden"> <input th:each="v : ${queryParams.get(p)}" th:name="${p}" th:value="${v}" type="hidden">
</th:block> </th:block>
<input type="hidden" name="remove_field" th:value="${filter.getField()}"> <input type="hidden" name="remove_field" th:value="${filter.getField().getJavaName()}">
<input type="hidden" name="remove_op" th:value="${filter.getOp()}"> <input type="hidden" name="remove_op" th:value="${filter.getOp()}">
<input type="hidden" name="remove_value" th:value="${filter.getValue()}"> <input type="hidden" name="remove_value" th:value="${filter.getValue()}">
</form> </form>