Style countdown creation
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
d45d2fa982
commit
142ff73e01
13 changed files with 211 additions and 35 deletions
|
@ -4,9 +4,9 @@ from wtforms.fields import html5
|
||||||
from wtforms.validators import Optional
|
from wtforms.validators import Optional
|
||||||
|
|
||||||
class CountdownAdminForm(FlaskForm):
|
class CountdownAdminForm(FlaskForm):
|
||||||
hours = html5.IntegerField("Hours", [Optional()],
|
hours = fields.IntegerField("Hours", [Optional()],
|
||||||
render_kw = {"min":0, "max":999, "placeholder": "00"})
|
render_kw = {"min":0, "max":999, "placeholder": "00", "autocomplete": "off"})
|
||||||
minutes = html5.IntegerField("Minutes", [Optional()],
|
minutes = fields.IntegerField("Minutes", [Optional()],
|
||||||
render_kw = {"min":0, "max":59, "placeholder": "00"})
|
render_kw = {"min":0, "max":59, "placeholder": "00", "autocomplete": "off"})
|
||||||
seconds = html5.IntegerField("Seconds", [Optional()],
|
seconds = fields.IntegerField("Seconds", [Optional()],
|
||||||
render_kw = {"min":0, "max":59, "placeholder": "00"})
|
render_kw = {"min":0, "max":59, "placeholder": "00", "autocomplete": "off"})
|
||||||
|
|
|
@ -2,18 +2,29 @@
|
||||||
{% block title %}Countdown{% endblock title %}
|
{% block title %}Countdown{% endblock title %}
|
||||||
|
|
||||||
{% block body %}
|
{% block body %}
|
||||||
<form method="POST" action="{{ url_for('countdown.create') }}">
|
<div class="center">
|
||||||
|
<form method="POST" action="{{ url_for('countdown.create') }}">
|
||||||
{{ form.csrf_token }}
|
{{ form.csrf_token }}
|
||||||
{{ form.hours.label }}: {{ form.hours }}
|
<div id="time">
|
||||||
{{ form.minutes.label }}: {{ form.minutes }}
|
<div class="time-input">
|
||||||
{{ form.seconds.label }}: {{ form.seconds }}
|
<div class="time-value"> {{ form.hours }} </div>
|
||||||
<input type="submit" value="Go">
|
<div class="time-label"> {{ form.hours.label }} </div>
|
||||||
</form>
|
</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 %}
|
<input id="btn-create" type="submit" value="Countdown">
|
||||||
Clock: <a href="http://localhost:5000/countdown/{{ clock }}">http://localhost:5000/countdown/{{ clock }}</a>
|
</form>
|
||||||
{% endif %}
|
</div>
|
||||||
{% endblock body %}
|
{% endblock body %}
|
||||||
|
|
||||||
{% block scripts %}
|
{% block scripts %}
|
||||||
|
<script src="{{ url_for('static', filename='dist/countdown_create.bundle.js') }}"></script>
|
||||||
{% endblock scripts %}
|
{% endblock scripts %}
|
||||||
|
|
1
countdown/templates/countdown/create.js
Normal file
1
countdown/templates/countdown/create.js
Normal file
|
@ -0,0 +1 @@
|
||||||
|
import './create.scss';
|
43
countdown/templates/countdown/create.scss
Normal file
43
countdown/templates/countdown/create.scss
Normal 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;
|
||||||
|
}
|
|
@ -2,14 +2,29 @@
|
||||||
{% block title %}Countdown{% endblock title %}
|
{% block title %}Countdown{% endblock title %}
|
||||||
|
|
||||||
{% block body %}
|
{% block body %}
|
||||||
{% for clock in clocks %}
|
|
||||||
<div id="created-countdowns">
|
<div id="created-countdowns">
|
||||||
<div class="created-countdown">
|
{% for countdown in countdowns %}
|
||||||
Clock: <a href="http://localhost:5000/countdown/{{ clock }}">http://localhost:5000/countdown/{{ clock }}</a>
|
<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>
|
</div>
|
||||||
</div>
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
|
||||||
{% endblock body %}
|
{% endblock body %}
|
||||||
|
|
||||||
{% block scripts %}
|
{% block scripts %}
|
||||||
|
<script src="{{ url_for('static', filename='dist/countdown_created.bundle.js') }}"></script>
|
||||||
{% endblock scripts %}
|
{% endblock scripts %}
|
||||||
|
|
101
countdown/templates/countdown/created.js
Normal file
101
countdown/templates/countdown/created.js
Normal 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))));
|
0
countdown/templates/countdown/created.scss
Normal file
0
countdown/templates/countdown/created.scss
Normal file
|
@ -12,5 +12,5 @@
|
||||||
<script>
|
<script>
|
||||||
var countdown_id = "{{ countdown_id }}";
|
var countdown_id = "{{ countdown_id }}";
|
||||||
</script>
|
</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 %}
|
{% endblock scripts %}
|
|
@ -1,12 +1,12 @@
|
||||||
// This file is packed by webpack into /static/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.bundle.js')`
|
// Use with: `url_for('static', filename='dist/countdown_view.bundle.js')`
|
||||||
// See: webpack.common.js
|
// See: webpack.common.js
|
||||||
import log from 'loglevel';
|
import log from 'loglevel';
|
||||||
import $ from 'jquery';
|
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/";
|
let api_base = "/countdown/api/v1/";
|
||||||
|
|
||||||
|
@ -75,7 +75,10 @@ let updateCountdown = () => {
|
||||||
let text = formatTime(time.hours, time.minutes, time.seconds);
|
let text = formatTime(time.hours, time.minutes, time.seconds);
|
||||||
|
|
||||||
sleep(time.milliseconds)
|
sleep(time.milliseconds)
|
||||||
.then(() => $("#countdown").text(text));
|
.then(() => {
|
||||||
|
$("#countdown").text(text);
|
||||||
|
$("#subtext").text();
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
let unsyncTimer = undefined;
|
let unsyncTimer = undefined;
|
|
@ -17,11 +17,8 @@ def create():
|
||||||
total += (form.minutes.data or 0) * 60
|
total += (form.minutes.data or 0) * 60
|
||||||
total += (form.hours.data or 0) * 60 * 60
|
total += (form.hours.data or 0) * 60 * 60
|
||||||
|
|
||||||
countdown_id = cache.add_countdown(total)
|
countdown = cache.add_countdown(total)
|
||||||
# user = User(form.username.data, form.email.data,
|
session['created_countdowns'].append(str(countdown['id']))
|
||||||
# form.password.data)
|
|
||||||
# db_session.add(user)
|
|
||||||
session['created_countdowns'].append(str(countdown_id))
|
|
||||||
session.modified = True
|
session.modified = True
|
||||||
return redirect(url_for('countdown.created'))
|
return redirect(url_for('countdown.created'))
|
||||||
|
|
||||||
|
@ -29,9 +26,9 @@ def create():
|
||||||
|
|
||||||
@app.route('/mine', methods=['GET'])
|
@app.route('/mine', methods=['GET'])
|
||||||
def created():
|
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'])
|
@app.route('/<uuid:countdown_id>', methods=['GET'])
|
||||||
def view(countdown_id):
|
def view(countdown_id):
|
||||||
return render_template('countdown/countdown.html', countdown_id=countdown_id)
|
return render_template('countdown/view.html', countdown_id=countdown_id)
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ Content-Type: application/json
|
||||||
{"total": "150"}
|
{"total": "150"}
|
||||||
|
|
||||||
# Set id
|
# Set id
|
||||||
:id = cddabcb5-9da1-4ecb-ad36-2ca468da68e1
|
:id = 224489a4-799d-4960-9dd1-56c4b81d1c2e
|
||||||
|
|
||||||
# Start
|
# Start
|
||||||
PATCH http://localhost:5000/countdown/api/v1/start/:id
|
PATCH http://localhost:5000/countdown/api/v1/start/:id
|
||||||
|
@ -16,3 +16,6 @@ PATCH http://localhost:5000/countdown/api/v1/stop/:id
|
||||||
|
|
||||||
# Reset
|
# Reset
|
||||||
PATCH http://localhost:5000/countdown/api/v1/reset/:id
|
PATCH http://localhost:5000/countdown/api/v1/reset/:id
|
||||||
|
|
||||||
|
# GET
|
||||||
|
GET http://localhost:5000/countdown/api/v1/:id
|
|
@ -4,7 +4,9 @@ const path = require('path');
|
||||||
module.exports = {
|
module.exports = {
|
||||||
entry: {
|
entry: {
|
||||||
netclock: './js/netclock.js',
|
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: [
|
plugins: [
|
||||||
new CleanWebpackPlugin()
|
new CleanWebpackPlugin()
|
||||||
|
|
Loading…
Reference in a new issue