Private
Public Access
1
0

force curve, comments, edit

This commit is contained in:
Sander Roosendaal
2018-10-09 20:35:37 +02:00
parent f8b09b7b6d
commit c693655966
9 changed files with 552 additions and 781 deletions

View File

@@ -1,4 +1,4 @@
{% extends "base.html" %} {% extends "newbase.html" %}
{% load staticfiles %} {% load staticfiles %}
{% load rowerfilters %} {% load rowerfilters %}
{% load tz %} {% load tz %}
@@ -6,7 +6,7 @@
{% block title %} Force Curve Plot {% endblock %} {% block title %} Force Curve Plot {% endblock %}
{% localtime on %} {% localtime on %}
{% block content %} {% block main %}
{{ js_res | safe }} {{ js_res | safe }}
{{ css_res| safe }} {{ css_res| safe }}
@@ -19,54 +19,34 @@
{{ the_script |safe }} {{ the_script |safe }}
<h1>Empower Force Curve</h1>
<style> <ul class="main-content">
/* Need this to get the page in "desktop mode"; not having an infinite height.*/ <li class="grid_4">
html, body {height: 100%; margin:5px;} {% if user.is_authenticated and mayedit %}
</style>
<div id="navigation" class="grid_12 alpha">
{% if user.is_authenticated and mayedit %}
<div class="grid_2 alpha">
<p>
<a class="button gray small" href="/rowers/workout/{{ id }}/edit">Edit Workout</a>
</p>
</div>
<div class="grid_2 suffix_2">
<p>
<a class="button gray small" href="/rowers/workout/{{ id }}/advanced">Advanced Edit</a>
</p>
</div>
{% endif %}
<div class="grid_2 suffix_4 omega tooltip">
<form enctype="multipart/form-data" action="{{ formloc }}" method="post"> <form enctype="multipart/form-data" action="{{ formloc }}" method="post">
{% csrf_token %} {% csrf_token %}
{% if workstrokesonly %} {% if workstrokesonly %}
<input type="hidden" name="workstrokesonly" value="True"> <input type="hidden" name="workstrokesonly" value="True">
<input class="grid_2 alpha button blue small" value="Remove Rest Strokes" type="Submit"> <input class="button blue small" value="Remove Rest Strokes" type="Submit">
{% else %} {% else %}
<input class="grid_2 alpha button blue small" type="hidden" name="workstrokesonly" value="False"> <input class="button blue small" type="hidden" name="workstrokesonly" value="False">
<input class="grid_2 alpha button blue small" value="Include Rest Strokes" type="Submit"> <input class="button blue small" value="Include Rest Strokes" type="Submit">
{% endif %}
</form> </form>
{% endif %}
<span class="tooltiptext">If your data source allows, this will show or hide strokes taken during rest intervals.</span> <span class="tooltiptext">If your data source allows, this will show or hide strokes taken during rest intervals.</span>
</div> {% endif %}
</li>
<li class="grid_4">
{{ the_div|safe }}
</div> </li>
</ul>
<p>&nbsp;</p>
<div id="theplot" class="grid_12 alpha">
{{ the_div|safe }}
</div>
{% endblock %} {% endblock %}
{% endlocaltime %} {% endlocaltime %}
{% block sidebar %}
{% include 'menu_workout.html' %}
{% endblock %}

View File

@@ -167,7 +167,6 @@ xo
<th> Max HR </th> <th> Max HR </th>
{% if not team %} {% if not team %}
<th> &nbsp;</th> <th> &nbsp;</th>
<th> &nbsp;</th>
{% else %} {% else %}
<th colspan="2"> <th colspan="2">
Owner Owner
@@ -216,11 +215,7 @@ xo
<td> {{ workout.duration |durationprint:"%H:%M:%S.%f" }} </td> <td> {{ workout.duration |durationprint:"%H:%M:%S.%f" }} </td>
<td> {{ workout.averagehr }} </td> <td> {{ workout.averagehr }} </td>
<td> {{ workout.maxhr }} </td> <td> {{ workout.maxhr }} </td>
{% if not team %} {% if team %}
<td>
<a class="small" href="/rowers/workout/{{ workout.id }}/export">Export</a>
</td>
{% else %}
<td colspan="2"> <td colspan="2">
<a class="small" href="/rowers/{{ workout.user.id }}/list-workouts"> <a class="small" href="/rowers/{{ workout.user.id }}/list-workouts">
{{ workout.user.user.first_name }} {{ workout.user.user.first_name }}

View File

@@ -28,6 +28,14 @@
</a> </a>
</li> </li>
{% endif %} {% endif %}
{% if user.is_authenticated %}
<li id="workout-comments">
<a href="/rowers/workout/{{ workout.id }}/comment">
<i class="fas fa-comments fa-fw"></i>&nbsp;Comments
({{ workout|aantalcomments }})
</a>
</li>
{% endif %}
<li id="workout-stats"> <li id="workout-stats">
<a href="/rowers/workout/{{ workout.id }}/stats"> <a href="/rowers/workout/{{ workout.id }}/stats">
<i class="fal fa-table fa-fw"></i>&nbsp;Statistics <i class="fal fa-table fa-fw"></i>&nbsp;Statistics
@@ -62,6 +70,11 @@
<i class="fas fa-map-marked-alt fa-fw"></i>&nbsp;Map <i class="fas fa-map-marked-alt fa-fw"></i>&nbsp;Map
</a> </a>
</li> </li>
<li id="chart-empower">
<a href="/rowers/workout/{{ workout.id }}/forcecurve">
<i class="fas fa-dumbbell fa-fw"></i>&nbsp;Force Curve
</a>
</li>
<li id="chart-otwpower"> <li id="chart-otwpower">
<a href="/rowers/workout/{{ workout.id }}/interactiveotwplot"> <a href="/rowers/workout/{{ workout.id }}/interactiveotwplot">
<i class="fal fa-calculator-alt fa-fw"></i>&nbsp;OTW Power <i class="fal fa-calculator-alt fa-fw"></i>&nbsp;OTW Power

