Changeset 778d53d in OpenWorkouts-current


Ignore:
Timestamp:
Mar 5, 2019, 11:45:32 PM (5 years ago)
Author:
Borja Lopez <borja@…>
Branches:
current
Children:
aa6dcaf
Parents:
35953eb
Message:

(#7) Show per-sport stats in the profile page:

  • Show a dropdown list of sports for which the user has activities. By default we choose the sport with most activities.
  • Show a dropdown list of years for which the user has activities. By default we show stats for the current year. If the user picks up a different year, we show the totals (distance, time, elevation, number of workouts) for that year.
  • Show the totals of all time for the chosen sport
Files:
1 added
10 edited

Legend:

Unmodified
Added
Removed
  • bin/js_deps

    r35953eb r778d53d  
    251251}
    252252
     253jquery_dropdown() {
     254    # We need version "master", as the latest release does not work properly
     255    NAME="jquery-dropdown"
     256    VERSION=master
     257    URL=https://github.com/soundasleep/${NAME}/archive/${VERSION}.tar.gz
     258    check_cache ${NAME} ${VERSION}
     259    in_cache=$?
     260    if [ ${in_cache} -eq 0 -a ${REINSTALL} -eq 1 ]; then
     261        echo "${NAME}-${VERSION} $ALREADY_INSTALLED"
     262    else
     263        echo "> Installing ${NAME} ${VERSION}"
     264        if [ -d ${COMPONENTS}/${NAME} ]; then
     265            # Clean up, delete previous install before installing
     266            rm -r ${COMPONENTS}/${NAME}
     267        fi
     268        mkdir ${COMPONENTS}/${NAME}
     269        cd ${TMP}
     270        ${GET} ${URL}
     271        ${TAR} ${VERSION}.tar.gz
     272        cd ${CURRENT}
     273        mv ${TMP}/${NAME}-${VERSION}/jquery.dropdown.{css,js} ${COMPONENTS}/${NAME}
     274        echo "${NAME}-${VERSION}" >> ${CACHE}
     275        echo "< Installed ${NAME} ${VERSION}"
     276    fi
     277}
     278
    253279
    254280echo "Installing JS dependencies in ${COMPONENTS}"
     
    261287pickadate
    262288d3
     289jquery_dropdown
    263290
    264291
  • ow/models/user.py

    r35953eb r778d53d  
    113113    def num_workouts(self):
    114114        return len(self.workout_ids())
     115
     116    @property
     117    def favorite_sport(self):
     118        """
     119        Return which sport is the one with most workouts for this user.
     120        In case of more than one sport with the maximum number of workouts,
     121        return the first in reversed alphabetical ordering
     122        """
     123        sports = {}
     124        for w in self.workouts():
     125            if w.sport not in sports.keys():
     126                sports[w.sport] = 0
     127            sports[w.sport] += 1
     128        _sports = sorted(sports.items(), reverse=True,
     129                         key=lambda x: (x[1], x[0]))
     130        if _sports:
     131            return _sports[0][0]
     132        return None
     133
     134    @property
     135    def activity_sports(self):
     136        return sorted(list(set(w.sport for w in self.workouts())))
    115137
    116138    @property
     
    368390
    369391        return stats
     392
     393    def sport_totals(self, sport=None, year=None):
     394        """
     395        Return totals for this user, filtered by sport.
     396
     397        If no sport is passed, the favorite sport is picked up
     398
     399        If the additional parameter year is passed, show stats only
     400        for that year
     401        """
     402        totals = {
     403            'workouts': 0,
     404            'time': timedelta(0),
     405            'distance': Decimal(0),
     406            'elevation': Decimal(0),
     407        }
     408        if self.activity_sports:
     409            sport = sport or self.favorite_sport
     410            for workout in self.workouts():
     411                if workout.sport == sport:
     412                    if year is None or workout.start.year == year:
     413                        totals['workouts'] += 1
     414                        totals['time'] += workout.duration or timedelta(0)
     415                        totals['distance'] += workout.distance or Decimal(0)
     416                        totals['elevation'] += workout.uphill or Decimal(0)
     417        return totals
  • ow/static/css/main.css

    r35953eb r778d53d  
    642642  background-color: #EE4056;
    643643}
     644/*
     645Very simple way to paint dropdown-like arrows, without
     646using any external dependencies.
     647
     648To use it, add something like this to your html, to display a "down" arrow:
     649
     650  <i class="arrow down"></i>
     651*/
     652i.arrow {
     653  border: solid black;
     654  border-width: 0 3px 3px 0;
     655  display: inline-block;
     656  padding: 3px;
     657  margin: 3px;
     658  margin-left: 6px;
     659  margin-right: 0px;
     660}
     661.right {
     662  transform: rotate(-45deg);
     663  -webkit-transform: rotate(-45deg);
     664}
     665.left {
     666  transform: rotate(135deg);
     667  -webkit-transform: rotate(135deg);
     668}
     669.up {
     670  transform: rotate(-135deg);
     671  -webkit-transform: rotate(-135deg);
     672}
     673.down {
     674  transform: rotate(45deg);
     675  -webkit-transform: rotate(45deg);
     676}
    644677.header-content {
    645678  padding: 1em 1.5em;
     
    14881521  font-size: 13px;
    14891522  font-size: 0.8125rem;
     1523}
     1524.profile-dropdown-sports,
     1525.profile-dropdown-years {
     1526  color: #151515;
     1527  text-decoration: none;
     1528}
     1529.profile-dropdown-sports:hover,
     1530.profile-dropdown-years:hover {
     1531  color: #151515;
     1532}
     1533.profile-dropdown-sports:active,
     1534.profile-dropdown-years:active,
     1535.profile-dropdown-sports:focus,
     1536.profile-dropdown-years:focus {
     1537  outline: 0;
     1538  border: none;
     1539  -moz-outline-style: none;
    14901540}
    14911541.verify-account-content {
  • ow/static/js/ow.js

    r35953eb r778d53d  
    486486
    487487};
     488
     489
     490owjs.sport_stats = function(spec) {
     491
     492    "use strict";
     493
     494    var link_selector = spec.link_selector;
     495    var stats_selector = spec.stats_selector;
     496    var selected = spec.selected;
     497    var dropdown_selector = spec.dropdown_selector;
     498    var current_year = spec.current_year;
     499    var year_link_selector = spec.year_link_selector;
     500
     501    var setup = function setup() {
     502        // Hide all sports stats by default
     503        $(stats_selector).hide();
     504        // Show the pre-selected one
     505        $(selected).show();
     506
     507        $(link_selector).on('click', function(e) {
     508            e.preventDefault();
     509            var selected = $(this).attr('class').split(' ')[1];
     510            var sport = selected.split('-')[1]
     511            // Hide them all
     512            $(stats_selector).hide();
     513            // Show the selected one
     514            $(stats_selector + '.' + selected).show();
     515            // Update the sport on the sports selector widget
     516            $(dropdown_selector + ' strong').html(sport);
     517            // finally "click" on the proper year to be displayed for this sport
     518            $(year_link_selector + sport + '-' + current_year).click();
     519        });
     520    };
     521
     522    var that = {}
     523    that.setup = setup;
     524    return that
     525
     526};
     527
     528
     529owjs.year_stats = function(spec) {
     530
     531    "use strict";
     532
     533    var link_selector = spec.link_selector;
     534    var stats_selector = spec.stats_selector;
     535    var selected = spec.selected;
     536    var dropdown_selector = spec.dropdown_selector;
     537
     538    var setup = function setup() {
     539        // Hide all years stats by default
     540        $(stats_selector).hide();
     541        // Show the pre-selected one
     542        $(selected).show();
     543
     544        $(link_selector).on('click', function(e) {
     545            e.preventDefault();
     546            var selected = $(this).attr('class').split(' ')[1];
     547            var sport = selected.split('-')[1]
     548            var year = selected.split('-')[2]
     549            // Hide them all
     550            $(stats_selector).hide();
     551            // Show the selected one
     552            $(stats_selector + '.' + selected).show();
     553            // Update the year on the years selector widget
     554            $(dropdown_selector + sport + ' strong').html(year);
     555        });
     556    };
     557
     558    var that = {}
     559    that.setup = setup;
     560    return that
     561
     562};
  • ow/static/less/main.less

    r35953eb r778d53d  
    2323@import "ui/form.less";
    2424@import "ui/buttons.less";
     25@import "ui/arrows.less";
    2526
    2627// Modules
  • ow/static/less/pages/profile.less

    r35953eb r778d53d  
    128128        }
    129129}
     130
     131.profile-dropdown-sports,
     132.profile-dropdown-years {
     133    color: @color-main;
     134    text-decoration: none;
     135    &:hover {
     136        color: @color-main;
     137    }
     138    &:active, &:focus {
     139        outline: 0;
     140        border: none;
     141        -moz-outline-style: none;
     142    }
     143}
  • ow/templates/profile.pt

    r35953eb r778d53d  
    1111    <tal:t i18n:translate="">My profile</tal:t>
    1212  </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>
    1317
    1418  <metal:content metal:fill-slot="content">
     
    168172
    169173        <div class="workout-aside">
     174
     175          <h3 i18n:translate="">Profile info</h3>
     176
    170177          <ul class="profile-data">
    171178            <li>
     
    188195            </li>
    189196          </ul>
     197
     198          <tal:has-workouts tal:condition="profile_stats['sports']">
     199
     200            <h3 i18n:translate="">Workout stats</h3>
     201
     202            <p>
     203              <a href="" data-jq-dropdown="#jq-dropdown-sports"
     204                 class="profile-dropdown-sports js-jq-dropdown-sel-sports">
     205                <strong tal:content="profile_stats['current_sport']"></strong>
     206                <i class="arrow down"></i>
     207              </a>
     208            </p>
     209
     210            <tal:sports tal:repeat="sport profile_stats['sports']">
     211              <div class="" tal:attributes="class 'js-sport-stats js-' + sport">
     212
     213                <a href="" data-jq-dropdown=""
     214                   tal:attributes="data-jq-dropdown '#jq-dropdown-' + sport;
     215                         class 'profile-dropdown-years js-jq-dropdown-sel-' + sport">
     216                  <strong tal:content="profile_stats['current_year']"></strong>
     217                  <i class="arrow down"></i>
     218                </a>
     219
     220                <tal:years tal:repeat="year profile_stats['years']">
     221                  <div class="" tal:attributes="class 'js-year-stats js-' + sport + '-' + str(year)">
     222                    <ul class="profile-data"
     223                        tal:define="sport_totals context.sport_totals(sport, year)">
     224                      <li>
     225                        <span>
     226                          <tal:t i18n:translate="">Workouts</tal:t>
     227                        </span>
     228                        <tal:w tal:replace="sport_totals['workouts']"></tal:w>
     229                      </li>
     230                      <li>
     231                        <span>
     232                          <tal:t i18n:translate="">Time</tal:t>
     233                        </span>
     234                        <tal:hms tal:define="hms timedelta_to_hms(sport_totals['time'])">
     235                          <tal:h tal:content="str(hms[0]).zfill(2)"></tal:h>
     236                          <tal:t i18n:translate="">hours</tal:t>,
     237                          <tal:h tal:content="str(hms[1]).zfill(2)"></tal:h>
     238                          <tal:t i18n:translate="">min.</tal:t>
     239                        </tal:hms>
     240                      </li>
     241                      <li>
     242                        <span>
     243                          <tal:t i18n:translate="">Distance</tal:t>
     244                        </span>
     245                        <tal:w tal:replace="round(sport_totals['distance'])"></tal:w>
     246                        <tal:t i18n:translate="">km</tal:t>
     247                      </li>
     248                      <li>
     249                        <span>
     250                          <tal:t i18n:translate="">Elevation</tal:t>
     251                        </span>
     252                        <tal:w tal:replace="round(sport_totals['elevation'])"></tal:w>
     253                        <tal:t i18n:translate="">m</tal:t>
     254                      </li>
     255                    </ul>
     256                  </div>
     257                </tal:years>
     258
     259                <strong i18n:translate="">All time</strong>
     260                <ul class="profile-data"
     261                    tal:define="sport_totals context.sport_totals(sport)">
     262                  <li>
     263                    <span>
     264                      <tal:t i18n:translate="">Workouts</tal:t>
     265                    </span>
     266                    <tal:w tal:replace="sport_totals['workouts']"></tal:w>
     267                  </li>
     268                  <li>
     269                    <span>
     270                      <tal:t i18n:translate="">Time</tal:t>
     271                    </span>
     272                    <tal:hms tal:define="hms timedelta_to_hms(sport_totals['time'])">
     273                      <tal:h tal:content="str(hms[0]).zfill(2)"></tal:h>
     274                      <tal:t i18n:translate="">hours</tal:t>,
     275                      <tal:h tal:content="str(hms[1]).zfill(2)"></tal:h>
     276                      <tal:t i18n:translate="">min.</tal:t>
     277                    </tal:hms>
     278                  </li>
     279                  <li>
     280                    <span>
     281                      <tal:t i18n:translate="">Distance</tal:t>
     282                    </span>
     283                    <tal:w tal:replace="round(sport_totals['distance'])"></tal:w>
     284                    <tal:t i18n:translate="">km</tal:t>
     285                  </li>
     286                  <li>
     287                    <span>
     288                      <tal:t i18n:translate="">Elevation</tal:t>
     289                    </span>
     290                    <tal:w tal:replace="round(sport_totals['elevation'])"></tal:w>
     291                    <tal:t i18n:translate="">m</tal:t>
     292                  </li>
     293                </ul>
     294              </div>
     295            </tal:sports>
     296
     297          </tal:has-workouts>
     298
    190299        </div>
    191300      </div>
    192301    </div>
    193302
     303      <div id="jq-dropdown-sports" class="jq-dropdown jq-dropdown-tip">
     304        <ul class="jq-dropdown-menu">
     305          <tal:sports tal:repeat="sport profile_stats['sports']">
     306            <li>
     307              <a href="#" class="" tal:content="sport"
     308                 tal:attributes="class 'js-choose-sport-stats js-' + sport">
     309              </a>
     310            </li>
     311          </tal:sports>
     312        </ul>
     313      </div>
     314
     315
     316    <tal:sports tal:repeat="sport profile_stats['sports']">
     317      <div id="" class="jq-dropdown jq-dropdown-tip"
     318           tal:attributes="id 'jq-dropdown-' + sport">
     319        <ul class="jq-dropdown-menu">
     320          <tal:years tal:repeat="year profile_stats['years']">
     321            <li>
     322              <a href="#" class="" tal:content="year"
     323                 tal:attributes="class 'js-choose-year-stats js-' + sport + '-' + str(year)">
     324              </a>
     325            </li>
     326          </tal:years>
     327        </ul>
     328      </div>
     329    </tal:sports>
     330
     331
    194332  </metal:content>
    195333
    196334  <metal:body-js metal:fill-slot="body-js">
    197335
     336    <script src="${request.static_url('ow:static/components/jquery-dropdown/jquery.dropdown.js')}"></script>
    198337    <script src="${request.static_url('ow:static/components/d3/d3.min.js')}"></script>
    199338    <script src="${request.static_url('ow:static/js/ow.js')}"></script>
     
    204343     })
    205344     map_shots.run();
     345
     346     var sport_stats = owjs.sport_stats({
     347         link_selector: 'a.js-choose-sport-stats',
     348         stats_selector: 'div.js-sport-stats',
     349         selected: 'div.js-sport-stats.js-${profile_stats['current_sport']}',
     350         dropdown_selector: 'a.js-jq-dropdown-sel-sports',
     351         current_year: '${profile_stats['current_year']}',
     352         year_link_selector: 'a.js-choose-year-stats.js-'
     353     })
     354     sport_stats.setup();
     355
     356     var year_stats = owjs.year_stats({
     357         link_selector: 'a.js-choose-year-stats',
     358         stats_selector: 'div.js-year-stats',
     359         selected: 'div.js-year-stats.js-${profile_stats['current_sport']}-${profile_stats['current_year']}',
     360         dropdown_selector: 'a.js-jq-dropdown-sel-'
     361     })
     362     year_stats.setup();
    206363
    207364     var y_axis_labels = {
  • ow/tests/models/test_user.py

    r35953eb r778d53d  
    8181        assert list(root['john'].workout_ids()) == ['1', '2', '3']
    8282        assert root['john'].num_workouts == len(workouts)
     83
     84    def test_favorite_sport(self, root):
     85        assert root['john'].favorite_sport is None
     86        # add a cycling workout
     87        workout = Workout(
     88            sport='cycling',
     89            start=datetime.now(timezone.utc),
     90            duration=timedelta(minutes=120),
     91            distance=66,
     92        )
     93        root['john'].add_workout(workout)
     94        assert root['john'].favorite_sport == 'cycling'
     95        # add a running workout, both sports have same amount of workouts,
     96        # favorite is picked up reversed alphabetically
     97        workout = Workout(
     98            sport='running',
     99            start=datetime.now(timezone.utc),
     100            duration=timedelta(minutes=45),
     101            distance=5,
     102        )
     103        root['john'].add_workout(workout)
     104        assert root['john'].favorite_sport == 'running'
     105        # add another cycling workout, now that is the favorite sport
     106        workout = Workout(
     107            sport='cycling',
     108            start=datetime.now(timezone.utc),
     109            duration=timedelta(minutes=60),
     110            distance=30,
     111        )
     112        root['john'].add_workout(workout)
     113        assert root['john'].favorite_sport == 'cycling'
     114
     115    def test_activity_sports(self, root):
     116        assert root['john'].activity_sports == []
     117        workout = Workout(
     118            sport='cycling',
     119            start=datetime.now(timezone.utc),
     120            duration=timedelta(minutes=120),
     121            distance=66,
     122        )
     123        root['john'].add_workout(workout)
     124        assert root['john'].activity_sports == ['cycling']
     125        workout = Workout(
     126            sport='running',
     127            start=datetime.now(timezone.utc),
     128            duration=timedelta(minutes=45),
     129            distance=5,
     130        )
     131        root['john'].add_workout(workout)
     132        assert root['john'].activity_sports == ['cycling', 'running']
     133
     134    def test_activity_years(self, root):
     135        assert root['john'].activity_years == []
     136        workout = Workout(
     137            sport='cycling',
     138            start=datetime.now(timezone.utc),
     139            duration=timedelta(minutes=120),
     140            distance=66,
     141        )
     142        root['john'].add_workout(workout)
     143        assert root['john'].activity_years == [datetime.now(timezone.utc).year]
     144        workout = Workout(
     145            sport='running',
     146            start=datetime(2018, 11, 25, 10, 00, tzinfo=timezone.utc),
     147            duration=timedelta(minutes=45),
     148            distance=5,
     149        )
     150        root['john'].add_workout(workout)
     151        assert root['john'].activity_years == [
     152            datetime.now(timezone.utc).year,
     153            2018
     154        ]
     155
     156    def test_activity_months(self, root):
     157        # we have to pass a year parameter
     158        with pytest.raises(TypeError):
     159            root['john'].activity_months()
     160        now = datetime.now(timezone.utc)
     161        assert root['john'].activity_months(now.year) == []
     162        workout = Workout(
     163            sport='cycling',
     164            start=datetime.now(timezone.utc),
     165            duration=timedelta(minutes=120),
     166            distance=66,
     167        )
     168        root['john'].add_workout(workout)
     169        assert root['john'].activity_months(now.year) == [now.month]
     170        assert root['john'].activity_months(now.year-1) == []
     171        assert root['john'].activity_months(now.year+1) == []
     172        workout = Workout(
     173            sport='running',
     174            start=datetime(2018, 11, 25, 10, 00, tzinfo=timezone.utc),
     175            duration=timedelta(minutes=45),
     176            distance=5,
     177        )
     178        root['john'].add_workout(workout)
     179        assert root['john'].activity_months(now.year) == [now.month]
     180        assert root['john'].activity_months(2018) == [11]
     181        assert root['john'].activity_months(now.year+1) == []
    83182
    84183    def test_activity_dates_tree(self, root):
     
    552651            else:
    553652                assert stats == expected_no_stats_per_week
     653
     654    def test_sport_totals(self, root):
     655        # user has no workouts, so no totals
     656        assert root['john'].sport_totals() == {
     657            'workouts': 0,
     658            'time': timedelta(0),
     659            'distance': Decimal(0),
     660            'elevation': Decimal(0),
     661        }
     662        # add a cycling workout happening now
     663        workout = Workout(
     664            sport='cycling',
     665            start=datetime.now(timezone.utc),
     666            duration=timedelta(minutes=120),
     667            distance=66,
     668        )
     669        root['john'].add_workout(workout)
     670        # only one workout, one sport, so the default will show totals
     671        # for that sport
     672        assert root['john'].sport_totals() == {
     673            'workouts': 1,
     674            'time': timedelta(minutes=120),
     675            'distance': Decimal(66),
     676            'elevation': Decimal(0),
     677        }
     678        # Add a running workout
     679        workout = Workout(
     680            sport='running',
     681            start=datetime(2018, 11, 25, 10, 00, tzinfo=timezone.utc),
     682            duration=timedelta(minutes=45),
     683            distance=5,
     684        )
     685        root['john'].add_workout(workout)
     686        # the favorite sport is running now
     687        assert root['john'].sport_totals() == {
     688            'workouts': 1,
     689            'time': timedelta(minutes=45),
     690            'distance': Decimal(5),
     691            'elevation': Decimal(0),
     692        }
     693        # but we can get the totals for cycling too
     694        assert root['john'].sport_totals('cycling') == {
     695            'workouts': 1,
     696            'time': timedelta(minutes=120),
     697            'distance': Decimal(66),
     698            'elevation': Decimal(0),
     699        }
     700        # adding a new cycling workout, in a different year
     701        workout = Workout(
     702            sport='cycling',
     703            start=datetime(2017, 11, 25, 10, 00, tzinfo=timezone.utc),
     704            duration=timedelta(minutes=60),
     705            distance=32,
     706        )
     707        root['john'].add_workout(workout)
     708        # now cycling is the favorite sport
     709        assert root['john'].sport_totals() == {
     710            'workouts': 2,
     711            'time': timedelta(minutes=180),
     712            'distance': Decimal(98),
     713            'elevation': Decimal(0),
     714        }
     715        # but we can get running stats too
     716        assert root['john'].sport_totals('running') == {
     717            'workouts': 1,
     718            'time': timedelta(minutes=45),
     719            'distance': Decimal(5),
     720            'elevation': Decimal(0),
     721        }
     722        # there are no running activities for 2016
     723        assert root['john'].sport_totals('running', 2016) == {
     724            'workouts': 0,
     725            'time': timedelta(0),
     726            'distance': Decimal(0),
     727            'elevation': Decimal(0),
     728        }
     729        # and not activities for cycling in 2016 neither
     730        assert root['john'].sport_totals('cycling', 2016) == {
     731            'workouts': 0,
     732            'time': timedelta(0),
     733            'distance': Decimal(0),
     734            'elevation': Decimal(0),
     735        }
     736        # and we can get the separate totals for cycling in different years
     737        year = datetime.now(timezone.utc).year
     738        assert root['john'].sport_totals('cycling', year) == {
     739            'workouts': 1,
     740            'time': timedelta(minutes=120),
     741            'distance': Decimal(66),
     742            'elevation': Decimal(0),
     743        }
     744        assert root['john'].sport_totals('cycling', 2017) == {
     745            'workouts': 1,
     746            'time': timedelta(minutes=60),
     747            'distance': Decimal(32),
     748            'elevation': Decimal(0),
     749        }
  • ow/tests/views/test_user.py

    r35953eb r778d53d  
    4646            start=datetime(2015, 6, 28, 12, 55, tzinfo=timezone.utc),
    4747            duration=timedelta(minutes=60),
    48             distance=30
     48            distance=30,
     49            sport='cycling'
    4950        )
    5051        john.add_workout(workout)
     
    413414        # profile page for the current day (no workouts avalable)
    414415        response = user_views.profile(john, request)
    415         assert len(response.keys()) == 6
     416        assert len(response.keys()) == 7
    416417        current_month = datetime.now(timezone.utc).strftime('%Y-%m')
    417418        assert response['user'] == john
     
    425426            'elevation': Decimal(0)
    426427        }
     428        assert response['profile_stats'] == {
     429            'sports': ['cycling'],
     430            'years': [2015],
     431            'current_year': datetime.now(timezone.utc).year,
     432            'current_sport': 'cycling'
     433        }
    427434        # profile page for a previous date, that has workouts
    428435        request.GET['year'] = 2015
    429436        request.GET['month'] = 6
    430437        response = user_views.profile(john, request)
    431         assert len(response.keys()) == 6
     438        assert len(response.keys()) == 7
    432439        assert response['user'] == john
    433440        assert response['user_gender'] == 'Robot'
     
    446453        request.GET['week'] = 25
    447454        response = user_views.profile(john, request)
    448         assert len(response.keys()) == 6
     455        assert len(response.keys()) == 7
    449456        assert response['user'] == john
    450457        assert response['user_gender'] == 'Robot'
     
    462469        request.GET['week'] = 26
    463470        response = user_views.profile(john, request)
    464         assert len(response.keys()) == 6
     471        assert len(response.keys()) == 7
    465472        assert response['user'] == john
    466473        assert response['user_gender'] == 'Robot'
  • ow/views/user.py

    r35953eb r778d53d  
    305305            user_gender = localizer.translate(g[1])
    306306
     307    # get some data to be shown in the "profile stats" totals column
     308    profile_stats = {
     309        'sports': user.activity_sports,
     310        'years': user.activity_years,
     311        'current_year': request.GET.get('stats_year', now.year),
     312        'current_sport': request.GET.get('stats_sport', user.favorite_sport),
     313    }
     314
    307315    return {
    308316        'user': user,
     
    312320            year=str(year), month=str(month).zfill(2)),
    313321        'current_week': week,
    314         'totals': totals
     322        'totals': totals,
     323        'profile_stats': profile_stats
    315324    }
    316325
Note: See TracChangeset for help on using the changeset viewer.