Private
Public Access
1
0
This commit is contained in:
2025-01-22 20:17:47 +01:00
parent 4cf92155a6
commit 95bc02e122
3 changed files with 176 additions and 164 deletions

View File

@@ -2755,6 +2755,12 @@ class PlannedSessionStep(models.Model):
return d return d
# string
def __str__(self):
str = 'Step {id} {name} {intensity}'.format(id=self.pk, name=self.name, intensity=self.intensity)
return str
class StepEditorForm(ModelForm): class StepEditorForm(ModelForm):
class Meta: class Meta:
model = PlannedSessionStep model = PlannedSessionStep

View File

@@ -20,9 +20,9 @@
<section class="drop-zone"> <section class="drop-zone">
<h2>Training Steps for {{ ps.name }}</h2> <h2>Training Steps for {{ ps.name }}</h2>
<p> <p>
<form onsubmit="event.preventDefault(); saveSession();"> <form target="/rowers/plans/stepadder/{{ ps.id}}/?save=1" onsubmit="event.preventDefault(); saveSession();">
<input id="hidden" type="hidden" value=""> <input id="hidden" type="hidden" value="">
<input id="savebutton" type="submit" value="Save"> <input id="savebutton" type="submit" value="Save">
</form> </form>
</p> </p>
{% for step in currentsteps %} {% for step in currentsteps %}
@@ -175,216 +175,219 @@
descriptions["{{ key }}"] = "{{ value }}" descriptions["{{ key }}"] = "{{ value }}"
{% endfor %} {% endfor %}
$(document).ready(function() { $(document).ready(function() {
csrftoken = jQuery("[name=csrfmiddlewaretoken]").val(); csrftoken = jQuery("[name=csrfmiddlewaretoken]").val();
}); });
function csrfSafeMethod(method) { function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection // these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
} }
$.ajaxSetup({ $.ajaxSetup({
beforeSend: function(xhr, settings) { beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) { if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken); xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
} }
}
}); });
let dragged; let dragged;
let origcolor; let origcolor;
function saveSession() { function saveSession() {
var list = []; var list = [];
steps = document.querySelector('.drop-zone'); steps = document.querySelector('.drop-zone');
steps.childNodes.forEach(function(item) { steps.childNodes.forEach(function(item) {
if (item.className && item.className.includes("trainingstep")) { if (item.className && item.className.includes("trainingstep")) {
item.childNodes.forEach(function(child) { item.childNodes.forEach(function(child) {
if (child.id && child.className == 'stepcontent') { if (child.id && child.className == 'stepcontent') {
list.push(child.id); list.push(child.id);
} }
}) })
} }
}); });
$.ajax({ $.ajax({
data: JSON.stringify(list), data: JSON.stringify(list),
type: 'POST', type: 'POST',
url: '/rowers/plans/stepadder/{{ ps.id }}/?save=1', url: '/rowers/plans/stepadder/{{ ps.id }}/?save=1',
error: function(result) { error: function(result) {
$("#id_waiting").replaceWith( $("#id_waiting").replaceWith(
'<div id="id_failed" class="grid_12 alpha message">Your upload failed</div>' '<div id="id_failed" class="grid_12 alpha message">Your upload failed</div>'
); );
}, },
success: function(result) { success: function(result) {
console.log(result) console.log(result)
} }
}) })
window.location.reload(true); saveState();
} // reload the page
location.reload();
// window.location.reload(true);
}
function saveState() { function saveState() {
var cntr = 0; var cntr = 0;
var list = []; var list = [];
steps = document.querySelector('.drop-zone'); steps = document.querySelector('.drop-zone');
steps.childNodes.forEach(function(item) { steps.childNodes.forEach(function(item) {
if (item.className && item.className.includes("trainingstep")) { if (item.className && item.className.includes("trainingstep")) {
item.childNodes.forEach(function(child) { item.childNodes.forEach(function(child) {
if (child.id && child.className == 'stepcontent') { if (child.id && child.className == 'stepcontent') {
list.push(child.id); list.push(child.id);
} }
if (child.className == "stepid") { if (child.className == "stepid") {
s = `(${cntr})` s = `(${cntr})`
child.replaceWith(s); child.replaceWith(s);
cntr++; cntr++;
} }
}) })
} }
}); });
$.ajax({ $.ajax({
data: JSON.stringify(list), data: JSON.stringify(list),
type: 'POST', type: 'POST',
url: '/rowers/plans/stepadder/{{ ps.id }}/', url: '/rowers/plans/stepadder/{{ ps.id }}/',
error: function(result) { error: function(result) {
$("#id_waiting").replaceWith( $("#id_waiting").replaceWith(
'<div id="id_failed" class="grid_12 alpha message">Your upload failed</div>' '<div id="id_failed" class="grid_12 alpha message">Your upload failed</div>'
); );
}, },
success: function(result) { success: function(result) {
console.log(result) console.log(result)
} }
}) })
}; };
function handleDragStart(event) { function handleDragStart(event) {
let target = event.target; let target = event.target;
if (target) { if (target) {
dragged = target; dragged = target;
origcolor = dragged.style.backgroundColor; origcolor = dragged.style.backgroundColor;
event.dataTransfer.setData('text', target.id); event.dataTransfer.setData('text', target.id);
event.dataTransfer.dropEffect = 'move'; event.dataTransfer.dropEffect = 'move';
// Make it half transparent // Make it half transparent
event.target.style.opacity = .3; event.target.style.opacity = .3;
} }
} }
function handleDragEnd(event) { function handleDragEnd(event) {
if (event.target) { if (event.target) {
// Reset the transparency // Reset the transparency
event.target.style.opacity = ''; // reset opacity when drag ends event.target.style.opacity = ''; // reset opacity when drag ends
items.forEach(function (item) { items.forEach(function (item) {
item.classList.remove('over'); item.classList.remove('over');
}); });
dragged = null; dragged = null;
origcolor = null; origcolor = null;
} }
saveState(); saveState();
} }
function handleMouseOver(event) { function handleMouseOver(event) {
if (event.preventDefault) {
const id = event.target.id;
if (id) {
var name = mysteps[id]['name'];
var txt = descriptions[id];
var divstring = `<p>${name}</p><p>${txt}</p>`
const div = document.getElementById("stepinfo");
div.innerHTML = divstring;
}
}
return false;
}
function handleMouseLeave(event) {
if (event.preventDefault) { if (event.preventDefault) {
const id = event.target.id;
if (id) {
var name = mysteps[id]['name'];
var txt = descriptions[id];
var divstring = `<p>${name}</p><p>${txt}</p>`
const div = document.getElementById("stepinfo"); const div = document.getElementById("stepinfo");
div.innerHTML = divstring; div.innerHTML = '<p>Hover over a step to get details</p>'
}
} }
return false; return false;
} }
function handleMouseLeave(event) { function handleDragOver(event) {
if (event.preventDefault) {
const div = document.getElementById("stepinfo");
div.innerHTML = '<p>Hover over a step to get details</p>'
}
return false;
}
function handleDragOver(event) {
event.preventDefault(); event.preventDefault();
} }
function handleDragEnter(event) { function handleDragEnter(event) {
this.classList.add('over'); this.classList.add('over');
const target = event.target; const target = event.target;
overcolor = event.target.style.backgroundColor; overcolor = event.target.style.backgroundColor;
if (target && dragged) { if (target && dragged) {
event.preventDefault(); event.preventDefault();
// Set the dropEffect to move // Set the dropEffect to move
event.dataTransfer.dropEffect = 'move' event.dataTransfer.dropEffect = 'move'
target.style.background = '#1f904e'; target.style.background = '#1f904e';
} }
} }
function handleDragLeave(event) { function handleDragLeave(event) {
event.target.style.backgroundColor = ''; event.target.style.backgroundColor = '';
if (dragged.parentNode.className.includes("drop-zone")) { if (dragged.parentNode.className.includes("drop-zone")) {
trash(event); trash(event);
} }
saveState(); saveState();
} }
function trash(event) { function trash(event) {
const target = event.target; const target = event.target;
event.target.style.backgroundColor = ''; event.target.style.backgroundColor = '';
if (target && dragged) { if (target && dragged) {
event.preventDefault(); event.preventDefault();
if (dragged.parentNode.className.includes("drop-zone")) { if (dragged.parentNode.className.includes("drop-zone")) {
dragged.remove(); dragged.remove();
} }
} }
} }
function handleDrop(event) { function handleDrop(event) {
const target = event.target; const target = event.target;
if (target && dragged) { if (target && dragged) {
target.style.backgroundColor = ''; target.style.backgroundColor = '';
event.preventDefault(); event.preventDefault();
// Get the id of the target and add the moved element to the target's DOM // Get the id of the target and add the moved element to the targets DOM
// dragged.parentNode.removeChild(dragged); // dragged.parentNode.removeChild(dragged);
if (target.nodeName == "SECTION") { if (target.nodeName == "SECTION") {
dragged.style.opacity = ''; dragged.style.opacity = '';
dragged.style.backgroundColor = origcolor; dragged.style.backgroundColor = origcolor;
var dropped = dragged.cloneNode(true); var dropped = dragged.cloneNode(true);
dropped.id = 0; dropped.id = 0;
target.appendChild(dropped); target.appendChild(dropped);
}
if (target.nodeName == 'DIV') {
// insert after
dragged.style.opacity = '';
dragged.style.backgroundColor = origcolor;
var dropped = dragged.cloneNode(true);
if (target.parentNode.nodeName == 'SECTION') {
target.after(dropped);
} }
if (target.parentNode.parentNode.nodeName == 'SECTION') { if (target.nodeName == 'DIV') {
target.parentNode.after(dropped); // insert after
dragged.style.opacity = '';
dragged.style.backgroundColor = origcolor;
var dropped = dragged.cloneNode(true);
if (target.parentNode.nodeName == 'SECTION') {
target.after(dropped);
}
if (target.parentNode.parentNode.nodeName == 'SECTION') {
target.parentNode.after(dropped);
}
} }
}
} }
saveState(); saveState();
} }
function noDrop(event) { function noDrop(event) {
event.preventDefault(); event.preventDefault();
} }
let dropzone = document.querySelector('.drop-zone') let dropzone = document.querySelector('.drop-zone')
dropzone.addEventListener('dragenter', handleDragEnter); dropzone.addEventListener('dragenter', handleDragEnter);
dropzone.addEventListener('dragleave', handleDragLeave); dropzone.addEventListener('dragleave', handleDragLeave);
dropzone.addEventListener('drop', handleDrop) dropzone.addEventListener('drop', handleDrop)
dropzone.addEventListener('dragover', handleDragOver); dropzone.addEventListener('dragover', handleDragOver);
dropzone.addEventListener('dragstart', handleDragStart); dropzone.addEventListener('dragstart', handleDragStart);
dropzone.addEventListener('dragend', handleDragEnd); dropzone.addEventListener('dragend', handleDragEnd);
let items = document.querySelectorAll('.stepcontainer .trainingstep'); let items = document.querySelectorAll('.stepcontainer .trainingstep');
items.forEach(function(item) { items.forEach(function(item) {
item.addEventListener('dragstart', handleDragStart); item.addEventListener('dragstart', handleDragStart);
item.addEventListener('dragend', handleDragEnd); item.addEventListener('dragend', handleDragEnd);
item.addEventListener('dragleave', handleDragLeave); item.addEventListener('dragleave', handleDragLeave);
@@ -392,10 +395,10 @@
item.addEventListener('dragenter',noDrop); item.addEventListener('dragenter',noDrop);
item.addEventListener('mouseover',handleMouseOver); item.addEventListener('mouseover',handleMouseOver);
item.addEventListener('mouseleave',handleMouseLeave); item.addEventListener('mouseleave',handleMouseLeave);
}); });
</script> </script>
{% endblock %} {% endblock %}
{% block sidebar %} {% block sidebar %}