View File

@@ -1,4 +1,4 @@
{% extends "base.html" %} {% extends "newbase.html" %}
{% load staticfiles %} {% load staticfiles %}
{% load rowerfilters %} {% load rowerfilters %}
{% load tz %} {% load tz %}
@@ -7,19 +7,13 @@
{% include "monitorjobs.html" %} {% include "monitorjobs.html" %}
{% endblock %} {% endblock %}
{% block title %}Change Workout {% endblock %} {% block title %}Comment Workout {% endblock %}
{% block content %} {% block main %}
<div id="left" class="grid_6 alpha"> <h1>Comments {{ workout.name }}</h1>
<div id="summary" class="grid_6 alpha">
{% if form.errors %}
<p style="color: red;">
Please correct the error{{ form.errors|pluralize }} below.
</p>
{% endif %}
<h1>Comments {{ workout.name }}</h1>
<ul class="main-content">
<li class="grid_4">
{% localtime on %} {% localtime on %}
<table width=100%> <table width=100%>
<tr> <tr>
@@ -35,153 +29,65 @@
<td> <td>
<a href="/rowers/workout/{{ workout.id }}">https://rowsandall.com/rowers/workout/{{ workout.id }}</a> <a href="/rowers/workout/{{ workout.id }}">https://rowsandall.com/rowers/workout/{{ workout.id }}</a>
<td> <td>
</tr><tr>
<th>Public link to interactive chart</th>
<td>
<a href="/rowers/workout/{{ workout.id }}/interactiveplot">https://rowsandall.com/rowers/workout/{{ workout.id }}/interactiveplot</a>
<td>
</tr> </tr>
</table> </table>
{% endlocaltime %} {% endlocaltime %}
</div> </li>
{% for c in comments %} <li class="grid_2">
<div class="grid_6 alpha"> {% for c in comments %}
<div class="grid_2 alpha"> {{ c.created }}
{{ c.created }} <b>{{ c.user.first_name }} {{ c.user.last_name }}</b>
<b>{{ c.user.first_name }} {{ c.user.last_name }}</b> <div class="talk-bubble tri-right left-top">
</div> <div class="talktext">
<div class="grid_4 omega"> {{ c.comment }}
<div class="talk-bubble tri-right left-top">
<div class="talktext">
{{ c.comment }}
</div>
</div> </div>
</div> </div>
</div>
{% endfor %} {% endfor %}
<div id="form" class="grid_6 alpha">
<form enctype="multipart/form-data" action="/rowers/workout/{{ workout.id }}/comment" method="post"> <form enctype="multipart/form-data" action="/rowers/workout/{{ workout.id }}/comment" method="post">
<table width=100%> <table width=100%>
{{ form.as_table }} {{ form.as_table }}
</table> </table>
{% csrf_token %} {% csrf_token %}
<div id="formbutton" class="grid_1 prefix_4 suffix_1 omega"> <input class="button green" type="submit" value="Save">
<input class="button green" type="submit" value="Save">
</div>
</form> </form>
</div> </li>
{% for graph in graphs %}
</div> <li>
<div id="images" class="grid_6 omega">
<h1>Images linked to this workout</h1>
{% if graphs1 %}
{% for graph in graphs1 %}
{% if forloop.counter == 1 %}
<div id="thumb-container" class="grid_2 alpha">
<a href="/rowers/graph/{{ graph.id }}/"> <a href="/rowers/graph/{{ graph.id }}/">
<img src="/{{ graph.filename }}" <img src="/{{ graph.filename }}"
onerror="this.src='/static/img/rowingtimer.gif'" onerror="this.src='/static/img/rowingtimer.gif'"
alt="{{ graph.filename }}" width="120" height="100"></a> alt="{{ graph.filename }}" width="120" height="100">
</div> </a>
{% elif forloop.counter == 3 %} </li>
<div id="thumb-container" class="grid_2 omega">
<a href="/rowers/graph/{{ graph.id }}/">
<img src="/{{ graph.filename }}"
onerror="this.src='/static/img/rowingtimer.gif'"
alt="{{ graph.filename }}" width="120" height="100"></a>
</div>
{% else %}
<div id="thumb-container" class="grid_2">
<a href="/rowers/graph/{{ graph.id }}/">
<img src="/{{ graph.filename }}"
onerror="this.src='/static/img/rowingtimer.gif'"
alt="{{ graph.filename }}" width="120" height="100"></a>
</div>
{% endif %}
{% endfor %} {% endfor %}
<li class="grid_2">
{% for graph in graphs2 %} <h1>Workout Summary</h1>
{% if forloop.counter == 1 %}
<div id="thumb-container" class="grid_2 alpha"> <p>
<a href="/rowers/graph/{{ graph.id }}/"> <pre>
<img src="/{{ graph.filename }}" {{ workout.summary }}
onerror="this.src='/static/img/rowingtimer.gif'" </pre>
alt="{{ graph.filename }}" width="120" height="100"></a> </p>
</div>
{% elif forloop.counter == 3 %} </li>
<div id="thumb-container" class="grid_2 omega">
<a href="/rowers/graph/{{ graph.id }}/">
<img src="/{{ graph.filename }}"
onerror="this.src='/static/img/rowingtimer.gif'"
alt="{{ graph.filename }}" width="120" height="100"></a>
</div>
{% else %}
<div id="thumb-container" class="grid_2">
<a href="/rowers/graph/{{ graph.id }}/">
<img src="/{{ graph.filename }}"
onerror="this.src='/static/img/rowingtimer.gif'"
alt="{{ graph.filename }}" width="120" height="100"></a>
</div>
{% endif %}
{% endfor %}
{% else %} <li class="grid_2">
<p> No graphs found </p> <script type="text/javascript" src="/static/js/bokeh-0.12.3.min.js"></script>
{% endif %} <script async="true" type="text/javascript">
</div> Bokeh.set_log_level("info");
</script>
<style>
/* Need this to get the page in "desktop mode"; not having an infinite height.*/
html, body {height: 100%; margin:5px;}
</style>
<div id="summary" class="grid_6 omega">
<h1>Workout Summary</h1>
<p> {{ gmscript |safe }}
<pre>
{{ workout.summary }}
</pre>
</p>
</div> <div id="mapdiv">
{{ gmdiv|safe }}
</div>
</li>
<div id="interactiveplot" class="grid_6 omega"> </ul>
<script type="text/javascript" src="/static/js/bokeh-0.12.3.min.js"></script>
<script async="true" type="text/javascript">
Bokeh.set_log_level("info");
</script>
{{ gmscript |safe }}
<style>
/* Need this to get the page in "desktop mode"; not having an infinite height.*/
html, body, #map_canvas {
height: 100%;
width: 100%;
margin:0;
padding: 0;
}
#map_canvas_container {position: relative; top:0; right:0; bottom:0; left:0;}
#map_canvas {position: relative; top: 0; right: 0; bottom: 0; left: 0;}
</style>
<div id="map_canvas">
{{ gmdiv|safe }}
</div>
</div>
{% endblock %} {% endblock %}
{% block sidebar %}
{% include 'menu_workout.html' %}
{% endblock %}

