This commit is contained in:
Francesco
2023-09-21 16:17:12 +02:00
parent f82761d538
commit e7a5328050
24 changed files with 182 additions and 147 deletions

View File

@@ -1,23 +0,0 @@
package tech.ailef.dbadmin;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
/**
* Utility class the get the ApplicationContext
*/
@Component
public class ApplicationContextUtils implements ApplicationContextAware {
private static ApplicationContext ctx;
@Override
public void setApplicationContext(ApplicationContext appContext) {
ctx = appContext;
}
public static ApplicationContext getApplicationContext() {
return ctx;
}
}

View File

@@ -6,11 +6,13 @@ import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.stereotype.Component;
@@ -25,8 +27,6 @@ import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToMany;
import jakarta.persistence.OneToOne;
import jakarta.persistence.PersistenceContext;
import tech.ailef.dbadmin.annotations.DbAdminAppConfiguration;
import tech.ailef.dbadmin.annotations.DbAdminConfiguration;
import tech.ailef.dbadmin.annotations.DisplayFormat;
import tech.ailef.dbadmin.dbmapping.AdvancedJpaRepository;
import tech.ailef.dbadmin.dbmapping.DbField;
@@ -46,6 +46,8 @@ import tech.ailef.dbadmin.misc.Utils;
*/
@Component
public class DbAdmin {
private static final Logger logger = Logger.getLogger(DbAdmin.class.getName());
@PersistenceContext
private EntityManager entityManager;
@@ -53,17 +55,8 @@ public class DbAdmin {
private String modelsPackage;
public DbAdmin(@Autowired EntityManager entityManager) {
Map<String, Object> beansWithAnnotation =
ApplicationContextUtils.getApplicationContext().getBeansWithAnnotation(DbAdminConfiguration.class);
if (beansWithAnnotation.size() != 1) {
throw new DbAdminException("Found " + beansWithAnnotation.size() + " beans with annotation @DbAdminConfiguration, but must be unique");
}
DbAdminAppConfiguration applicationClass = (DbAdminAppConfiguration) beansWithAnnotation.values().iterator().next();
this.modelsPackage = applicationClass.getModelsPackage();
public DbAdmin(@Autowired EntityManager entityManager, @Autowired DbAdminProperties properties) {
this.modelsPackage = properties.getModelsPackage();
this.entityManager = entityManager;
ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
@@ -73,6 +66,9 @@ public class DbAdmin {
for (BeanDefinition bd : beanDefs) {
schemas.add(processBeanDefinition(bd));
}
logger.info("Spring Boot Database Admin initialized. Loaded " + schemas.size() + " table definitions");
logger.info("Spring Boot Database Admin web interface at: http://YOUR_HOST:YOUR_PORT/" + properties.getBaseUrl());
}
/**

View File

@@ -0,0 +1,14 @@
package tech.ailef.dbadmin;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.ComponentScan;
@ConditionalOnProperty(name = "dbadmin.enabled", matchIfMissing = true)
@ComponentScan
@EnableConfigurationProperties(DbAdminProperties.class)
@AutoConfiguration
public class DbAdminAutoConfiguration {
}

View File

@@ -0,0 +1,51 @@
package tech.ailef.dbadmin;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* The 'dbadmin.*' properties that can be set in the properties file
* to configure the behaviour of Spring Boot Admin Panel.
*/
@ConfigurationProperties("dbadmin")
public class DbAdminProperties {
/**
* Whether Spring Boot Database Admin is enabled.
*/
public boolean enabled = true;
/**
* The prefix that is prepended to all routes registered by Spring Boot Database Admin.
*/
private String baseUrl;
/**
* The path of the package that contains your JPA `@Entity` classes to be scanned.
*/
private String modelsPackage;
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public String getBaseUrl() {
return baseUrl;
}
public void setBaseUrl(String baseUrl) {
this.baseUrl = baseUrl;
}
public String getModelsPackage() {
return modelsPackage;
}
public void setModelsPackage(String modelsPackage) {
this.modelsPackage = modelsPackage;
}
}

View File

@@ -1,10 +0,0 @@
package tech.ailef.dbadmin.annotations;
/**
* An interface that includes all the configuration methods that
* the user has to implement in order to integrate DbAdmin.
*
*/
public interface DbAdminAppConfiguration {
public String getModelsPackage();
}

View File

@@ -1,15 +0,0 @@
package tech.ailef.dbadmin.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Marks the class that holds the DbAdmin configuration.
*
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface DbAdminConfiguration {
}

View File

@@ -28,6 +28,7 @@ import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import tech.ailef.dbadmin.DbAdmin;
import tech.ailef.dbadmin.DbAdminProperties;
import tech.ailef.dbadmin.dbmapping.DbAdminRepository;
import tech.ailef.dbadmin.dbmapping.DbObject;
import tech.ailef.dbadmin.dbmapping.DbObjectSchema;
@@ -41,8 +42,11 @@ import tech.ailef.dbadmin.misc.Utils;
* The main DbAdmin controller that register most of the routes of the web interface.
*/
@Controller
@RequestMapping("/dbadmin")
@RequestMapping(value= {"/${dbadmin.baseUrl}", "/${dbadmin.baseUrl}/"})
public class DefaultDbAdminController {
@Autowired
private DbAdminProperties properties;
@Autowired
private DbAdminRepository repository;
@@ -163,7 +167,7 @@ public class DefaultDbAdminController {
return "model/list";
} catch (InvalidPageException e) {
return "redirect:/dbadmin/model/" + className;
return "redirect:/" + properties.getBaseUrl() + "/model/" + className;
}
}
@@ -260,7 +264,7 @@ public class DefaultDbAdminController {
attr.addFlashAttribute("error", e.getMessage());
}
return "redirect:/dbadmin/model/" + className;
return "redirect:/" + properties.getBaseUrl() + "/model/" + className;
}
@PostMapping(value="/model/{className}/delete")
@@ -287,7 +291,7 @@ public class DefaultDbAdminController {
if (countDeleted > 0)
attr.addFlashAttribute("message", "Deleted " + countDeleted + " of " + ids.length + " items");
return "redirect:/dbadmin/model/" + className;
return "redirect:/" + properties.getBaseUrl() + "/model/" + className;
}
@PostMapping(value="/model/{className}/create")
@@ -397,11 +401,11 @@ public class DefaultDbAdminController {
if (attr.getFlashAttributes().containsKey("error")) {
if (create)
return "redirect:/dbadmin/model/" + schema.getClassName() + "/create";
return "redirect:/" + properties.getBaseUrl() + "/model/" + schema.getClassName() + "/create";
else
return "redirect:/dbadmin/model/" + schema.getClassName() + "/edit/" + pkValue;
return "redirect:/" + properties.getBaseUrl() + "/model/" + schema.getClassName() + "/edit/" + pkValue;
} else {
return "redirect:/dbadmin/model/" + schema.getClassName() + "/show/" + pkValue;
return "redirect:/" + properties.getBaseUrl() + "/model/" + schema.getClassName() + "/show/" + pkValue;
}
}

View File

@@ -28,7 +28,7 @@ import tech.ailef.dbadmin.exceptions.DbAdminException;
* Controller to serve file or images (`@DisplayImage`)
*/
@Controller
@RequestMapping("/dbadmin/download")
@RequestMapping(value = {"/${dbadmin.baseUrl}/download", "/${dbadmin.baseUrl}/download/"})
public class DownloadController {
@Autowired
private DbAdminRepository repository;

View File

@@ -2,10 +2,12 @@ package tech.ailef.dbadmin.controller;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ModelAttribute;
import jakarta.servlet.http.HttpServletRequest;
import tech.ailef.dbadmin.DbAdminProperties;
/**
* This class registers some ModelAttribute objects that are
@@ -14,6 +16,9 @@ import jakarta.servlet.http.HttpServletRequest;
@ControllerAdvice
public class GlobalController {
@Autowired
private DbAdminProperties props;
/**
* A multi valued map containing the query parameters. It is used primarily
* in building complex URL when performing faceted search with multiple filters.
@@ -24,4 +29,14 @@ public class GlobalController {
public Map<String, String[]> getQueryParams(HttpServletRequest request) {
return request.getParameterMap();
}
/**
* The baseUrl as specified in the properties file by the user
* @param request
* @return
*/
@ModelAttribute("baseUrl")
public String getBaseUrl(HttpServletRequest request) {
return props.getBaseUrl();
}
}

View File

@@ -20,7 +20,7 @@ import tech.ailef.dbadmin.dto.AutocompleteSearchResult;
* API controller for autocomplete results
*/
@RestController
@RequestMapping("/dbadmin/api/autocomplete")
@RequestMapping(value= {"/${dbadmin.baseUrl}/api/autocomplete", "/${dbadmin.baseUrl}/api/autocomplete/"})
public class AutocompleteController {
@Autowired
private DbAdmin dbAdmin;

View File

@@ -19,7 +19,7 @@ import tech.ailef.dbadmin.dto.PaginatedResult;
import tech.ailef.dbadmin.exceptions.DbAdminException;
@RestController
@RequestMapping("/dbadmin/api")
@RequestMapping(value = {"/${dbadmin.baseUrl}/api", "/${dbadmin.baseUrl}/api/"})
public class DefaultDbAdminRestController {
@Autowired
public DbAdmin dbAdmin;

View File

@@ -36,7 +36,6 @@ public class DbAdminRepository {
public DbAdminRepository(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
/**
@@ -119,7 +118,7 @@ public class DbAdminRepository {
return new PaginatedResult(
new PaginationInfo(page, maxPage, pageSize, maxElement, null, sortKey, sortOrder, new HashSet<>()),
new PaginationInfo(page, maxPage, pageSize, maxElement, null, new HashSet<>()),
results
);
}
@@ -229,7 +228,7 @@ public class DbAdminRepository {
}
return new PaginatedResult(
new PaginationInfo(page, maxPage, pageSize, maxElement, query, sortKey, sortOrder, queryFilters),
new PaginationInfo(page, maxPage, pageSize, maxElement, query, queryFilters),
jpaRepository.search(query, page, pageSize, sortKey, sortOrder, queryFilters).stream()
.map(o -> new DbObject(o, schema))
.toList()

View File

@@ -41,20 +41,13 @@ public class PaginationInfo {
private String query;
private String sortKey;
private String sortOrder;
public PaginationInfo(int currentPage, int maxPage, int pageSize, long maxElement, String query,
String sortKey, String sortOrder, Set<QueryFilter> queryFilters) {
public PaginationInfo(int currentPage, int maxPage, int pageSize, long maxElement, String query, Set<QueryFilter> 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() {
@@ -122,7 +115,14 @@ public class PaginationInfo {
public List<Integer> getAfterPages() {
return IntStream.range(currentPage + 1, Math.min(currentPage + PAGE_RANGE, maxPage + 1)).boxed().collect(Collectors.toList());
}
//
// public String getSortKey() {
// return sortKey;
// }
//
// public String getSortOrder() {
// return sortOrder;
// }
public boolean isLastPage() {
return currentPage == maxPage;

View File

@@ -8,10 +8,10 @@
th:value="${row.getPrimaryKeyValue()}" form="multi-delete-form">
</td>
<td class="text-center row-icons">
<a class="ps-1" th:href="|/dbadmin/model/${schema.getJavaClass().getName()}/edit/${row.getPrimaryKeyValue()}|">
<a class="ps-1" th:href="|/${baseUrl}/model/${schema.getJavaClass().getName()}/edit/${row.getPrimaryKeyValue()}|">
<i class="bi bi-pencil-square"></i></a>
<form class="delete-form" method="POST"
th:action="|/dbadmin/model/${schema.getJavaClass().getName()}/delete/${row.getPrimaryKeyValue()}|">
th:action="|/${baseUrl}/model/${schema.getJavaClass().getName()}/delete/${row.getPrimaryKeyValue()}|">
<button><i class="bi bi-trash"></i></button>
</form>
</td>
@@ -34,7 +34,7 @@
<!-- data-row-field fragment -->
<th:block th:fragment="data_row_field(field, object)">
<th:block th:if="${field.getConnectedType() != null && object.traverse(field) != null}">
<a th:href="|/dbadmin/model/${field.getConnectedType().getName()}/show/${object.traverse(field).getPrimaryKeyValue()}|">
<a th:href="|/${baseUrl}/model/${field.getConnectedType().getName()}/show/${object.traverse(field).getPrimaryKeyValue()}|">
<span th:text="${object.has(field) ? object.traverse(field).getPrimaryKeyValue() : 'NULL'}"></span>
</a>
<p class="p-0 m-0"
@@ -42,7 +42,7 @@
</th:block>
<th:block th:if="${field.getConnectedType() == null}">
<th:block th:if="${field.isPrimaryKey()}">
<a th:href="|/dbadmin/model/${schema.getClassName()}/show/${object.get(field).getValue()}|">
<a th:href="|/${baseUrl}/model/${schema.getClassName()}/show/${object.get(field).getValue()}|">
<span th:text="${object.get(field).getFormattedValue()}">
</span>
</a>
@@ -63,11 +63,11 @@
<th:block th:if="${object.get(field).getValue()}">
<div th:if="${field.isImage()}" class="mb-2">
<img class="thumb-image"
th:src="|/dbadmin/download/${schema.getClassName()}/${field.getJavaName()}/${object.getPrimaryKeyValue()}/image|">
th:src="|/${baseUrl}/download/${schema.getClassName()}/${field.getJavaName()}/${object.getPrimaryKeyValue()}/image|">
</div>
<a class="text-decoration-none null-label"
th:href="|/dbadmin/download/${schema.getClassName()}/${field.getJavaName()}/${object.getPrimaryKeyValue()}|">
th:href="|/${baseUrl}/download/${schema.getClassName()}/${field.getJavaName()}/${object.getPrimaryKeyValue()}|">
<i class="align-middle bi bi-box-arrow-down"></i><span class="align-middle"> Download
<!--/*--> <span class="text-muted">([[ ${object.get(field).getValue().length} ]] bytes)</span> <!--*/-->
</span>

View File

@@ -38,7 +38,7 @@
<h6 class="fw-bold pt-2 ms-3 menu-subheading d-none d-md-block">MENU</h6>
<ul class="sidebar-menu pb-0 mb-0 ">
<li th:class="${#strings.equals(activePage, 'home') ? 'active' : ''}">
<a href="/dbadmin">
<a th:href="|/${baseUrl}|">
<div class="d-flex align-items-center">
<div class="menu-icon">
<i class="bi bi-house"></i>
@@ -50,7 +50,7 @@
</a>
</li>
<li th:class="${#strings.equals(activePage, 'entities') ? 'active' : ''}">
<a href="/dbadmin">
<a th:href="|/${baseUrl}|">
<div class="d-flex align-items-center">
<div class="menu-icon">
<i class="bi bi-database"></i>
@@ -87,7 +87,7 @@
</a>
</li>
<li th:class="${#strings.equals(activePage, 'settings') ? 'active' : ''}">
<a href="/dbadmin/settings">
<a th:href="|/${baseUrl}/settings|">
<div class="d-flex align-items-center">
<div class="menu-icon">
<i class="bi bi-gear"></i>
@@ -127,7 +127,7 @@
<ul class="pagination me-3">
<li class="page-item" th:if="${page.getPagination().getCurrentPage() != 1}">
<a class="page-link"
th:href="@{|/dbadmin/model/${schema.getClassName()}${page.getPagination().getLink(page.getPagination.getCurrentPage() - 1)}|}"
th:href="@{|/${baseUrl}/model/${schema.getClassName()}${page.getPagination().getLink(page.getPagination.getCurrentPage() - 1)}|}"
aria-label="Previous">
<span aria-hidden="true">&laquo;</span>
<span class="sr-only">Previous</span>
@@ -136,7 +136,7 @@
<li class="page-item" th:each="p : ${page.getPagination().getBeforePages()}">
<a class="page-link"
th:href="@{|/dbadmin/model/${schema.getClassName()}${page.getPagination().getLink(p)}|}" th:text="${p}"></a>
th:href="@{|/${baseUrl}/model/${schema.getClassName()}${page.getPagination().getLink(p)}|}" th:text="${p}"></a>
</li>
<li class="page-item active">
@@ -145,13 +145,13 @@
<li class="page-item" th:each="p : ${page.getPagination().getAfterPages()}">
<a class="page-link"
th:href="@{|/dbadmin/model/${schema.getClassName()}${page.getPagination().getLink(p)}|}"
th:href="@{|/${baseUrl}/model/${schema.getClassName()}${page.getPagination().getLink(p)}|}"
th:text="${p}"></a>
</li>
<li class="page-item">
<a class="page-link"
th:if="${!page.getPagination().isLastPage()}"
th:href="@{|/dbadmin/model/${schema.getClassName()}${page.getPagination().getLink(page.getPagination.getCurrentPage() + 1)}|}"
th:href="@{|/${baseUrl}/model/${schema.getClassName()}${page.getPagination().getLink(page.getPagination.getCurrentPage() + 1)}|}"
aria-label="Next">
<span class="sr-only">Next</span>
<span aria-hidden="true">&raquo;</span>
@@ -159,7 +159,7 @@
</li>
</ul>
<div class="me-3">
<form method="GET" th:action="@{|/dbadmin/model/${schema.getClassName()}|}">
<form method="GET" th:action="@{|/${baseUrl}/model/${schema.getClassName()}|}">
<input type="hidden" th:value="${page.getPagination().getCurrentPage()}" th:name="page">
<input type="hidden" th:value="${query}" th:name="query">
<input type="hidden" name="pageSize">
@@ -187,7 +187,7 @@
<div class="d-flex align-items-center" th:if="${page.getPagination().getMaxPage() == 1}">
<div class="me-3">
<form method="GET" th:action="@{|/dbadmin/model/${schema.getClassName()}|}">
<form method="GET" th:action="@{|/${baseUrl}/model/${schema.getClassName()}|}">
<input type="hidden" th:value="${page.getPagination().getCurrentPage()}" th:name="page">
<input type="hidden" th:value="${query}" th:name="query">
<input type="hidden" name="pageSize">

View File

@@ -7,7 +7,7 @@
<p>This table contains no data.</p>
</div>
<div th:if="${results.size() > 0}">
<form id="multi-delete-form" th:action="|/dbadmin/model/${schema.getClassName()}/delete|" method="POST">
<form id="multi-delete-form" th:action="|/${baseUrl}/model/${schema.getClassName()}/delete|" method="POST">
</form>
<nav th:replace="~{fragments/resources :: pagination(${page})}">
</nav>
@@ -29,17 +29,17 @@
<div class="align-items-center">
<h4 class="m-0" th:if="${page}">
<th:block th:if="${sortKey != field.getJavaName()}" >
<a th:href="@{|/dbadmin/model/${schema.getClassName()}${page.getPagination().getSortedPageLink(field.getJavaName(), 'DESC')}|}">
<a th:href="@{|/${baseUrl}/model/${schema.getClassName()}${page.getPagination().getSortedPageLink(field.getJavaName(), 'DESC')}|}">
<i title="Sort" class="bi bi-caret-up"></i>
</a>
</th:block>
<th:block th:unless="${sortKey != field.getJavaName()}">
<a th:if="${sortOrder == 'DESC'}"
th:href="@{|/dbadmin/model/${schema.getClassName()}${page.getPagination().getSortedPageLink(field.getJavaName(), 'ASC')}|}">
th:href="@{|/${baseUrl}/model/${schema.getClassName()}${page.getPagination().getSortedPageLink(field.getJavaName(), 'ASC')}|}">
<i title="Sort" class="bi bi-caret-down-fill"></i>
</a>
<a th:if="${sortOrder == 'ASC'}"
th:href="@{|/dbadmin/model/${schema.getClassName()}${page.getPagination().getSortedPageLink(field.getJavaName(), 'DESC')}|}">
th:href="@{|/${baseUrl}/model/${schema.getClassName()}${page.getPagination().getSortedPageLink(field.getJavaName(), 'DESC')}|}">
<i title="Sort" class="bi bi-caret-up-fill"></i>
</a>
</th:block>

View File

@@ -9,7 +9,7 @@
<div th:replace="~{fragments/resources :: sidebar('entities')}"></div>
<div class="main-content bg-lighter">
<h1 class="fw-bold mb-4"><i class="align-middle bi bi-house"></i><span class="align-middle"> Home</span></h1>
<form action="/dbadmin" method="GET">
<form th:action="${baseUrl}" method="GET">
<div class="input-group">
<input type="text" th:value="${query}"
placeholder="Type a class or a table name and press ENTER to search"
@@ -31,7 +31,7 @@
<tr th:each="schema : ${schemas}">
<td>
<a th:text="${schema.getTableName()}"
th:href="|/dbadmin/model/${schema.getClassName()}|"></a>
th:href="|/${baseUrl}/model/${schema.getClassName()}|"></a>
</td>
<td>
<span th:text="${counts.get(schema.getClassName())}"></span>
@@ -40,8 +40,8 @@
<span th:text="${schema.getClassName()}"></span>
</td>
<td class="text-end row-icons">
<a title="List all" th:href="|/dbadmin/model/${schema.getClassName()}|"><i class="bi bi-list"></i></i></a>
<a title="Create new" th:href="|/dbadmin/model/${schema.getClassName()}/create|"><i class="bi bi-plus-square"></i></a>
<a title="List all" th:href="|/${baseUrl}/model/${schema.getClassName()}|"><i class="bi bi-list"></i></i></a>
<a title="Create new" th:href="|/${baseUrl}/model/${schema.getClassName()}/create|"><i class="bi bi-plus-square"></i></a>
</td>
</tr>
</table>

View File

@@ -13,9 +13,9 @@
<h1 class="fw-bold mb-4">
<i class="align-middle bi bi-database"></i>
<span class="align-middle"><a href="/dbadmin">Entities</a></span>
<span class="align-middle"><a th:href="|/${baseUrl}|">Entities</a></span>
<i class="align-middle bi bi-chevron-double-right"></i>
<a class="align-middle" th:href="|/dbadmin/model/${schema.getJavaClass().getName()}|">
<a class="align-middle" th:href="|/${baseUrl}/model/${schema.getJavaClass().getName()}|">
[[ ${schema.getJavaClass().getSimpleName()} ]] </a>
<i class="align-middle bi bi-chevron-double-right"></i>
<span class="align-middle" th:text="${create ? 'Create' : 'Edit'}"></span>
@@ -28,7 +28,7 @@
<div class="col">
<div class="box">
<h3 class="fw-bold mb-4" th:text="${create ? schema.getJavaClass().getSimpleName() : object.getDisplayName()}"></h3>
<form class="form" enctype="multipart/form-data" method="post" th:action="|/dbadmin/model/${className}/create|">
<form class="form" enctype="multipart/form-data" method="post" th:action="|/${baseUrl}/model/${className}/create|">
<input type="hidden" name="__dbadmin_create" th:value="${create}">
<div th:each="field : ${schema.getSortedFields()}" class="mt-2">
<label th:for="|__id_${field.getName()}|" class="mb-1 fw-bold">
@@ -70,7 +70,7 @@
<span>Keep current data</span>
<div th:if="${field.isImage()}" class="mb-2">
<img class="thumb-image" th:id="|__thumb_${field.getName()}|"
th:src="|/dbadmin/download/${schema.getClassName()}/${field.getJavaName()}/${object.getPrimaryKeyValue()}/image|">
th:src="|/${baseUrl}/download/${schema.getClassName()}/${field.getJavaName()}/${object.getPrimaryKeyValue()}/image|">
</div>
</div>
<!--/*--> File input <!--*/-->
@@ -94,7 +94,7 @@
<div class="d-flex mt-4 justify-content-between">
<a th:href="|/dbadmin/model/${schema.getClassName()}|" class="ui-btn btn btn-secondary">Cancel</a>
<a th:href="|/${baseUrl}/model/${schema.getClassName()}|" class="ui-btn btn btn-secondary">Cancel</a>
<input type="submit" class="ui-btn btn btn-primary" th:value="${object != null ? 'Save' : 'Create'}">
</div>
</form>

View File

@@ -10,19 +10,19 @@
<div class="main-content bg-lighter">
<th:block th:replace="~{fragments/resources :: alerts}"></th:block>
<h1 class="fw-bold mb-4"><i class="align-middle bi bi-database"></i>
<span class="align-middle"><a href="/dbadmin">Entities</a></span>
<span class="align-middle"><a th:href="|/${baseUrl}|">Entities</a></span>
<i class="align-middle bi bi-chevron-double-right"></i>
<span class="align-middle"> [[ ${schema.getJavaClass().getSimpleName()} ]] </span>
</h1>
<div class="row mt-4">
<div th:class="${schema.getFilterableFields().isEmpty() ? 'col' : 'col-9'}">
<div class="w-100 d-flex inner-navigation">
<a th:href="|/dbadmin/model/${className}|" class="active">
<a th:href="|/${baseUrl}/model/${className}|" class="active">
<div class="ui-tab ps-5 pe-5 p-3">
<i class="bi bi-database pe-2"></i> DATA
</div>
</a>
<a th:href="|/dbadmin/model/${className}/schema|">
<a th:href="|/${baseUrl}/model/${className}/schema|">
<div class="ui-tab ps-5 pe-5 p-3">
<i class="bi bi-table pe-2"></i> SCHEMA
</div>
@@ -31,7 +31,7 @@
</div>
</div>
<div class="box with-navigation">
<form th:action="|/dbadmin/model/${className}|" method="GET" class="mb-3">
<form th:action="|/${baseUrl}/model/${className}|" method="GET" class="mb-3">
<div class="input-group">
<span class="input-group-text"><i class="bi bi-search"></i></span>
<input type="text" th:value="${query}"
@@ -63,7 +63,7 @@
<h3>
<a title="Create new item"
th:href="|/dbadmin/model/${schema.getClassName()}/create|"><i class="bi bi-plus-square"></i></a>
th:href="|/${baseUrl}/model/${schema.getClassName()}/create|"><i class="bi bi-plus-square"></i></a>
</h3>
</div>

View File

@@ -10,20 +10,20 @@
<div th:replace="~{fragments/resources :: sidebar('entities')}"></div>
<div class="main-content bg-lighter">
<h1 class="fw-bold mb-4"><i class="bi bi-database"></i>
<a class="align-middle" href="/dbadmin">Entities</a>
<a class="align-middle" th:href="|/${baseUrl}|">Entities</a>
<i class="align-middle bi bi-chevron-double-right"></i>
<a class="align-middle" th:href="|/dbadmin/model/${schema.getJavaClass().getName()}|"> [[ ${schema.getJavaClass().getSimpleName()} ]]</a>
<a class="align-middle" th:href="|/${baseUrl}/model/${schema.getJavaClass().getName()}|"> [[ ${schema.getJavaClass().getSimpleName()} ]]</a>
<i class="align-middle bi bi-chevron-double-right"></i><span class="align-middle"> Schema</span>
</h1>
<div class="row mt-4">
<div class="col">
<div class="w-100 d-flex inner-navigation">
<a th:href="|/dbadmin/model/${schema.getJavaClass().getName()}|">
<a th:href="|/${baseUrl}/model/${schema.getJavaClass().getName()}|">
<div class="ui-tab ps-5 pe-5 p-3">
<i class="bi bi-database pe-2"></i> DATA
</div>
</a>
<a th:href="|/dbadmin/model/${schema.getJavaClass().getName()}/schema|" class="active">
<a th:href="|/${baseUrl}/model/${schema.getJavaClass().getName()}/schema|" class="active">
<div class="ui-tab ps-5 pe-5 p-3">
<i class="bi bi-table pe-2"></i> SCHEMA
</div>
@@ -40,7 +40,7 @@
</span>
</h3>
<h3><a title="Create new item"
th:href="|/dbadmin/model/${schema.getClassName()}/create|"><i class="bi bi-plus-square"></i></a></h3>
th:href="|/${baseUrl}/model/${schema.getClassName()}/create|"><i class="bi bi-plus-square"></i></a></h3>
</div>
<table class="table table-striped align-middle">

View File

@@ -10,9 +10,9 @@
<div th:replace="~{fragments/resources :: sidebar('entities')}"></div>
<div class="main-content bg-lighter">
<h1 class="fw-bold mb-4"><i class="align-middle bi bi-database"></i>
<a class="align-middle" href="/dbadmin">Entities</a>
<a class="align-middle" th:href="|/${baseUrl}|">Entities</a>
<i class="align-middle bi bi-chevron-double-right"></i>
<a class="align-middle" th:href="|/dbadmin/model/${schema.getJavaClass().getName()}|">
<a class="align-middle" th:href="|/${baseUrl}/model/${schema.getJavaClass().getName()}|">
[[ ${schema.getJavaClass().getSimpleName()} ]]</a>
<i class="align-middle bi bi-chevron-double-right"></i>
<span class="align-middle"> [[ ${object.getDisplayName()} ]]</span>
@@ -22,7 +22,7 @@
<div class="box">
<div class="d-flex justify-content-between">
<h3 class="mb-3 fw-bold" th:text="${object.getDisplayName()}"></h3>
<h3><a th:href="|/dbadmin/model/${schema.getClassName()}/edit/${object.getPrimaryKeyValue()}|">
<h3><a th:href="|/${baseUrl}/model/${schema.getClassName()}/edit/${object.getPrimaryKeyValue()}|">
<i class="bi bi-pencil"></i></a>
</h3>
</div>

View File

@@ -10,7 +10,7 @@
<div class="main-content bg-lighter">
<th:block th:replace="~{fragments/resources :: alerts}"></th:block>
<h1 class="fw-bold mb-4"><i class="align-middle bi bi-gear"></i>
<span class="align-middle"><a href="/dbadmin">Settings</a></span>
<span class="align-middle"><a th:href="|/${baseUrl}|">Settings</a></span>
</h1>
<div class="row mt-4">
<div class="col">