Changes via Javascript work.

feature/js
Daniel Perelman 4 years ago
parent 11f661fd8a
commit 28ab47e5e4

@ -150,6 +150,9 @@
clone.querySelector("." + suffix).name = prefix + suffix;
clone.querySelector("." + suffix + "-orig").name = prefix + suffix + "-orig";
});
for(let el of clone.querySelectorAll('select')) {
el.addEventListener("change", formElementChanged);
}
effDiv.appendChild(clone);
}
function addEmptyEffects(clearAll) {
@ -188,7 +191,6 @@
if(oldStatus.hash == newStatus.hash) return true;
if(oldStatus.phase_id != newStatus.phase_id
|| oldStatus.turn != newStatus.turn) {
// Reload for new phase.
addEmptyEffects(true);
}
@ -214,6 +216,10 @@
}
document.getElementById(prefix + "ready-orig").value = ready;
document.getElementById(prefix + "ready").checked = ready;
for(let el of document.querySelectorAll(".player-" + ord + " select")) {
el.disabled = ready;
}
} else if(pkey == "total_fear") {
let total_fear = player[pkey];
for(let el of document.getElementsByClassName(prefix + "total-fear")) {
@ -260,25 +266,124 @@
return true;
{% endblock %}
}
setInterval(function() {
fetch(new Request("{% url 'status' access_code=access_code %}"
+ statusObj.hash + "/"))
.then(response => {
if(response.status === 304) {
// TODO Just skip the next step?
return statusObj;
var activeRequests = new Set();
function formElementChanged(e) {
let form = document.forms[0];
let el = e.target;
let name = el.name;
let origName = name + "-orig";
let origEl = form.elements[origName];
let newValue = el.type == "checkbox" ? el.checked : el.value;
let oldValue = origEl.value;
el.disabled = true;
if(el.name.endsWith("ready") && newValue) {
let ord = name.split("-")[1];
// If marking a player ready, disable all selects immediately.
for(let el of document.querySelectorAll(".player-" + ord + " select")) {
el.disabled = true;
}
}
activeRequests.add(el);
statusObj.hash = '';
// From https://stackoverflow.com/a/5588435
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie != '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = cookies[i];
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
fetch("{% url 'update_game' access_code=access_code %}",
{
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
"X-CSRFToken": getCookie("csrftoken"),
},
body: name + "=" + newValue + "&" + origName + "=" + oldValue
+ "&game_turn=" + statusObj["turn"]
+ "&game_phase=" + statusObj["phase_id"]
+ "&phase_name=" + statusObj["phase"]
+ "&csrfmiddlewaretoken=" + form.elements["csrfmiddlewaretoken"].value,
}).then(response => response.json()
).then(data => {
if("success" in data && data["success"]) {
form.elements[origName].value = newValue;
} else {
var updatedValue = oldValue;
if("value" in data) {
let updatedValue = data['value'];
origEl.value = updatedValue;
}
if(el.type == "checkbox") {
el.checked = updatedValue == "true";
} else {
return response.json();
el.value = updatedValue;
}
})
.then(data => {
if(!handleNewStatus(statusObj, data)) {
document.getElementById("button-refresh").click();
if("errors" in data) {
alert(data["errors"]);
} else {
statusObj = data;
alert("Unknown error: " + data);
}
});
}, 5000);
}
el.disabled = false;
activeRequests.delete(el);
});
}
window.addEventListener("DOMContentLoaded", e => {
for(let updateButton of document.getElementsByClassName("update-button")) {
updateButton.disabled = true;
updateButton.style.display = "none";
}
let form = document.forms[0];
for(let el of form.elements) {
if(el.type == 'checkbox' && !el.name.endsWith("visible")) {
el.addEventListener("change", formElementChanged);
}
}
for(let el of document.querySelectorAll('select')) {
el.addEventListener("change", formElementChanged);
}
setInterval(function() {
if(activeRequests.size != 0) return;
fetch(new Request("{% url 'status' access_code=access_code %}"
+ (statusObj.hash != ""
? statusObj.hash + "/"
: "")))
.then(response => {
if(response.status === 304) {
// TODO Just skip the next step?
return statusObj;
} else {
return response.json();
}
})
.then(data => {
if(activeRequests.size != 0) return;
if(!handleNewStatus(statusObj, data)) {
document.getElementById("button-refresh").click();
} else {
statusObj = data;
}
});
}, 5000);
});
</script>
{% endif %}
{% endblock %}

@ -24,6 +24,7 @@ urlpatterns = [
path('new/', views.new_game, name='new_game'),
url(r'^(?P<access_code>[a-zA-Z]{6})/', include([
path('', views.game, name='game'),
path('update/', views.update_game, name='update_game'),
path('qr/', views.qr_code, name='qr_code'),
path('status/', views.status, name='status'),
url('^status/(?P<hashcode>[a-z0-9]{64})/',

@ -8,7 +8,8 @@ import qrcode
from django.db import transaction
from django.http import HttpResponse
from django.shortcuts import get_object_or_404, redirect, render
from django.views.decorators.http import require_safe, require_http_methods
from django.views.decorators.http import require_safe, require_http_methods,\
require_POST
from django.urls import reverse
from .forms import NewGameForm, JoinGameForm, PlayerFormSet
@ -153,10 +154,21 @@ def game_status_object(game, current_phase=None, players_with_fear=None):
return status_obj
@transaction.atomic
@lookup_access_code
@require_POST
def update_game(request, game):
return handle_game_request(request, game, update=True)
@transaction.atomic
@lookup_access_code
@require_http_methods(["HEAD", "GET", "POST"])
def game(request, game):
return handle_game_request(request, game, update=False)
def handle_game_request(request, game, update):
# TODO Should check if game is over and redirect to summary table view.
players = load_players(game)
@ -169,14 +181,17 @@ def game(request, game):
'towns': 'towns_destroyed',
'cities': 'cities_destroyed',
}
current_value = None
current_phase = game.get_current_phase()
if request.method == 'POST':
post_data = request.POST
correct_phase =\
current_phase.game_turn == int(request.POST['game_turn'])\
and current_phase.game_phase == int(request.POST['game_phase'])
advance_phase = 'advance' in request.POST
revert_phase = 'revert' in request.POST
for key, value in request.POST.items():
current_phase.game_turn == int(post_data['game_turn'])\
and current_phase.game_phase == int(post_data['game_phase'])
advance_phase = 'advance' in post_data
revert_phase = 'revert' in post_data
for key, value in post_data.items():
sections = key.split('-')
if key in ['csrfmiddlewaretoken',
'update', 'advance', 'revert',
@ -184,7 +199,7 @@ def game(request, game):
or sections[-1] == 'orig':
pass
elif sections[0] == 'player':
orig_value = request.POST.get(key + '-orig', None)
orig_value = post_data.get(key + '-orig', None)
player_ord = int(sections[1])
player = players[player_ord]
if sections[2] == 'visible':
@ -214,7 +229,7 @@ def game(request, game):
f"from {orig} to {amount} " +
"was not processed.")
elif not correct_phase or advance_phase:
old_phase = request.POST['phase_name']
old_phase = post_data['phase_name']
errors.append(
f"{player.name} " +
f"({player.get_spirit_name()})'s " +
@ -261,6 +276,18 @@ def game(request, game):
for player in players.values():
player.ready = True
if update:
if errors:
res = {
'success': False,
'errors': '\n'.join(errors)
}
if current_value is not None:
res['value'] = current_value
else:
res = {'success': True}
return HttpResponse(json.dumps(res))
players = get_players_with_fear(game, current_phase, players)
status_obj = game_status_object(game, current_phase, players)
status_string = json.dumps(status_obj)

Loading…
Cancel
Save