mirror of
https://github.com/dalbodeule/snap-admin.git
synced 2025-06-08 21:38:21 +00:00
WIP
This commit is contained in:
parent
d34676f7a7
commit
82311fd23e
@ -39,19 +39,23 @@ import tech.ailef.dbadmin.misc.Utils;
|
||||
@Controller
|
||||
@RequestMapping("/dbadmin")
|
||||
/**
|
||||
* FOR 0.0.3:
|
||||
* @DisplayImage DONE TODO: write docs in README
|
||||
* Fixed/improved edit page for binary fields (files) DONE
|
||||
*
|
||||
* TODO
|
||||
* - double data source for internal database and settings
|
||||
* - role based authorization (PRO)
|
||||
* - Pagination in one to many results?
|
||||
* - BLOB upload (WIP: check edit not working)
|
||||
* - AI console (PRO)
|
||||
* - Action logs
|
||||
* - Boolean icons
|
||||
* - Boolean in create/edit is checkbox
|
||||
* - Documentation
|
||||
* - SQL console (PRO)
|
||||
* - JPA Validation (PRO)
|
||||
* - Logging
|
||||
* - Selenium tests
|
||||
* - @DisplayImage
|
||||
* - Logs in web ui
|
||||
* - Tests: AutocompleteController, REST API, create/edit
|
||||
*/
|
||||
@ -81,7 +85,6 @@ public class DefaultDbAdminController {
|
||||
model.addAttribute("activePage", "home");
|
||||
model.addAttribute("title", "Entities | Index");
|
||||
|
||||
|
||||
return "home";
|
||||
}
|
||||
|
||||
@ -272,8 +275,6 @@ public class DefaultDbAdminController {
|
||||
@RequestParam MultiValueMap<String, String> formParams,
|
||||
@RequestParam Map<String, MultipartFile> files,
|
||||
RedirectAttributes attr) {
|
||||
|
||||
|
||||
// Extract all parameters that have exactly 1 value,
|
||||
// as these will be the raw values for the object that is being
|
||||
// created.
|
||||
|
@ -22,6 +22,7 @@ import tech.ailef.dbadmin.dbmapping.DbAdminRepository;
|
||||
import tech.ailef.dbadmin.dbmapping.DbFieldValue;
|
||||
import tech.ailef.dbadmin.dbmapping.DbObject;
|
||||
import tech.ailef.dbadmin.dbmapping.DbObjectSchema;
|
||||
import tech.ailef.dbadmin.exceptions.DbAdminException;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/dbadmin/download")
|
||||
@ -65,7 +66,18 @@ public class DownloadController {
|
||||
|
||||
if (object.isPresent()) {
|
||||
DbObject dbObject = object.get();
|
||||
DbFieldValue dbFieldValue = dbObject.get(fieldName);
|
||||
|
||||
DbFieldValue dbFieldValue;
|
||||
try {
|
||||
dbFieldValue = dbObject.get(fieldName);
|
||||
} catch (DbAdminException e) {
|
||||
throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Field not found", e);
|
||||
}
|
||||
|
||||
if (dbFieldValue.getValue() == null) {
|
||||
throw new ResponseStatusException(HttpStatus.NOT_FOUND, "There's no file attached to this item");
|
||||
}
|
||||
|
||||
byte[] file = (byte[])dbFieldValue.getValue();
|
||||
|
||||
String filename = schema.getClassName() + "_" + id + "_" + fieldName;
|
||||
|
@ -179,8 +179,11 @@ public class DbObject {
|
||||
String capitalize = Character.toUpperCase(fieldName.charAt(0)) + fieldName.substring(1);
|
||||
Method[] methods = instance.getClass().getDeclaredMethods();
|
||||
|
||||
DbField dbField = schema.getFieldByJavaName(fieldName);
|
||||
if (dbField == null) return null;
|
||||
|
||||
String prefix = "get";
|
||||
if (schema.getFieldByJavaName(fieldName).getType() == DbFieldType.BOOLEAN) {
|
||||
if (dbField.getType() == DbFieldType.BOOLEAN) {
|
||||
prefix = "is";
|
||||
}
|
||||
|
||||
|
@ -56,7 +56,7 @@ tr.table-data-row td:last-child, tr.table-data-row th:last-child {
|
||||
|
||||
.row-icons {
|
||||
font-size: 1.2rem;
|
||||
width: 128px;
|
||||
width: 96px;
|
||||
}
|
||||
|
||||
h1 .bi {
|
||||
@ -116,6 +116,8 @@ h1 a:hover {
|
||||
max-height: 300px;
|
||||
overflow: auto;
|
||||
z-index: 999;
|
||||
-webkit-box-shadow: 0px 11px 12px -1px rgba(0,0,0,0.13);
|
||||
box-shadow: 0px 11px 12px -1px rgba(0,0,0,0.13);
|
||||
}
|
||||
|
||||
.suggestion {
|
||||
@ -128,7 +130,7 @@ h1 a:hover {
|
||||
|
||||
.suggestion:hover {
|
||||
cursor: pointer;
|
||||
background-color: #FFF;
|
||||
background-color: #EBF7FF;
|
||||
border-bottom: 2px solid #ADDEFF;
|
||||
}
|
||||
|
||||
|
@ -1,15 +1,23 @@
|
||||
function updateBulkActions(table, selected) {
|
||||
let divs = document.querySelectorAll(".bulk-actions");
|
||||
divs.forEach(div => {
|
||||
div.innerHTML = `${selected} items selected <input type="submit" form="delete-form" class="ui-btn btn btn-secondary" value="Delete">`;
|
||||
div.innerHTML = `${selected} items selected <input type="submit" form="multi-delete-form" class="ui-btn btn btn-secondary" value="Delete">`;
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
let selected = 0;
|
||||
|
||||
if (document.getElementById('delete-form') != null) {
|
||||
document.getElementById('delete-form').addEventListener('submit', function(e) {
|
||||
document.querySelectorAll(".delete-form").forEach(form => {
|
||||
form.addEventListener('submit', function(e) {
|
||||
if (!confirm('Are you sure you want to delete this item?')) {
|
||||
e.preventDefault();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
if (document.getElementById('multi-delete-form') != null) {
|
||||
document.getElementById('multi-delete-form').addEventListener('submit', function(e) {
|
||||
if (selected == 0) {
|
||||
e.preventDefault();
|
||||
alert('No items selected');
|
||||
|
@ -5,7 +5,15 @@
|
||||
<tr th:fragment="data_row(row, selectable)" class="table-data-row">
|
||||
<td th:if=${selectable} class="table-checkbox">
|
||||
<input type="checkbox" class="form-check-input" name="ids"
|
||||
th:value="${row.getPrimaryKeyValue()}" form="delete-form">
|
||||
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()}|">
|
||||
<i class="bi bi-pencil-square"></i></a>
|
||||
<form class="delete-form" method="POST"
|
||||
th:action="|/dbadmin/model/${schema.getJavaClass().getName()}/delete/${row.getPrimaryKeyValue()}|">
|
||||
<button><i class="bi bi-trash"></i></button>
|
||||
</form>
|
||||
</td>
|
||||
<td th:each="field : ${schema.getSortedFields()}"
|
||||
th:classAppend="${field.isBinary() ? 'text-center' : ''}">
|
||||
@ -20,15 +28,6 @@
|
||||
<td th:each="colName : ${schema.getComputedColumnNames()}">
|
||||
<span th:text="${row.compute(colName)}"></span>
|
||||
</td>
|
||||
|
||||
<td class="text-center row-icons" th:if="${selectable}">
|
||||
<a class="ps-1" th:href="|/dbadmin/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()}|">
|
||||
<button><i class="bi bi-trash"></i></button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
<div th:if="${results != null && results.size() > 0}">
|
||||
<table class="table table-striped align-middle mt-3">
|
||||
<tr class="table-data-row">
|
||||
<th class="row-icons"></th>
|
||||
<th th:each="field : ${schema.getSortedFields()}">
|
||||
<div class="m-0 p-0 d-flex justify-content-between">
|
||||
<div class="column-title">
|
||||
|
@ -2,18 +2,19 @@
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org">
|
||||
<head></head>
|
||||
<body>
|
||||
<div class="table-selectable" th:fragment="table(results, schema)">
|
||||
<div class="table-selectable table-responsive" th:fragment="table(results, schema)">
|
||||
<div th:if="${results.isEmpty()}">
|
||||
<p>This table contains no data.</p>
|
||||
</div>
|
||||
<div th:if="${results.size() > 0}">
|
||||
<form id="delete-form" th:action="|/dbadmin/model/${schema.getClassName()}/delete|" method="POST">
|
||||
<form id="multi-delete-form" th:action="|/dbadmin/model/${schema.getClassName()}/delete|" method="POST">
|
||||
</form>
|
||||
<nav th:replace="~{fragments/resources :: pagination(${page})}">
|
||||
</nav>
|
||||
<table class="table table-striped align-middle mt-3">
|
||||
<tr class="table-data-row">
|
||||
<th class="table-checkbox"><input type="checkbox" class="form-check-input check-all"></th>
|
||||
<th></th>
|
||||
<th class="table-data-row" th:each="field : ${schema.getSortedFields()}">
|
||||
<div class="m-0 p-0 d-flex justify-content-between">
|
||||
<div class="column-title">
|
||||
@ -56,7 +57,6 @@
|
||||
</div>
|
||||
<p class="m-0 p-0 dbfieldtype"><small>COMPUTED</small></p>
|
||||
</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
<th:block th:each="r : ${results}">
|
||||
<tr th:replace="~{fragments/data_row :: data_row(row=${r},selectable=${true})}"></tr>
|
||||
|
Loading…
x
Reference in New Issue
Block a user