diff --git a/src/main/java/nl/tudelft/queue/controller/LabController.java b/src/main/java/nl/tudelft/queue/controller/LabController.java index 91c55393e2aa05948a538c70b0ea07af428435a8..46d7f3e8d66df747688aa6713cc2dd58668e8472 100644 --- a/src/main/java/nl/tudelft/queue/controller/LabController.java +++ b/src/main/java/nl/tudelft/queue/controller/LabController.java @@ -654,6 +654,15 @@ public class LabController { .body(resource); } + @GetMapping("/lab/{session}/room/{roomId}/slide-show") + public String getSlideShow(@PathEntity QueueSession<?> session, @PathVariable Long roomId, + Model model) { + var room = rCache.getOrThrow(roomId); + model.addAttribute("room", room); + model.addAttribute("lsession", session.toViewDTO()); + return "slide-show/view"; + } + /** * Sets the model attributes for an enqueueing or editing requests page. * diff --git a/src/main/resources/scss/slideshow.scss b/src/main/resources/scss/slideshow.scss new file mode 100644 index 0000000000000000000000000000000000000000..9ee66d1dbf29757f48337e38026baaeb97665674 --- /dev/null +++ b/src/main/resources/scss/slideshow.scss @@ -0,0 +1,111 @@ +@import "variables"; + +@keyframes fade { + from { + opacity: .4; + } + to { + opacity: 1; + } +} +* { + box-sizing: border-box; +} +.slideshow-container { + width: 100%; + height: 94vh; + position: relative; + margin: auto; +} +.slides { + display: none; +} +.prev { + cursor: pointer; + position: absolute; + top: 50%; + width: auto; + margin-top: -22px; + padding: 16px; + color: white; + font-weight: bold; + font-size: 18px; + transition: 0.6s ease; + border-radius: 0 3px 3px 0; + user-select: none; + &:hover { + background-color: rgba(0,0,0,0.8); + } +} +.next { + cursor: pointer; + position: absolute; + top: 50%; + width: auto; + margin-top: -22px; + padding: 16px; + color: white; + font-weight: bold; + font-size: 18px; + transition: 0.6s ease; + border-radius: 0 3px 3px 0; + user-select: none; + right: 0; + border-radius: 3px 0 0 3px; + &:hover { + background-color: rgba(0,0,0,0.8); + } +} +.text { + color: #f2f2f2; + font-size: 15px; + padding: 8px 12px; + position: absolute; + bottom: 8px; + width: 100%; + text-align: center; +} + +.counter { + color: var(--primary-blue); + font-size: 12px; + padding: 8px 12px; + position: absolute; + top: 0; +} + +.dot { + cursor: pointer; + height: 15px; + width: 15px; + margin: 0 2px; + background-color: #bbb; + border-radius: 50%; + display: inline-block; + transition: background-color 0.6s ease; + &:hover { + background-color: var(--primary-blue); + } +} +.active { + background-color: var(--primary-blue); +} +.fade { + animation-name: fade; + animation-duration: 1.5s; + animation-fill-mode: forwards; +} + +.slide-content { + position: absolute; + left: 50%; + top: 50%; + -webkit-transform: translate(-50%, -50%); + transform: translate(-50%, -50%); + + img { + height: 10rem; + margin: auto; + display: block; + } +} diff --git a/src/main/resources/static/js/slideshow.js b/src/main/resources/static/js/slideshow.js new file mode 100644 index 0000000000000000000000000000000000000000..65beb8085c4951330b367bce4067b93624e52531 --- /dev/null +++ b/src/main/resources/static/js/slideshow.js @@ -0,0 +1,37 @@ +let slideIndex = 1; +window.addEventListener("load", function() { + showSlides(slideIndex); +}) + +// Next/previous controls +function plusSlides(n) { + showSlides(slideIndex += n); +} + +// Thumbnail image controls +function currentSlide(n) { + showSlides(slideIndex = n); +} + +function showSlides(n) { + let i; + let slides = document.getElementsByClassName("slides"); + let dots = document.getElementsByClassName("dot"); + if (n > slides.length) {slideIndex = 1} + if (n < 1) {slideIndex = slides.length} + for (i = 0; i < slides.length; i++) { + slides[i].style.display = "none"; + } + for (i = 0; i < dots.length; i++) { + dots[i].className = dots[i].className.replace(" active", ""); + } + slides[slideIndex-1].style.display = "block"; + dots[slideIndex-1].className += " active"; + console.log(slides) +} + +function generateQRCode(id) { + let url = "http://" + window.location.hostname + "/lab/" + id + "/enqueue" + let qrCode = 'https://api.qrserver.com/v1/create-qr-code/?data=' + url + '&size=50x50' + $("#qrCode").attr('src', qrCode) +} diff --git a/src/main/resources/templates/slide-show/view.html b/src/main/resources/templates/slide-show/view.html new file mode 100644 index 0000000000000000000000000000000000000000..8f9ab8b137ce36b1f4e1676e87329f388cac0206 --- /dev/null +++ b/src/main/resources/templates/slide-show/view.html @@ -0,0 +1,122 @@ +<!DOCTYPE html> +<html lang="en" xmlns:th="http://www.thymeleaf.org" + xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"> +<head> + <meta charset="utf-8"/> + <meta http-equiv="X-UA-Compatible" content="IE=edge"/> + <meta http-equiv="Content-Language" content="en_GB"/> + <meta name="viewport" content="width=device-width, initial-scale=1"/> + + <meta name="description" content="Queue system"/> + <meta name="author" content=""/> + <meta name="_csrf_header" th:content="${_csrf.headerName}"/> + <meta name="_csrf" th:content="${_csrf.token}"/> + + <link rel="icon" href="/favicon.ico"/> + + <title th:unless="${@thymeleafConfig.isTheDay()}">Queue</title> + <title th:if="${@thymeleafConfig.isTheDay()}">Stack</title> + <title>Queue</title> + + <link rel="stylesheet" href="/webjars/bootstrap/css/bootstrap.min.css"/> + <link rel="stylesheet" href="/webjars/font-awesome/css/all.css"/> + <link rel="stylesheet" href="/webjars/font-awesome/css/v4-shims.css"/> + <link rel="stylesheet" type="text/css" href="/css/slideshow.css"/> + <link rel="stylesheet" type="text/css" href="/css/global.css"/> + + <script src="/webjars/jquery/jquery.min.js"></script> + <script src="/webjars/jquery-cookie/jquery.cookie.js"></script> + <script src="/webjars/bootstrap/js/bootstrap.bundle.min.js"></script> + + <script src="/webjars/sockjs-client/sockjs.min.js"></script> + <script src="/webjars/stomp-websocket/stomp.min.js"></script> + +<!-- <script src="/js/global.js"></script>--> +</head> +<!--@thymesVar id="lsession" type="nl.tudelft.queue.dto.view.QueueSessionViewDTO"--> +<body> +<main> + <div class="slideshow-container"> + <div class="slides fade"> + <div class="counter"> 1/ 3</div> + <div class="slide-content"> + <h2 th:text="|Welcome to lab ${lsession.session.name}|"></h2> + <p th:text="|You are currently in room ${room.name}|"></p> + <p>Use the following QR code to find the enqueue page</p> + <img id="qrCode" alt="QR code pointing to the enqueue page" + title="Enqueue page QR code"/> + </div> + </div> + + <div class="slides fade"> + <div class="counter"> 2 / 3</div> + <div class="slide-content"> + <h2>Assignments</h2> + <h5>During this lab you can work on the following assignments</h5> + <table class="table"> + <thead> + <tr> + <td>Name</td> + <td>Description</td> + <td>Due date</td> + </tr> + </thead> + <th:block th:each="m : ${lsession.modules}"> + <thead> + <tr th:text="${m.name}"> + </tr> + </thead> + <tbody> + <tr th:each="a : ${m.assignments}"> + <td th:text="${a.name}"></td> + <td th:text="${a.description.text}"></td> + <td th:text="${#temporals.format(a.deadline, 'dd MMMM yyyy HH:mm')}"></td> + </tr> + </tbody> + </th:block> + </table> + </div> + </div> + </div> + <div style="text-align:center"> + <span class="dot" onclick="currentSlide(1)"></span> + <span class="dot" onclick="currentSlide(2)"></span> +<!-- <span class="dot" onclick="currentSlide(3)"></span>--> + </div> + <script src="/js/slideshow.js"></script> + <script defer> + /*<![CDATA[*/ + generateQRCode(/*[[${lsession.id}]]*/) + /*]]>*/ + </script> +</main> + + +<footer class="bg-light"> + <div class="container-fluid"> + <div class="row no-gutters justify-content-center"> + <div class="col-12 col-lg-9 col-xl-8"> + <div class="row justify-content-center"> + <div class="d-none d-sm-block col-sm-6"> + <p class="text-muted btn mb-0">© Delft University of Technology</p> + </div> + <div class="col-5 col-sm-2"> + <a class="text-muted btn" th:href="@{/privacy}">Privacy</a> + </div> + <div class="col-4 col-sm-2"> + <a class="text-muted btn" th:href="@{/about}">About</a> + </div> + <div class="col-3 col-sm-2"> + <img th:src="@{${@instituteProperties.logo}}" + class="float-right pr-2 mr-0" + height="40px" + alt="Logo"/> + </div> + </div> + </div> + </div> + </div> +</footer> + +</body> +</html>