source: OpenWorkouts-current/ow/templates/profile.pt

current
Last change on this file was 4678c5e, checked in by Borja Lopez <borja@…>, 5 years ago

(#71) Keep the "distance/time/elevation" filter when clicking on bars
in the profile yearly stats chart

  • Property mode set to 100644
File size: 23.9 KB
Line 
1<html xmlns="http://www.w3.org/1999/xhtml"
2      xml:lang="en"
3      xmlns:tal="http://xml.zope.org/namespaces/tal"
4      xmlns:metal="http://xml.zope.org/namespaces/metal"
5      xmlns:i18n="http://xml.zope.org/namespaces/i18n"
6      i18n:domain="OpenWorkouts"
7      metal:use-macro="load: base.pt"
8      tal:attributes="lang request.locale_name">
9
10  <metal:head-title metal:fill-slot="head-title">
11    <tal:t i18n:translate="">My profile</tal:t>
12  </metal:head-title>
13
14  <metal:css metal:fill-slot="css">
15    <link rel="stylesheet" href="${request.static_url('ow:static/components/jquery-dropdown/jquery.dropdown.css')}" />
16  </metal:css>
17
18  <metal:content metal:fill-slot="content">
19
20    <div class="user-profile">
21      <div class="user-profile-account">
22        <div>
23          <tal:c tal:condition="getattr(user, 'picture', None)">
24            <img tal:attributes="src request.resource_path(user, 'picture', query={'size': 200})"
25                 width="450" />
26          </tal:c>
27          <div>
28            <h2>
29              <tal:fullname tal:content="user.fullname"></tal:fullname>
30            </h2>
31            <p>
32              <tal:has-nickname tal:condition="user.nickname">
33                <a href=""
34                   tal:attributes="href request.resource_url(request.root, 'profile', user.nickname)"
35                   tal:content="request.resource_url(request.root, 'profile', user.nickname)">
36                </a> |
37              </tal:has-nickname>
38              <span><tal:email tal:content="user.email"></tal:email></span>
39            </p>
40            <div class="profile-bio">
41              <p tal:repeat="paragraph getattr(user, 'bio', '').split('\n')"
42                 tal:content="paragraph"></p>
43            </div>
44            <ul class="workout-options">
45              <li><a href=""
46                     tal:attributes="href request.resource_url(user, 'edit')"
47                     i18n:translate="">edit profile</a></li>
48              <li><a href=""
49                     tal:attributes="href request.resource_url(user, 'passwd')"
50                     i18n:translate="">change password</a></li>
51            </ul>
52          </div>
53          <div class="calendar-heatmap js-calendar-heatmap">
54          </div>
55          <div class="calendar-heatmap-tooltip js-ch-tooltip">
56            <ul class="profile-data">
57              <li>
58                <span class="js-ch-tooltip-date"></span>
59              </li>
60              <li>
61                <span><tal:t i18n:translate="">Workouts:</tal:t></span>
62                <span class="js-ch-tooltip-workouts"></span>
63              </li>
64              <li>
65                <span><tal:t i18n:translate="">Time:</tal:t></span>
66                <span class="js-ch-tooltip-time"></span>
67              </li>
68              <li>
69                <span><tal:t i18n:translate="">Distance:</tal:t></span>
70                <span class="js-ch-tooltip-distance"></span>
71              </li>
72              <li>
73                <span><tal:t i18n:translate="">Elevation:</tal:t></span>
74                <span class="js-ch-tooltip-elevation"></span>
75              </li>
76            </ul>
77          </div>
78        </div>
79
80      </div>
81
82      <div class="workout-content">
83        <div class="workout-list">
84          <div class="total-workouts">
85            <span>
86              <tal:w tal:replace="len(workouts)"></tal:w>
87              <tal:t i18n:translate="">workouts</tal:t>
88            </span>
89            <span>
90              <tal:hms tal:define="hms timedelta_to_hms(totals['time'])">
91                <tal:h tal:content="str(hms[0]).zfill(2)"></tal:h>
92                <tal:t i18n:translate="">hours</tal:t>,
93                <tal:h tal:content="str(hms[1]).zfill(2)"></tal:h>
94                <tal:t i18n:translate="">min.</tal:t>
95              </tal:hms>
96            </span>
97            <span>
98              <tal:w tal:replace="round(totals['distance'])"></tal:w>
99              <tal:t i18n:translate="">km</tal:t>
100            </span>
101            <span>
102              <tal:w tal:replace="round(totals['elevation'])"></tal:w>
103              <tal:t i18n:translate="">m</tal:t>
104            </span>
105          </div>
106
107          <div class="month-stats js-month-stats">
108            <div class="svg-content">
109              <svg width="900" height="180" viewBox="0 0 900 180"></svg>
110            </div>
111            <div class="center">
112              <ul class="workout-options filters js-filters">
113                <li>
114                  <a href="#" class="js-distance is-active"
115                     tal:attributes="class 'js-distance is-active' if filter_by == 'distance' else 'js-distance'"
116                     i18n:translate="">distance</a>
117                </li>
118                <li>
119                  <a href="#" class="js-time"
120                     tal:attributes="class 'js-time is-active' if filter_by == 'time' else 'js-time'"
121                     i18n:translate="">time</a>
122                </li>
123                <li>
124                  <a href="#" class="js-elevation"
125                     tal:attributes="class 'js-elevation is-active' if filter_by == 'elevation' else 'js-elevation'"
126                     i18n:translate="">elevation</a>
127                </li>
128              </ul>
129
130              <ul class="workout-options switcher js-switcher"
131                  tal:define="weekly 'week' in request.GET">
132                <li>
133                  <a href="#" class="" i18n:translate=""
134                     tal:attributes="class 'js-weekly is-active' if weekly else 'js-weekly'">
135                    weekly</a></li>
136                <li>
137                  <a href="#" class="" i18n:translate=""
138                     tal:attributes="class 'js-monthly is-active' if not weekly else 'js-monthly'">
139                    monthly</a></li>
140              </ul>
141            </div>
142          </div>
143
144
145          <tal:r tal:repeat="workout workouts">
146
147            <article class="workout-resume">
148
149              <h2 class="workout-title">
150                <a href="" tal:content="workout.title"
151                   tal:attributes="href request.resource_url(workout)"></a>
152              </h2>
153
154              <ul class="workout-info">
155                <li>
156                  <tal:c tal:content="workout.start_in_timezone(user.timezone)"></tal:c>
157                </li>
158                <li>
159                  <!--! use the properly formatted duration instead of the timedelta object -->
160                  <tal:c tal:content="workout._duration"></tal:c>
161                </li>
162                <li tal:condition="workout.distance">
163                  <tal:c tal:content="workout.rounded_distance"></tal:c> km
164                </li>
165                <li tal:condition="workout.uphill">
166                  +<tal:c tal:content="workout.uphill"></tal:c> m
167                </li>
168              </ul>
169
170              <ul class="workout-info" tal:define="hr workout.hr; cad workout.cad">
171                <li tal:condition="hr">
172                  <span i18n:translate="">HR (bpm)</span>:
173                  <tal:c tal:content="hr['avg']"></tal:c>
174                  <tal:t i18n:translate="">Avg.</tal:t>,
175                  <tal:c tal:content="hr['max']"></tal:c>
176                  <tal:t i18n:translate="">Max.</tal:t>
177                </li>
178                <li tal:condition="cad">
179                  <span i18n:translate="">Cad</span>:
180                  <tal:c tal:content="cad['avg']"></tal:c>
181                  <tal:t i18n:translate="">Avg.</tal:t>,
182                  <tal:c tal:content="cad['max']"></tal:c>
183                  <tal:t i18n:translate="">Max.</tal:t>
184                </li>
185              </ul>
186
187              <div class="workout-intro">
188                <p tal:repeat="paragraph workout.trimmed_notes.split('\n')"
189                   tal:content="paragraph"></p>
190              </div>
191
192              <div class="workout-map" tal:condition="workout.has_gpx">
193                <a href="" tal:attributes="href request.resource_url(workout)">
194                  <tal:has-screenshot tal:condition="workout.map_screenshot is not None">
195                    <img src="" tal:attributes="src request.static_url(workout.map_screenshot);
196                              alt workout.title; title workout.title">
197                  </tal:has-screenshot>
198                  <tal:has-not-screenshot tal:condition="workout.map_screenshot is None">
199                    <img src="" tal:attributes="src request.static_url('ow:static/media/img/no_map.gif');
200                              alt workout.title; title workout.title; class 'js-needs-map'">
201                  </tal:has-not-screenshot>
202                </a>
203              </div>
204
205            </article>
206
207          </tal:r>
208        </div>
209
210        <div class="workout-aside">
211
212          <h3 i18n:translate="">Profile info</h3>
213
214          <ul class="profile-data">
215            <li>
216              <span><tal:t i18n:translate="">Gender:</tal:t></span>
217              <tal:c tal:content="user_gender"></tal:c>
218            </li>
219            <li tal:define="birth_date getattr(user, 'birth_date', None)">
220              <span><tal:t i18n:translate="">Birth date:</tal:t></span>
221              <tal:c tal:condition="birth_date"
222                     tal:content="birth_date.strftime('%d/%m/%Y')"></tal:c>
223              <tal:c tal:condition="birth_date is None">-</tal:c>
224            </li>
225            <li>
226              <span><tal:t i18n:translate="">Height:</tal:t></span>
227              <tal:c tal:content="getattr(user, 'height', '-')"></tal:c> meters
228            </li>
229            <li>
230              <span><tal:t i18n:translate="">Weight:</tal:t></span>
231              <tal:c tal:content="getattr(user, 'weight', '-')"></tal:c> kg
232            </li>
233          </ul>
234
235          <tal:has-workouts tal:condition="profile_stats['sports']">
236
237            <h3 i18n:translate="">Workout stats</h3>
238
239            <p>
240              <a href="" data-jq-dropdown="#jq-dropdown-sports"
241                 class="profile-dropdown-sports js-jq-dropdown-sel-sports">
242                <strong tal:content="profile_stats['current_sport']"></strong>
243                <i class="arrow down"></i>
244              </a>
245            </p>
246
247            <tal:sports tal:repeat="sport profile_stats['sports']">
248              <div class="" tal:attributes="class 'js-sport-stats js-' + sport">
249
250                <a href="" data-jq-dropdown=""
251                   tal:attributes="data-jq-dropdown '#jq-dropdown-' + sport;
252                         class 'profile-dropdown-years js-jq-dropdown-sel-' + sport">
253                  <strong tal:content="profile_stats['current_year']"></strong>
254                  <i class="arrow down"></i>
255                </a>
256
257                <tal:years tal:repeat="year profile_stats['years']">
258                  <div class="" tal:attributes="class 'js-year-stats js-' + sport + '-' + str(year)">
259                    <ul class="profile-data"
260                        tal:define="sport_totals user.sport_totals(sport, year)">
261                      <li>
262                        <span>
263                          <tal:t i18n:translate="">Workouts</tal:t>
264                        </span>
265                        <tal:w tal:replace="sport_totals['workouts']"></tal:w>
266                      </li>
267                      <li>
268                        <span>
269                          <tal:t i18n:translate="">Time</tal:t>
270                        </span>
271                        <tal:hms tal:define="hms timedelta_to_hms(sport_totals['time'])">
272                          <tal:h tal:content="str(hms[0]).zfill(2)"></tal:h>
273                          <tal:t i18n:translate="">hours</tal:t>,
274                          <tal:h tal:content="str(hms[1]).zfill(2)"></tal:h>
275                          <tal:t i18n:translate="">min.</tal:t>
276                        </tal:hms>
277                      </li>
278                      <li>
279                        <span>
280                          <tal:t i18n:translate="">Distance</tal:t>
281                        </span>
282                        <tal:w tal:replace="round(sport_totals['distance'])"></tal:w>
283                        <tal:t i18n:translate="">km</tal:t>
284                      </li>
285                      <li>
286                        <span>
287                          <tal:t i18n:translate="">Elevation</tal:t>
288                        </span>
289                        <tal:w tal:replace="round(sport_totals['elevation'])"></tal:w>
290                        <tal:t i18n:translate="">m</tal:t>
291                      </li>
292                      <li><span i18n:translate="">Single workout records:</span></li>
293                      <li>
294                        <span>
295                          <tal:t i18n:translate="">Farthest distance</tal:t>
296                        </span>
297                        <tal:has-wid tal:condition="sport_totals['max_distance_wid'] is not None">
298                          <a href="" tal:attributes="href request.resource_url(user[sport_totals['max_distance_wid']])">
299                            <tal:w tal:replace="round(sport_totals['max_distance'])"></tal:w>
300                            <tal:t i18n:translate="">km</tal:t>
301                          </a>
302                        </tal:has-wid>
303                        <tal:has-not-wid tal:condition="sport_totals['max_distance_wid'] is None">
304                          <tal:w tal:replace="round(sport_totals['max_distance'])"></tal:w>
305                          <tal:t i18n:translate="">km</tal:t>
306                        </tal:has-not-wid>
307                      </li>
308                      <li>
309                        <span>
310                          <tal:t i18n:translate="">Longer workout</tal:t>
311                        </span>
312                        <tal:has-wid tal:condition="sport_totals['max_time_wid'] is not None">
313                          <a href="" tal:attributes="href request.resource_url(user[sport_totals['max_time_wid']])">
314                            <tal:hms tal:define="hms timedelta_to_hms(sport_totals['max_time'])">
315                              <tal:h tal:content="str(hms[0]).zfill(2)"></tal:h>
316                              <tal:t i18n:translate="">hours</tal:t>,
317                              <tal:h tal:content="str(hms[1]).zfill(2)"></tal:h>
318                              <tal:t i18n:translate="">min.</tal:t>
319                            </tal:hms>
320                          </a>
321                        </tal:has-wid>
322                        <tal:has-not-wid tal:condition="sport_totals['max_time_wid'] is None">
323                          <tal:hms tal:define="hms timedelta_to_hms(sport_totals['max_time'])">
324                            <tal:h tal:content="str(hms[0]).zfill(2)"></tal:h>
325                            <tal:t i18n:translate="">hours</tal:t>,
326                            <tal:h tal:content="str(hms[1]).zfill(2)"></tal:h>
327                            <tal:t i18n:translate="">min.</tal:t>
328                          </tal:hms>
329                        </tal:has-not-wid>
330                      </li>
331                      <li>
332                        <span>
333                          <tal:t i18n:translate="">Higher elevation gain</tal:t>
334                        </span>
335                        <tal:has-wid tal:condition="sport_totals['max_elevation_wid'] is not None">
336                          <a href="" tal:attributes="href request.resource_url(user[sport_totals['max_elevation_wid']])">
337                            <tal:w tal:replace="round(sport_totals['max_elevation'])"></tal:w>
338                            <tal:t i18n:translate="">m</tal:t>
339                          </a>
340                        </tal:has-wid>
341                        <tal:has-not-wid tal:condition="sport_totals['max_elevation_wid'] is None">
342                          <tal:w tal:replace="round(sport_totals['max_elevation'])"></tal:w>
343                          <tal:t i18n:translate="">m</tal:t>
344                        </tal:has-not-wid>
345                      </li>
346                    </ul>
347                  </div>
348                </tal:years>
349
350                <strong i18n:translate="">All time</strong>
351                <ul class="profile-data"
352                    tal:define="sport_totals user.sport_totals(sport)">
353                  <li>
354                    <span>
355                      <tal:t i18n:translate="">Workouts</tal:t>
356                    </span>
357                    <tal:w tal:replace="sport_totals['workouts']"></tal:w>
358                  </li>
359                  <li>
360                    <span>
361                      <tal:t i18n:translate="">Time</tal:t>
362                    </span>
363                    <tal:hms tal:define="hms timedelta_to_hms(sport_totals['time'])">
364                      <tal:h tal:content="str(hms[0]).zfill(2)"></tal:h>
365                      <tal:t i18n:translate="">hours</tal:t>,
366                      <tal:h tal:content="str(hms[1]).zfill(2)"></tal:h>
367                      <tal:t i18n:translate="">min.</tal:t>
368                    </tal:hms>
369                  </li>
370                  <li>
371                    <span>
372                      <tal:t i18n:translate="">Distance</tal:t>
373                    </span>
374                    <tal:w tal:replace="round(sport_totals['distance'])"></tal:w>
375                    <tal:t i18n:translate="">km</tal:t>
376                  </li>
377                  <li>
378                    <span>
379                      <tal:t i18n:translate="">Elevation</tal:t>
380                    </span>
381                    <tal:w tal:replace="round(sport_totals['elevation'])"></tal:w>
382                    <tal:t i18n:translate="">m</tal:t>
383                  </li>
384                  <li><span i18n:translate="">Single workout records:</span></li>
385                  <li>
386                    <span>
387                      <tal:t i18n:translate="">Farthest distance</tal:t>
388                    </span>
389                    <tal:has-wid tal:condition="sport_totals['max_distance_wid'] is not None">
390                      <a href="" tal:attributes="href request.resource_url(user[sport_totals['max_distance_wid']])">
391                        <tal:w tal:replace="round(sport_totals['max_distance'])"></tal:w>
392                        <tal:t i18n:translate="">km</tal:t>
393                      </a>
394                    </tal:has-wid>
395                    <tal:has-not-wid tal:condition="sport_totals['max_distance_wid'] is None">
396                      <tal:w tal:replace="round(sport_totals['max_distance'])"></tal:w>
397                      <tal:t i18n:translate="">km</tal:t>
398                    </tal:has-not-wid>
399                  </li>
400                  <li>
401                    <span>
402                      <tal:t i18n:translate="">Longer workout</tal:t>
403                    </span>
404                    <tal:has-wid tal:condition="sport_totals['max_time_wid'] is not None">
405                      <a href="" tal:attributes="href request.resource_url(user[sport_totals['max_time_wid']])">
406                        <tal:hms tal:define="hms timedelta_to_hms(sport_totals['max_time'])">
407                          <tal:h tal:content="str(hms[0]).zfill(2)"></tal:h>
408                          <tal:t i18n:translate="">hours</tal:t>,
409                          <tal:h tal:content="str(hms[1]).zfill(2)"></tal:h>
410                          <tal:t i18n:translate="">min.</tal:t>
411                        </tal:hms>
412                      </a>
413                    </tal:has-wid>
414                    <tal:has-not-wid tal:condition="sport_totals['max_time_wid'] is None">
415                      <tal:hms tal:define="hms timedelta_to_hms(sport_totals['max_time'])">
416                        <tal:h tal:content="str(hms[0]).zfill(2)"></tal:h>
417                        <tal:t i18n:translate="">hours</tal:t>,
418                        <tal:h tal:content="str(hms[1]).zfill(2)"></tal:h>
419                        <tal:t i18n:translate="">min.</tal:t>
420                      </tal:hms>
421                    </tal:has-not-wid>
422                  </li>
423                  <li>
424                    <span>
425                      <tal:t i18n:translate="">Higher elevation gain</tal:t>
426                    </span>
427                    <tal:has-wid tal:condition="sport_totals['max_elevation_wid'] is not None">
428                      <a href="" tal:attributes="href request.resource_url(user[sport_totals['max_elevation_wid']])">
429                        <tal:w tal:replace="round(sport_totals['max_elevation'])"></tal:w>
430                        <tal:t i18n:translate="">m</tal:t>
431                      </a>
432                    </tal:has-wid>
433                    <tal:has-not-wid tal:condition="sport_totals['max_elevation_wid'] is None">
434                      <tal:w tal:replace="round(sport_totals['max_elevation'])"></tal:w>
435                      <tal:t i18n:translate="">m</tal:t>
436                    </tal:has-not-wid>
437                  </li>
438                </ul>
439              </div>
440            </tal:sports>
441
442          </tal:has-workouts>
443
444        </div>
445      </div>
446    </div>
447
448      <div id="jq-dropdown-sports" class="jq-dropdown jq-dropdown-tip">
449        <ul class="jq-dropdown-menu">
450          <tal:sports tal:repeat="sport profile_stats['sports']">
451            <li>
452              <a href="#" class="" tal:content="sport"
453                 tal:attributes="class 'js-choose-sport-stats js-' + sport">
454              </a>
455            </li>
456          </tal:sports>
457        </ul>
458      </div>
459
460
461    <tal:sports tal:repeat="sport profile_stats['sports']">
462      <div id="" class="jq-dropdown jq-dropdown-tip"
463           tal:attributes="id 'jq-dropdown-' + sport">
464        <ul class="jq-dropdown-menu">
465          <tal:years tal:repeat="year profile_stats['years']">
466            <li>
467              <a href="#" class="" tal:content="year"
468                 tal:attributes="class 'js-choose-year-stats js-' + sport + '-' + str(year)">
469              </a>
470            </li>
471          </tal:years>
472        </ul>
473      </div>
474    </tal:sports>
475
476
477  </metal:content>
478
479  <metal:body-js metal:fill-slot="body-js">
480
481    <script src="${request.static_url('ow:static/components/jquery-dropdown/jquery.dropdown.js')}"></script>
482    <script src="${request.static_url('ow:static/components/d3/d3.min.js')}"></script>
483    <script src="${request.static_url('ow:static/js/ow.js')}"></script>
484
485    <script type="text/javascript">
486     var map_shots = owjs.map_shots({
487         img_selector: 'img.js-needs-map',
488     })
489     map_shots.run();
490
491     var sport_stats = owjs.sport_stats({
492         link_selector: 'a.js-choose-sport-stats',
493         stats_selector: 'div.js-sport-stats',
494         selected: 'div.js-sport-stats.js-${profile_stats['current_sport']}',
495         dropdown_selector: 'a.js-jq-dropdown-sel-sports',
496         current_year: '${profile_stats['current_year']}',
497         year_link_selector: 'a.js-choose-year-stats.js-'
498     })
499     sport_stats.setup();
500
501     var heatmap_chart = owjs.calendar_heatmap_chart({
502         chart_selector: 'div.js-calendar-heatmap',
503         tooltip_selector: '.js-ch-tooltip',
504         url: "${request.resource_url(user, 'month')}",
505         // Trick to have all those shortened day names translated
506         day_names_list: "${_('Mo Tu We Th Fr Sa Su')}".split(' ')
507     });
508     heatmap_chart.render();
509
510     var year_stats = owjs.year_stats({
511         link_selector: 'a.js-choose-year-stats',
512         stats_selector: 'div.js-year-stats',
513         selected: 'div.js-year-stats.js-${profile_stats['current_sport']}-${profile_stats['current_year']}',
514         dropdown_selector: 'a.js-jq-dropdown-sel-'
515     })
516     year_stats.setup();
517
518     var y_axis_labels = {
519         "distance": "Kilometers",
520         "time": "Hours",
521         "elevation": "Meters"
522     };
523
524     var year_chart = owjs.year_chart({
525         chart_selector: '.js-month-stats svg',
526         filters_selector: '.js-month-stats .js-filters a',
527         switcher_selector: '.js-month-stats .js-switcher a',
528         is_active_class: 'is-active',
529         urls: {"monthly": "${request.resource_url(user, 'monthly')}",
530                "weekly": "${request.resource_url(user, 'weekly')}"},
531         current_month: "${current_month}",
532         current_week: "${current_week}",
533         y_axis_labels: y_axis_labels,
534         filter_by: "${filter_by}",
535         url: "${'monthly' if current_week is None else 'weekly'}",
536     });
537     year_chart.render("${filter_by}", "${'monthly' if current_week is None else 'weekly'}");
538     year_chart.filters_setup();
539     year_chart.switcher_setup();
540    </script>
541
542  </metal:body-js>
543
544</html>
Note: See TracBrowser for help on using the repository browser.