added next
This commit is contained in:
		| @@ -42,7 +42,20 @@ public abstract class CommonController { | ||||
| 			return false; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	 | ||||
| 	@ModelAttribute("hasDiakoneRole") | ||||
| 	public Boolean hasDiakoneRole(Principal principal) { | ||||
| 		OAuth2AuthenticationToken token = (OAuth2AuthenticationToken) principal; | ||||
| 		if (token != null) { | ||||
| 			OAuth2User user = token.getPrincipal(); | ||||
| 			@SuppressWarnings("unchecked") | ||||
| 			List<String> roles = (List<String>) user.getAttributes().get("roles"); | ||||
| 			return roles.contains("Diakone"); | ||||
| 		} else { | ||||
| 			LOGGER.warn("token is null, no roles can be detected"); | ||||
| 			return false; | ||||
| 		} | ||||
| 	} | ||||
| 	/** | ||||
| 	 * get the theme for the current session | ||||
| 	 * | ||||
|   | ||||
| @@ -14,6 +14,6 @@ import de.jottyfan.bico.modules.CommonController; | ||||
| public class IndexController extends CommonController { | ||||
| 	@GetMapping("/") | ||||
| 	public String getIndex() { | ||||
| 		return "redirect:/sheet"; | ||||
| 		return "redirect:/next"; | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -0,0 +1,38 @@ | ||||
| package de.jottyfan.bico.modules.next; | ||||
|  | ||||
| import java.time.LocalDate; | ||||
| import java.time.format.DateTimeFormatter; | ||||
|  | ||||
| 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.PathVariable; | ||||
|  | ||||
| import de.jottyfan.bico.modules.CommonController; | ||||
|  | ||||
| /** | ||||
|  *  | ||||
|  * @author jotty | ||||
|  *  | ||||
|  */ | ||||
| @Controller | ||||
| public class NextController extends CommonController { | ||||
|  | ||||
| 	@Autowired | ||||
| 	private NextService service; | ||||
| 	 | ||||
| 	@GetMapping("/next") | ||||
| 	public String getNext(Model model) { | ||||
| 		model.addAttribute("list", service.getNext(LocalDate.now())); | ||||
| 		return "/next"; | ||||
| 	} | ||||
| 	 | ||||
| 	@GetMapping("/next/{date}") | ||||
| 	public String getNextForDate(@PathVariable("date") String dateStr, Model model) { | ||||
| 		DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); | ||||
|     LocalDate date = LocalDate.parse(dateStr, formatter); | ||||
| 		model.addAttribute("list", service.getNext(date)); | ||||
| 		return "/next"; | ||||
| 	} | ||||
| } | ||||
| @@ -0,0 +1,56 @@ | ||||
| package de.jottyfan.bico.modules.next; | ||||
|  | ||||
| import static de.jottyfan.bico.db.Tables.V_CALENDAR; | ||||
|  | ||||
| import java.time.LocalDate; | ||||
| import java.util.ArrayList; | ||||
| import java.util.Iterator; | ||||
| import java.util.List; | ||||
|  | ||||
| import org.apache.logging.log4j.LogManager; | ||||
| import org.apache.logging.log4j.Logger; | ||||
| import org.jooq.DSLContext; | ||||
| import org.jooq.Record2; | ||||
| import org.jooq.SelectSeekStep1; | ||||
| import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.stereotype.Repository; | ||||
|  | ||||
| import de.jottyfan.bico.modules.next.model.NextBean; | ||||
|  | ||||
| /** | ||||
|  *  | ||||
|  * @author jotty | ||||
|  *  | ||||
|  */ | ||||
| @Repository | ||||
| public class NextRepository { | ||||
| 	private static final Logger LOGGER = LogManager.getLogger(NextRepository.class); | ||||
|  | ||||
| 	@Autowired | ||||
| 	private DSLContext jooq; | ||||
|  | ||||
| 	/** | ||||
| 	 * get the next dates from date on | ||||
| 	 *  | ||||
| 	 * @param date the date | ||||
| 	 * @return the next dates as beans in a list; an empty list at least | ||||
| 	 */ | ||||
| 	public List<NextBean> getNext(LocalDate date) { | ||||
| 		SelectSeekStep1<Record2<String, LocalDate>, LocalDate> sql = jooq | ||||
| 		// @formatter:off | ||||
| 			.selectDistinct(V_CALENDAR.FULLNAME, V_CALENDAR.SLOT_DAY) | ||||
| 			.from(V_CALENDAR) | ||||
| 			.where(V_CALENDAR.SLOT_DAY.ge(date)) | ||||
| 			.orderBy(V_CALENDAR.SLOT_DAY.asc()); | ||||
| 		// @formatter:on | ||||
| 		LOGGER.trace(sql); | ||||
| 		Iterator<Record2<String, LocalDate>> i = sql.fetch().iterator(); | ||||
| 		List<NextBean> list = new ArrayList<>(); | ||||
| 		while (i.hasNext()) { | ||||
| 			Record2<String, LocalDate> r = i.next(); | ||||
| 			list.add(NextBean.of(r.get(V_CALENDAR.FULLNAME), r.get(V_CALENDAR.SLOT_DAY))); | ||||
| 		} | ||||
| 		return list; | ||||
| 	} | ||||
|  | ||||
| } | ||||
							
								
								
									
										32
									
								
								src/main/java/de/jottyfan/bico/modules/next/NextService.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								src/main/java/de/jottyfan/bico/modules/next/NextService.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| package de.jottyfan.bico.modules.next; | ||||
