everything working,
This commit is contained in:
@@ -2414,7 +2414,7 @@ class PlannedSessionStep(models.Model):
|
||||
manager = models.ForeignKey(User, null=True, on_delete=models.CASCADE)
|
||||
name = models.TextField(default='',max_length=200, blank=True, null=True)
|
||||
type = models.TextField(default='',max_length=200, blank=True, null=True)
|
||||
durationvalue = models.IntegerField(default=0)
|
||||
durationvalue = models.FloatField(default=0)
|
||||
durationtype = models.TextField(default='',max_length=200, blank=True, null=True,
|
||||
choices=durationtypes)
|
||||
targetvalue = models.IntegerField(default=0)
|
||||
@@ -2435,6 +2435,8 @@ class PlannedSessionStep(models.Model):
|
||||
elif self.intensity == "Rest":
|
||||
self.color = 'add8e6'
|
||||
|
||||
self.durationvalue = int(self.durationvalue)
|
||||
|
||||
super(PlannedSessionStep, self).save(*args, **kwargs)
|
||||
|
||||
def asdict(self):
|
||||
@@ -2442,7 +2444,10 @@ class PlannedSessionStep(models.Model):
|
||||
'wkt_step_name': self.name,
|
||||
'durationType': self.durationtype,
|
||||
'durationValue': self.durationvalue,
|
||||
'targetType': self.targettype,
|
||||
'targetValue': self.targetvalue,
|
||||
'targetValueLow': self.targetvaluelow,
|
||||
'targetValueHigh': self.targetvaluehigh,
|
||||
'description': self.description,
|
||||
'stepId': self.pk,
|
||||
'intensity': self.intensity,
|
||||
@@ -2458,13 +2463,33 @@ class StepEditorForm(ModelForm):
|
||||
#'type',
|
||||
'durationtype',
|
||||
'durationvalue',
|
||||
'targettype',
|
||||
'targetvalue',
|
||||
'targetvaluelow',
|
||||
'targetvaluehigh',
|
||||
'intensity',
|
||||
'description',
|
||||
]
|
||||
|
||||
widgets = {
|
||||
'name': forms.Textarea(attrs={'rows':1, 'cols':50}),
|
||||
}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(StepEditorForm, self).__init__(*args, **kwargs)
|
||||
if self.instance.durationtype == 'Time':
|
||||
self.initial['durationvalue'] = self.instance.durationvalue / 60000
|
||||
elif self.instance.durationtype == 'Distance':
|
||||
form.initial['durationvalue'] = self.instance.durationvalue / 100
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
# conversions
|
||||
if self.instance.durationtype == 'Time':
|
||||
self.instance.durationvalue *= 60000
|
||||
elif self.instance.durationtype == 'Distance':
|
||||
self.instance.durationvalue *= 100
|
||||
return super(StepEditorForm, self).save(*args, **kwargs)
|
||||
|
||||
|
||||
class PlannedSession(models.Model):
|
||||
|
||||
|
||||
@@ -35,6 +35,15 @@
|
||||
</form>
|
||||
|
||||
</li>
|
||||
<li class="grid_2">
|
||||
{% if steps %}
|
||||
<h2>Steps</h2>
|
||||
<p>{{ steps|safe }}</p>
|
||||
<p>
|
||||
<a href="/rowers/plans/stepeditor/{{ thesession.id }}/">Edit Steps (experimental)</a>
|
||||
</p>
|
||||
{% endif %}
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
38
rowers/templates/stepedit.html
Normal file
38
rowers/templates/stepedit.html
Normal file
@@ -0,0 +1,38 @@
|
||||
{% extends "newbase.html" %}
|
||||
{% load static %}
|
||||
{% load rowerfilters %}
|
||||
|
||||
{% block title %}Rowsandall Training Plans{% endblock %}
|
||||
|
||||
|
||||
{% block main %}
|
||||
<h2>Edit {{ step.name }}</h2>
|
||||
<ul class="main-content">
|
||||
<li class="grid_2">
|
||||
<p>
|
||||
WARNING: This is experimental functionality which may not behave as you
|
||||
expect. Does not work on smartphones.
|
||||
</p>
|
||||
</li>
|
||||
<li class="grid_2">
|
||||
<h2>Step Description</h2>
|
||||
{{ stepdescription }}
|
||||
</li>
|
||||
<li class="grid_2">
|
||||
<h2>Add new step</h2>
|
||||
<form enctype="multipart/multipart/form-data" method="post">
|
||||
<table>
|
||||
{{ form.as_table }}
|
||||
</table>
|
||||
{% csrf_token %}
|
||||
<input name="stepsave" type="submit" value="Update">
|
||||
<input name="stepsave_and_return" type="submit" value="Update and Return to Steps">
|
||||
</form>
|
||||
</li>
|
||||
</ul>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block sidebar %}
|
||||
{% include 'menu_plan.html' %}
|
||||
{% endblock %}
|
||||
@@ -19,14 +19,47 @@
|
||||
<div class="stepcontainer" id="list">
|
||||
<section class="drop-zone">
|
||||
<h2>Training Steps for {{ ps.name }}</h2>
|
||||
<p>
|
||||
<form onsubmit="event.preventDefault(); saveSession();">
|
||||
<input id="hidden" type="hidden" value="">
|
||||
<input id="savebutton" type="submit" value="Save">
|
||||
</form>
|
||||
</p>
|
||||
{% for step in currentsteps %}
|
||||
<div id="{{ step.id }}" draggable="true" class="trainingstep {{ step.intensity }}" >
|
||||
<span id="{{ step.id }}" class="stepcontent">
|
||||
{{ step.name }}
|
||||
</span>
|
||||
<span id="{{ step.id }}">
|
||||
<a href="/rowers/plans/step/{{ step.id }}/edit/{{ ps.id }}/">
|
||||
<i class="fas fa-pencil-alt fa-fw"></i>
|
||||
</a>
|
||||
</span>
|
||||
<span id="{{ step.id }}">
|
||||
<a href="/rowers/plans/step/{{ step.id }}/delete/?id={{ ps.id }}">
|
||||
<i class="fas fa-trash-alt fa-fw"></i>
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</section>
|
||||
<section class="library">
|
||||
<h2>Library</h2>
|
||||
{% for step in steps %}
|
||||
<div draggable="true" class="trainingstep {{ step.intensity }}" >
|
||||
<div id="{{ forloop.counter }}" class="stepcontent">
|
||||
<div id="{{ step.id }}" draggable="true" class="trainingstep {{ step.intensity }}" >
|
||||
<span id="{{ step.id }}" class="stepcontent">
|
||||
{{ step.name }}
|
||||
</div>
|
||||
</span>
|
||||
<span id="{{ step.id }}">
|
||||
<a href="/rowers/plans/step/{{ step.id }}/edit/{{ ps.id }}/">
|
||||
<i class="fas fa-pencil-alt fa-fw"></i>
|
||||
</a>
|
||||
</span>
|
||||
<span id="{{ step.id }}">
|
||||
<a href="/rowers/plans/step/{{ step.id }}/delete/?id={{ ps.id }}">
|
||||
<i class="fas fa-trash-alt fa-fw"></i>
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
@@ -57,18 +90,16 @@
|
||||
</script>
|
||||
<script>
|
||||
let csrftoken;
|
||||
let steps = {};
|
||||
let mysteps = {};
|
||||
{% for step in steps %}
|
||||
steps["{{ step.id }}"] = { 'name': '{{ step.name }}' };
|
||||
mysteps["{{ step.id }}"] = { 'name': '{{ step.name }}' };
|
||||
{% endfor %}
|
||||
let descriptions = {}
|
||||
{% for key, value in stepdescriptions.items %}
|
||||
descriptions["{{ key }}"] = "{{ value }}"
|
||||
{% endfor %}
|
||||
console.log(descriptions);
|
||||
$(document).ready(function() {
|
||||
csrftoken = jQuery("[name=csrfmiddlewaretoken]").val();
|
||||
console.log("CSRF token",csrftoken);
|
||||
});
|
||||
function csrfSafeMethod(method) {
|
||||
// these HTTP methods do not require CSRF protection
|
||||
@@ -85,20 +116,46 @@
|
||||
let dragged;
|
||||
let origcolor;
|
||||
|
||||
function saveSession() {
|
||||
|
||||
var list = [];
|
||||
steps = document.querySelector('.drop-zone');
|
||||
steps.childNodes.forEach(function(item) {
|
||||
if (item.className && item.className.includes("trainingstep")) {
|
||||
item.childNodes.forEach(function(child) {
|
||||
if (child.id && child.className == 'stepcontent') {
|
||||
list.push(child.id);
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
$.ajax({
|
||||
data: JSON.stringify(list),
|
||||
type: 'POST',
|
||||
url: '/rowers/plans/stepadder/{{ ps.id }}/?save=1',
|
||||
error: function(result) {
|
||||
$("#id_waiting").replaceWith(
|
||||
'<div id="id_failed" class="grid_12 alpha message">Your upload failed</div>'
|
||||
);
|
||||
},
|
||||
success: function(result) {
|
||||
console.log(result)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function saveState() {
|
||||
var list = [];
|
||||
steps = document.querySelector('.drop-zone');
|
||||
steps.childNodes.forEach(function(item) {
|
||||
if (item.className && item.className.includes("trainingstep")) {
|
||||
item.childNodes.forEach(function(child) {
|
||||
console.log(child.id);
|
||||
if (child.id) {
|
||||
if (child.id && child.className == 'stepcontent') {
|
||||
list.push(child.id);
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
console.log(list);
|
||||
$.ajax({
|
||||
data: JSON.stringify(list),
|
||||
type: 'POST',
|
||||
@@ -109,8 +166,7 @@
|
||||
);
|
||||
},
|
||||
success: function(result) {
|
||||
console.log('got something back');
|
||||
console.log(result);
|
||||
console.log(result)
|
||||
}
|
||||
})
|
||||
};
|
||||
@@ -142,12 +198,13 @@
|
||||
function handleMouseOver(event) {
|
||||
if (event.preventDefault) {
|
||||
const id = event.target.id;
|
||||
console.log(id);
|
||||
var name = steps[id]['name'];
|
||||
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
|
||||
div.innerHTML = divstring;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -183,7 +240,6 @@
|
||||
event.target.style.backgroundColor = '';
|
||||
|
||||
if (dragged.parentNode.className.includes("drop-zone")) {
|
||||
console.log("trashing");
|
||||
trash(event);
|
||||
}
|
||||
}
|
||||
@@ -211,6 +267,7 @@
|
||||
dragged.style.opacity = '';
|
||||
dragged.style.backgroundColor = origcolor;
|
||||
var dropped = dragged.cloneNode(true);
|
||||
dropped.id = 0;
|
||||
target.appendChild(dropped);
|
||||
}
|
||||
if (target.nodeName == 'DIV') {
|
||||
@@ -253,6 +310,7 @@
|
||||
item.addEventListener('mouseleave',handleMouseLeave);
|
||||
});
|
||||
|
||||
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
@@ -875,6 +875,12 @@ urlpatterns = [
|
||||
views.rower_create_trainingplan, name='rower_create_trainingplan'),
|
||||
re_path(r'^plans/$', views.rower_select_instantplan,
|
||||
name='rower_select_instantplan'),
|
||||
re_path(r'^plans/step/(?P<id>\d+)/edit/$',
|
||||
views.stepedit, name='stepedit'),
|
||||
re_path(r'^plans/step/(?P<id>\d+)/edit/(?P<psid>\d+)/$',
|
||||
views.stepedit, name='stepedit'),
|
||||
re_path(r'^plans/step/(?P<id>\d+)/delete/$',
|
||||
views.stepdelete, name='stepdelete'),
|
||||
re_path(r'^plans/stepeditor/$',
|
||||
views.stepeditor, name='stepeditor'),
|
||||
re_path(r'^plans/stepeditor/(?P<id>\d+)/$',
|
||||
|
||||
@@ -2005,6 +2005,12 @@ def plannedsession_templateedit_view(request, id=0):
|
||||
|
||||
sessiontemplates = sessiontemplates | sessiontemplates2
|
||||
|
||||
steps = ''
|
||||
if ps.steps: # pragma: no cover
|
||||
d = ps.steps
|
||||
|
||||
steps = ps_dict_get_description_html(d, short=False)
|
||||
|
||||
return render(request, 'plannedsessiontemplateedit.html',
|
||||
{
|
||||
'teams': get_my_teams(request.user),
|
||||
@@ -2015,6 +2021,7 @@ def plannedsession_templateedit_view(request, id=0):
|
||||
'thesession': ps,
|
||||
'sessiontemplates': sessiontemplates,
|
||||
'rower': r,
|
||||
'steps': steps,
|
||||
})
|
||||
|
||||
|
||||
@@ -2975,6 +2982,8 @@ def stepadder(request, id=0):
|
||||
)
|
||||
ps = get_object_or_404(PlannedSession, pk=id)
|
||||
|
||||
is_save = request.GET.get('save',0)
|
||||
|
||||
if request.method != 'POST':
|
||||
message = {'status': 'false',
|
||||
'message': 'this view cannot be accessed through GET'}
|
||||
@@ -2996,27 +3005,159 @@ def stepadder(request, id=0):
|
||||
return JSONResponse(status=403, data=message)
|
||||
|
||||
steps = {
|
||||
"filename": "",
|
||||
"filename": ps.steps['filename'],
|
||||
"sport": ps.steps['sport'],
|
||||
"steps": []
|
||||
}
|
||||
for id in post_data:
|
||||
|
||||
for nr,id in enumerate(post_data):
|
||||
try:
|
||||
step = PlannedSessionStep.objects.get(id=int(id))
|
||||
print(step.name)
|
||||
# add JSON
|
||||
d = step.asdict()
|
||||
d['stepId'] = nr
|
||||
steps['steps'].append(d)
|
||||
except PlannedSessionStep.DoesNotExist:
|
||||
print('fail')
|
||||
pass
|
||||
|
||||
if is_save:
|
||||
# save the darn thing
|
||||
ps.steps = steps
|
||||
|
||||
ps.interval_string = ''
|
||||
ps.fitfile = None
|
||||
ps.save()
|
||||
|
||||
return JSONResponse(status=200,data=post_data)
|
||||
|
||||
@user_passes_test(can_plan, login_url="/rowers/paidplans",
|
||||
message="This functionality requires a Coach or Self-Coach plan",
|
||||
redirect_field_name=None)
|
||||
def stepdelete(request, id=0):
|
||||
step = get_object_or_404(PlannedSessionStep, pk=id)
|
||||
|
||||
step.delete()
|
||||
|
||||
backid = request.GET.get('id')
|
||||
|
||||
url = reverse(stepeditor,kwargs={'id':backid})
|
||||
|
||||
return HttpResponseRedirect(url)
|
||||
|
||||
@user_passes_test(can_plan, login_url="/rowers/paidplans",
|
||||
message="This functionality requires a Coach or Self-Coach plan",
|
||||
redirect_field_name=None)
|
||||
def stepedit(request, id=0, psid=0):
|
||||
step = get_object_or_404(PlannedSessionStep, pk=id)
|
||||
try:
|
||||
ps = PlannedSession.objects.get(id=psid)
|
||||
except PlannedSession.DoesNotExist:
|
||||
ps = None
|
||||
|
||||
form = StepEditorForm(instance=step)
|
||||
|
||||
if request.method == 'POST':
|
||||
form = StepEditorForm(request.POST)
|
||||
if form.is_valid():
|
||||
if ps:
|
||||
dd = step.asdict()
|
||||
dd.pop('stepId')
|
||||
for id,ss in enumerate(ps.steps['steps']):
|
||||
ee = ss.copy()
|
||||
ee.pop('stepId')
|
||||
|
||||
if (dd == ee):
|
||||
ss['durationType'] = form.cleaned_data['durationtype']
|
||||
ss['durationValue'] = form.cleaned_data['durationvalue']
|
||||
ss['targetType'] = form.cleaned_data['targettype']
|
||||
ss['targetValue'] = form.cleaned_data['targetvalue']
|
||||
ss['targetValueLow']= form.cleaned_data['targetvaluelow']
|
||||
ss['targetValueHigh'] = form.cleaned_data['targetvaluehigh']
|
||||
ss['intensity'] = form.cleaned_data['intensity']
|
||||
ss['wkt_step_name'] = form.cleaned_data['name']
|
||||
ss['description'] = form.cleaned_data['description']
|
||||
|
||||
if form.cleaned_data['durationtype'] == 'Time':
|
||||
ss['durationValue'] = form.cleaned_data['durationvalue']*60000
|
||||
elif form.cleaned_data['durationtype'] == 'Distance':
|
||||
ss[durationValue] = form.cleaned_data['durationvalue']*100
|
||||
|
||||
ss['durationValue'] = int(ss['durationValue'])
|
||||
ps.fitfile = None
|
||||
ps.interval_string = ""
|
||||
|
||||
ps.save()
|
||||
|
||||
step.durationtype = form.cleaned_data['durationtype']
|
||||
step.durationvalue = form.cleaned_data['durationvalue']
|
||||
step.targettype = form.cleaned_data['targettype']
|
||||
step.targetvalue = form.cleaned_data['targetvalue']
|
||||
step.targetvaluelow = form.cleaned_data['targetvaluelow']
|
||||
step.targetvaluehigh = form.cleaned_data['targetvaluehigh']
|
||||
step.intensity = form.cleaned_data['intensity']
|
||||
step.name = form.cleaned_data['name']
|
||||
step.description = form.cleaned_data['description']
|
||||
|
||||
if step.durationtype == 'Time':
|
||||
step.durationvalue *= 60000
|
||||
elif step.durationtype == 'Distance':
|
||||
step.durationvalue *= 100
|
||||
|
||||
step.save()
|
||||
|
||||
|
||||
if step.durationtype == 'Time':
|
||||
form.fields['durationvalue'].initial = step.durationvalue / 60000
|
||||
elif step.durationtype == 'Distance':
|
||||
form.fields['durationvalue'].initial = step.durationvalue / 100
|
||||
|
||||
|
||||
stepdescription = step_to_string(step.asdict(), short=False)[0]
|
||||
|
||||
if request.method == 'POST':
|
||||
if 'stepsave_and_return' in request.POST:
|
||||
url = reverse('stepeditor',kwargs = {'id': ps.id})
|
||||
return HttpResponseRedirect(url)
|
||||
|
||||
breadcrumbs = [
|
||||
{
|
||||
'url': reverse('template_library_view'),
|
||||
'name': 'Session Templates'
|
||||
},
|
||||
{
|
||||
'url': reverse('plannedsession_templateedit_view', kwargs={'id': ps.id}),
|
||||
'name': ps.name
|
||||
},
|
||||
{
|
||||
'url': reverse('stepeditor', kwargs={'id':ps.id}),
|
||||
'name': 'Edit Steps'
|
||||
},
|
||||
{
|
||||
'url': reverse('stepedit', kwargs={'psid': ps.id, 'id': step.id}),
|
||||
'name': 'Edit Step'
|
||||
}
|
||||
]
|
||||
|
||||
return render(request,'stepedit.html',
|
||||
{
|
||||
'step': step,
|
||||
'stepdescription': stepdescription,
|
||||
'form': form,
|
||||
'ps': ps,
|
||||
'breadcrumbs': breadcrumbs,
|
||||
})
|
||||
|
||||
|
||||
|
||||
@user_passes_test(can_plan, login_url="/rowers/paidplans",
|
||||
message="This functionality requires a Coach or Self-Coach plan",
|
||||
redirect_field_name=None)
|
||||
def stepeditor(request, id=0):
|
||||
ps = get_object_or_404(PlannedSession, pk=id)
|
||||
|
||||
currentsteps = []
|
||||
if ps.steps:
|
||||
for step in ps.steps['steps']:
|
||||
print(step)
|
||||
durationtype = step.get('durationType','')
|
||||
durationvalue = step.get('durationValue',0)
|
||||
targetvalue = step.get('targetValue',0)
|
||||
@@ -3034,8 +3175,8 @@ def stepeditor(request, id=0):
|
||||
targetvaluelow = targetvaluelow,
|
||||
targetvaluehigh = targetvaluehigh,
|
||||
intensity = intensity,
|
||||
).count()
|
||||
if not archived_steps and durationvalue != 0:
|
||||
)
|
||||
if not archived_steps.count() and durationvalue != 0:
|
||||
s = PlannedSessionStep(
|
||||
manager = request.user,
|
||||
durationtype = durationtype,
|
||||
@@ -3048,7 +3189,9 @@ def stepeditor(request, id=0):
|
||||
name = step.get('wkt_step_name','Step')
|
||||
)
|
||||
s.save()
|
||||
ps.steps = {}
|
||||
else:
|
||||
s = archived_steps[0]
|
||||
currentsteps.append(s)
|
||||
|
||||
|
||||
form = StepEditorForm()
|
||||
@@ -3069,16 +3212,30 @@ def stepeditor(request, id=0):
|
||||
for step in steps:
|
||||
stepdescriptions[step.id] = step_to_string(step.asdict(), short=False)[0]
|
||||
|
||||
print(stepdescriptions)
|
||||
print(steps)
|
||||
breadcrumbs = [
|
||||
{
|
||||
'url': reverse('template_library_view'),
|
||||
'name': 'Session Templates'
|
||||
},
|
||||
{
|
||||
'url': reverse('plannedsession_templateedit_view', kwargs={'id': ps.id}),
|
||||
'name': ps.name
|
||||
},
|
||||
{
|
||||
'url': reverse('stepeditor', kwargs={'id': ps.id}),
|
||||
'name': 'Edit Steps'
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
return render(request, 'stepeditor.html',
|
||||
{
|
||||
'steps':steps,
|
||||
'currentsteps': currentsteps,
|
||||
'stepdescriptions': stepdescriptions,
|
||||
'form':form,
|
||||
'ps':ps,
|
||||
'breadcrumbs': breadcrumbs,
|
||||
})
|
||||
|
||||
@user_passes_test(can_plan, login_url="/rowers/paidplans",
|
||||
|
||||
@@ -357,7 +357,7 @@ th.rotate > div > span {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
background: #878787;
|
||||
color: white;
|
||||
/* color: white; */
|
||||
padding: 10px;
|
||||
padding-bottom: 40px;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user