Changeset 5cf5787 in OpenWorkouts-current
- Timestamp:
- Feb 4, 2019, 12:37:35 PM (5 years ago)
- Branches:
- current, feature/docs, master
- Children:
- 3357e47
- Parents:
- 63df989
- Location:
- ow
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
ow/static/js/ow.js
r63df989 r5cf5787 236 236 var chart_selector = spec.chart_selector, 237 237 filters_selector = spec.filters_selector, 238 url = spec.url, 238 switcher_selector = spec.switcher_selector, 239 urls = spec.urls, 239 240 current_month = spec.current_month, 240 y_axis_labels = spec.y_axis_labels; 241 current_week = spec.current_week, 242 y_axis_labels = spec.y_axis_labels, 243 filter_by = spec.filter_by, 244 url = spec.url; 241 245 242 246 // Helpers … … 256 260 }; 257 261 262 function get_name_for_x(d) { 263 if (d.week == undefined || d.week == 0) { 264 return d.name; 265 } 266 else { 267 return d.id.split('-')[2]; 268 } 269 } 270 258 271 // Methods 259 272 var filters_setup = function filters_setup() { 260 273 $(filters_selector).on('click', function(e) { 261 var filter_by = 'distance';262 274 e.preventDefault(); 263 275 filter_by = $(this).attr('class').split('-')[1] 264 276 var chart = d3.select(chart_selector); 265 277 chart.selectAll("*").remove(); 266 render(filter_by); 267 }); 268 }; 269 270 var render = function render(filter_by) { 278 render(filter_by, url); 279 }); 280 }; 281 282 var switcher_setup = function switcher_setup() { 283 $(switcher_selector).on('click', function(e) { 284 e.preventDefault(); 285 url = $(this).attr('class').split('-')[1] 286 var chart = d3.select(chart_selector); 287 chart.selectAll("*").remove(); 288 render(filter_by, url); 289 }); 290 }; 291 292 var render = function render(filter_by, url) { 271 293 /* 272 294 Build a d3 bar chart, populated with data from the given url. … … 280 302 y = d3.scaleLinear().rangeRound([height, 0]); 281 303 282 d3.json(url ).then(function (data) {304 d3.json(urls[url]).then(function (data) { 283 305 x.domain(data.map(function (d) { 284 return d.name; 306 return get_name_for_x(d); 307 // return d.name; 285 308 })); 286 309 … … 308 331 .enter().append("rect") 309 332 .attr("class", function(d) { 310 if (d.id == current_month){ 333 var sel_week = current_month + '-' + current_week; 334 if (d.id == current_month || d.id == sel_week){ 335 /* Bar for the currently selected month or week */ 311 336 select_x_axis_label(d).attr('style', "font-weight: bold;"); 312 return 'bar current' 337 return 'bar current'; 313 338 } 314 339 else { 315 return 'bar' 340 if (!current_week && d.id.indexOf(current_month) >=0 ) { 341 /* 342 User selected a month, then switched to weekly 343 view, we do highlight all the bars for weeks in 344 that month 345 */ 346 select_x_axis_label(d).attr('style', "font-weight: bold;"); 347 return 'bar current'; 348 } 349 else { 350 /* Non-selected bar */ 351 return 'bar'; 352 } 353 316 354 } 317 355 }) 318 356 .attr("x", function (d) { 319 return x( d.name);357 return x(get_name_for_x(d)); 320 358 }) 321 359 .attr("y", function (d) { … … 340 378 }); 341 379 342 g.selectAll(".text") 343 .data(data) 344 .enter() 345 .append("text") 346 .attr("class","label") 347 .attr("x", function (d) { 348 return x(d.name) + x.bandwidth()/2; 349 }) 350 .attr("y", function (d) { 351 /* 352 Get the value for the current bar, then get the maximum 353 value to be displayed in the bar, which is used to 354 calculate the proper position of the label for this bar, 355 relatively to its height (1% above the bar) 356 */ 357 var value = get_y_value(d, filter_by); 358 var max = y.domain()[1]; 359 return y(value + y.domain()[1] * 0.01); 360 }) 361 .text(function(d) { 362 var value = get_y_value(d, filter_by) 363 if ( value > 0) { 364 return value; 365 } 366 }); 367 380 if (url == 'monthly') { 381 g.selectAll(".text") 382 .data(data) 383 .enter() 384 .append("text") 385 .attr("class","label") 386 .attr("x", function (d) { 387 return x(get_name_for_x(d)) + x.bandwidth()/2; 388 }) 389 .attr("y", function (d) { 390 /* 391 Get the value for the current bar, then get the maximum 392 value to be displayed in the bar, which is used to 393 calculate the proper position of the label for this bar, 394 relatively to its height (1% above the bar) 395 */ 396 var value = get_y_value(d, filter_by); 397 var max = y.domain()[1]; 398 return y(value + y.domain()[1] * 0.01); 399 }) 400 .text(function(d) { 401 var value = get_y_value(d, filter_by) 402 if ( value > 0) { 403 return value; 404 } 405 }); 406 } 407 408 if (url == 'weekly') { 409 g.selectAll(".tick") 410 .each(function (d, i) { 411 /* 412 Remove from the x-axis tickets those without letters 413 on them (useful for the weekly chart) 414 */ 415 if (d !== parseInt(d, 10)) { 416 if(!d.match(/[a-z]/i)) { 417 this.remove(); 418 } 419 } 420 }); 421 } 368 422 }); 369 423 }; … … 371 425 var that = {} 372 426 that.filters_setup = filters_setup; 427 that.switcher_setup = switcher_setup; 373 428 that.render = render; 374 429 return that -
ow/templates/profile.pt
r63df989 r5cf5787 72 72 <a href="#" class="js-time" i18n:translate="">time</a> 73 73 <a href="#" class="js-elevation" i18n:translate="">elevation</a> 74 </div> 75 <div class="switcher js-switcher"> 76 <a href="#" class="js-weekly" i18n:translate="">weekly</a> 77 <a href="#" class="js-monthly" i18n:translate="">monthly</a> 74 78 </div> 75 79 </div> … … 154 158 chart_selector: 'div.js-month-stats svg', 155 159 filters_selector: 'div.js-month-stats div.js-filters a', 156 url: "${request.resource_url(context, 'yearly')}", 160 switcher_selector: 'div.js-month-stats div.js-switcher a', 161 urls: {"monthly": "${request.resource_url(context, 'monthly')}", 162 "weekly": "${request.resource_url(context, 'weekly')}"}, 157 163 current_month: "${current_month}", 164 current_week: "${current_week}", 158 165 y_axis_labels: y_axis_labels, 166 filter_by: "distance", 167 url: "${'monthly' if current_week is None else 'weekly'}", 159 168 }); 160 year_chart.render("distance" );169 year_chart.render("distance", "${'monthly' if current_week is None else 'weekly'}"); 161 170 year_chart.filters_setup(); 171 year_chart.switcher_setup(); 162 172 </script> 163 173 -
ow/tests/views/test_user.py
r63df989 r5cf5787 269 269 # profile page for the current day (no workouts avalable) 270 270 response = user_views.profile(john, request) 271 assert len(response.keys()) == 2271 assert len(response.keys()) == 3 272 272 current_month = datetime.now(timezone.utc).strftime('%Y-%m') 273 273 assert response['current_month'] == current_month 274 assert response['current_week'] is None 274 275 assert response['workouts'] == [] 275 276 # profile page for a previous date, that has workouts … … 277 278 request.GET['month'] = 8 278 279 response = user_views.profile(john, request) 279 assert len(response.keys()) == 2280 assert len(response.keys()) == 3 280 281 assert response['current_month'] == '2015-08' 282 assert response['current_week'] is None 283 assert response['workouts'] == john.workouts(2015, 8) 284 # same, passing a week, first on a week without workouts 285 request.GET['year'] = 2015 286 request.GET['month'] = 8 287 request.GET['week'] = 25 288 response = user_views.profile(john, request) 289 assert len(response.keys()) == 3 290 assert response['current_month'] == '2015-08' 291 assert response['current_week'] is 25 292 assert response['workouts'] == [] 293 # now in a week with workoutss 294 request.GET['year'] = 2015 295 request.GET['month'] = 8 296 request.GET['week'] = 26 297 response = user_views.profile(john, request) 298 assert len(response.keys()) == 3 299 assert response['current_month'] == '2015-08' 300 assert response['current_week'] is 26 281 301 assert response['workouts'] == john.workouts(2015, 8) 282 302 -
ow/views/user.py
r63df989 r5cf5787 168 168 year = int(request.GET.get('year', now.year)) 169 169 month = int(request.GET.get('month', now.month)) 170 week = request.GET.get('week', None) 170 171 return { 171 'workouts': context.workouts(year, month ),172 'workouts': context.workouts(year, month, week), 172 173 'current_month': '{year}-{month}'.format( 173 year=str(year), month=str(month).zfill(2)) 174 year=str(year), month=str(month).zfill(2)), 175 'current_week': week 174 176 } 175 177 … … 262 264 context=User, 263 265 permission='view', 264 name=' yearly')266 name='monthly') 265 267 def last_months_stats(context, request): 266 268 """ … … 294 296 charset='utf-8', 295 297 body=json.dumps(json_stats)) 298 299 300 @view_config( 301 context=User, 302 permission='view', 303 name='weekly') 304 def last_weeks_stats(context, request): 305 """ 306 Return a json-encoded stream with statistics for the last 12-months, but 307 in a per-week basis 308 """ 309 stats = context.weekly_year_stats 310 # this sets which month is 2 times in the stats, once this year, once 311 # the previous year. We will show it a bit different in the UI (showing 312 # the year too to prevent confusion) 313 repeated_month = datetime.now(timezone.utc).date().month 314 json_stats = [] 315 for week in stats: 316 hms = timedelta_to_hms(stats[week]['time']) 317 name = month_name[week[1]][:3] 318 if week[1] == repeated_month: 319 name += ' ' + str(week[0]) 320 week_stats = { 321 'id': '-'.join( 322 [str(week[0]), str(week[1]).zfill(2), str(week[2])]), 323 'week': str(week[3]), # the number of week in the current month 324 'name': name, 325 'time': str(hms[0]).zfill(2), 326 'distance': int(round(stats[week]['distance'])), 327 'elevation': int(stats[week]['elevation']), 328 'workouts': stats[week]['workouts'], 329 'url': request.resource_url( 330 context, 'profile', 331 query={'year': str(week[0]), 332 'month': str(week[1]), 333 'week': str(week[2])}, 334 anchor='workouts') 335 } 336 json_stats.append(week_stats) 337 return Response(content_type='application/json', 338 charset='utf-8', 339 body=json.dumps(json_stats))
Note: See TracChangeset
for help on using the changeset viewer.