|  | ||||
| import java.time.LocalDate; | ||||
| import java.util.List; | ||||
|  | ||||
| import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.stereotype.Service; | ||||
|  | ||||
| import de.jottyfan.bico.modules.next.model.NextBean; | ||||
|  | ||||
| /** | ||||
|  *  | ||||
|  * @author jotty | ||||
|  *  | ||||
|  */ | ||||
| @Service | ||||
| public class NextService { | ||||
|  | ||||
| 	@Autowired | ||||
| 	private NextRepository repository; | ||||
| 	 | ||||
| 	/** | ||||
| 	 * get the next dates | ||||
| 	 *  | ||||
| 	 * @param date the date | ||||
| 	 * @return the list of next dates | ||||
| 	 */ | ||||
| 	public List<NextBean> getNext(LocalDate date) { | ||||
| 		return repository.getNext(date); | ||||
| 	} | ||||
| 	 | ||||
| } | ||||
| @@ -0,0 +1,54 @@ | ||||
| package de.jottyfan.bico.modules.next.model; | ||||
|  | ||||
| import java.io.Serializable; | ||||
| import java.time.LocalDate; | ||||
|  | ||||
| /** | ||||
|  *  | ||||
|  * @author jotty | ||||
|  *  | ||||
|  */ | ||||
| public class NextBean implements Serializable { | ||||
| 	private static final long serialVersionUID = 1L; | ||||
|  | ||||
| 	private String fullname; | ||||
| 	private LocalDate day; | ||||
| 	 | ||||
| 	private NextBean() { | ||||
| 	} | ||||
| 	 | ||||
| 	public final static NextBean of(String fullname, LocalDate day) { | ||||
| 		NextBean bean = new NextBean(); | ||||
| 		bean.setDay(day); | ||||
| 		bean.setFullname(fullname); | ||||
| 		return bean; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @return the fullname | ||||
| 	 */ | ||||
| 	public String getFullname() { | ||||
| 		return fullname; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @return the day | ||||
| 	 */ | ||||
| 	public LocalDate getDay() { | ||||
| 		return day; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @param fullname the fullname to set | ||||
| 	 */ | ||||
| 	private void setFullname(String fullname) { | ||||
| 		this.fullname = fullname; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * @param day the day to set | ||||
| 	 */ | ||||
| 	private void setDay(LocalDate day) { | ||||
| 		this.day = day; | ||||
| 	}	 | ||||
| } | ||||
							
								
								
									
										18
									
								
								src/main/resources/templates/next.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								src/main/resources/templates/next.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | ||||
| <!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" sec:authorize="hasAnyRole('Diakone', 'Bibelunterricht')"> | ||||
| 				<div class="row"> | ||||
| 					<div class="col-sm-6 col-md-4 col-lg-2 card p-2 m-1" th:each="s : ${list}"> | ||||
| 						<div th:text="${#temporals.format(s.day, 'dd.MM.yyyy')}"></div> | ||||
| 					  <div th:text="${s.fullname}"></div> | ||||
| 					</div> | ||||
| 					<div class="alert alert-info" th:if="${list.size() < 1}">Es gibt noch keine neuen Termine oder Zusagen für Termine.</div> | ||||
| 				</div> | ||||
| 			</div> | ||||
| 		</div> | ||||
| 	</th:block> | ||||
| </body> | ||||
| </html> | ||||
| @@ -4,13 +4,13 @@ | ||||
| <title>Bible Class Organizer</title> | ||||
| <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> | ||||
| <meta name="viewport" content="width=device-width, initial-scale=1" /> | ||||
| <link th:rel="stylesheet" type="text/css" media="all" th:href="@{/webjars/bootstrap/5.3.2/css/bootstrap.min.css}" /> | ||||
| <link th:rel="stylesheet" type="text/css" media="all" th:href="@{/webjars/bootstrap-icons/1.10.5/font/bootstrap-icons.css}" /> | ||||
| <link th:rel="stylesheet" type="text/css" media="all" th:href="@{/webjars/datatables/1.13.5/css/jquery.dataTables.min.css}" /> | ||||
| <link th:rel="stylesheet" type="text/css" media="all" th:href="@{/webjars/bootstrap/5.3.3/css/bootstrap.min.css}" /> | ||||
| <link th:rel="stylesheet" type="text/css" media="all" th:href="@{/webjars/bootstrap-icons/1.11.3/font/bootstrap-icons.css}" /> | ||||
| <link th:rel="stylesheet" type="text/css" media="all" th:href="@{/webjars/datatables/2.1.0/css/jquery.dataTables.min.css}" /> | ||||
| <link th:rel="stylesheet" type="text/css" media="all" th:href="@{/css/style.css}" /> | ||||
| <script th:src="@{/webjars/bootstrap/5.3.2/js/bootstrap.bundle.min.js}"></script> | ||||
| <script th:src="@{/webjars/bootstrap/5.3.3/js/bootstrap.bundle.min.js}"></script> | ||||
| <script th:src="@{/webjars/jquery/3.7.1/jquery.min.js}"></script> | ||||
| <script th:src="@{/webjars/datatables/1.13.5/js/jquery.dataTables.min.js}"></script> | ||||
| <script th:src="@{/webjars/datatables/2.1.0/js/jquery.dataTables.min.js}"></script> | ||||
| <script th:src="@{/js/dataTables.de.js}"></script> | ||||
| <script th:src="@{/js/stylehelp.js}"></script> | ||||
| </head> | ||||
| @@ -21,10 +21,11 @@ | ||||
| 			<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" th:if="${hasBUrole}"> | ||||
| 				<li class="nav-item"><a class="btn btn-outline-secondary" th:href="@{/}" style="margin-left: 12px">Einteilung</a></li> | ||||
| 				<li class="nav-item"><a class="btn btn-outline-secondary" th:href="@{/subject/list}" style="margin-left: 12px">Themen</a></li> | ||||
| 				<li class="nav-item"><a class="btn btn-outline-secondary" th:href="@{/download}" style="margin-left: 12px">Download</a></li> | ||||
| 			<ul class="navbar-nav mb-2 mb-lg-0" th:if="${hasBUrole || hasDiakoneRole}"> | ||||
| 				<li class="nav-item"><a class="btn btn-outline-secondary" th:href="@{/next}" style="margin-left: 12px">Dienstplan</a></li> | ||||
| 				<li class="nav-item"><a class="btn btn-outline-secondary" th:href="@{/sheet}" style="margin-left: 12px" th:if="${hasBUrole}">Einteilung</a></li> | ||||
| 				<li class="nav-item"><a class="btn btn-outline-secondary" th:href="@{/subject/list}" style="margin-left: 12px" th:if="${hasBUrole}">Themen</a></li> | ||||
| 				<li class="nav-item"><a class="btn btn-outline-secondary" th:href="@{/download}" style="margin-left: 12px" th:if="${hasBUrole}">Download</a></li> | ||||
| 			</ul> | ||||
| 			<ul layout:fragment="header"></ul> | ||||
| 			<ul class="nav navbar-nav ms-auto"> | ||||
| @@ -40,8 +41,8 @@ | ||||
| 			</ul> | ||||
| 		</div> | ||||
| 	</nav> | ||||
| 	<div layout:fragment="content" th:if="${hasBUrole}">content</div> | ||||
| 	<div th:unless="${hasBUrole}"> | ||||
| 	<div layout:fragment="content" th:if="${hasBUrole || hasDiakoneRole}">content</div> | ||||
| 	<div th:unless="${hasBUrole || hasDiakoneRole}"> | ||||
| 		<div class="borderdist"> | ||||
| 			<div class="alert alert-danger">Leider fehlen Ihnen die Berechtigungen, um diese Anwendung nutzen zu können.</div> | ||||
| 		</div> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user