Style countdown creation
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Armin Friedl 2020-09-13 20:04:03 +02:00
parent d45d2fa982
commit 142ff73e01
Signed by: armin
GPG key ID: 48C726EEE7FBCBC8
13 changed files with 211 additions and 35 deletions

View file

@ -4,9 +4,9 @@ from wtforms.fields import html5
from wtforms.validators import Optional
class CountdownAdminForm(FlaskForm):
hours = html5.IntegerField("Hours", [Optional()],
render_kw = {"min":0, "max":999, "placeholder": "00"})
minutes = html5.IntegerField("Minutes", [Optional()],
render_kw = {"min":0, "max":59, "placeholder": "00"})
seconds = html5.IntegerField("Seconds", [Optional()],
render_kw = {"min":0, "max":59, "placeholder": "00"})
hours = fields.IntegerField("Hours", [Optional()],
render_kw = {"min":0, "max":999, "placeholder": "00", "autocomplete": "off"})
minutes = fields.IntegerField("Minutes", [Optional()],
render_kw = {"min":0, "max":59, "placeholder": "00", "autocomplete": "off"})
seconds = fields.IntegerField("Seconds", [Optional()],
render_kw = {"min":0, "max":59, "placeholder": "00", "autocomplete": "off"})

View file

@ -2,18 +2,29 @@
{% block title %}Countdown{% endblock title %}
{% block body %}
<div class="center">
<form method="POST" action="{{ url_for('countdown.create') }}">
{{ form.csrf_token }}
{{ form.hours.label }}: {{ form.hours }}
{{ form.minutes.label }}: {{ form.minutes }}
{{ form.seconds.label }}: {{ form.seconds }}
<input type="submit" value="Go">
</form>
<div id="time">
<div class="time-input">
<div class="time-value"> {{ form.hours }} </div>
<div class="time-label"> {{ form.hours.label }} </div>
</div>
<div class="time-input">
<div class="time-value"> {{ form.minutes }} </div>
<div class="time-label"> {{ form.minutes.label }} </div>
</div>
<div class="time-input">
<div class="time-value"> {{ form.seconds }} </div>
<div class="time-label"> {{ form.seconds.label }} </div>
</div>
</div>
{% if clock %}
Clock: <a href="http://localhost:5000/countdown/{{ clock }}">http://localhost:5000/countdown/{{ clock }}</a>
{% endif %}
<input id="btn-create" type="submit" value="Countdown">
</form>
</div>
{% endblock body %}
{% block scripts %}
<script src="{{ url_for('static', filename='dist/countdown_create.bundle.js') }}"></script>
{% endblock scripts %}

View file

@ -0,0 +1 @@
import './create.scss';

View file

@ -0,0 +1,43 @@
#btn-create {
margin-top: 2em;
margin-left: auto;
margin-right: auto;
font-size: 1.5em;
background-color: none;
border-style: solid;
border-width: 0px;
border-width: 1px;
border-right-width: 1px;
border-color: #7676ff;
display: block;
padding: 0.2em;
padding-left: 0.7em;
padding-right: 0.7em;
cursor: pointer;
color: #7676ff;
background-color: white;
}
#time {
display: flex;
}
.time-value {
margin-bottom: 0.3em;
}
.time-label {
color: gray;
text-align: center;
font-size: 1.2em;
}
#hours, #minutes, #seconds {
font-size: 3em;
font-style: bold;
border-style: none;
display: block;
width: 5em;
text-align: center;
color: blue;
}

View file

@ -2,14 +2,29 @@
{% block title %}Countdown{% endblock title %}
{% block body %}
{% for clock in clocks %}
<div id="created-countdowns">
<div class="created-countdown">
Clock: <a href="http://localhost:5000/countdown/{{ clock }}">http://localhost:5000/countdown/{{ clock }}</a>
{% for countdown in countdowns %}
<div class="created-countdown" countdown-id="{{ countdown }}">
<div class="created-countdown-header">
<h1>Countdown {{ loop.index }}</h1>
<div class="created-countdown-time"></div>
<div class="created-countdown-info"></div>
<div class="created-countdown-link">
<a href="{{ countdown }}">Link</a>
</div>
</div>
<div class="created-countdown-controls">
<button class="created-countdown-start" type="button" name="start" value="{{ countdown }}">Start</button>
<button class="created-countdown-stop" type="button" name="stop" value="{{ countdown }}">Stop</button>
<button class="created-countdown-reset" type="button" name="reset" value="{{ countdown }}">Reset</button>
</div>
</div>
{% endfor %}
</div>
{% endblock body %}
{% block scripts %}
<script src="{{ url_for('static', filename='dist/countdown_created.bundle.js') }}"></script>
{% endblock scripts %}

View file

