Merge remote-tracking branch 'origin/feature/manual_cronjobs' into feature/dashboard

Butfixes
This commit is contained in:
Danny 2020-06-15 21:41:54 +02:00
commit e904eba7a4
6 changed files with 168 additions and 7 deletions

View File

@ -29,6 +29,11 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.annotation.PostConstruct;
import java.sql.Timestamp;
@ -60,10 +65,22 @@ interface ICronjob {
* @param controller Back-reference that allows to use repositories.
*/
void executeAt(Calendar time, CronjobController controller);
/**
* Get a name for this cronjob, that can be presented to the user in the frontend.
*
* @return A german name of this cronjob.
*/
String getDisplayName();
}
@Component
class Reorder implements ICronjob {
@Override
public String getDisplayName() {
return "Nachbestellung";
}
@Override
public Calendar nextExecution(Calendar reference) {
if (reference.get(Calendar.HOUR_OF_DAY) >= 8) {
@ -212,6 +229,7 @@ class ScheduledCronjob {
}
@Component
@RequestMapping("intern/cronjobs")
class CronjobController {
private static final Logger log = LoggerFactory.getLogger(CronjobController.class);
@ -335,4 +353,42 @@ class CronjobController {
public void onPostConstruct() {
new Thread(this::runCronjobExecutionLoop).start();
}
class ManualCronjob {
public final String identifier;
public final String visibleName;
public ManualCronjob(String identifier, String visibleName) {
this.identifier = identifier;
this.visibleName = visibleName;
}
}
private List<ManualCronjob> listAllCronjobs() {
ArrayList<ManualCronjob> entries = new ArrayList<>();
for (Entry<String, ICronjob> job : cronjobs.entrySet()) {
entries.add(new ManualCronjob(job.getKey(), job.getValue().getDisplayName()));
}
return entries;
}
@GetMapping("/")
public String cronjobOverview(Model model) {
model.addAttribute("jobs", listAllCronjobs());
return "intern/cronjobs/index";
}
@PostMapping("/run/{identifier}")
public String runCronjob(Model model, @PathVariable("identifier") String identifier) {
ICronjob jobToExecute = cronjobs.get(identifier);
if (jobToExecute != null) {
jobToExecute.executeAt(new GregorianCalendar(), this);
model.addAttribute("info",
String.format("Der Cronjob \"%s\" wurde ausgeführt.", jobToExecute.getDisplayName()));
} else {
model.addAttribute("error", "Der Cronjob konnte nicht gefunden werden.");
}
model.addAttribute("jobs", listAllCronjobs());
return "intern/cronjobs/index";
}
}

View File

@ -49,16 +49,20 @@ public class DashboardCronjob implements ICronjob {
CalculateWarehouseStatsAction.WarehouseStats warehouseStats = new CalculateWarehouseStatsAction(entries).finish();
dashboardSummary.created = new java.sql.Date(time.getTimeInMillis());
dashboardSummary.todaysCustomersOrders = getSales(oneDayBefore, time, controller);
dashboardSummary.todaysNewCustomers = getNewUsers(oneDayBefore, time, controller);
dashboardSummary.todaysCustomersOrders = nullToZero(getSales(oneDayBefore, time, controller));
dashboardSummary.todaysNewCustomers = nullToZero(getNewUsers(oneDayBefore, time, controller));
dashboardSummary.todaysWarehouseCapacity = warehouseStats.efficiency;
dashboardSummary.currentWarehouseCapacity = warehouseStats.ratioUsedSlots;
dashboardSummary.todaysSalesCent = getTurnover(oneDayBefore, time, controller);
dashboardSummary.todaysSalesCent = nullToZero(getTurnover(oneDayBefore, time, controller));
controller.dashboardSummaryRepository.save(dashboardSummary);
}
@Override
public String getDisplayName() {
return "Dashboard refresh";
}
private Integer getSales (Calendar begin, Calendar end, CronjobController controller)
{
return controller.customerOrderRepository.countOrdersInTimespan(
@ -76,4 +80,8 @@ public class DashboardCronjob implements ICronjob {
return controller.userRepository.countUsersInTimespan(
new Timestamp(begin.getTimeInMillis()), new Timestamp(end.getTimeInMillis()));
}
private int nullToZero(Integer input) {
return input == null ? 0 : input;
}
}

View File

@ -0,0 +1,35 @@
.alert {
display: block;
text-transform: uppercase;
background: #c0392b;
color: white;
animation: blinking 1s linear infinite;
overflow: hidden;
}
.alert > span {
display: inline-block;
padding-left: 100%;
animation: marquee 10s linear infinite;
white-space: nowrap;
}
@keyframes marquee {
0% { transform: translateX(0); }
100% { transform: translateX(-100%); }
}
@keyframes blinking {
60% {
color: white;
}
75% {
color: #c0392b;
}
85% {
color: #c0392b;
}
100% {
color: white;
}
}

View File

@ -47,6 +47,8 @@
</ul>
</li>
<li><a th:href="@{/intern/cronjobs/}">Cronjobs</a></li>
</ul>
</ul>
</nav>

View File

@ -0,0 +1,60 @@
<!DOCTYPE html>
<html lang="de" dir="ltr" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=0.75, user-scalable=no">
<title>Cronjobs</title>
<script th:src="@{/js/filterTable.js}"></script>
<link rel="stylesheet" th:href="@{/css/ecom.css}"/>
<link rel="stylesheet" th:href="@{/css/manual-cronjobs.css}"/>
</head>
<body>
<nav th:replace="fragments/header :: header">Header</nav>
<div class="sidebar-layout content-width">
<nav></nav>
<div>
<h1>Cronjobs</h1>
</div>
</div>
<main class="sidebar-layout content-width">
<nav th:replace="fragments/intern :: sidebar"></nav>
<div class="content-width">
<h3>Manuelle Ausführung von Cronjobs</h3>
<div class="alert"><span>
WARNUNG<br>
Manuelles Triggern von Cronjobs kann zu unerwartetem Verhalten führen!<br>
Diese Seite ist nur für Debugging-Zwecke gedacht.
</span></div>
<p>
<table id="main-table">
<tr>
<th colspan="7">
<input type="text" placeholder="Filtern" class="smaller jsFilterTable full-width"
data-target-id="main-table"></input>
</th>
</tr>
<tr>
<th>Cronjob</th>
<th></th>
</tr>
<tr th:each="job: ${jobs}">
<td th:text="${job.visibleName}"></td>
<td>
<form th:action="@{/intern/cronjobs/run/{identifier}(identifier = ${job.identifier})}" method="post">
<input class="button smaller" type="submit" value="Ausführen" />
</form>
</td>
</tr>
</table>
</p>
</div>
</main>
<footer th:replace="fragments/footer :: footer"></footer>
</body>
</html>

View File

@ -110,7 +110,7 @@
.then(response => response.json())
.then(data => {
chart('sales', 'Verkäufe/Tag', data.map(d => d.todaysCustomersOrders),
"", data.map(g => g.created));
"", data.map(g => " "+g.created));
});
</script>
@ -124,7 +124,7 @@
.then(response => response.json())
.then(data => {
chart('umsatz', 'Umsatz/Tag', data.map(d => d.todaysSalesCent / 100),
"€", data.map(g => g.created));
"€", data.map(g => " "+g.created));
});
</script>
@ -138,7 +138,7 @@
.then(response => response.json())
.then(data => {
chart('Neukunden', 'Neukunden', data.map(d => d.todaysNewCustomers),
"", data.map(g => g.created));
"", data.map(g => " "+g.created));
});
</script>