View File

@@ -1,4 +1,4 @@
{% extends "base.html" %} {% extends "newbase.html" %}
{% load staticfiles %} {% load staticfiles %}
{% load rowerfilters %} {% load rowerfilters %}
{% load tz %} {% load tz %}
@@ -42,261 +42,105 @@ $('#id_workouttype').change();
</script> </script>
{% endblock %} {% endblock %}
{% block content %} {% block main %}
<div id="workouts" class="grid_6 alpha">
{% if form.errors %} <h1>Edit Workout {{ workout.name }}</h1>
<p style="color: red;"> <ul class="main-content">
Please correct the error{{ form.errors|pluralize }} below. <li class="grid_4">
</p> <p>
{% endif %} <div class="fb-share-button"
data-href="https://rowsandall.com/rowers/workout/{{ workout.id }}"
<h1>Edit Workout {{ workout.name }}</h1> data-layout="button" data-size="small" data-mobile-iframe="false">
<div class="grid_6 alpha"> <a class="fb-xfbml-parse-ignore" target="_blank" href="https://www.facebook.com/sharer/sharer.php?u=https://rowsandall.com/rowers/workout/{{ workout.id }}">Share</a>
<div class="grid_2 alpha"> </div>
<p> </p>
<a class="button red small" href="/rowers/workout/{{ workout.id }}/deleteconfirm">Delete</a> <p>
</p> <a class="twitter-share-button"
</div> href="https://twitter.com/intent/tweet"
<div class="grid_2"> data-url="https://rowsandall.com/rowers/workout/{{ workout.id }}"
<p> data-text="@rowsandall #rowingdata">Tweet</a>
<a class="button gray small" href="/rowers/workout/{{ workout.id }}/export">Export</a> </p>
<table width=100%>
</p> <tr>
</div> {% localtime on %}
<div class="grid_2 omega tooltip"> {% if workout.user.user != user %}
<p>
<a class="button gray small" href="/rowers/workout/{{ workout.id }}/advanced">Advanced</a>
</p>
<span class="tooltiptext">Advanced Functionality (More interactive Charts)</span>
</div>
</div>
<div class="grid_6 alpha">
<div class="grid_2 alpha">
<p>
<a class="button gray small" href="/rowers/workout/{{ workout.id }}/workflow">Workflow View</a>
</p>
</div>
<div class="grid_2">
<p>
<a class="button gray small" href="/rowers/workout/{{ workout.id }}/map">Map View</a>
</p>
</div>
<div class="grid_2 omega">
<p>
<a class="button gray small" href="/rowers/workout/{{ workout.id }}/stats">Statistics</a>
</p>
</div>
</div>
<div class="grid_6 alpha">
<table width=100%>
<tr>
{% localtime on %}
{% if workout.user.user != user %}
<th>Rower:</th><td>{{ rower.user.first_name }} {{ rower.user.last_name }}</td> <th>Rower:</th><td>{{ rower.user.first_name }} {{ rower.user.last_name }}</td>
</tr><tr> </tr><tr>
{% endif %} {% endif %}
<th>Date/Time:</th><td>{{ workout.startdatetime|localtime}}</td> <th>Date/Time:</th><td>{{ workout.startdatetime|localtime}}</td>
{% endlocaltime %} {% endlocaltime %}
</tr><tr> </tr><tr>
<th>Distance:</th><td>{{ workout.distance }}m</td> <th>Distance:</th><td>{{ workout.distance }}m</td>
</tr><tr> </tr><tr>
<th>Duration:</th><td>{{ workout.duration |durationprint:"%H:%M:%S.%f" }}</td> <th>Duration:</th><td>{{ workout.duration |durationprint:"%H:%M:%S.%f" }}</td>
</tr><tr> </tr><tr>
<th>Public link to this workout</th> <th>Public link to this workout</th>
<td> <td>
<a href="/rowers/workout/{{ workout.id }}">https://rowsandall.com/rowers/workout/{{ workout.id }}</a> <a href="/rowers/workout/{{ workout.id }}">https://rowsandall.com/rowers/workout/{{ workout.id }}</a>
</td> </td>
</tr><tr> </tr>
<th>Comments</th> </table>
<td> </li>
<a href="/rowers/workout/{{ workout.id }}/comment">Comment ({{ aantalcomments }})</a> <li class="grid_2">
</td> {% if form.errors %}
<p style="color: red;">
</tr><tr> Please correct the error{{ form.errors|pluralize }} below.
<th>Public link to interactive chart</th> </p>
<td> {% endif %}
<a href="/rowers/workout/{{ workout.id }}/interactiveplot">https://rowsandall.com/rowers/workout/{{ workout.id }}/interactiveplot</a>
<td>
</tr>
</table>
</div>
<div id="form-div" class="grid_6 alpha">
<form id="importantform" <form id="importantform"
enctype="multipart/form-data" action="" method="post"> enctype="multipart/form-data" action="" method="post">
<table width=100%> <table width=100%>
{{ form.as_table }} {{ form.as_table }}
</table> </table>
{% csrf_token %} {% csrf_token %}
<div id="formbutton" class="grid_1 prefix_2 suffix_1 omega">
<input class="button green" type="submit" value="Save"> <input class="button green" type="submit" value="Save">
</div> </form>
</form> </li>
</div> <li class="grid_2">
</div>
<div id="images" class="grid_6 omega">
<h1>Images linked to this workout</h1>
<div class="grid_6 alpha">
<div class="grid_2 alpha">
<p>
<a class="button blue small" href="/rowers/workout/{{ workout.id }}/addtimeplot">Add Time Plot</a>
</p>
</div>
<div class="grid_2">
<p>
<a class="button blue small" href="/rowers/workout/{{ workout.id }}/adddistanceplot">Add Distance Plot</a>
</p>
</div>
<div class="grid_2 omega">
<p>
<a class="button blue small" href="/rowers/workout/{{ workout.id }}/addpiechart">Add HR Pie Chart</a>
</p>
</div>
<div class="grid_6 alpha">
<div class="grid_2 alpha">
<p>
<a class="button blue small" href="/rowers/workout/{{ workout.id }}/image">Attach Image</a>
</p>
</div>
<div class="grid_2 prefix_2 omega">
<p>
<a class="button blue small" href="/rowers/workout/{{ workout.id }}/addpowerpiechart">Power Pie Chart</a>
</p>
</div>
<div class="grid_6">
<p>Generating images takes roughly 1 second per minute
of your workout's duration. Please reload after a minute or so.</p>
</div>
</div>
{% if graphs1 %}
{% for graph in graphs1 %} <h1>Workout Summary</h1>
{% if forloop.counter == 1 %}
<div id="thumb-container" class="grid_2 alpha">
<a href="/rowers/graph/{{ graph.id }}/">
<img src="/{{ graph.filename }}"
onerror="this.src='/static/img/rowingtimer.gif'"
alt="{{ graph.filename }}" width="120" height="100"></a>
</div>
{% elif forloop.counter == 3 %}
<div id="thumb-container" class="grid_2 omega">
<a href="/rowers/graph/{{ graph.id }}/">
<img src="/{{ graph.filename }}"
onerror="this.src='/static/img/rowingtimer.gif'"
alt="{{ graph.filename }}" width="120" height="100"></a>
</div>
{% else %} <p>
<div id="thumb-container" class="grid_2"> <pre>
<a href="/rowers/graph/{{ graph.id }}/"> {{ workout.summary }}
<img src="/{{ graph.filename }}" </pre>
onerror="this.src='/static/img/rowingtimer.gif'" </p>
alt="{{ graph.filename }}" width="120" height="100"></a> <p>
</div> <a href="/rowers/workout/{{ workout.id }}/recalcsummary">Update Summary</a>
{% endif %} </p>
{% endfor %} </li>
{% if mapdiv %}
<li class="grid_2">
{% for graph in graphs2 %}
{% if forloop.counter == 1 %}
<div id="thumb-container" class="grid_2 alpha">
<a href="/rowers/graph/{{ graph.id }}/">
<img src="/{{ graph.filename }}"
onerror="this.src='/static/img/rowingtimer.gif'"
alt="{{ graph.filename }}" width="120" height="100"></a>
</div>
{% elif forloop.counter == 3 %}
<div id="thumb-container" class="grid_2 omega">
<a href="/rowers/graph/{{ graph.id }}/">
<img src="/{{ graph.filename }}"
onerror="this.src='/static/img/rowingtimer.gif'"
alt="{{ graph.filename }}" width="120" height="100"></a>
</div>
{% else %}
<div id="thumb-container" class="grid_2">
<a href="/rowers/graph/{{ graph.id }}/">
<img src="/{{ graph.filename }}"
onerror="this.src='/static/img/rowingtimer.gif'"
alt="{{ graph.filename }}" width="120" height="100"></a>
</div>
{% endif %}
{% endfor %}
{% else %}
<p> No graphs found </p>
{% endif %}
</div>
<style>
/* Need this to get the page in "desktop mode"; not having an infinite height.*/
html, body {height: 100%; margin:5px;}
</style>
<div id="summary" class="grid_6 omega">
<div class="grid_5 alpha">
<h1>Workout Summary</h1>
<p>
<pre>
{{ workout.summary }}
</pre>
</p>
<div class="grid_2 alpha">
<p>
<a class="button green small" href="/rowers/workout/{{ workout.id }}/recalcsummary">Update Summary</a>
</p>
</div>
</div>
<div class="grid_1 omega">
<div class="grid_1 alpha">
<div class="fb-share-button" data-href="https://rowsandall.com/rowers/workout/{{ workout.id }}" data-layout="button" data-size="small" data-mobile-iframe="false">
<a class="fb-xfbml-parse-ignore" target="_blank" href="https://www.facebook.com/sharer/sharer.php?u=https://rowsandall.com/rowers/workout/{{ workout.id }}">Share</a></div>
</div>
<div class="grid_1 alpha">
<p>&nbsp;</p>
<a class="twitter-share-button"
href="https://twitter.com/intent/tweet"
data-url="https://rowsandall.com/rowers/workout/{{ workout.id }}"
data-text="@rowsandall #rowingdata">Tweet</a>
</div>
</div>
</div>
<div id="interactiveplot" class="grid_6 omega">
<script type="text/javascript" src="/static/js/bokeh-0.12.3.min.js"></script> <script type="text/javascript" src="/static/js/bokeh-0.12.3.min.js"></script>
<script async="true" type="text/javascript"> <script async="true" type="text/javascript">
Bokeh.set_log_level("info"); Bokeh.set_log_level("info");
</script> </script>
<style>
/* Need this to get the page in "desktop mode"; not having an infinite height.*/
html, body, #map_canvas {
height: 100%;
width: 100%;
margin:0;
padding: 0;
}
#map_canvas_container {position: relative; top:0; right:0; bottom:0; left:0;}
#map_canvas {position: relative; top: 0; right: 0; bottom: 0; left: 0;}
</style>
<div class="mapdiv">
{{ mapdiv|safe }} {{ mapdiv|safe }}
</div>
{{ mapscript|safe }} {{ mapscript|safe }}
</div> </li>
</div> {% endif %}
{% for graph in graphs %}
<li>
<a href="/rowers/graph/{{ graph.id }}/">
<img src="/{{ graph.filename }}"
onerror="this.src='/static/img/rowingtimer.gif'"
alt="{{ graph.filename }}" width="120" height="100">
</a>
</li>
{% endfor %}
</ul>
{% endblock %} {% endblock %}
{% block sidebar %}
{% include 'menu_workout.html' %}
{% endblock %}

