basic theme selection

This commit is contained in:
Jottyfan
2023-12-16 17:59:15 +01:00
parent 690f28f4fe
commit bff5d1e54f
10 changed files with 625 additions and 3 deletions

View File

@ -0,0 +1,20 @@
package de.jottyfan.bico.modules.subject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import de.jottyfan.bico.modules.CommonController;
/**
*
* @author jotty
*
*/
@Controller
public class SubjectController extends CommonController {
@GetMapping("/subject/new")
public String loadNewSubjectForm() {
return "/subject/new";
}
}

View File

@ -0,0 +1,54 @@
package de.jottyfan.bico.modules.theme;
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.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import de.jottyfan.bico.db.tables.records.TLessonRecord;
import de.jottyfan.bico.modules.CommonController;
import jakarta.servlet.http.HttpServletRequest;
/**
*
* @author jotty
*
*/
@Controller
public class ThemeController extends CommonController {
@Autowired
private ThemeService service;
@GetMapping("/theme")
public String getThemeManipulationBySlotId(@RequestParam("slotId") Integer slotId, Model model) {
model.addAttribute("slotId", slotId);
model.addAttribute("list", service.getThemeManipulation(slotId));
model.addAttribute("themes", service.getAllThemes());
model.addAttribute("lesson", service.getLesson(slotId));
return "/theme";
}
@PostMapping("/theme/add")
public String addThemeToSlot(@RequestParam("slotId") Integer slotId, Model model, HttpServletRequest request) {
String subjectId = request.getParameter("pkSubject");
Integer pkSubject = Integer.valueOf(subjectId);
service.addThemeToSlot(slotId, pkSubject);
return "redirect:/theme?slotId=" + slotId;
}
@GetMapping("/theme/delete")
public String addThemeToSlot(@RequestParam("lessonSubjectId") Integer pkLessonSubject, @RequestParam("slotId") Integer slotId) {
service.removeThemeFromSlot(pkLessonSubject);
return "redirect:/theme?slotId=" + slotId;
}
@PostMapping("/theme/update")
public String updateLesson(@RequestParam("slotId") Integer slotId, @ModelAttribute("lesson") TLessonRecord bean) {
service.updateLesson(bean);
return "redirect:/theme?slotId=" + bean.getFkSlot();
}
}

View File

