Initial commit
This commit is contained in:
21
ui/html/base.layout.tmpl.html
Normal file
21
ui/html/base.layout.tmpl.html
Normal file
@@ -0,0 +1,21 @@
|
||||
{{ define "base" -}}
|
||||
<!DOCTYPE html>
|
||||
<html lang='cs'>
|
||||
<head>
|
||||
<meta charset='utf-8'>
|
||||
<title>Tinyquiz</title>
|
||||
<link rel="stylesheet" href="/static/style.css">
|
||||
{{ block "aditional-css" . }}{{ end }}
|
||||
<script src="/static/script.js" defer type="text/javascript"></script>
|
||||
{{ block "aditional-js" . }}{{ end }}
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
{{- block "header" . }}{{ end -}}
|
||||
</header>
|
||||
<main>
|
||||
{{- template "main" . -}}
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
{{- end }}
|
||||
107
ui/html/game.page.tmpl.html
Normal file
107
ui/html/game.page.tmpl.html
Normal file
@@ -0,0 +1,107 @@
|
||||
{{- template "base" . -}}
|
||||
|
||||
{{- define "aditional-css" -}}
|
||||
<link rel="stylesheet" href="/static/game.css">
|
||||
{{ end -}}
|
||||
|
||||
{{- define "aditional-js" -}}
|
||||
{{ end -}}
|
||||
|
||||
{{- define "header" }}
|
||||
<h1>{{ .P.Edges.Session.Edges.Game.Name }}</h1>
|
||||
{{ end -}}
|
||||
|
||||
{{- define "main" }}
|
||||
<template id="name-template">
|
||||
<span class="name"></span>
|
||||
</template>
|
||||
<section id="names" data-my-name="{{ .P.Name }}"></section>
|
||||
|
||||
<template id="answer-template">
|
||||
<button class="answer"></button>
|
||||
</template>
|
||||
<template id="question-template">
|
||||
<h1 class="question"></h1>
|
||||
<div class="answers"></div>
|
||||
</template>
|
||||
<section id="question"></section>
|
||||
|
||||
<section id="controls">
|
||||
<button class="next" data-session="{{ .P.Edges.Session.ID }}">Další otázka</button>
|
||||
</section>
|
||||
|
||||
<script>
|
||||
const socket = new WebSocket('ws://' + window.location.host + '/ws/' + encodeURIComponent({{ .P.ID }}));
|
||||
|
||||
//TODO remove
|
||||
socket.addEventListener('open', () => {
|
||||
console.log("WS oppened");
|
||||
});
|
||||
|
||||
const namesSection = document.getElementById('names');
|
||||
const nameTemplate = document.getElementById('name-template')
|
||||
|
||||
const questionSection = document.getElementById('question');
|
||||
const questionTemplate = document.getElementById('question-template');
|
||||
const answerTemplate = document.getElementById('answer-template');
|
||||
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
const next = document.querySelector('#controls .next');
|
||||
next.addEventListener("click", () => {
|
||||
let url = window.location.path + '/rpc/next';
|
||||
if (questionSection.dataset.id) {
|
||||
url += '?current=' + encodeURIComponent(questionSection.dataset.id);
|
||||
}
|
||||
fetch(url, {method: "POST"})
|
||||
.catch(() => {
|
||||
console.warn("Setting next question failed")
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
socket.addEventListener('message', (e) => {
|
||||
const data = JSON.parse(e.data);
|
||||
console.log(data); //TODO remove debug
|
||||
|
||||
if ('players' in data) {
|
||||
namesSection.innerHTML = '';
|
||||
for (const player of data.players) {
|
||||
const nameClone = nameTemplate.content.cloneNode(true);
|
||||
const name = nameClone.querySelector('.name');
|
||||
name.innerText = player.name;
|
||||
if (player.name === namesSection.dataset.myName) {
|
||||
if (player.organiser) {
|
||||
document.body.classList.add('organiser');
|
||||
} else {
|
||||
document.body.classList.remove('organiser');
|
||||
}
|
||||
name.classList.add('my-name');
|
||||
}
|
||||
if (player.organiser) {
|
||||
name.classList.add('organiser');
|
||||
}
|
||||
namesSection.appendChild(nameClone);
|
||||
}
|
||||
}
|
||||
|
||||
if ('question' in data) {
|
||||
questionSection.innerHTML = '';
|
||||
if (data.question) {
|
||||
const questionClone = questionTemplate.content.cloneNode(true);
|
||||
questionClone.querySelector('.question').innerText = data.question.title;
|
||||
const answers = questionClone.querySelector('.answers');
|
||||
const organiser = document.body.classList.contains('organiser');
|
||||
for (const answer of data.question.answers) {
|
||||
const answerClone = answerTemplate.content.cloneNode(true);
|
||||
answerClone.querySelector('.answer').innerText = answer.title;
|
||||
if (organiser) {
|
||||
answerClone.querySelector('.answer').disabled = true;
|
||||
}
|
||||
answers.appendChild(answerClone);
|
||||
}
|
||||
questionSection.appendChild(questionClone);
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{{ end -}}
|
||||
45
ui/html/home.page.tmpl.html
Normal file
45
ui/html/home.page.tmpl.html
Normal file
@@ -0,0 +1,45 @@
|
||||
{{- template "base" . -}}
|
||||
|
||||
{{- define "aditional-css" -}}
|
||||
<link rel="stylesheet" href="/static/home.css">
|
||||
{{ end -}}
|
||||
|
||||
{{- define "aditional-js" -}}
|
||||
<script src="/static/home.js"></script>
|
||||
{{ end -}}
|
||||
|
||||
{{- define "main" }}
|
||||
<main>
|
||||
<section>
|
||||
<h1>Statistiky</h1>
|
||||
<p>
|
||||
Celkem odehráno {{ .Stats.Sessions }} her {{ .Stats.Players }} hráči.
|
||||
Celkem je k dispozici {{ .Stats.Games }} kvízů.
|
||||
</p>
|
||||
</section>
|
||||
<section>
|
||||
<h1>Připojit se ke hře</h1>
|
||||
<form id="join" method="post">
|
||||
<label>Kód hry: <input type="text" name="code" placeholder="Kód hry"></label>
|
||||
<label>Jméno hráče: <input type="text" name="player" placeholder="Jméno"></label>
|
||||
<input type="submit" value="Připojit do hry">
|
||||
</form>
|
||||
</section>
|
||||
<section>
|
||||
<h1>Začít hrát</h1>
|
||||
<form id="play" method="post" action="/play">
|
||||
<label>Kód kvízu: <input type="text" name="code" placeholder="Kód kvizu"></label>
|
||||
<label>Jméno organizátora: <input type="text" name="organiser" placeholder="Jméno"></label>
|
||||
<input type="submit" value="Začit hrát">
|
||||
</form>
|
||||
</section>
|
||||
<section>
|
||||
<h1>Vytvořit nový kvíz</h1>
|
||||
<form id="new" method="get" action="/new">
|
||||
<label>Jméno kvízu: <input type="text" name="quiz" placeholder="Jméno kvízu"></label>
|
||||
<label>Jméno autora: <input type="text" name="author" placeholder="Jméno"></label>
|
||||
<input type="submit" value="Vytvořit">
|
||||
</form>
|
||||
</section>
|
||||
</main>
|
||||
{{ end -}}
|
||||
68
ui/static/game.css
Normal file
68
ui/static/game.css
Normal file
@@ -0,0 +1,68 @@
|
||||
#names {
|
||||
display: flex;
|
||||
justify-content: space-evenly;
|
||||
padding: 0 10vw;
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.my-name {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.name.organiser::before {
|
||||
content: "👑";
|
||||
margin-right: .75rem;
|
||||
}
|
||||
|
||||
.name.organiser {
|
||||
color: gold;
|
||||
}
|
||||
|
||||
.name {
|
||||
animation-name: appear;
|
||||
animation-duration: .5s;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
#question {
|
||||
flex-basis: 50%;
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
padding-top: 10vh;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#question > h1 {
|
||||
font-size: 3rem;
|
||||
}
|
||||
|
||||
#question .answer {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
/*body.organiser #question > .answers {
|
||||
display: none;
|
||||
}*/
|
||||
|
||||
#controls {
|
||||
display: none;
|
||||
}
|
||||
|
||||
body.organiser #controls {
|
||||
display: flex;
|
||||
padding-right: 20vw;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
@keyframes appear {
|
||||
from {
|
||||
transform: scale(2, 2);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
to {
|
||||
transform: scale(1, 1);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
18
ui/static/home.css
Normal file
18
ui/static/home.css
Normal file
@@ -0,0 +1,18 @@
|
||||
main {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-content: center;
|
||||
justify-content: center;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
section {
|
||||
border: 2px solid black;
|
||||
margin: 2rem;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
#join, #play, #new {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
7
ui/static/home.js
Normal file
7
ui/static/home.js
Normal file
@@ -0,0 +1,7 @@
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
const joinForm = document.getElementById("join");
|
||||
joinForm.addEventListener("submit", (e) => {
|
||||
const code = joinForm.querySelector("input[name=\"code\"]").value;
|
||||
joinForm.action = "/play/" + encodeURIComponent(code);
|
||||
});
|
||||
});
|
||||
0
ui/static/script.js
Normal file
0
ui/static/script.js
Normal file
30
ui/static/style.css
Normal file
30
ui/static/style.css
Normal file
@@ -0,0 +1,30 @@
|
||||
html {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
min-height: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
display: grid;
|
||||
grid-template-rows: 10vh auto;
|
||||
grid-template-columns: auto;
|
||||
grid-template-areas:
|
||||
"header"
|
||||
"main";
|
||||
}
|
||||
|
||||
header {
|
||||
grid-area: header;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
main {
|
||||
grid-area: main;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
flex-direction: column;
|
||||
}
|
||||
Reference in New Issue
Block a user