View File

@@ -8,7 +8,7 @@ import datetime
import re import re
register = template.Library() register = template.Library()
from rowers.utils import calculate_age from rowers.utils import calculate_age
from rowers.models import course_length from rowers.models import course_length,WorkoutComment
from rowers.plannedsessions import ( from rowers.plannedsessions import (
race_can_register, race_can_submit,race_rower_status race_can_register, race_can_submit,race_rower_status
) )
@@ -55,6 +55,14 @@ def secondstotimestring(tdelta):
return res return res
@register.filter
def aantalcomments(workout):
comments = WorkoutComment.objects.filter(workout=workout)
aantalcomments = len(comments)
return aantalcomments
@register.filter @register.filter
def water(workout): def water(workout):
try: try:

View File

@@ -226,7 +226,7 @@ urlpatterns = [
url(r'^workout/(?P<id>\d+)/task$',views.workout_test_task_view), url(r'^workout/(?P<id>\d+)/task$',views.workout_test_task_view),
url(r'^workout/(?P<id>\d+)/forcecurve$',views.workout_forcecurve_view), url(r'^workout/(?P<id>\d+)/forcecurve$',views.workout_forcecurve_view),
url(r'^workout/(?P<id>\d+)/unsubscribe$',views.workout_unsubscribe_view), url(r'^workout/(?P<id>\d+)/unsubscribe$',views.workout_unsubscribe_view),
url(r'^workout/(?P<id>\d+)/export$',views.workout_export_view), # url(r'^workout/(?P<id>\d+)/export$',views.workout_export_view),
url(r'^workout/(?P<id>\d+)/comment$',views.workout_comment_view), url(r'^workout/(?P<id>\d+)/comment$',views.workout_comment_view),
url(r'^workout/(?P<id>\d+)/emailtcx$',views.workout_tcxemail_view), url(r'^workout/(?P<id>\d+)/emailtcx$',views.workout_tcxemail_view),
url(r'^workout/(?P<id>\d+)/emailgpx$',views.workout_gpxemail_view), url(r'^workout/(?P<id>\d+)/emailgpx$',views.workout_gpxemail_view),
@@ -328,8 +328,7 @@ urlpatterns = [
url(r'^workout/(?P<id>\d+)/underarmouruploadw/$',views.workout_underarmour_upload_view), url(r'^workout/(?P<id>\d+)/underarmouruploadw/$',views.workout_underarmour_upload_view),
url(r'^workout/(?P<id>\d+)/tpuploadw/$',views.workout_tp_upload_view), url(r'^workout/(?P<id>\d+)/tpuploadw/$',views.workout_tp_upload_view),
url(r'^multi-compare$',views.multi_compare_view), url(r'^multi-compare$',views.multi_compare_view),
url(r'^user-boxplot/(?P<userid>\d+)$',views.boxplot_view), url(r'^user-boxplot/user/(?P<userid>\d+)$',views.boxplot_view),
url(r'^user-boxplot/$',views.boxplot_view),
url(r'^user-boxplot$',views.boxplot_view), url(r'^user-boxplot$',views.boxplot_view),
url(r'^user-boxplot-data$',views.boxplot_view_data), url(r'^user-boxplot-data$',views.boxplot_view_data),
url(r'^user-multiflex/(?P<userid>\d+)$',views.multiflex_view), url(r'^user-multiflex/(?P<userid>\d+)$',views.multiflex_view),

View File

@@ -2830,10 +2830,32 @@ def workout_forcecurve_view(request,id=0,workstrokesonly=False):
script,div,js_resources,css_resources = interactive_forcecurve([row], script,div,js_resources,css_resources = interactive_forcecurve([row],
workstrokesonly=workstrokesonly) workstrokesonly=workstrokesonly)
breadcrumbs = [
{
'url':'/rowers/list-workouts',
'name':'Workouts'
},
{
'url':get_workout_default_page(request,id),
'name': str(row.id)
},
{
'url':reverse(workout_forcecurve_view,kwargs={'id':id}),
'name': 'Empower Force Curve'
}
]
r = getrower(request.user)
return render(request, return render(request,
'forcecurve_single.html', 'forcecurve_single.html',
{ {
'the_script':script, 'the_script':script,
'rower':r,
'workout':row,
'breadcrumbs':breadcrumbs,
'active':'nav-workouts',
'the_div':div, 'the_div':div,
'js_res': js_resources, 'js_res': js_resources,
'css_res':css_resources, 'css_res':css_resources,
@@ -8823,7 +8845,7 @@ def workout_unsubscribe_view(request,id=0):
@login_required() @login_required()
def workout_comment_view(request,id=0): def workout_comment_view(request,id=0):
w = get_workout(id) w = get_workout(id)
if w.privacy == 'private' and w.user.user != request.user: if w.privacy == 'private' and w.user.user != request.user:
return HttpResponseForbidden("Permission error") return HttpResponseForbidden("Permission error")
@@ -8903,26 +8925,36 @@ def workout_comment_view(request,id=0):
except: except:
pass pass
rower = getrower(request.user)
if (len(g)<=3): breadcrumbs = [
return render(request, {
'workout_comments.html', 'url':'/rowers/list-workouts',
{'workout':w, 'name':'Workouts'
'teams':get_my_teams(request.user), },
'graphs1':g[0:3], {
'comments':comments, 'url':get_workout_default_page(request,id),
'form':form, 'name': str(w.id)
}) },
else: {
return render(request, 'url':reverse(workout_comment_view,kwargs={'id':id}),
'workout_comments.html', 'name': 'Comments'
{'workout':w, }
'teams':get_my_teams(request.user),
'graphs1':g[0:3], ]
'graphs1':g[3:6],
'comments':comments,
'form':form, return render(request,
}) 'workout_comments.html',
{'workout':w,
'rower':rower,
'breadcrumbs':breadcrumbs,
'active':'nav-workouts',
'teams':get_my_teams(request.user),
'graphs':g,
'comments':comments,
'form':form,
})
# for ajax calls # for ajax calls
def course_map_view(request,id=0): def course_map_view(request,id=0):
@@ -9083,6 +9115,9 @@ def workout_edit_view(request,id=0,message="",successmessage=""):
row = get_workout(id) row = get_workout(id)
if (checkworkoutuser(request.user,row)==False):
raise PermissionDenied("Access denied")
form = WorkoutForm(instance=row) form = WorkoutForm(instance=row)
if request.method == 'POST': if request.method == 'POST':
@@ -9142,50 +9177,43 @@ def workout_edit_view(request,id=0,message="",successmessage=""):
thetimezone = 'UTC' thetimezone = 'UTC'
# check if user is owner of this workout
if checkworkoutuser(request.user,row):
row.name = name
row.date = date
row.starttime = starttime
row.startdatetime = startdatetime
row.workouttype = workouttype
row.weightcategory = weightcategory
row.notes = notes
row.duration = duration
row.distance = distance
row.boattype = boattype
row.privacy = privacy
row.rankingpiece = rankingpiece
row.timezone = thetimezone
try:
row.save()
except IntegrityError:
pass
# change data in csv file
r = rdata(row.csvfilename) row.name = name
if r == 0: row.date = date
return HttpResponse("Error: CSV Data File Not Found") row.starttime = starttime
r.rowdatetime = startdatetime row.startdatetime = startdatetime
r.write_csv(row.csvfilename,gzip=True) row.workouttype = workouttype
dataprep.update_strokedata(id,r.df) row.weightcategory = weightcategory
successmessage = "Changes saved" row.notes = notes
row.duration = duration
row.distance = distance
row.boattype = boattype
row.privacy = privacy
row.rankingpiece = rankingpiece
row.timezone = thetimezone
try:
row.save()
except IntegrityError:
pass
# change data in csv file
r = rdata(row.csvfilename)
if r == 0:
return HttpResponse("Error: CSV Data File Not Found")
r.rowdatetime = startdatetime
r.write_csv(row.csvfilename,gzip=True)
dataprep.update_strokedata(id,r.df)
successmessage = "Changes saved"
if rankingpiece: if rankingpiece:
dataprep.runcpupdate(row.user,type=row.workouttype) dataprep.runcpupdate(row.user,type=row.workouttype)
messages.info(request,successmessage) messages.info(request,successmessage)
url = reverse(workout_edit_view, url = reverse(workout_edit_view,
kwargs = { kwargs = {
'id':str(row.id), 'id':str(row.id),
}) })
response = HttpResponseRedirect(url) response = HttpResponseRedirect(url)
else:
message = "You are not allowed to change this workout"
messages.error(request,message)
url = reverse(workouts_view)
response = HttpResponseRedirect(url)
#else: # form not POSTed #else: # form not POSTed
form = WorkoutForm(instance=row) form = WorkoutForm(instance=row)
@@ -9203,15 +9231,6 @@ def workout_edit_view(request,id=0,message="",successmessage=""):
pass pass
# check if user is owner of this workout
comments = WorkoutComment.objects.filter(workout=row)
aantalcomments = len(comments)
if (checkworkoutuser(request.user,row)==False):
raise PermissionDenied("Access denied")
# create interactive plot # create interactive plot
f1 = row.csvfilename f1 = row.csvfilename
u = row.user.user u = row.user.user
@@ -9245,34 +9264,40 @@ def workout_edit_view(request,id=0,message="",successmessage=""):
except KeyError: except KeyError:
pass pass
breadcrumbs = [
{
'url':'/rowers/list-workouts',
'name':'Workouts'
},
{
'url':get_workout_default_page(request,id),
'name': str(row.id)
},
{
'url':reverse(workout_edit_view,kwargs={'id':id}),
'name': 'Edit'
}
]
r = getrower(request.user)
# render page # render page
if (len(g)<=3): return render(request, 'workout_form.html',
return render(request, 'workout_form.html', {'form':form,
{'form':form, 'workout':row,
'workout':row, 'teams':get_my_teams(request.user),
'teams':get_my_teams(request.user), 'graphs':g,
'graphs1':g[0:3], 'breadcrumbs':breadcrumbs,
'mapscript':mapscript, 'rower':r,
'aantalcomments':aantalcomments, 'active':'nav-workouts',
'mapdiv':mapdiv, 'mapscript':mapscript,
'rower':r, 'mapdiv':mapdiv,
}) 'rower':r,
})
else:
return render(request, 'workout_form.html',
{'form':form,
'teams':get_my_teams(request.user),
'workout':row,
'graphs1':g[0:3],
'graphs2':g[3:6],
'mapscript':mapscript,
'aantalcomments':aantalcomments,
'mapdiv':mapdiv,
'rower':r,
})
return HttpResponseRedirect(url)
@login_required() @login_required()
def workout_map_view(request,id=0): def workout_map_view(request,id=0):

View File

@@ -332,6 +332,261 @@ th.rotate > div > span {
color: #fcd3a5; color: #fcd3a5;
} }
/* CSS talk bubble */
.talk-bubble {
margin: 40px;
display: inline-block;
position: relative;
width: 200px;
height: auto;
background-color: lightyellow;
}
.border{
border: 8px solid #666;
}
.round{
border-radius: 30px;
-webkit-border-radius: 30px;
-moz-border-radius: 30px;
}
/* Right triangle placed top left flush. */
.tri-right.border.left-top:before {
content: ' ';
position: absolute;
width: 0;
height: 0;
left: -40px;
right: auto;
top: -8px;
bottom: auto;
border: 32px solid;
border-color: #666 transparent transparent transparent;
}
.tri-right.left-top:after{
content: ' ';
position: absolute;
width: 0;
height: 0;
left: -20px;
right: auto;
top: 0px;
bottom: auto;
border: 22px solid;
border-color: lightyellow transparent transparent transparent;
}
/* Right triangle, left side slightly down */
.tri-right.border.left-in:before {
content: ' ';
position: absolute;
width: 0;
height: 0;
left: -40px;
right: auto;
top: 30px;
bottom: auto;
border: 20px solid;
border-color: #666 #666 transparent transparent;
}
.tri-right.left-in:after{
content: ' ';
position: absolute;
width: 0;
height: 0;
left: -20px;
right: auto;
top: 38px;
bottom: auto;
border: 12px solid;
border-color: lightyellow lightyellow transparent transparent;
}
/*Right triangle, placed bottom left side slightly in*/
.tri-right.border.btm-left:before {
content: ' ';
position: absolute;
width: 0;
height: 0;
left: -8px;
right: auto;
top: auto;
bottom: -40px;
border: 32px solid;
border-color: transparent transparent transparent #666;
}
.tri-right.btm-left:after{
content: ' ';
position: absolute;
width: 0;
height: 0;
left: 0px;
right: auto;
top: auto;
bottom: -20px;
border: 22px solid;
border-color: transparent transparent transparent lightyellow;
}
/*Right triangle, placed bottom left side slightly in*/
.tri-right.border.btm-left-in:before {
content: ' ';
position: absolute;
width: 0;
height: 0;
left: 30px;
right: auto;
top: auto;
bottom: -40px;
border: 20px solid;
border-color: #666 transparent transparent #666;
}
.tri-right.btm-left-in:after{
content: ' ';
position: absolute;
width: 0;
height: 0;
left: 38px;
right: auto;
top: auto;
bottom: -20px;
border: 12px solid;
border-color: lightyellow transparent transparent lightyellow;
}
/*Right triangle, placed bottom right side slightly in*/
.tri-right.border.btm-right-in:before {
content: ' ';
position: absolute;
width: 0;
height: 0;
left: auto;
right: 30px;
bottom: -40px;
border: 20px solid;
border-color: #666 #666 transparent transparent;
}
.tri-right.btm-right-in:after{
content: ' ';
position: absolute;
width: 0;
height: 0;
left: auto;
right: 38px;
bottom: -20px;
border: 12px solid;
border-color: lightyellow lightyellow transparent transparent;
}
/*
left: -8px;
right: auto;
top: auto;
bottom: -40px;
border: 32px solid;
border-color: transparent transparent transparent #666;
left: 0px;
right: auto;
top: auto;
bottom: -20px;
border: 22px solid;
border-color: transparent transparent transparent lightyellow;
/*Right triangle, placed bottom right side slightly in*/
.tri-right.border.btm-right:before {
content: ' ';
position: absolute;
width: 0;
height: 0;
left: auto;
right: -8px;
bottom: -40px;
border: 20px solid;
border-color: #666 #666 transparent transparent;
}
.tri-right.btm-right:after{
content: ' ';
position: absolute;
width: 0;
height: 0;
left: auto;
right: 0px;
bottom: -20px;
border: 12px solid;
border-color: lightyellow lightyellow transparent transparent;
}
/* Right triangle, right side slightly down*/
.tri-right.border.right-in:before {
content: ' ';
position: absolute;
width: 0;
height: 0;
left: auto;
right: -40px;
top: 30px;
bottom: auto;
border: 20px solid;
border-color: #666 transparent transparent #666;
}
.tri-right.right-in:after{
content: ' ';
position: absolute;
width: 0;
height: 0;
left: auto;
right: -20px;
top: 38px;
bottom: auto;
border: 12px solid;
border-color: lightyellow transparent transparent lightyellow;
}
/* Right triangle placed top right flush. */
.tri-right.border.right-top:before {
content: ' ';
position: absolute;
width: 0;
height: 0;
left: auto;
right: -40px;
top: -8px;
bottom: auto;
border: 32px solid;
border-color: #666 transparent transparent transparent;
}
.tri-right.right-top:after{
content: ' ';
position: absolute;
width: 0;
height: 0;
left: auto;
right: -20px;
top: 0px;
bottom: auto;
border: 20px solid;
border-color: lightyellow transparent transparent transparent;
}
/* talk bubble contents */
.talktext{
padding: 1em;
text-align: left;
line-height: 1.5em;
word-wrap: break-word;
}
.talktext p{
/* remove webkit p margins */
-webkit-margin-before: 0em;
-webkit-margin-after: 0em;
}
.drop-files {
border: 1px solid #000;
color: #000;
}
.input { .input {
font: 1.1em/1.5em sans-serif; font: 1.1em/1.5em sans-serif;
@@ -609,260 +864,6 @@ a.wh:hover {
padding: 5% 5%; padding: 5% 5%;
} }
/* CSS talk bubble */
.talk-bubble {
margin: 40px;
display: inline-block;
position: relative;
width: 200px;
height: auto;
background-color: lightyellow;
}
.border{
border: 8px solid #666;
}
.round{
border-radius: 30px;
-webkit-border-radius: 30px;
-moz-border-radius: 30px;
}
/* Right triangle placed top left flush. */
.tri-right.border.left-top:before {
content: ' ';
position: absolute;
width: 0;
height: 0;
left: -40px;
right: auto;
top: -8px;
bottom: auto;
border: 32px solid;
border-color: #666 transparent transparent transparent;
}
.tri-right.left-top:after{
content: ' ';
position: absolute;
width: 0;
height: 0;
left: -20px;
right: auto;
top: 0px;
bottom: auto;
border: 22px solid;
border-color: lightyellow transparent transparent transparent;
}
/* Right triangle, left side slightly down */
.tri-right.border.left-in:before {
content: ' ';
position: absolute;
width: 0;
height: 0;
left: -40px;
right: auto;
top: 30px;
bottom: auto;
border: 20px solid;
border-color: #666 #666 transparent transparent;
}
.tri-right.left-in:after{
content: ' ';
position: absolute;
width: 0;
height: 0;
left: -20px;
right: auto;
top: 38px;
bottom: auto;
border: 12px solid;
border-color: lightyellow lightyellow transparent transparent;
}
/*Right triangle, placed bottom left side slightly in*/
.tri-right.border.btm-left:before {
content: ' ';
position: absolute;
width: 0;
height: 0;
left: -8px;
right: auto;
top: auto;
bottom: -40px;
border: 32px solid;
border-color: transparent transparent transparent #666;
}
.tri-right.btm-left:after{
content: ' ';
position: absolute;
width: 0;
height: 0;
left: 0px;
right: auto;
top: auto;
bottom: -20px;
border: 22px solid;
border-color: transparent transparent transparent lightyellow;
}
/*Right triangle, placed bottom left side slightly in*/
.tri-right.border.btm-left-in:before {
content: ' ';
position: absolute;
width: 0;
height: 0;
left: 30px;
right: auto;
top: auto;
bottom: -40px;
border: 20px solid;
border-color: #666 transparent transparent #666;
}
.tri-right.btm-left-in:after{
content: ' ';
position: absolute;
width: 0;
height: 0;
left: 38px;
right: auto;
top: auto;
bottom: -20px;
border: 12px solid;
border-color: lightyellow transparent transparent lightyellow;
}
/*Right triangle, placed bottom right side slightly in*/
.tri-right.border.btm-right-in:before {
content: ' ';
position: absolute;
width: 0;
height: 0;
left: auto;
right: 30px;
bottom: -40px;
border: 20px solid;
border-color: #666 #666 transparent transparent;
}
.tri-right.btm-right-in:after{
content: ' ';
position: absolute;
width: 0;
height: 0;
left: auto;
right: 38px;
bottom: -20px;
border: 12px solid;
border-color: lightyellow lightyellow transparent transparent;
}
/*
left: -8px;
right: auto;
top: auto;
bottom: -40px;
border: 32px solid;
border-color: transparent transparent transparent #666;
left: 0px;
right: auto;
top: auto;
bottom: -20px;
border: 22px solid;
border-color: transparent transparent transparent lightyellow;
/*Right triangle, placed bottom right side slightly in*/
.tri-right.border.btm-right:before {
content: ' ';
position: absolute;
width: 0;
height: 0;
left: auto;
right: -8px;
bottom: -40px;
border: 20px solid;
border-color: #666 #666 transparent transparent;
}
.tri-right.btm-right:after{
content: ' ';
position: absolute;
width: 0;
height: 0;
left: auto;
right: 0px;
bottom: -20px;
border: 12px solid;
border-color: lightyellow lightyellow transparent transparent;
}
/* Right triangle, right side slightly down*/
.tri-right.border.right-in:before {
content: ' ';
position: absolute;
width: 0;
height: 0;
left: auto;
right: -40px;
top: 30px;
bottom: auto;
border: 20px solid;
border-color: #666 transparent transparent #666;
}
.tri-right.right-in:after{
content: ' ';
position: absolute;
width: 0;
height: 0;
left: auto;
right: -20px;
top: 38px;
bottom: auto;
border: 12px solid;
border-color: lightyellow transparent transparent lightyellow;
}
/* Right triangle placed top right flush. */
.tri-right.border.right-top:before {
content: ' ';
position: absolute;
width: 0;
height: 0;
left: auto;
right: -40px;
top: -8px;
bottom: auto;
border: 32px solid;
border-color: #666 transparent transparent transparent;
}
.tri-right.right-top:after{
content: ' ';
position: absolute;
width: 0;
height: 0;
left: auto;
right: -20px;
top: 0px;
bottom: auto;
border: 20px solid;
border-color: lightyellow transparent transparent transparent;
}
/* talk bubble contents */
.talktext{
padding: 1em;
text-align: left;
line-height: 1.5em;
word-wrap: break-word;
}
.talktext p{
/* remove webkit p margins */
-webkit-margin-before: 0em;
-webkit-margin-after: 0em;
}
.drop-files {
border: 1px solid #000;
color: #000;
}
.wrapwords{ .wrapwords{
-ms-word-break: break-all; -ms-word-break: break-all;