@ -0,0 +1,141 @@
package de.jottyfan.bico.modules.theme;
import static de.jottyfan.bico.db.Tables.T_LESSON;
import static de.jottyfan.bico.db.Tables.T_LESSON_SUBJECT;
import static de.jottyfan.bico.db.Tables.T_SOURCE;
import static de.jottyfan.bico.db.Tables.T_SUBJECT;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.jboss.logging.Logger;
import org.jooq.DSLContext;
import org.jooq.DeleteConditionStep;
import org.jooq.InsertOnDuplicateStep;
import org.jooq.Record10;
import org.jooq.Record4;
import org.jooq.SelectConditionStep;
import org.jooq.SelectSeekStep1;
import org.jooq.UpdateConditionStep;
import org.jooq.impl.DSL;
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.TLessonSubjectRecord;
import de.jottyfan.bico.modules.theme.model.KeyValueBean;
import de.jottyfan.bico.modules.theme.model.ThemeBean;
/**
*
* @author jotty
*
*/
@Repository
public class ThemeRepository {
private static final Logger LOGGER = Logger.getLogger(ThemeRepository.class);
@Autowired
private DSLContext jooq;
public List<ThemeBean> getThemeManipulation(Integer slotId) {
SelectConditionStep<Record10<String, String, String, String, String, String, String, Integer, String, Integer>> sql = jooq
// @formatter:off
.select(T_SUBJECT.THEME, T_SUBJECT.SUBTHEME, T_SUBJECT.BOOK_PAGES, T_SUBJECT.WORKSHEETS, T_SUBJECT.BIBLEVERSE, T_SUBJECT.NOTES,
T_SOURCE.NAME,
T_LESSON.PK_LESSON, T_LESSON.NOTES,
T_LESSON_SUBJECT.PK_LESSON_SUBJECT)
.from(T_LESSON)
.leftJoin(T_LESSON_SUBJECT).on(T_LESSON_SUBJECT.FK_LESSON.eq(T_LESSON.PK_LESSON))
.leftJoin(T_SUBJECT).on(T_SUBJECT.PK_SUBJECT.eq(T_LESSON_SUBJECT.FK_SUBJECT))
.leftJoin(T_SOURCE).on(T_SOURCE.PK_SOURCE.eq(T_SUBJECT.FK_SOURCE))
.where(T_LESSON.FK_SLOT.eq(slotId));
// @formatter:on
LOGGER.trace(sql);
Iterator<Record10<String, String, String, String, String, String, String, Integer, String, Integer>> i = sql.fetch()
.iterator();
List<ThemeBean> list = new ArrayList<>();
while (i.hasNext()) {
Record10<String, String, String, String, String, String, String, Integer, String, Integer> r = i.next();
ThemeBean bean = ThemeBean.of(r.get(T_LESSON.PK_LESSON));
bean.setSlotId(slotId);
bean.setPkLessonSubject(r.get(T_LESSON_SUBJECT.PK_LESSON_SUBJECT));
bean.setTheme(r.get(T_SUBJECT.THEME));
bean.setSubtheme(r.get(T_SUBJECT.SUBTHEME));
bean.setBookPages(r.get(T_SUBJECT.BOOK_PAGES));
bean.setWorksheets(r.get(T_SUBJECT.WORKSHEETS));
bean.setBibleverse(r.get(T_SUBJECT.BIBLEVERSE));
bean.setNotes(r.get(T_SUBJECT.NOTES));
bean.setSourceName(r.get(T_SOURCE.NAME));
bean.setLessonNotes(r.get(T_LESSON.NOTES));
list.add(bean);
}
return list;
}
public List<KeyValueBean> getAllThemes() {
SelectSeekStep1<Record4<Integer, String, String, String>, Integer> sql = jooq
// @formatter:off
.select(T_SUBJECT.PK_SUBJECT, T_SUBJECT.THEME, T_SUBJECT.SUBTHEME, T_SOURCE.NAME)
.from(T_SUBJECT)
.leftJoin(T_SOURCE).on(T_SOURCE.PK_SOURCE.eq(T_SUBJECT.FK_SOURCE))
.orderBy(T_SUBJECT.ORDER_NR);
// @formatter:on
LOGGER.trace(sql);
List<KeyValueBean> list = new ArrayList<>();
Iterator<Record4<Integer, String, String, String>> i = sql.fetch().iterator();
while (i.hasNext()) {
Record4<Integer, String, String, String> r = i.next();
StringBuilder buf = new StringBuilder();
buf.append(r.get(T_SOURCE.NAME)).append(": ");
buf.append(r.get(T_SUBJECT.THEME)).append(", ");
buf.append(r.get(T_SUBJECT.SUBTHEME));
list.add(KeyValueBean.of(r.get(T_SUBJECT.PK_SUBJECT), buf.toString()));
}
return list;
}
public void addThemeToSlot(Integer slotId, Integer pkSubject) {
InsertOnDuplicateStep<TLessonSubjectRecord> sql = jooq
// @formatter:off
.insertInto(T_LESSON_SUBJECT, T_LESSON_SUBJECT.FK_LESSON, T_LESSON_SUBJECT.FK_SUBJECT)
.select(jooq
.select(T_LESSON.PK_LESSON, DSL.val(pkSubject))
.from(T_LESSON)
.where(T_LESSON.FK_SLOT.eq(slotId))
);
// @formatter:on
LOGGER.trace(sql);
sql.execute();
}
public void removeThemeFromSlot(Integer pkLessonSubject) {
DeleteConditionStep<TLessonSubjectRecord> sql = jooq.deleteFrom(T_LESSON_SUBJECT)
.where(T_LESSON_SUBJECT.PK_LESSON_SUBJECT.eq(pkLessonSubject));
LOGGER.trace(sql);
sql.execute();
}
public TLessonRecord getLesson(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.fetchOne();
}
public void updateLesson(TLessonRecord bean) {
UpdateConditionStep<TLessonRecord> sql = jooq
// @formatter:off
.update(T_LESSON)
.set(T_LESSON.NOTES, bean.getNotes())
.where(T_LESSON.PK_LESSON.eq(bean.getPkLesson()));
// @formatter:on
LOGGER.trace(sql);
sql.execute();
}
}

View File

