mirror of
https://github.com/dalbodeule/snap-admin.git
synced 2025-06-09 05:48:20 +00:00
0.0.4
This commit is contained in:
parent
f82761d538
commit
e7a5328050
44
README.md
44
README.md
@ -1,10 +1,18 @@
|
|||||||
# Spring Boot Database Admin Panel
|
# Spring Boot Database Admin Panel
|
||||||
|
|
||||||
An add-on for Spring Boot apps that automatically generates a database admin panel based on your `@Entity` annotated classes.
|
Generate a powerful CRUD management dashboard for your Spring Boot application in a few minutes.
|
||||||
The panel offers basic CRUD and search functionalities to manage the database.
|
|
||||||
|
Spring Boot Database Admin scans your `@Entity` classes to generate a simple but powerful database management interface.
|
||||||
|
|
||||||
[](https://i.imgur.com/Nz19f8e.png)
|
[](https://i.imgur.com/Nz19f8e.png)
|
||||||
|
|
||||||
|
Features:
|
||||||
|
* List objects with pagination and sorting
|
||||||
|
* Show detailed object page which also includes `@OneToMany`, `@ManyToMany`, etc... fields
|
||||||
|
* Create/Edit objects
|
||||||
|
* Search
|
||||||
|
* Customization
|
||||||
|
|
||||||
The code is in a very early version and I'm trying to collect as much feedback as possible in order to fix the
|
The code is in a very early version and I'm trying to collect as much feedback as possible in order to fix the
|
||||||
most common issues that will inevitably arise. If you are so kind to try the project and you find something
|
most common issues that will inevitably arise. If you are so kind to try the project and you find something
|
||||||
broken, please report it as an issue and I will try to take a look at it.
|
broken, please report it as an issue and I will try to take a look at it.
|
||||||
@ -17,44 +25,40 @@ broken, please report it as an issue and I will try to take a look at it.
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>tech.ailef</groupId>
|
<groupId>tech.ailef</groupId>
|
||||||
<artifactId>spring-boot-db-admin</artifactId>
|
<artifactId>spring-boot-db-admin</artifactId>
|
||||||
<version>0.0.1-SNAPSHOT</version>
|
<version>0.0.4</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
```
|
```
|
||||||
|
|
||||||
2. A few configuration steps are required on your code in order to integrate the library in your project. If you don't want
|
2. A few simple configuration steps are required on your end in order to integrate the library into your project. If you don't want
|
||||||
to test on your own code, you can clone the [test project](https://github.com/aileftech/spring-boot-database-admin-test) which provides
|
to test on your own code, you can clone the [test project](https://github.com/aileftech/spring-boot-database-admin-test) which provides
|
||||||
a sample database and already configured code.
|
a sample database and already configured code.
|
||||||
|
|
||||||
If you wish to integrate it into your project instead, the first step is create creating a configuration class:
|
If you wish to integrate it into your project instead, the first step is adding these to your `application.properties` file:
|
||||||
|
|
||||||
```
|
```
|
||||||
@DbAdminConfiguration
|
# Optional, default true
|
||||||
@Configuration
|
dbadmin.enabled=true
|
||||||
public class TestConfiguration implements DbAdminAppConfiguration {
|
|
||||||
|
|
||||||
@Override
|
# The first-level part of the URL path: http://localhost:8080/${baseUrl}/
|
||||||
public String getModelsPackage() {
|
dbadmin.baseUrl=admin
|
||||||
return "your.models.package"; // The package where your @Entity classes are located
|
|
||||||
}
|
# The package that contains your @Entity classes
|
||||||
}
|
dbadmin.modelsPackage=tech.ailef.dbadmin.test.models
|
||||||
```
|
```
|
||||||
|
|
||||||
The last step is to annotate your `@SpringBootApplication` class containing the `main` method with the following:
|
The last step is to annotate your `@SpringBootApplication` class containing the `main` method with the following:
|
||||||
|
|
||||||
```
|
```
|
||||||
@ComponentScan(basePackages = {"your.project.root.package", "tech.ailef.dbadmin"})
|
@ImportAutoConfiguration(DbAdminAutoConfiguration.class)
|
||||||
@EnableJpaRepositories(basePackages = {"your.project.root.package", "tech.ailef.dbadmin"})
|
|
||||||
@EntityScan(basePackages = {"your.project.root.package", "tech.ailef.dbadmin"})
|
|
||||||
```
|
```
|
||||||
|
|
||||||
This tells Spring to scan the `tech.ailef.dbadmin` packages and look for components there as well. Remember to also include
|
This will autoconfigure the various DbAdmin components when your application starts.
|
||||||
your original root package as shown, or Spring will not scan it otherwise.
|
|
||||||
|
|
||||||
3. At this point, when you run your application, you should be able to visit `http://localhost:$PORT/dbadmin` and access the web interface.
|
3. At this point, when you run your application, you should be able to visit `http://localhost:$PORT/${baseUrl}` and access the web interface.
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
Once you are correctly running Spring Boot Database Admin you will see the web interface at `http://localhost:$PORT/dbadmin`. Most of the features are already available with the basic configuration. However, some customization to the interface might be applied by using appropriate annotations on your classes fields or methods.
|
Once you are correctly running Spring Boot Database Admin, you will be able to access the web interface. Most of the features are already available with the basic configuration. However, some customization to the interface might be applied by using appropriate annotations on your classes fields or methods.
|
||||||
The following annotations are supported.
|
The following annotations are supported.
|
||||||
|
|
||||||
### @DisplayName
|
### @DisplayName
|
||||||
|
2
pom.xml
2
pom.xml
@ -11,7 +11,7 @@
|
|||||||
</parent>
|
</parent>
|
||||||
<groupId>tech.ailef</groupId>
|
<groupId>tech.ailef</groupId>
|
||||||
<artifactId>spring-boot-db-admin</artifactId>
|
<artifactId>spring-boot-db-admin</artifactId>
|
||||||
<version>0.0.3</version>
|
<version>0.0.4</version>
|
||||||
<name>spring-boot-db-admin</name>
|
<name>spring-boot-db-admin</name>
|
||||||
<description>Srping Boot DB Admin Dashboard</description>
|
<description>Srping Boot DB Admin Dashboard</description>
|
||||||
<properties>
|
<properties>
|
||||||
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -6,11 +6,13 @@ import java.lang.reflect.ParameterizedType;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.beans.factory.config.BeanDefinition;
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
|
import org.springframework.boot.autoconfigure.web.ServerProperties;
|
||||||
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
|
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
|
||||||
import org.springframework.core.type.filter.AnnotationTypeFilter;
|
import org.springframework.core.type.filter.AnnotationTypeFilter;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
@ -25,8 +27,6 @@ import jakarta.persistence.ManyToOne;
|
|||||||
import jakarta.persistence.OneToMany;
|
import jakarta.persistence.OneToMany;
|
||||||
import jakarta.persistence.OneToOne;
|
import jakarta.persistence.OneToOne;
|
||||||
import jakarta.persistence.PersistenceContext;
|
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.annotations.DisplayFormat;
|
||||||
import tech.ailef.dbadmin.dbmapping.AdvancedJpaRepository;
|
import tech.ailef.dbadmin.dbmapping.AdvancedJpaRepository;
|
||||||
import tech.ailef.dbadmin.dbmapping.DbField;
|
import tech.ailef.dbadmin.dbmapping.DbField;
|
||||||
@ -46,6 +46,8 @@ import tech.ailef.dbadmin.misc.Utils;
|
|||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
public class DbAdmin {
|
public class DbAdmin {
|
||||||
|
private static final Logger logger = Logger.getLogger(DbAdmin.class.getName());
|
||||||
|
|
||||||
@PersistenceContext
|
@PersistenceContext
|
||||||
private EntityManager entityManager;
|
private EntityManager entityManager;
|
||||||
|
|
||||||
@ -53,17 +55,8 @@ public class DbAdmin {
|
|||||||
|
|
||||||
private String modelsPackage;
|
private String modelsPackage;
|
||||||
|
|
||||||
public DbAdmin(@Autowired EntityManager entityManager) {
|
public DbAdmin(@Autowired EntityManager entityManager, @Autowired DbAdminProperties properties) {
|
||||||
Map<String, Object> beansWithAnnotation =
|
this.modelsPackage = properties.getModelsPackage();
|
||||||
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();
|
|
||||||
this.entityManager = entityManager;
|
this.entityManager = entityManager;
|
||||||
|
|
||||||
ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
|
ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
|
||||||
@ -73,6 +66,9 @@ public class DbAdmin {
|
|||||||
for (BeanDefinition bd : beanDefs) {
|
for (BeanDefinition bd : beanDefs) {
|
||||||
schemas.add(processBeanDefinition(bd));
|
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());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -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 {
|
||||||
|
|
||||||
|
}
|
51
src/main/java/tech/ailef/dbadmin/DbAdminProperties.java
Normal file
51
src/main/java/tech/ailef/dbadmin/DbAdminProperties.java
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -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();
|
|
||||||
}
|
|
@ -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 {
|
|
||||||
}
|
|
@ -28,6 +28,7 @@ import org.springframework.web.servlet.mvc.support.RedirectAttributes;
|
|||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import tech.ailef.dbadmin.DbAdmin;
|
import tech.ailef.dbadmin.DbAdmin;
|
||||||
|
import tech.ailef.dbadmin.DbAdminProperties;
|
||||||
import tech.ailef.dbadmin.dbmapping.DbAdminRepository;
|
import tech.ailef.dbadmin.dbmapping.DbAdminRepository;
|
||||||
import tech.ailef.dbadmin.dbmapping.DbObject;
|
import tech.ailef.dbadmin.dbmapping.DbObject;
|
||||||
import tech.ailef.dbadmin.dbmapping.DbObjectSchema;
|
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.
|
* The main DbAdmin controller that register most of the routes of the web interface.
|
||||||
*/
|
*/
|
||||||
@Controller
|
@Controller
|
||||||
@RequestMapping("/dbadmin")
|
@RequestMapping(value= {"/${dbadmin.baseUrl}", "/${dbadmin.baseUrl}/"})
|
||||||
public class DefaultDbAdminController {
|
public class DefaultDbAdminController {
|
||||||
|
@Autowired
|
||||||
|
private DbAdminProperties properties;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private DbAdminRepository repository;
|
private DbAdminRepository repository;
|
||||||
|
|
||||||
@ -163,7 +167,7 @@ public class DefaultDbAdminController {
|
|||||||
return "model/list";
|
return "model/list";
|
||||||
|
|
||||||
} catch (InvalidPageException e) {
|
} 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());
|
attr.addFlashAttribute("error", e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
return "redirect:/dbadmin/model/" + className;
|
return "redirect:/" + properties.getBaseUrl() + "/model/" + className;
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping(value="/model/{className}/delete")
|
@PostMapping(value="/model/{className}/delete")
|
||||||
@ -287,7 +291,7 @@ public class DefaultDbAdminController {
|
|||||||
if (countDeleted > 0)
|
if (countDeleted > 0)
|
||||||
attr.addFlashAttribute("message", "Deleted " + countDeleted + " of " + ids.length + " items");
|
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")
|
@PostMapping(value="/model/{className}/create")
|
||||||
@ -397,11 +401,11 @@ public class DefaultDbAdminController {
|
|||||||
|
|
||||||
if (attr.getFlashAttributes().containsKey("error")) {
|
if (attr.getFlashAttributes().containsKey("error")) {
|
||||||
if (create)
|
if (create)
|
||||||
return "redirect:/dbadmin/model/" + schema.getClassName() + "/create";
|
return "redirect:/" + properties.getBaseUrl() + "/model/" + schema.getClassName() + "/create";
|
||||||
else
|
else
|
||||||
return "redirect:/dbadmin/model/" + schema.getClassName() + "/edit/" + pkValue;
|
return "redirect:/" + properties.getBaseUrl() + "/model/" + schema.getClassName() + "/edit/" + pkValue;
|
||||||
} else {
|
} else {
|
||||||
return "redirect:/dbadmin/model/" + schema.getClassName() + "/show/" + pkValue;
|
return "redirect:/" + properties.getBaseUrl() + "/model/" + schema.getClassName() + "/show/" + pkValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ import tech.ailef.dbadmin.exceptions.DbAdminException;
|
|||||||
* Controller to serve file or images (`@DisplayImage`)
|
* Controller to serve file or images (`@DisplayImage`)
|
||||||
*/
|
*/
|
||||||
@Controller
|
@Controller
|
||||||
@RequestMapping("/dbadmin/download")
|
@RequestMapping(value = {"/${dbadmin.baseUrl}/download", "/${dbadmin.baseUrl}/download/"})
|
||||||
public class DownloadController {
|
public class DownloadController {
|
||||||
@Autowired
|
@Autowired
|
||||||
private DbAdminRepository repository;
|
private DbAdminRepository repository;
|
||||||
|
@ -2,10 +2,12 @@ package tech.ailef.dbadmin.controller;
|
|||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||||
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import tech.ailef.dbadmin.DbAdminProperties;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class registers some ModelAttribute objects that are
|
* This class registers some ModelAttribute objects that are
|
||||||
@ -14,6 +16,9 @@ import jakarta.servlet.http.HttpServletRequest;
|
|||||||
@ControllerAdvice
|
@ControllerAdvice
|
||||||
public class GlobalController {
|
public class GlobalController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private DbAdminProperties props;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A multi valued map containing the query parameters. It is used primarily
|
* A multi valued map containing the query parameters. It is used primarily
|
||||||
* in building complex URL when performing faceted search with multiple filters.
|
* 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) {
|
public Map<String, String[]> getQueryParams(HttpServletRequest request) {
|
||||||
return request.getParameterMap();
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
@ -20,7 +20,7 @@ import tech.ailef.dbadmin.dto.AutocompleteSearchResult;
|
|||||||
* API controller for autocomplete results
|
* API controller for autocomplete results
|
||||||
*/
|
*/
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/dbadmin/api/autocomplete")
|
@RequestMapping(value= {"/${dbadmin.baseUrl}/api/autocomplete", "/${dbadmin.baseUrl}/api/autocomplete/"})
|
||||||
public class AutocompleteController {
|
public class AutocompleteController {
|
||||||
@Autowired
|
@Autowired
|
||||||
private DbAdmin dbAdmin;
|
private DbAdmin dbAdmin;
|
||||||
|
@ -19,7 +19,7 @@ import tech.ailef.dbadmin.dto.PaginatedResult;
|
|||||||
import tech.ailef.dbadmin.exceptions.DbAdminException;
|
import tech.ailef.dbadmin.exceptions.DbAdminException;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/dbadmin/api")
|
@RequestMapping(value = {"/${dbadmin.baseUrl}/api", "/${dbadmin.baseUrl}/api/"})
|
||||||
public class DefaultDbAdminRestController {
|
public class DefaultDbAdminRestController {
|
||||||
@Autowired
|
@Autowired
|
||||||
public DbAdmin dbAdmin;
|
public DbAdmin dbAdmin;
|
||||||
|
@ -36,7 +36,6 @@ public class DbAdminRepository {
|
|||||||
|
|
||||||
public DbAdminRepository(JdbcTemplate jdbcTemplate) {
|
public DbAdminRepository(JdbcTemplate jdbcTemplate) {
|
||||||
this.jdbcTemplate = jdbcTemplate;
|
this.jdbcTemplate = jdbcTemplate;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -119,7 +118,7 @@ public class DbAdminRepository {
|
|||||||
|
|
||||||
|
|
||||||
return new PaginatedResult(
|
return new PaginatedResult(
|
||||||
new PaginationInfo(page, maxPage, pageSize, maxElement, null, sortKey, sortOrder, new HashSet<>()),
|
new PaginationInfo(page, maxPage, pageSize, maxElement, null, new HashSet<>()),
|
||||||
results
|
results
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -229,7 +228,7 @@ public class DbAdminRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return new PaginatedResult(
|
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()
|
jpaRepository.search(query, page, pageSize, sortKey, sortOrder, queryFilters).stream()
|
||||||
.map(o -> new DbObject(o, schema))
|
.map(o -> new DbObject(o, schema))
|
||||||
.toList()
|
.toList()
|
||||||
|
@ -41,20 +41,13 @@ public class PaginationInfo {
|
|||||||
|
|
||||||
private String query;
|
private String query;
|
||||||
|
|
||||||
private String sortKey;
|
public PaginationInfo(int currentPage, int maxPage, int pageSize, long maxElement, String query, Set<QueryFilter> queryFilters) {
|
||||||
|
|
||||||
private String sortOrder;
|
|
||||||
|
|
||||||
public PaginationInfo(int currentPage, int maxPage, int pageSize, long maxElement, String query,
|
|
||||||
String sortKey, String sortOrder, Set<QueryFilter> queryFilters) {
|
|
||||||
this.currentPage = currentPage;
|
this.currentPage = currentPage;
|
||||||
this.maxPage = maxPage;
|
this.maxPage = maxPage;
|
||||||
this.pageSize = pageSize;
|
this.pageSize = pageSize;
|
||||||
this.query = query;
|
this.query = query;
|
||||||
this.maxElement = maxElement;
|
this.maxElement = maxElement;
|
||||||
this.queryFilters = queryFilters;
|
this.queryFilters = queryFilters;
|
||||||
this.sortKey = sortKey;
|
|
||||||
this.sortOrder = sortOrder;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getCurrentPage() {
|
public int getCurrentPage() {
|
||||||
@ -122,7 +115,14 @@ public class PaginationInfo {
|
|||||||
public List<Integer> getAfterPages() {
|
public List<Integer> getAfterPages() {
|
||||||
return IntStream.range(currentPage + 1, Math.min(currentPage + PAGE_RANGE, maxPage + 1)).boxed().collect(Collectors.toList());
|
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() {
|
public boolean isLastPage() {
|
||||||
return currentPage == maxPage;
|
return currentPage == maxPage;
|
||||||
|
@ -8,10 +8,10 @@
|
|||||||
th:value="${row.getPrimaryKeyValue()}" form="multi-delete-form">
|
th:value="${row.getPrimaryKeyValue()}" form="multi-delete-form">
|
||||||
</td>
|
</td>
|
||||||
<td class="text-center row-icons">
|
<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>
|
<i class="bi bi-pencil-square"></i></a>
|
||||||
<form class="delete-form" method="POST"
|
<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>
|
<button><i class="bi bi-trash"></i></button>
|
||||||
</form>
|
</form>
|
||||||
</td>
|
</td>
|
||||||
@ -34,7 +34,7 @@
|
|||||||
<!-- data-row-field fragment -->
|
<!-- data-row-field fragment -->
|
||||||
<th:block th:fragment="data_row_field(field, object)">
|
<th:block th:fragment="data_row_field(field, object)">
|
||||||
<th:block th:if="${field.getConnectedType() != null && object.traverse(field) != null}">
|
<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>
|
<span th:text="${object.has(field) ? object.traverse(field).getPrimaryKeyValue() : 'NULL'}"></span>
|
||||||
</a>
|
</a>
|
||||||
<p class="p-0 m-0"
|
<p class="p-0 m-0"
|
||||||
@ -42,7 +42,7 @@
|
|||||||
</th:block>
|
</th:block>
|
||||||
<th:block th:if="${field.getConnectedType() == null}">
|
<th:block th:if="${field.getConnectedType() == null}">
|
||||||
<th:block th:if="${field.isPrimaryKey()}">
|
<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 th:text="${object.get(field).getFormattedValue()}">
|
||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
@ -63,11 +63,11 @@
|
|||||||
<th:block th:if="${object.get(field).getValue()}">
|
<th:block th:if="${object.get(field).getValue()}">
|
||||||
<div th:if="${field.isImage()}" class="mb-2">
|
<div th:if="${field.isImage()}" class="mb-2">
|
||||||
<img class="thumb-image"
|
<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>
|
</div>
|
||||||
|
|
||||||
<a class="text-decoration-none null-label"
|
<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
|
<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 class="text-muted">([[ ${object.get(field).getValue().length} ]] bytes)</span> <!--*/-->
|
||||||
</span>
|
</span>
|
||||||
|
@ -38,7 +38,7 @@
|
|||||||
<h6 class="fw-bold pt-2 ms-3 menu-subheading d-none d-md-block">MENU</h6>
|
<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 ">
|
<ul class="sidebar-menu pb-0 mb-0 ">
|
||||||
<li th:class="${#strings.equals(activePage, 'home') ? 'active' : ''}">
|
<li th:class="${#strings.equals(activePage, 'home') ? 'active' : ''}">
|
||||||
<a href="/dbadmin">
|
<a th:href="|/${baseUrl}|">
|
||||||
<div class="d-flex align-items-center">
|
<div class="d-flex align-items-center">
|
||||||
<div class="menu-icon">
|
<div class="menu-icon">
|
||||||
<i class="bi bi-house"></i>
|
<i class="bi bi-house"></i>
|
||||||
@ -50,7 +50,7 @@
|
|||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li th:class="${#strings.equals(activePage, 'entities') ? 'active' : ''}">
|
<li th:class="${#strings.equals(activePage, 'entities') ? 'active' : ''}">
|
||||||
<a href="/dbadmin">
|
<a th:href="|/${baseUrl}|">
|
||||||
<div class="d-flex align-items-center">
|
<div class="d-flex align-items-center">
|
||||||
<div class="menu-icon">
|
<div class="menu-icon">
|
||||||
<i class="bi bi-database"></i>
|
<i class="bi bi-database"></i>
|
||||||
@ -87,7 +87,7 @@
|
|||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li th:class="${#strings.equals(activePage, 'settings') ? 'active' : ''}">
|
<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="d-flex align-items-center">
|
||||||
<div class="menu-icon">
|
<div class="menu-icon">
|
||||||
<i class="bi bi-gear"></i>
|
<i class="bi bi-gear"></i>
|
||||||
@ -127,7 +127,7 @@
|
|||||||
<ul class="pagination me-3">
|
<ul class="pagination me-3">
|
||||||
<li class="page-item" th:if="${page.getPagination().getCurrentPage() != 1}">
|
<li class="page-item" th:if="${page.getPagination().getCurrentPage() != 1}">
|
||||||
<a class="page-link"
|
<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">
|
aria-label="Previous">
|
||||||
<span aria-hidden="true">«</span>
|
<span aria-hidden="true">«</span>
|
||||||
<span class="sr-only">Previous</span>
|
<span class="sr-only">Previous</span>
|
||||||
@ -136,7 +136,7 @@
|
|||||||
|
|
||||||
<li class="page-item" th:each="p : ${page.getPagination().getBeforePages()}">
|
<li class="page-item" th:each="p : ${page.getPagination().getBeforePages()}">
|
||||||
<a class="page-link"
|
<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>
|
||||||
|
|
||||||
<li class="page-item active">
|
<li class="page-item active">
|
||||||
@ -145,13 +145,13 @@
|
|||||||
|
|
||||||
<li class="page-item" th:each="p : ${page.getPagination().getAfterPages()}">
|
<li class="page-item" th:each="p : ${page.getPagination().getAfterPages()}">
|
||||||
<a class="page-link"
|
<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>
|
th:text="${p}"></a>
|
||||||
</li>
|
</li>
|
||||||
<li class="page-item">
|
<li class="page-item">
|
||||||
<a class="page-link"
|
<a class="page-link"
|
||||||
th:if="${!page.getPagination().isLastPage()}"
|
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">
|
aria-label="Next">
|
||||||
<span class="sr-only">Next</span>
|
<span class="sr-only">Next</span>
|
||||||
<span aria-hidden="true">»</span>
|
<span aria-hidden="true">»</span>
|
||||||
@ -159,7 +159,7 @@
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<div class="me-3">
|
<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="${page.getPagination().getCurrentPage()}" th:name="page">
|
||||||
<input type="hidden" th:value="${query}" th:name="query">
|
<input type="hidden" th:value="${query}" th:name="query">
|
||||||
<input type="hidden" name="pageSize">
|
<input type="hidden" name="pageSize">
|
||||||
@ -187,7 +187,7 @@
|
|||||||
|
|
||||||
<div class="d-flex align-items-center" th:if="${page.getPagination().getMaxPage() == 1}">
|
<div class="d-flex align-items-center" th:if="${page.getPagination().getMaxPage() == 1}">
|
||||||
<div class="me-3">
|
<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="${page.getPagination().getCurrentPage()}" th:name="page">
|
||||||
<input type="hidden" th:value="${query}" th:name="query">
|
<input type="hidden" th:value="${query}" th:name="query">
|
||||||
<input type="hidden" name="pageSize">
|
<input type="hidden" name="pageSize">
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
<p>This table contains no data.</p>
|
<p>This table contains no data.</p>
|
||||||
</div>
|
</div>
|
||||||
<div th:if="${results.size() > 0}">
|
<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>
|
</form>
|
||||||
<nav th:replace="~{fragments/resources :: pagination(${page})}">
|
<nav th:replace="~{fragments/resources :: pagination(${page})}">
|
||||||
</nav>
|
</nav>
|
||||||
@ -29,17 +29,17 @@
|
|||||||
<div class="align-items-center">
|
<div class="align-items-center">
|
||||||
<h4 class="m-0" th:if="${page}">
|
<h4 class="m-0" th:if="${page}">
|
||||||
<th:block th:if="${sortKey != field.getJavaName()}" >
|
<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>
|
<i title="Sort" class="bi bi-caret-up"></i>
|
||||||
</a>
|
</a>
|
||||||
</th:block>
|
</th:block>
|
||||||
<th:block th:unless="${sortKey != field.getJavaName()}">
|
<th:block th:unless="${sortKey != field.getJavaName()}">
|
||||||
<a th:if="${sortOrder == 'DESC'}"
|
<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>
|
<i title="Sort" class="bi bi-caret-down-fill"></i>
|
||||||
</a>
|
</a>
|
||||||
<a th:if="${sortOrder == 'ASC'}"
|
<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>
|
<i title="Sort" class="bi bi-caret-up-fill"></i>
|
||||||
</a>
|
</a>
|
||||||
</th:block>
|
</th:block>
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
<div th:replace="~{fragments/resources :: sidebar('entities')}"></div>
|
<div th:replace="~{fragments/resources :: sidebar('entities')}"></div>
|
||||||
<div class="main-content bg-lighter">
|
<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>
|
<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">
|
<div class="input-group">
|
||||||
<input type="text" th:value="${query}"
|
<input type="text" th:value="${query}"
|
||||||
placeholder="Type a class or a table name and press ENTER to search"
|
placeholder="Type a class or a table name and press ENTER to search"
|
||||||
@ -31,7 +31,7 @@
|
|||||||
<tr th:each="schema : ${schemas}">
|
<tr th:each="schema : ${schemas}">
|
||||||
<td>
|
<td>
|
||||||
<a th:text="${schema.getTableName()}"
|
<a th:text="${schema.getTableName()}"
|
||||||
th:href="|/dbadmin/model/${schema.getClassName()}|"></a>
|
th:href="|/${baseUrl}/model/${schema.getClassName()}|"></a>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<span th:text="${counts.get(schema.getClassName())}"></span>
|
<span th:text="${counts.get(schema.getClassName())}"></span>
|
||||||
@ -40,8 +40,8 @@
|
|||||||
<span th:text="${schema.getClassName()}"></span>
|
<span th:text="${schema.getClassName()}"></span>
|
||||||
</td>
|
</td>
|
||||||
<td class="text-end row-icons">
|
<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="List all" th:href="|/${baseUrl}/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="Create new" th:href="|/${baseUrl}/model/${schema.getClassName()}/create|"><i class="bi bi-plus-square"></i></a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
@ -13,9 +13,9 @@
|
|||||||
|
|
||||||
<h1 class="fw-bold mb-4">
|
<h1 class="fw-bold mb-4">
|
||||||
<i class="align-middle bi bi-database"></i>
|
<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>
|
<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>
|
[[ ${schema.getJavaClass().getSimpleName()} ]] </a>
|
||||||
<i class="align-middle bi bi-chevron-double-right"></i>
|
<i class="align-middle bi bi-chevron-double-right"></i>
|
||||||
<span class="align-middle" th:text="${create ? 'Create' : 'Edit'}"></span>
|
<span class="align-middle" th:text="${create ? 'Create' : 'Edit'}"></span>
|
||||||
@ -28,7 +28,7 @@
|
|||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="box">
|
<div class="box">
|
||||||
<h3 class="fw-bold mb-4" th:text="${create ? schema.getJavaClass().getSimpleName() : object.getDisplayName()}"></h3>
|
<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}">
|
<input type="hidden" name="__dbadmin_create" th:value="${create}">
|
||||||
<div th:each="field : ${schema.getSortedFields()}" class="mt-2">
|
<div th:each="field : ${schema.getSortedFields()}" class="mt-2">
|
||||||
<label th:for="|__id_${field.getName()}|" class="mb-1 fw-bold">
|
<label th:for="|__id_${field.getName()}|" class="mb-1 fw-bold">
|
||||||
@ -70,7 +70,7 @@
|
|||||||
<span>Keep current data</span>
|
<span>Keep current data</span>
|
||||||
<div th:if="${field.isImage()}" class="mb-2">
|
<div th:if="${field.isImage()}" class="mb-2">
|
||||||
<img class="thumb-image" th:id="|__thumb_${field.getName()}|"
|
<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>
|
||||||
</div>
|
</div>
|
||||||
<!--/*--> File input <!--*/-->
|
<!--/*--> File input <!--*/-->
|
||||||
@ -94,7 +94,7 @@
|
|||||||
|
|
||||||
|
|
||||||
<div class="d-flex mt-4 justify-content-between">
|
<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'}">
|
<input type="submit" class="ui-btn btn btn-primary" th:value="${object != null ? 'Save' : 'Create'}">
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
@ -10,19 +10,19 @@
|
|||||||
<div class="main-content bg-lighter">
|
<div class="main-content bg-lighter">
|
||||||
<th:block th:replace="~{fragments/resources :: alerts}"></th:block>
|
<th:block th:replace="~{fragments/resources :: alerts}"></th:block>
|
||||||
<h1 class="fw-bold mb-4"><i class="align-middle bi bi-database"></i>
|
<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>
|
<i class="align-middle bi bi-chevron-double-right"></i>
|
||||||
<span class="align-middle"> [[ ${schema.getJavaClass().getSimpleName()} ]] </span>
|
<span class="align-middle"> [[ ${schema.getJavaClass().getSimpleName()} ]] </span>
|
||||||
</h1>
|
</h1>
|
||||||
<div class="row mt-4">
|
<div class="row mt-4">
|
||||||
<div th:class="${schema.getFilterableFields().isEmpty() ? 'col' : 'col-9'}">
|
<div th:class="${schema.getFilterableFields().isEmpty() ? 'col' : 'col-9'}">
|
||||||
<div class="w-100 d-flex inner-navigation">
|
<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">
|
<div class="ui-tab ps-5 pe-5 p-3">
|
||||||
<i class="bi bi-database pe-2"></i> DATA
|
<i class="bi bi-database pe-2"></i> DATA
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</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">
|
<div class="ui-tab ps-5 pe-5 p-3">
|
||||||
<i class="bi bi-table pe-2"></i> SCHEMA
|
<i class="bi bi-table pe-2"></i> SCHEMA
|
||||||
</div>
|
</div>
|
||||||
@ -31,7 +31,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="box with-navigation">
|
<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">
|
<div class="input-group">
|
||||||
<span class="input-group-text"><i class="bi bi-search"></i></span>
|
<span class="input-group-text"><i class="bi bi-search"></i></span>
|
||||||
<input type="text" th:value="${query}"
|
<input type="text" th:value="${query}"
|
||||||
@ -63,7 +63,7 @@
|
|||||||
|
|
||||||
<h3>
|
<h3>
|
||||||
<a title="Create new item"
|
<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>
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -10,20 +10,20 @@
|
|||||||
<div th:replace="~{fragments/resources :: sidebar('entities')}"></div>
|
<div th:replace="~{fragments/resources :: sidebar('entities')}"></div>
|
||||||
<div class="main-content bg-lighter">
|
<div class="main-content bg-lighter">
|
||||||
<h1 class="fw-bold mb-4"><i class="bi bi-database"></i>
|
<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>
|
<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>
|
<i class="align-middle bi bi-chevron-double-right"></i><span class="align-middle"> Schema</span>
|
||||||
</h1>
|
</h1>
|
||||||
<div class="row mt-4">
|
<div class="row mt-4">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="w-100 d-flex inner-navigation">
|
<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">
|
<div class="ui-tab ps-5 pe-5 p-3">
|
||||||
<i class="bi bi-database pe-2"></i> DATA
|
<i class="bi bi-database pe-2"></i> DATA
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</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">
|
<div class="ui-tab ps-5 pe-5 p-3">
|
||||||
<i class="bi bi-table pe-2"></i> SCHEMA
|
<i class="bi bi-table pe-2"></i> SCHEMA
|
||||||
</div>
|
</div>
|
||||||
@ -40,7 +40,7 @@
|
|||||||
</span>
|
</span>
|
||||||
</h3>
|
</h3>
|
||||||
<h3><a title="Create new item"
|
<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>
|
</div>
|
||||||
|
|
||||||
<table class="table table-striped align-middle">
|
<table class="table table-striped align-middle">
|
||||||
|
@ -10,9 +10,9 @@
|
|||||||
<div th:replace="~{fragments/resources :: sidebar('entities')}"></div>
|
<div th:replace="~{fragments/resources :: sidebar('entities')}"></div>
|
||||||
<div class="main-content bg-lighter">
|
<div class="main-content bg-lighter">
|
||||||
<h1 class="fw-bold mb-4"><i class="align-middle bi bi-database"></i>
|
<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>
|
<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>
|
[[ ${schema.getJavaClass().getSimpleName()} ]]</a>
|
||||||
<i class="align-middle bi bi-chevron-double-right"></i>
|
<i class="align-middle bi bi-chevron-double-right"></i>
|
||||||
<span class="align-middle"> [[ ${object.getDisplayName()} ]]</span>
|
<span class="align-middle"> [[ ${object.getDisplayName()} ]]</span>
|
||||||
@ -22,7 +22,7 @@
|
|||||||
<div class="box">
|
<div class="box">
|
||||||
<div class="d-flex justify-content-between">
|
<div class="d-flex justify-content-between">
|
||||||
<h3 class="mb-3 fw-bold" th:text="${object.getDisplayName()}"></h3>
|
<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>
|
<i class="bi bi-pencil"></i></a>
|
||||||
</h3>
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
<div class="main-content bg-lighter">
|
<div class="main-content bg-lighter">
|
||||||
<th:block th:replace="~{fragments/resources :: alerts}"></th:block>
|
<th:block th:replace="~{fragments/resources :: alerts}"></th:block>
|
||||||
<h1 class="fw-bold mb-4"><i class="align-middle bi bi-gear"></i>
|
<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>
|
</h1>
|
||||||
<div class="row mt-4">
|
<div class="row mt-4">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
|
Loading…
x
Reference in New Issue
Block a user