From 4177bdcd439fb72d92ba60e2f6fee8682bd3e698 Mon Sep 17 00:00:00 2001 From: Francesco Date: Thu, 5 Oct 2023 09:38:17 +0200 Subject: [PATCH] - Small refactor to the rendering part for input fileds: each field now has its own Thymeleaf fragment in order to allow easier customization and easier support for different field types (required for #7) - WIP Handle unsupported types gracefully (#9) --- .../tech/ailef/dbadmin/external/DbAdmin.java | 20 +++++--- .../external/dbmapping/DbFieldType.java | 50 +++++++++---------- .../external/dbmapping/DbObjectSchema.java | 11 ++++ .../dbadmin/external/dto/MappingError.java | 14 ++++++ .../UnsupportedFieldTypeException.java | 38 ++++++++++++++ src/main/resources/static/css/dbadmin.css | 8 +++ .../resources/templates/fragments/inputs.html | 2 + src/main/resources/templates/home.html | 7 +++ .../resources/templates/model/schema.html | 6 +++ 9 files changed, 124 insertions(+), 32 deletions(-) create mode 100644 src/main/java/tech/ailef/dbadmin/external/dto/MappingError.java create mode 100644 src/main/java/tech/ailef/dbadmin/external/exceptions/UnsupportedFieldTypeException.java diff --git a/src/main/java/tech/ailef/dbadmin/external/DbAdmin.java b/src/main/java/tech/ailef/dbadmin/external/DbAdmin.java index a93bb61..8e58431 100644 --- a/src/main/java/tech/ailef/dbadmin/external/DbAdmin.java +++ b/src/main/java/tech/ailef/dbadmin/external/DbAdmin.java @@ -52,7 +52,9 @@ import tech.ailef.dbadmin.external.dbmapping.CustomJpaRepository; import tech.ailef.dbadmin.external.dbmapping.DbField; import tech.ailef.dbadmin.external.dbmapping.DbFieldType; import tech.ailef.dbadmin.external.dbmapping.DbObjectSchema; +import tech.ailef.dbadmin.external.dto.MappingError; import tech.ailef.dbadmin.external.exceptions.DbAdminException; +import tech.ailef.dbadmin.external.exceptions.UnsupportedFieldTypeException; import tech.ailef.dbadmin.external.misc.Utils; /** @@ -174,17 +176,21 @@ public class DbAdmin { CustomJpaRepository simpleJpaRepository = new CustomJpaRepository(schema, entityManager); schema.setJpaRepository(simpleJpaRepository); - logger.debug("Processing class: " + klass + " - Table: " + schema.getTableName()); Field[] fields = klass.getDeclaredFields(); for (Field f : fields) { - DbField field = mapField(f, schema); - if (field == null) { - throw new DbAdminException("Impossible to map field: " + f); + try { + DbField field = mapField(f, schema); + field.setSchema(schema); + schema.addField(field); + } catch (UnsupportedFieldTypeException e) { + schema.addError( + new MappingError( + "The class contains the field `" + f.getName() + "` of type `" + f.getType().getSimpleName() + "`, which is not supported" + ) + ); } - field.setSchema(schema); - schema.addField(field); } logger.debug("Processed " + klass + ", extracted " + schema.getSortedFields().size() + " fields"); @@ -280,7 +286,7 @@ public class DbAdmin { } if (fieldType == null) { - throw new DbAdminException("Unable to determine fieldType for " + f.getType()); + throw new UnsupportedFieldTypeException("Unable to determine fieldType for " + f.getType()); } DisplayFormat displayFormat = f.getAnnotation(DisplayFormat.class); diff --git a/src/main/java/tech/ailef/dbadmin/external/dbmapping/DbFieldType.java b/src/main/java/tech/ailef/dbadmin/external/dbmapping/DbFieldType.java index 1da4bf4..64ef97b 100644 --- a/src/main/java/tech/ailef/dbadmin/external/dbmapping/DbFieldType.java +++ b/src/main/java/tech/ailef/dbadmin/external/dbmapping/DbFieldType.java @@ -123,29 +123,29 @@ public enum DbFieldType { return List.of(CompareOperator.GT, CompareOperator.EQ, CompareOperator.LT); } }, - OFFSET_DATE_TIME { - @Override - public String getFragmentName(FragmentContext c) { - return "offset_datetime"; - } - - @Override - public Object parseValue(Object value) { - if (value == null) return null; - return OffsetDateTime.parse(value.toString()); - } - - @Override - public Class getJavaClass() { - return OffsetDateTime.class; - } - - @Override - public List getCompareOperators() { - return List.of(CompareOperator.AFTER, CompareOperator.STRING_EQ, CompareOperator.BEFORE); - } - - }, +// OFFSET_DATE_TIME { +// @Override +// public String getFragmentName(FragmentContext c) { +// return "text"; +// } +// +// @Override +// public Object parseValue(Object value) { +// if (value == null) return null; +// return OffsetDateTime.parse(value.toString()); +// } +// +// @Override +// public Class getJavaClass() { +// return OffsetDateTime.class; +// } +// +// @Override +// public List getCompareOperators() { +// return List.of(CompareOperator.AFTER, CompareOperator.STRING_EQ, CompareOperator.BEFORE); +// } +// +// }, LOCAL_DATE { @Override public String getFragmentName(FragmentContext c) { @@ -450,8 +450,8 @@ public enum DbFieldType { return BIG_DECIMAL; } else if (klass == byte[].class) { return BYTE_ARRAY; - } else if (klass == OffsetDateTime.class) { - return OFFSET_DATE_TIME; +// } else if (klass == OffsetDateTime.class) { +// return OFFSET_DATE_TIME; } else { throw new DbAdminException("Unsupported field type: " + klass); } diff --git a/src/main/java/tech/ailef/dbadmin/external/dbmapping/DbObjectSchema.java b/src/main/java/tech/ailef/dbadmin/external/dbmapping/DbObjectSchema.java index 9c3b4b6..922e97a 100644 --- a/src/main/java/tech/ailef/dbadmin/external/dbmapping/DbObjectSchema.java +++ b/src/main/java/tech/ailef/dbadmin/external/dbmapping/DbObjectSchema.java @@ -39,6 +39,7 @@ import jakarta.persistence.Table; import tech.ailef.dbadmin.external.DbAdmin; import tech.ailef.dbadmin.external.annotations.ComputedColumn; import tech.ailef.dbadmin.external.annotations.HiddenColumn; +import tech.ailef.dbadmin.external.dto.MappingError; import tech.ailef.dbadmin.external.exceptions.DbAdminException; import tech.ailef.dbadmin.external.misc.Utils; @@ -79,6 +80,8 @@ public class DbObjectSchema { */ private String tableName; + private List errors = new ArrayList<>(); + /** * Initializes this schema for the specific `@Entity` class. * Determines the table name from the `@Table` annotation and also @@ -155,6 +158,10 @@ public class DbObjectSchema { return Collections.unmodifiableList(fields); } + public List getErrors() { + return Collections.unmodifiableList(errors); + } + /** * Get a field by its Java name, i.e. the name of the instance variable * in the `@Entity` class @@ -184,6 +191,10 @@ public class DbObjectSchema { fields.add(f); } + public void addError(MappingError error) { + errors.add(error); + } + /** * Returns the underlying CustomJpaRepository * @return diff --git a/src/main/java/tech/ailef/dbadmin/external/dto/MappingError.java b/src/main/java/tech/ailef/dbadmin/external/dto/MappingError.java new file mode 100644 index 0000000..4e8f1c8 --- /dev/null +++ b/src/main/java/tech/ailef/dbadmin/external/dto/MappingError.java @@ -0,0 +1,14 @@ +package tech.ailef.dbadmin.external.dto; + +public class MappingError { + private String message; + + public MappingError(String message) { + this.message = message; + } + + public String getMessage() { + return message; + } + +} diff --git a/src/main/java/tech/ailef/dbadmin/external/exceptions/UnsupportedFieldTypeException.java b/src/main/java/tech/ailef/dbadmin/external/exceptions/UnsupportedFieldTypeException.java new file mode 100644 index 0000000..0f68dd7 --- /dev/null +++ b/src/main/java/tech/ailef/dbadmin/external/exceptions/UnsupportedFieldTypeException.java @@ -0,0 +1,38 @@ +/* + * Spring Boot Database Admin - An automatically generated CRUD admin UI for Spring Boot apps + * Copyright (C) 2023 Ailef (http://ailef.tech) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +package tech.ailef.dbadmin.external.exceptions; + +/** + * Thrown during the computation of pagination if the requested + * page number is not valid within the current request (e.g. it is greater + * than the maximum available page). Used internally to redirect the + * user to a default page. + */ +public class UnsupportedFieldTypeException extends DbAdminException { + private static final long serialVersionUID = -8891734807568233099L; + + public UnsupportedFieldTypeException() { + } + + public UnsupportedFieldTypeException(String msg) { + super(msg); + } + +} diff --git a/src/main/resources/static/css/dbadmin.css b/src/main/resources/static/css/dbadmin.css index 9adbd7d..70b4eb7 100644 --- a/src/main/resources/static/css/dbadmin.css +++ b/src/main/resources/static/css/dbadmin.css @@ -59,6 +59,14 @@ tr.table-data-row td:last-child, tr.table-data-row th:last-child { width: 96px; } +.warning-col { + width: 32px; +} + +.warning-col a .bi { + color: red !important; +} + h1 .bi { font-size: 2rem; } diff --git a/src/main/resources/templates/fragments/inputs.html b/src/main/resources/templates/fragments/inputs.html index d8f92ca..da51b69 100644 --- a/src/main/resources/templates/fragments/inputs.html +++ b/src/main/resources/templates/fragments/inputs.html @@ -39,6 +39,7 @@ th:required="${!field.isNullable() && !field.isPrimaryKey()}" > + + +
Table Rows Java class
+ + + diff --git a/src/main/resources/templates/model/schema.html b/src/main/resources/templates/model/schema.html index 015129c..838ad79 100644 --- a/src/main/resources/templates/model/schema.html +++ b/src/main/resources/templates/model/schema.html @@ -67,6 +67,12 @@
+
+

Errors

+
    +
  • +
  • +