@ -0,0 +1,47 @@
package de.jottyfan.bico.modules.theme;
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.modules.theme.model.KeyValueBean;
import de.jottyfan.bico.modules.theme.model.ThemeBean;
/**
*
* @author jotty
*
*/
@Service
public class ThemeService {
@Autowired
private ThemeRepository repository;
public List<ThemeBean> getThemeManipulation(Integer slotId) {
return repository.getThemeManipulation(slotId);
}
public List<KeyValueBean> getAllThemes() {
return repository.getAllThemes();
}
public void addThemeToSlot(Integer slotId, Integer pkSubject) {
repository.addThemeToSlot(slotId, pkSubject);
}
public void removeThemeFromSlot(Integer pkLessonSubject) {
repository.removeThemeFromSlot(pkLessonSubject);
}
public TLessonRecord getLesson(Integer slotId) {
return repository.getLesson(slotId);
}
public void updateLesson(TLessonRecord bean) {
repository.updateLesson(bean);
}
}

View File

@ -0,0 +1,48 @@
package de.jottyfan.bico.modules.theme.model;
import java.io.Serializable;
/**
*
* @author jotty
*
*/
public class KeyValueBean implements Serializable {
private static final long serialVersionUID = 7364119756528512005L;
private Integer key;
private String value;
public static final KeyValueBean of(Integer key, String value) {
KeyValueBean bean = new KeyValueBean();
bean.setKey(key);
bean.setValue(value);
return bean;
}
/**
* @return the key
*/
public Integer getKey() {
return key;
}
/**
* @param key the key to set
*/
public void setKey(Integer key) {
this.key = key;
}
/**
* @return the value
*/
public String getValue() {
return value;
}
/**
* @param value the value to set
*/
public void setValue(String value) {
this.value = value;
}
}

View File

@ -0,0 +1,201 @@
package de.jottyfan.bico.modules.theme.model;
import java.io.Serializable;
/**
*
* @author jotty
*
*/
public class ThemeBean implements Serializable {
private static final long serialVersionUID = 1L;
private Integer lessonId;
private Integer slotId;
private Integer pkLessonSubject;
private String theme;
private String subtheme;
private String bookPages;
private String worksheets;
private String bibleverse;
private String notes;
private String sourceName;
private String lessonNotes;
public static ThemeBean of(Integer lessonId) {
ThemeBean bean = new ThemeBean();
bean.setLessonId(lessonId);
return bean;
}
/**
* @return the theme
*/
public String getTheme() {
return theme;
}
/**
* @param theme the theme to set
*/
public void setTheme(String theme) {
this.theme = theme;
}
/**
* @return the subtheme
*/
public String getSubtheme() {
return subtheme;
}
/**
* @param subtheme the subtheme to set
*/
public void setSubtheme(String subtheme) {
this.subtheme = subtheme;
}
/**
* @return the sourceName
*/
public String getSourceName() {
return sourceName;
}
/**
* @param sourceName the sourceName to set
*/
public void setSourceName(String sourceName) {
this.sourceName = sourceName;
}
/**
* @return the slotId
*/
public Integer getSlotId() {
return slotId;
}
/**
* @param slotId the slotId to set
*/
public void setSlotId(Integer slotId) {
this.slotId = slotId;
}
/**
* @return the bookPages
*/
public String getBookPages() {
return bookPages;
}
/**
* @param bookPages the bookPages to set
*/
public void setBookPages(String bookPages) {
this.bookPages = bookPages;
}
/**
* @return the worksheets
*/
public String getWorksheets() {
return worksheets;
}
/**
* @param worksheets the worksheets to set
*/
public void setWorksheets(String worksheets) {
this.worksheets = worksheets;
}
/**
* @return the bibleverse
*/
public String getBibleverse() {
return bibleverse;
}
/**
* @param bibleverse the bibleverse to set
*/
public void setBibleverse(String bibleverse) {
this.bibleverse = bibleverse;
}
/**
* @return the notes
*/
public String getNotes() {
return notes;
}
/**
* @param notes the notes to set
*/
public void setNotes(String notes) {
this.notes = notes;
}
/**
* @return the lessonNotes
*/
public String getLessonNotes() {
return lessonNotes;
}
/**
* @param lessonNotes the lessonNotes to set
*/
public void setLessonNotes(String lessonNotes) {
this.lessonNotes = lessonNotes;
}
/**
* @return the lessonId
*/
public Integer getLessonId() {
return lessonId;
}
/**
* @param lessonId the lessonId to set
*/
public void setLessonId(Integer lessonId) {
this.lessonId = lessonId;
}
/**
* @return the pkLessonSubject
*/
public Integer getPkLessonSubject() {
return pkLessonSubject;
}
/**
* @param pkLessonSubject the pkLessonSubject to set
*/
public void setPkLessonSubject(Integer pkLessonSubject) {
this.pkLessonSubject = pkLessonSubject;
}
}