@ -0,0 +1,101 @@
// This file is packed by webpack into /static/dist/countdown_created.bundle.js
// Use with: `url_for('static', filename='dist/countdown_created.bundle.js')`
// See: webpack.common.js
import log from 'loglevel';
import $ from 'jquery';
import {sleep} from '../../../js/netclock.js';
import './created.scss';
let api_base = "/countdown/api/v1/";
let padTime = (t) => {
let t_s = t.toString();
// Pads to at least two digits filling with 0
let leftPad = t_s.length < 2 ?
"0".repeat(2 - t.toString().length) :
"";
return `${leftPad+t_s}`;
};
let formatTime = (h, m, s) => {
let htext = padTime(h);
let mtext = padTime(m);
let stext = padTime(s);
htext = htext !== "00" ? htext + ":" : "";
mtext = mtext !== "00" || htext !== "00" ? mtext + ":" : "";
return htext + mtext + stext;
};
let splitTimestamp = (t) => {
// Timestamp as full seconds
let seconds = Math.floor(t);
return {
"hours": ~~(seconds / 3600),
"minutes": ~~((seconds % 3600) / 60),
"seconds": ~~(seconds % 60),
"milliseconds": ~~((t % 1) * 1000)
};
};
let fillCountdown = (el) => {
let x = el.attr("countdown-id");
$.getJSON({
url: api_base + el.attr('countdown-id'),
success: function(resp) {
let header = el.children(".created-countdown-header");
let split = splitTimestamp(resp.total);
header.children(".created-countdown-time")
.text(formatTime(split.hours, split.minutes, split.seconds));
let countdownInfo = header.children(".created-countdown-info");
if(resp.start === "-1") {
countdownInfo.text("Not started");
} else if(resp.left <= 0) {
countdownInfo.text("Ended");
} else {
countdownInfo.text("Running");
}
}
});
};
let startCountdown = (el) => {
$.ajax({
url: api_base + "start/" + el.val(),
method: 'PATCH'
}).done(() => {
$(".created-countdown").each((idx, el) => fillCountdown($(el)));
});
};
let stopCountdown = (el) => {
$.ajax({
url: api_base + "stop/" + el.val(),
method: 'PATCH'
}).done(() => {
$(".created-countdown").each((idx, el) => fillCountdown($(el)));
});
};
let resetCountdown = (el) => {
$.ajax({
url: api_base + "reset/" + el.val(),
method: 'PATCH'
}).done(() => {
$(".created-countdown").each((idx, el) => fillCountdown($(el)));
});
};
$(".created-countdown").each((idx, el) => fillCountdown($(el)));
$(".created-countdown-start").each((idx, el) => $(el).click(() => startCountdown($(el))));
$(".created-countdown-stop").each((idx, el) => $(el).click(() => stopCountdown($(el))));
$(".created-countdown-reset").each((idx, el) => $(el).click(() => resetCountdown($(el))));

View file

@ -12,5 +12,5 @@
<script>
var countdown_id = "{{ countdown_id }}";
</script>
<script src="{{ url_for('static', filename='dist/countdown.bundle.js') }}"></script>
<script src="{{ url_for('static', filename='dist/countdown_view.bundle.js') }}"></script>
{% endblock scripts %}

View file

@ -1,12 +1,12 @@
// This file is packed by webpack into /static/dist/countdown.bundle.js
// Use with: `url_for('static', filename='dist/countdown.bundle.js')`
// This file is packed by webpack into /static/dist/countdown_view.bundle.js
// Use with: `url_for('static', filename='dist/countdown_view.bundle.js')`
// See: webpack.common.js
import log from 'loglevel';
import $ from 'jquery';
import {sleep} from '../js/netclock.js';
import {sleep} from '../../../js/netclock.js';
import './countdown.scss';
import './view.scss';
let api_base = "/countdown/api/v1/";
@ -75,7 +75,10 @@ let updateCountdown = () => {
let text = formatTime(time.hours, time.minutes, time.seconds);
sleep(time.milliseconds)
.then(() => $("#countdown").text(text));
.then(() => {
$("#countdown").text(text);
$("#subtext").text();
});
};
let unsyncTimer = undefined;

View file

@ -17,11 +17,8 @@ def create():
total += (form.minutes.data or 0) * 60
total += (form.hours.data or 0) * 60 * 60
countdown_id = cache.add_countdown(total)
# user = User(form.username.data, form.email.data,
# form.password.data)
# db_session.add(user)
session['created_countdowns'].append(str(countdown_id))
countdown = cache.add_countdown(total)
session['created_countdowns'].append(str(countdown['id']))
session.modified = True
return redirect(url_for('countdown.created'))
@ -29,9 +26,9 @@ def create():
@app.route('/mine', methods=['GET'])
def created():
return render_template('countdown/created.html', clocks=session['created_countdowns'])
return render_template('countdown/created.html', countdowns=session.get('created_countdowns') or [])
@app.route('/<uuid:countdown_id>', methods=['GET'])
def view(countdown_id):
return render_template('countdown/countdown.html', countdown_id=countdown_id)
return render_template('countdown/view.html', countdown_id=countdown_id)

View file

@ -6,7 +6,7 @@ Content-Type: application/json
{"total": "150"}
# Set id
:id = cddabcb5-9da1-4ecb-ad36-2ca468da68e1
:id = 224489a4-799d-4960-9dd1-56c4b81d1c2e
# Start
PATCH http://localhost:5000/countdown/api/v1/start/:id
@ -16,3 +16,6 @@ PATCH http://localhost:5000/countdown/api/v1/stop/:id
# Reset
PATCH http://localhost:5000/countdown/api/v1/reset/:id
# GET
GET http://localhost:5000/countdown/api/v1/:id

View file

@ -4,7 +4,9 @@ const path = require('path');
module.exports = {
entry: {
netclock: './js/netclock.js',
countdown: './countdown/countdown.js'
countdown_create: './countdown/templates/countdown/create.js',
countdown_view: './countdown/templates/countdown/view.js',
countdown_created: './countdown/templates/countdown/created.js'
},
plugins: [
new CleanWebpackPlugin()