lesson
This commit is contained in:
5
.project
5
.project
@ -25,6 +25,11 @@
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.springframework.ide.eclipse.boot.validation.springbootbuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
|
2
.settings/org.springframework.ide.eclipse.prefs
Normal file
2
.settings/org.springframework.ide.eclipse.prefs
Normal file
@ -0,0 +1,2 @@
|
||||
boot.validation.initialized=true
|
||||
eclipse.preferences.version=1
|
@ -1,12 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
|
||||
<display-name>BiCO</display-name>
|
||||
<welcome-file-list>
|
||||
<welcome-file>index.html</welcome-file>
|
||||
<welcome-file>index.htm</welcome-file>
|
||||
<welcome-file>index.jsp</welcome-file>
|
||||
<welcome-file>default.html</welcome-file>
|
||||
<welcome-file>default.htm</welcome-file>
|
||||
<welcome-file>default.jsp</welcome-file>
|
||||
</welcome-file-list>
|
||||
</web-app>
|
@ -8,7 +8,7 @@ plugins {
|
||||
}
|
||||
|
||||
group = 'de.jottyfan.bico'
|
||||
version = '0.0.2'
|
||||
version = '0.0.3'
|
||||
|
||||
description = """BibleClassOrganizer"""
|
||||
|
||||
|
@ -0,0 +1,45 @@
|
||||
package de.jottyfan.bico.modules.lesson;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
import de.jottyfan.bico.db.tables.records.TLessonRecord;
|
||||
import de.jottyfan.bico.modules.CommonController;
|
||||
/**
|
||||
*
|
||||
* @author jotty
|
||||
*
|
||||
*/
|
||||
@Controller
|
||||
public class LessonController extends CommonController {
|
||||
|
||||
@Autowired
|
||||
private LessonService service;
|
||||
|
||||
@GetMapping("/lesson")
|
||||
public String getPerson(@RequestParam("slotId") Integer slotId, Model model) {
|
||||
model.addAttribute("bean", service.getLesson(slotId, true));
|
||||
model.addAttribute("persons", service.getPersons());
|
||||
model.addAttribute("slotDay", service.getSlotDay(slotId));
|
||||
return "/lesson/item";
|
||||
}
|
||||
|
||||
@PostMapping("/lesson/{id}")
|
||||
public String updateLesson(@PathVariable("id") Integer lessonId, @ModelAttribute("bean") TLessonRecord bean, Model model) {
|
||||
bean.setPkLesson(lessonId);
|
||||
service.updateLesson(bean);
|
||||
return "redirect:/sheet";
|
||||
}
|
||||
|
||||
@GetMapping("/lesson/{id}/remove")
|
||||
public String removeLesson(@PathVariable("id") Integer lessonId) {
|
||||
service.removeLesson(lessonId);
|
||||
return "redirect:/sheet";
|
||||
}
|
||||
}
|
@ -0,0 +1,100 @@
|
||||
package de.jottyfan.bico.modules.lesson;
|
||||
|
||||
import static de.jottyfan.bico.db.Tables.T_LESSON;
|
||||
import static de.jottyfan.bico.db.Tables.T_PERSON;
|
||||
import static de.jottyfan.bico.db.Tables.T_SLOT;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.jooq.DSLContext;
|
||||
import org.jooq.DeleteConditionStep;
|
||||
import org.jooq.InsertResultStep;
|
||||
import org.jooq.Record1;
|
||||
import org.jooq.SelectConditionStep;
|
||||
import org.jooq.SelectWhereStep;
|
||||
import org.jooq.UpdateConditionStep;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import de.jottyfan.bico.db.tables.records.TLessonRecord;
|
||||
import de.jottyfan.bico.db.tables.records.TPersonRecord;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author jotty
|
||||
*
|
||||
*/
|
||||
@Repository
|
||||
public class LessonRepository {
|
||||
private final static Logger LOGGER = LogManager.getLogger(LessonRepository.class);
|
||||
|
||||
@Autowired
|
||||
private DSLContext jooq;
|
||||
|
||||
public TLessonRecord getLesson(Integer slotId, Boolean createIfNecessary) {
|
||||
SelectConditionStep<TLessonRecord> sql = jooq
|
||||
// @formatter:off
|
||||
.selectFrom(T_LESSON)
|
||||
.where(T_LESSON.FK_SLOT.eq(slotId));
|
||||
// @formatter:on
|
||||
LOGGER.trace(sql);
|
||||
TLessonRecord r = sql.fetchOne();
|
||||
if (r == null && createIfNecessary) {
|
||||
InsertResultStep<TLessonRecord> sql2 = jooq
|
||||
// @formatter:off
|
||||
.insertInto(T_LESSON,
|
||||
T_LESSON.FK_SLOT)
|
||||
.values(slotId)
|
||||
.returning(T_LESSON.PK_LESSON);
|
||||
// @formatter:on
|
||||
LOGGER.trace(sql);
|
||||
Integer pkLesson = sql2.fetchOne(T_LESSON.PK_LESSON);
|
||||
r = new TLessonRecord();
|
||||
r.setPkLesson(pkLesson);
|
||||
r.setFkSlot(slotId);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
public List<TPersonRecord> getPersons() {
|
||||
SelectWhereStep<TPersonRecord> sql = jooq.selectFrom(T_PERSON);
|
||||
LOGGER.trace(sql);
|
||||
return sql.fetchStream().toList();
|
||||
}
|
||||
|
||||
public LocalDate getSlotDay(Integer slotId) {
|
||||
SelectConditionStep<Record1<LocalDate>> sql = jooq
|
||||
// @formatter:off
|
||||
.select(T_SLOT.SLOT_DAY)
|
||||
.from(T_SLOT)
|
||||
.where(T_SLOT.PK_SLOT.eq(slotId));
|
||||
// @formatter:on
|
||||
LOGGER.trace(sql);
|
||||
return sql.fetchOne(T_SLOT.SLOT_DAY);
|
||||
}
|
||||
|
||||
public void updateLesson(TLessonRecord bean) {
|
||||
UpdateConditionStep<TLessonRecord> sql = jooq
|
||||
// @formatter:off
|
||||
.update(T_LESSON)
|
||||
.set(T_LESSON.NOTES, bean.getNotes())
|
||||
.set(T_LESSON.FK_PERSON, bean.getFkPerson())
|
||||
.where(T_LESSON.PK_LESSON.eq(bean.getPkLesson()));
|
||||
// @formatter:on
|
||||
LOGGER.trace(sql);
|
||||
sql.execute();
|
||||
}
|
||||
|
||||
public void removeLesson(Integer lessonId) {
|
||||
DeleteConditionStep<TLessonRecord> sql = jooq
|
||||
// @formatter:off
|
||||
.deleteFrom(T_LESSON)
|
||||
.where(T_LESSON.PK_LESSON.eq(lessonId));
|
||||
// @formatter:on
|
||||
LOGGER.trace(sql);
|
||||
sql.execute();
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
package de.jottyfan.bico.modules.lesson;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import de.jottyfan.bico.db.tables.records.TLessonRecord;
|
||||
import de.jottyfan.bico.db.tables.records.TPersonRecord;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author jotty
|
||||
*
|
||||
*/
|
||||
@Service
|
||||
public class LessonService {
|
||||
|
||||
@Autowired
|
||||
private LessonRepository repository;
|
||||
|
||||
public TLessonRecord getLesson(Integer slotId, Boolean createIfNecessary) {
|
||||
return repository.getLesson(slotId, createIfNecessary);
|
||||
}
|
||||
|
||||
public List<TPersonRecord> getPersons() {
|
||||
return repository.getPersons();
|
||||
}
|
||||
|
||||
public LocalDate getSlotDay(Integer slotId) {
|
||||
return repository.getSlotDay(slotId);
|
||||
}
|
||||
|
||||
public void updateLesson(TLessonRecord bean) {
|
||||
repository.updateLesson(bean);
|
||||
}
|
||||
|
||||
public void removeLesson(Integer lessonId) {
|
||||
repository.removeLesson(lessonId);
|
||||
}
|
||||
}
|
@ -32,6 +32,7 @@ public class SlotController extends CommonController {
|
||||
@GetMapping("/slot/{id}")
|
||||
public String load(@PathVariable Integer id, Model model) {
|
||||
model.addAttribute("bean", id == null ? new SlotBean() : service.loadSlot(id));
|
||||
model.addAttribute("hasLesson", service.slotHasLesson(id));
|
||||
return "/slot/item";
|
||||
}
|
||||
|
||||
|
@ -126,4 +126,20 @@ public class SlotRepository {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* return true if this slot already has at least one lesson
|
||||
*
|
||||
* @param slotId the ID of the slot
|
||||
* @return true or false
|
||||
*/
|
||||
public Boolean getHasLesson(Integer slotId) {
|
||||
SelectConditionStep<TLessonRecord> sql = jooq
|
||||
// @formatter:off
|
||||
.selectFrom(T_LESSON)
|
||||
.where(T_LESSON.FK_SLOT.eq(slotId));
|
||||
// @formatter:on
|
||||
LOGGER.trace(sql);
|
||||
return sql.fetch().size() > 0;
|
||||
}
|
||||
}
|
||||
|
@ -36,4 +36,8 @@ public class SlotService {
|
||||
public SlotBean loadDeletableSlot(Integer id) {
|
||||
return repository.getSlotIfDeletable(id);
|
||||
}
|
||||
|
||||
public Boolean slotHasLesson(Integer id) {
|
||||
return id == null ? false : repository.getHasLesson(id);
|
||||
}
|
||||
}
|
||||
|
@ -1,16 +1,9 @@
|
||||
/*
|
||||
html {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
*/
|
||||
|
||||
body {
|
||||
background-color: #abc;
|
||||
}
|
||||
|
||||
[data-bs-theme=dark] body {
|
||||
background-color: rgb(36, 31, 49);
|
||||
background-color: #001213;
|
||||
}
|
||||
|
||||
.borderdist {
|
||||
@ -24,3 +17,21 @@ body {
|
||||
[data-bs-theme=dark] .borderdist {
|
||||
background-color: #333;
|
||||
}
|
||||
|
||||
.headerback {
|
||||
background-color: #eee;
|
||||
border-bottom: 1px solid silver;
|
||||
}
|
||||
|
||||
[data-bs-theme=dark] .headerback {
|
||||
background-color: #333;
|
||||
}
|
||||
|
||||
.rightaligned {
|
||||
right: 5px;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.rightpadding64 {
|
||||
margin-right: 64px;
|
||||
}
|
41
src/main/resources/templates/lesson/item.html
Normal file
41
src/main/resources/templates/lesson/item.html
Normal file
@ -0,0 +1,41 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns:th="http://www.thymeleaf.org" layout:decorate="~{template}" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
|
||||
<body>
|
||||
<th:block layout:fragment="content">
|
||||
<div class="borderdist">
|
||||
<div class="container">
|
||||
<div class="row g-2">
|
||||
<div class="col-sm-12">
|
||||
<h2>Dozent-Reservierung</h2>
|
||||
</div>
|
||||
</div>
|
||||
<form th:action="@{/lesson/{id}(id=${bean.pkLesson})}" method="post" th:object="${bean}">
|
||||
<div class="row g-3">
|
||||
<div class="col-sm-3">Tag</div>
|
||||
<div class="col-sm-9">
|
||||
<span th:text="${#temporals.format(slotDay, 'dd.MM.yyyy')}"></span>
|
||||
</div>
|
||||
<div class="col-sm-3">Dozent</div>
|
||||
<div class="col-sm-9">
|
||||
<select th:field="*{fkPerson}" class="form-select">
|
||||
<option value="">--- bitte wählen ---</option>
|
||||
<option th:each="p : ${persons}" th:value="${p.pkPerson}" th:text="${p.forename + ' ' + p.surname}"></option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-sm-3">Anmerkungen</div>
|
||||
<div class="col-sm-9">
|
||||
<textarea th:field="*{notes}" class="form-control"></textarea>
|
||||
</div>
|
||||
<div class="col-sm-3"></div>
|
||||
<div class="col-sm-9">
|
||||
<button type="submit" class="btn btn-outline-success">Speichern</button>
|
||||
<a th:href="@{/}" class="btn btn-outline-secondary">Abbrechen</a>
|
||||
<a th:href="@{/lesson/{id}/remove(id=${bean.pkLesson})}" class="btn btn-outline-danger">Löschen</a>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</th:block>
|
||||
</body>
|
||||
</html>
|
@ -7,29 +7,26 @@
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Tag</th>
|
||||
<th>Kürzel</th>
|
||||
<th>Wer</th>
|
||||
<th>Thema</th>
|
||||
<th>Notiz</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr th:each="s : ${list}">
|
||||
<td><span th:text="${#temporals.format(s.slotDay, 'yyyy-MM-dd')}" th:if="${s.pkLesson}"></span> <a th:href="@{/slot/{id}(id=${s.pkSlot})}"
|
||||
th:text="${#temporals.format(s.slotDay, 'yyyy-MM-dd')}" class="btn btn-outline-secondary" th:unless="${s.pkLesson}"></a></td>
|
||||
<td><a th:href="@{/person?slotId={id}(id=${s.pkSlot})}" class="btn btn-outline-secondary"> <span th:text="${s.abbreviation}" th:if="${s.abbreviation}"></span> <i
|
||||
<td><span th:text="${#temporals.format(s.slotDay, 'yyyy-MM-dd')}"></span></td>
|
||||
<td><a th:href="@{/lesson?slotId={id}(id=${s.pkSlot})}" class="btn btn-outline-secondary"> <span th:text="${s.abbreviation}" th:if="${s.abbreviation}"></span> <i
|
||||
class="bi bi-pencil" th:if="${s.abbreviation == null || s.abbreviation.isBlank()}"></i>
|
||||
</a></td>
|
||||
<td th:text="${s.theme}"></td>
|
||||
<td><a th:href="@{/slot/{id}(id=${s.pkSlot})}" class="btn btn-outline-secondary"> <span th:text="${s.slotNotes}"></span> <i class="bi bi-pencil"
|
||||
th:if="${s.slotNotes == null || s.slotNotes.isBlank()}"></i>
|
||||
</a></td>
|
||||
<td>
|
||||
<td><div th:text="${s.theme}"></div>
|
||||
<div th:text="${s.subtheme}"></div></td>
|
||||
<td><span th:text="${s.slotNotes}" class="rightpadding64"></span><a th:href="@{/slot/{id}(id=${s.pkSlot})}" class="btn btn-outline-secondary rightaligned"><i
|
||||
class="bi bi-pencil"></i></a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan="5"><a th:href="@{/slot}" class="btn btn-outline-success">einen neues Datum anlegen</a></td>
|
||||
<td colspan="4"><a th:href="@{/slot}" class="btn btn-outline-success">einen neues Datum anlegen</a></td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
|
@ -4,6 +4,11 @@
|
||||
<th:block layout:fragment="content">
|
||||
<div class="borderdist">
|
||||
<div class="container">
|
||||
<div class="row g-2">
|
||||
<div class="col-sm-12">
|
||||
<h2>Terminfestlegung</h2>
|
||||
</div>
|
||||
</div>
|
||||
<form th:action="@{/slot/save}" th:object="${bean}" method="post">
|
||||
<input type="hidden" th:field="*{pkSlot}" />
|
||||
<div class="row g-2">
|
||||
@ -19,7 +24,15 @@
|
||||
<div class="col-sm-2"></div>
|
||||
<div class="col-sm-10">
|
||||
<button type="submit" class="btn btn-outline-primary">Speichern</button>
|
||||
<th:block th:unless="${hasLesson}">
|
||||
<a th:href="@{/slot/{id}/delete(id=${bean.pkSlot})}" class="btn btn-outline-danger" th:if="${bean.pkSlot}">Löschen</a>
|
||||
</th:block>
|
||||
</div>
|
||||
<div class="col-sm-2" th:if="${hasLesson}">Hinweis</div>
|
||||
<div class="col-sm-10" th:if="${hasLesson}">
|
||||
<div class="alert alert-primary">Termine, die bereits für einen Dozenten reserviert wurden, können nicht gelöscht werden.
|
||||
<a th:href="@{/lesson?slotId={id}(id=${bean.pkSlot})}" class="btn btn-outline-secondary">Reservierung bearbeiten</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -15,14 +15,14 @@
|
||||
<script th:src="@{/js/stylehelp.js}"></script>
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar sticky-top navbar-expand-lg headerlayout">
|
||||
<nav class="navbar sticky-top navbar-expand-lg headerlayout headerback">
|
||||
<button class="navbar-toggler" style="margin-right: 40px" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent"
|
||||
aria-expanded="false">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarSupportedContent" style="margin-right: 20px">
|
||||
<ul class="navbar-nav mb-2 mb-lg-0">
|
||||
<li class="nav-item"><a class="btn btn-outline-secondary" th:href="@{/}">Startseite</a></li>
|
||||
<li class="nav-item"><a class="btn btn-outline-secondary" th:href="@{/}" style="margin-left: 12px">Startseite</a></li>
|
||||
</ul>
|
||||
<ul layout:fragment="header"></ul>
|
||||
<ul class="nav navbar-nav ms-auto">
|
||||
|
Reference in New Issue
Block a user