View File

@ -34,4 +34,15 @@ body {
.rightpadding64 {
margin-right: 64px;
}
.sidenote {
font-style: italic;
}
.blockframe {
border: 1px solid gray;
padding: 4px;
margin: 4px;
border-radius: 4px;
}

View File

@ -18,15 +18,30 @@
<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><div th:text="${s.theme}"></div>
<div th:text="${s.subtheme}"></div></td>
<td>
<div class="container">
<div class="row">
<div class="col-11">
<div th:text="${s.theme}"></div>
<div th:text="${s.subtheme}"></div>
<div th:text="${s.lessonNotes}" class="sidenote"></div>
</div>
<div class="col-1">
<a th:href="@{/theme?slotId={id}(id=${s.pkSlot})}" class="btn btn-outline-secondary"><i class="bi bi-pencil"></i></a>
</div>
</div>
</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="4"><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">ein neues Datum anlegen</a>
<a th:href="@{/subject/new}" class="btn btn-outline-primary">ein neues Thema anlegen</a>
</td>
</tr>
</tfoot>
</table>

View File

@ -0,0 +1,21 @@
<!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">
TODO: implement
<pre>
fields:
fk_source
theme
subtheme
book_pages
worksheets
bibleverse
notes
order_nr
</pre>
</div>
</th:block>
</body>
</html>

View File

@ -0,0 +1,64 @@
<!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">
<th:block th:each="b : ${list}" th:if="${list.size() > 0}">
<div class="row g-2 blockframe">
<div class="col-sm-3">Thema:</div>
<div class="col-sm-8"><span th:text="${b.theme}"></span></div>
<div class="col-sm-1">
<div class="dropdown">
<button class="btn btn-outline-danger dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false">
<i class="bi bi-trash"></i>
</button>
<ul class="dropdown-menu">
<li><a class="dropdown-item" th:href="@{/theme/delete?lessonSubjectId={id}&slotId={s}(id=${b.pkLessonSubject},s=${slotId})}">ja, endgültig verwerfen</a></li>
</ul>
</div>
</div>
<div class="col-sm-3">Unterthema:</div>
<div class="col-sm-9"><span th:text="${b.subtheme}"></span></div>
<div class="col-sm-3">Buchseiten:</div>
<div class="col-sm-9"><span th:text="${b.bookPages}"></span></div>
<div class="col-sm-3">Arbeitsblätter:</div>
<div class="col-sm-9"><span th:text="${b.worksheets}"></span></div>
<div class="col-sm-3">Bibelvers (Lernvers):</div>
<div class="col-sm-9"><span th:text="${b.bibleverse}"></span></div>
<div class="col-sm-3">Anmerkungen zum Thema:</div>
<div class="col-sm-9"><span th:text="${b.notes}"></span></div>
<div class="col-sm-3">Quelle:</div>
<div class="col-sm-9"><span th:text="${b.sourceName}"></span></div>
</div>
</th:block>
<form th:action="@{/theme/update?slotId={id}(id=${slotId})}" method="post" th:object="${lesson}">
<input type="hidden" th:field="*{pkLesson}" />
<div class="row g-2 blockframe">
<div class="col-sm-3">Anmerkungen zur Stunde</div>
<div class="col-sm-9">
<textarea th:field="*{notes}" class="form-control"></textarea>
</div>
<div class="col-sm-3">&nbsp;</div>
<div class="col-sm-9">
<button type="submit" class="btn btn-outline-primary">Übernehmen</button>
<button type="reset" class="btn btn-outline-secondary">Verwerfen</button>
</div>
</div>
</form>
<form th:action="@{/theme/add?slotId={id}(id=${slotId})}" method="post">
<div class="row g-2">
<div class="col-sm-3">ein Thema hinzufügen</div>
<div class="col-sm-7">
<select name="pkSubject" class="form-select">
<option th:each="t : ${themes}" th:value="${t.key}" th:text="${t.value}"></option>
</select>
</div>
<div class="col-sm-2"><button type="submit" class="btn btn-outline-primary">hinzufügen</button></div>
</div>
</form>
</div>
</div>
</th:block>
</body>
</html>