View File

@@ -3077,6 +3077,7 @@ def rower_create_trainingplan(request, id=0):
'old_targets': old_targets, 'old_targets': old_targets,
}) })
@csrf_exempt
@user_passes_test(can_plan, login_url="/rowers/paidplans", @user_passes_test(can_plan, login_url="/rowers/paidplans",
message="This functionality requires a Coach or Self-Coach plan", message="This functionality requires a Coach or Self-Coach plan",
redirect_field_name=None) redirect_field_name=None)
@@ -3116,6 +3117,7 @@ def stepadder(request, id=0):
'message': 'permission denied for host '+hostt[0]} 'message': 'permission denied for host '+hostt[0]}
return JSONResponse(status=403, data=message) return JSONResponse(status=403, data=message)
if ps.steps: if ps.steps:
filename = ps.steps.get('filename','') filename = ps.steps.get('filename','')
sport = ps.steps.get('sport','rowing') sport = ps.steps.get('sport','rowing')
@@ -3208,6 +3210,7 @@ def stepedit(request, id=0, psid=0):
ps.fitfile = None ps.fitfile = None
ps.interval_string = "" ps.interval_string = ""
ps.save() ps.save()
step.durationtype = form.cleaned_data['durationtype'] step.durationtype = form.cleaned_data['durationtype']