272 lines
8.5 KiB
HTML
272 lines
8.5 KiB
HTML
{% extends "newbase.html" %}
|
|
{% load static %}
|
|
{% load rowerfilters %}
|
|
|
|
{% block title %}Rowsandall Courses List{% endblock %}
|
|
{% block scripts %}
|
|
|
|
{% endblock %}
|
|
{% block main %}
|
|
<style>
|
|
#mypointer {
|
|
cursor: pointer;
|
|
}
|
|
tr:hover {
|
|
background-color: #f5f5f5;
|
|
}
|
|
</style>
|
|
|
|
|
|
|
|
<h1>Courses</h1>
|
|
|
|
<ul class="main-content">
|
|
<li class="grid_4">
|
|
<p>
|
|
Courses allow you to mark the start & finish lines of your
|
|
test pieces and measure the time spent on the course (as opposed
|
|
to the total duration of a workout). This allows you to row and rank
|
|
marked courses.
|
|
</p>
|
|
<p>
|
|
Rowsandall courses are compatible with Google Earth and with
|
|
<a href="http://performancephones.com/crewnerd/">CrewNerd</a>. You can create
|
|
and alter courses in Google Earth, and if you have CrewNerd and
|
|
a Rowsandall account, you can easily synchronize your courses between
|
|
the two applications, allowing you to use CrewNerd to get in-boat information
|
|
about the course.
|
|
</p>
|
|
</li>
|
|
<li class="grid_1">
|
|
<form id="searchform" action="/rowers/list-courses/"
|
|
method="get" accept-charset="utf-8">
|
|
{{ searchform }}
|
|
<input type="submit" value="GO"></input>
|
|
</form>
|
|
</li>
|
|
{% if location %}
|
|
<li>
|
|
<p><a href="/rowers/list-courses/?nearby=true">Filter courses closest to you</a></p>
|
|
<p>{% if city %}{{ city }}{% endif %} {{ country_name }}, time zone {{ time_zone }}</p>
|
|
</li>
|
|
<a href="/rowers/list-courses/">All courses</a>
|
|
</li>
|
|
{% endif %}
|
|
<li>
|
|
<a href="/rowers/list-courses/?liked=true">Courses I like</a>
|
|
</li>
|
|
{% if request.user.is_authenticated %}
|
|
<li class="grid_4">
|
|
<a href="{% url 'course_export_zip_view' %}"
|
|
target="download_frame"
|
|
class="btn btn-default">
|
|
Download my courses (ZIP)
|
|
</a> - With this button you can download all your courses in one ZIP file. The ZIP file contains one KML file per course, which you can open in Google Earth or CrewNerd and port to the new courses library supporting CrewNerd.
|
|
<iframe name="download_frame" style="display:none"></iframe>
|
|
</a>
|
|
<li>
|
|
{% endif %}
|
|
<li class="grid_4">
|
|
{% if courses %}
|
|
<p>
|
|
<form enctype="multipart/form-data" method="post">
|
|
{% csrf_token %}
|
|
<input name="courses" type="submit" value="Download selected courses">
|
|
Click on a column header to sort the table.
|
|
<table width="100%" class="listtable shortpadded" id="courseTable">
|
|
<thead>
|
|
<tr>
|
|
<th> Download</th>
|
|
<th onClick="sortTable(1)"> Country</th>
|
|
<th onClick="sortTable(2)"> Name</th>
|
|
<th onClick="sortTable(3)"> Distance</th>
|
|
<th onClick="sortTable(4)"> Updated on</th>
|
|
{% if not user.is_anonymous %}
|
|
<th onClick="sortTable(5)"> Like</th>
|
|
{% endif %}
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for course in courses %}
|
|
<tr>
|
|
<td> <input type="checkbox" value={{ course.id }} name="courseid"> </td>
|
|
<td> {{ course.country }} </td>
|
|
<td>
|
|
<a href="/rowers/courses/{{ course.id }}/">{{ course.name }}</a>
|
|
</td>
|
|
<td>
|
|
{{ course.distance }} m
|
|
</td>
|
|
<td>
|
|
{{ course.updated|date:"Y-m-d" }}
|
|
</td>
|
|
{% if not user.is_anonymous %}
|
|
<td>
|
|
{% if course in rower.followed_courses.all %}
|
|
<a class="unfollow" href="/rowers/courses/{{ course.id }}/unfollow"><span class="icon"><i class="fas fa-heart"></i></span></a>
|
|
{% else %}
|
|
<a class="follow" href="/rowers/courses/{{ course.id }}/follow"><span class="icon"><i class="far fa-heart"></i></span></a>
|
|
{% endif %}
|
|
</tr>
|
|
{% endif %}
|
|
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</form>
|
|
</p>
|
|
{% else %}
|
|
<p> No courses found </p>
|
|
{% endif %}
|
|
</li>
|
|
<li>
|
|
<a href="/rowers/courses/upload/">Add Courses</a>
|
|
</li>
|
|
|
|
<li class="grid_4">
|
|
<h2>How-to</h2>
|
|
<p>
|
|
|
|
To create a course, you use <a href="https://www.google.com/earth/">Google Earth</a>
|
|
to mark the start and finish lines using polygons. The process is identical
|
|
to creating custom courses for the
|
|
<a href="http://performancephones.com/crewnerd/">CrewNerd</a>
|
|
app.
|
|
|
|
</p>
|
|
|
|
<p>CrewNerd has published a nice video tutorial of the process.
|
|
<a href="https://youtu.be/whhWFmMJbhM">Click here</a> to see the video. The part
|
|
we're interested in starts at 2:05.
|
|
There is also a <a href="https://performancephones.com/custom-courses/">written tutorial</a> by CrewNerd.
|
|
</p>
|
|
|
|
<p>
|
|
In addition to start and finish areas, on rowsandall.com you can add additional
|
|
polygons to mark areas that you must pass (in that order). This allows for
|
|
courses with turns around buoys, respecting buoy lines, or respecting traffic
|
|
patterns on rivers and lakes.
|
|
</p>
|
|
|
|
<p>
|
|
<ul>
|
|
<li>Open Google Earth</li>
|
|
<li>Create a folder "Courses" under "Temporary Places" or under "My Places"</li>
|
|
<li>Create a folder for each Course under "Courses", and for each course:</li>
|
|
<li>Create Start polygon</li>
|
|
<li>Optional: Create First "must row through" polygon</li>
|
|
<li>Optional: Create subsequent "must row through" polygons</li>
|
|
<li>Create Finish polygon</li>
|
|
<li>Save "Courses" as KML file</li>
|
|
<li>Upload the file to rowsandall.com using the "Add Courses" button</li>
|
|
</ul>
|
|
</p>
|
|
|
|
<p>You are allowed to have multiple courses in one KML file.
|
|
Your CrewNerd "courses.kml" file works out of the box</p>
|
|
|
|
<p>The site doesn't test for duplicate courses.</p>
|
|
|
|
</li>
|
|
</ul>
|
|
|
|
<script type='text/javascript'
|
|
src='https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js'>
|
|
</script>
|
|
<script>
|
|
$(document).ready(function() {
|
|
$(document).on('click', 'a.follow', function(event) {
|
|
event.preventDefault();
|
|
var ajaxEndpoint = $(this).attr('href');
|
|
var $ajaxLink = $(this);
|
|
var id = ajaxEndpoint.split('/').slice(-2, -1)[0];
|
|
console.log(id, ajaxEndpoint)
|
|
|
|
$.ajax({
|
|
url: ajaxEndpoint,
|
|
method: 'GET',
|
|
success: function(response) {
|
|
console.log(response);
|
|
$ajaxLink.removeClass('follow').addClass('unfollow');
|
|
$ajaxLink.attr('href', '/rowers/courses/' + id + '/unfollow')
|
|
$ajaxLink.find('i').removeClass('far').removeClass('fa-heart').addClass('fas').addClass('fa-heart'); // Change star icon to filled
|
|
$ajaxLink.find('.icon i').attr('class', 'fas fa-heart');
|
|
$ajaxLink.find('.icon i').html('');
|
|
$ajaxLink.html('<span class="icon"><i class="fas fa-heart"></i></span>');
|
|
|
|
},
|
|
error: function(xhr, status, error) {
|
|
console.error(error);
|
|
}
|
|
|
|
});
|
|
});
|
|
$(document).on('click', 'a.unfollow', function(event) {
|
|
event.preventDefault();
|
|
var ajaxEndpoint = $(this).attr('href');
|
|
var $ajaxLink = $(this);
|
|
var id = ajaxEndpoint.split('/').slice(-2, -1)[0];
|
|
console.log(id, ajaxEndpoint)
|
|
|
|
$.ajax({
|
|
url: ajaxEndpoint,
|
|
method: 'GET',
|
|
success: function(response) {
|
|
console.log(response);
|
|
$ajaxLink.removeClass('unfollow').addClass('follow');
|
|
$ajaxLink.attr('href', '/rowers/courses/' + id + '/follow')
|
|
$ajaxLink.find('i').removeClass('fas').removeClass('fa-heart').addClass('far').addClass('fa-heart'); // Change star icon to outline
|
|
$ajaxLink.find('.icon i').attr('class', 'far fa-heart');
|
|
$ajaxLink.find('.icon i').html('');
|
|
$ajaxLink.html('<span class="icon"><i class="far fa-heart"></i></span>');
|
|
},
|
|
error: function(xhr, status, error) {
|
|
console.error(error);
|
|
}
|
|
|
|
});
|
|
});
|
|
|
|
|
|
});
|
|
</script>
|
|
<script>
|
|
var ascending = true;
|
|
|
|
function sortTable(col) {
|
|
var table, rows, switching, i, x, y, shouldSwitch;
|
|
table = document.getElementById("courseTable");
|
|
switching = true;
|
|
while (switching) {
|
|
switching = false;
|
|
rows = table.rows;
|
|
for (i = 1; i < (rows.length - 1); i++) {
|
|
shouldSwitch = false;
|
|
x = rows[i].getElementsByTagName("td")[col];
|
|
y = rows[i + 1].getElementsByTagName("td")[col];
|
|
if (ascending) {
|
|
if (x.innerHTML.toLowerCase() > y.innerHTML.toLowerCase()) {
|
|
shouldSwitch = true;
|
|
break;
|
|
}
|
|
} else {
|
|
if (x.innerHTML.toLowerCase() < y.innerHTML.toLowerCase()) {
|
|
shouldSwitch = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (shouldSwitch) {
|
|
rows[i].parentNode.insertBefore(rows[i + 1], rows[i]);
|
|
switching = true;
|
|
}
|
|
}
|
|
ascending = !ascending; // Reverse the sorting order
|
|
}
|
|
</script>
|
|
{% endblock %}
|
|
|
|
{% block sidebar %}
|
|
{% include 'menu_racing.html' %}
|
|
{% endblock %}
|