From 52901a0e2df5d3fb0df82ce41fafcd59b5ec7c0e Mon Sep 17 00:00:00 2001 From: Tom Ladendorf Date: Fri, 4 Sep 2015 10:33:37 -0500 Subject: [PATCH 1/8] Finished basics of history graph --- .../distribution-graph.directive.jade | 2 +- .../history-graph.directive.jade | 11 + .../history-graph/history-graph.directive.js | 200 ++++++++++++++++++ app/profile/subtrack/develop/develop.jade | 2 + app/profile/subtrack/subtrack.controller.js | 6 + app/services/profile.service.js | 5 + assets/css/directives/history-graph.scss | 78 +++++++ 7 files changed, 303 insertions(+), 1 deletion(-) create mode 100644 app/directives/history-graph/history-graph.directive.jade create mode 100644 app/directives/history-graph/history-graph.directive.js create mode 100644 assets/css/directives/history-graph.scss diff --git a/app/directives/distribution-graph/distribution-graph.directive.jade b/app/directives/distribution-graph/distribution-graph.directive.jade index c8f122857..b8a821474 100644 --- a/app/directives/distribution-graph/distribution-graph.directive.jade +++ b/app/directives/distribution-graph/distribution-graph.directive.jade @@ -1,4 +1,4 @@ -.graph-viewer +.graph-viewer(ng-if="fasdf") .distribution-graph .info-port diff --git a/app/directives/history-graph/history-graph.directive.jade b/app/directives/history-graph/history-graph.directive.jade new file mode 100644 index 000000000..07ab1d4e6 --- /dev/null +++ b/app/directives/history-graph/history-graph.directive.jade @@ -0,0 +1,11 @@ +.history-graph-container + .history-graph + + .info-port + .rating + .num {{historyRating || rating}} + .label RATING + .history-info(ng-if="historyRating") + | Attained on {{historyDate}} in challenge "{{historyChallenge}}" + .compare + button COMPARE diff --git a/app/directives/history-graph/history-graph.directive.js b/app/directives/history-graph/history-graph.directive.js new file mode 100644 index 000000000..82f14e264 --- /dev/null +++ b/app/directives/history-graph/history-graph.directive.js @@ -0,0 +1,200 @@ +(function() { + 'use strict'; + + angular.module('tcUIComponents').directive('historyGraph', historyGraph); + + function historyGraph() { + return { + restrict: 'E', + templateUrl: function(elem, attrs) { + return 'directives/history-graph/history-graph.directive.html'; + }, + scope: { + promise: '=', + rating: '=' + }, + controller: ['$scope', HistoryGraphController] + }; + } + + function HistoryGraphController($scope) { + $scope.colors = [ + // grey + { + 'color': '#7f7f7f', + 'darkerColor': '#656565', + 'start': 0, + 'end': 899 + }, + // green + { + 'color': '#99cc09', + 'darkerColor': '#7aa307', + 'start': 900, + 'end': 1199 + }, + // blue + { + 'color': '#09affe', + 'darkerColor': '#078ccb', + 'start': 1200, + 'end': 1499 + }, + // yellow + { + 'color': '#f39426', + 'darkerColor': '#c2761e', + 'start': 1500, + 'end': 2199 + }, + // red + { + 'color': '#fe0866', + 'darkerColor': '#cb0651', + 'start': 2200, + 'end': Infinity + } + ]; + var w = 600, + h = 400, + padding = { top: 20, right: 5, bottom: 30, left: 50 }; + + activate(); + + function activate() { + $scope.promise.then(function(history) { + + var parseDate = d3.time.format.utc("%Y-%m-%dT%H:%M:%S.%LZ").parse; + history.forEach(function(d) { + d.ratingDate = parseDate(d.ratingDate); + }); + + var x = d3.time.scale() + .range([0 + padding.left, w + padding.left]) + .domain(d3.extent(history, function(d) { return d.ratingDate; })); + + var y = d3.scale.linear() + .range([h + padding.top, padding.top]) + .domain(d3.extent(history, function(d) { return d.newRating; })); + + + function yAxis(ticks) { + return d3.svg.axis() + .scale(y) + .ticks(ticks || 10) + .orient("left"); + } + + function xAxis(ticks) { + return d3.svg.axis() + .scale(x) + .ticks(ticks || 10) + .orient("bottom"); + } + + var line = d3.svg.line() + .interpolate('cardinal') + .x(function(d) { return x(d.ratingDate); }) + .y(function(d) { return y(d.newRating); }) + + + var svg = d3.select('.history-graph').append('svg') + .attr('width', w + padding.left + padding.right) + .attr('height', h + padding.top + padding.bottom) + + + svg.append('rect') + .attr('x', padding.left) + .attr('y', padding.top) + .attr('width', w) + .attr('height', h) + + + + svg.append('g') + .attr('class', 'x axis') + .attr('transform', 'translate(0,' + (h + padding.top) +')') + .call(xAxis()); + + + svg.append('g') + .attr('class', 'y axis') + .attr('transform', 'translate(' + padding.left + ')') + .call(yAxis()) + + svg.append('g') + .attr('class', 'grid') + .attr('transform', 'translate(0, ' + (h + padding.top) + ')') + .call( + xAxis(Math.round(w / 35)).tickSize(-h, 0, 0) + .tickFormat('') + ) + + svg.append('g') + .attr('class', 'grid') + .attr('transform', 'translate(' + padding.left + ',0)') + .call( + yAxis(Math.round(h / 30)).tickSize(-w, 0, 0) + .tickFormat('') + ) + + + svg.append('path') + .datum(history) + .attr('class', 'line') + .attr('d', line) + + svg.selectAll('circle') + .data(history) + .enter() + .append('circle') + .attr('cx', function(d) { + return x(d.ratingDate); + }) + .attr('cy', function(d) { + return y(d.newRating); + }) + .attr('fill', function(d) { + return ratingToColor($scope.colors, d.newRating); + }) + .on('mouseover', function(d) { + $scope.historyRating = d.newRating; + $scope.historyDate = moment(d.ratingDate).format('YYYY-MM-DD'); + $scope.historyChallenge = d.challengeName; + $scope.$digest(); + d3.select(this) + .attr('r', 4.0) + .attr('stroke', 'black') + .attr('stroke-width', '.5px'); + }) + .on('mouseout', function(d) { + $scope.historyRating = undefined; + $scope.$digest(); + d3.select(this) + .attr('r', 3.0) + .attr('stroke', 'none') + .attr('stroke-width', '0px'); + }) + .attr('r', 3.0) + + }); + + } + + function ratingToColor(colors, rating) { + colors = colors.filter(function(color) { + return rating >= color.start && rating <= color.end; + }); + return colors[0] && colors[0].color || 'black'; + } + + function ratingToDarkerColor(colors, rating) { + colors = colors.filter(function(color) { + return rating >= color.start && rating <= color.end; + }); + return colors[0] && colors[0].darkerColor || 'black'; + } + + } + +})(); diff --git a/app/profile/subtrack/develop/develop.jade b/app/profile/subtrack/develop/develop.jade index 3364de99b..74502cf83 100644 --- a/app/profile/subtrack/develop/develop.jade +++ b/app/profile/subtrack/develop/develop.jade @@ -46,6 +46,8 @@ .graphs distribution-graph(promise="vm.distributionPromise", rating="vm.typeStats.rank.rating") + history-graph(promise="vm.historyPromise", rating="vm.typeStats.rank.rating") + h2.detailed Detailed Stats ul.vertical-stats diff --git a/app/profile/subtrack/subtrack.controller.js b/app/profile/subtrack/subtrack.controller.js index 58b6264d6..212f0cdc0 100644 --- a/app/profile/subtrack/subtrack.controller.js +++ b/app/profile/subtrack/subtrack.controller.js @@ -39,6 +39,12 @@ vm.distributionPromise.then(function(data) { vm.distribution = data.distribution; }); + var historyDeferred = $q.defer(); + vm.historyPromise = historyDeferred.promise; + ProfileService.getHistoryStats(profileVm.profile.handle).then(function(data) { + vm.history = ProfileService.getChallengeTypeStats(data, vm.track, vm.subTrack).history; + historyDeferred.resolve(vm.history); + }); profileVm.statsPromise.then(function(data) { vm.typeStats = ProfileService.getChallengeTypeStats( profileVm.stats, diff --git a/app/services/profile.service.js b/app/services/profile.service.js index 4504aefd9..43ac6d96e 100644 --- a/app/services/profile.service.js +++ b/app/services/profile.service.js @@ -17,6 +17,7 @@ getUserFinancials: getUserFinancials, getUserStats: getUserStats, getDistributionStats: getDistributionStats, + getHistoryStats: getHistoryStats, // auxiliary functions for profile getNumProjects: getNumProjects, getNumWins: getNumWins, @@ -64,6 +65,10 @@ }); } + function getHistoryStats(handle) { + return restangular.one('members', handle).one('stats').one('history').get(); + } + function getNumProjects(stats) { return stats.challenges; } diff --git a/assets/css/directives/history-graph.scss b/assets/css/directives/history-graph.scss new file mode 100644 index 000000000..6ca29463a --- /dev/null +++ b/assets/css/directives/history-graph.scss @@ -0,0 +1,78 @@ +.history-graph-container { + display: flex; + flex-direction: row; + .history-graph { + + .axis path, + .axis line { + fill: none; + stroke: none; + shape-rendering: crispEdges; + } + + .x.axis path { + display: none; + } + + rect { + fill: #f6f6f6; + } + + .line { + fill: none; + stroke: #c5c5c5; + stroke-width: 2.3px; + } + + .grid .tick { + stroke: white; + opacity: 0.7; + } + + .tick text { + font-size: 10px; + } + + + } + .info-port { + background: #f6f6f6; + margin-top: 20px; + height: 400px; + width: 250px; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + margin-right: 100px; + .rating { + width: 130px; + height: 130px; + background: #09affe; + -moz-border-radius: 65px; + -webkit-border-radius: 65px; + border-radius: 65px; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + + .num { + color: white; + font-size: 25px; + font-weight: bold; + } + .label { + color: white; + } + margin-bottom: 20px; + } + .history-info { + margin-bottom: 20px; + padding: 0 5px; + text-align: center; + } + .compare { + } + } +} From f8093b0ad40fa4e92a901a26b0532bbf107238ab Mon Sep 17 00:00:00 2001 From: Tom Ladendorf Date: Fri, 4 Sep 2015 11:20:29 -0500 Subject: [PATCH 2/8] Added graph switching --- .../distribution-graph.directive.jade | 5 ++++- .../distribution-graph.directive.js | 3 ++- .../history-graph/history-graph.directive.jade | 6 +++--- .../history-graph/history-graph.directive.js | 11 +++++++++-- app/profile/subtrack/develop/develop.jade | 4 ++-- app/profile/subtrack/subtrack.controller.js | 1 + assets/css/directives/distribution-graph.scss | 5 +++++ assets/css/directives/history-graph.scss | 4 ++-- 8 files changed, 28 insertions(+), 11 deletions(-) diff --git a/app/directives/distribution-graph/distribution-graph.directive.jade b/app/directives/distribution-graph/distribution-graph.directive.jade index b8a821474..8dab4837b 100644 --- a/app/directives/distribution-graph/distribution-graph.directive.jade +++ b/app/directives/distribution-graph/distribution-graph.directive.jade @@ -1,4 +1,4 @@ -.graph-viewer(ng-if="fasdf") +.graph-viewer(ng-show="graphState.show == 'distribution'") .distribution-graph .info-port @@ -8,3 +8,6 @@ .rating(ng-if="!displayCoders") .num {{rating}} .label RATING + + .compare + button(ng-click="graphState.show = 'history'") COMPARE diff --git a/app/directives/distribution-graph/distribution-graph.directive.js b/app/directives/distribution-graph/distribution-graph.directive.js index 76c72e56a..303cb9ed0 100644 --- a/app/directives/distribution-graph/distribution-graph.directive.js +++ b/app/directives/distribution-graph/distribution-graph.directive.js @@ -11,7 +11,8 @@ }, scope: { promise: '=', - rating: '=' + rating: '=', + graphState: '=' }, controller: ['$scope', DistributionGraphController] }; diff --git a/app/directives/history-graph/history-graph.directive.jade b/app/directives/history-graph/history-graph.directive.jade index 07ab1d4e6..21b01e1b5 100644 --- a/app/directives/history-graph/history-graph.directive.jade +++ b/app/directives/history-graph/history-graph.directive.jade @@ -1,4 +1,4 @@ -.history-graph-container +.history-graph-container(ng-show="graphState.show == 'history'") .history-graph .info-port @@ -7,5 +7,5 @@ .label RATING .history-info(ng-if="historyRating") | Attained on {{historyDate}} in challenge "{{historyChallenge}}" - .compare - button COMPARE + .lower + button(ng-click="graphState.show = 'distribution'") COMPARE diff --git a/app/directives/history-graph/history-graph.directive.js b/app/directives/history-graph/history-graph.directive.js index 82f14e264..8404e556c 100644 --- a/app/directives/history-graph/history-graph.directive.js +++ b/app/directives/history-graph/history-graph.directive.js @@ -11,7 +11,8 @@ }, scope: { promise: '=', - rating: '=' + rating: '=', + graphState: '=' }, controller: ['$scope', HistoryGraphController] }; @@ -116,11 +117,17 @@ .attr('transform', 'translate(0,' + (h + padding.top) +')') .call(xAxis()); + svg.selectAll('g.x.axis .tick text') + .attr('font-size', function(d) { + return moment(d).format('MM') == '01' ? 12 : 10; + }); + svg.append('g') .attr('class', 'y axis') .attr('transform', 'translate(' + padding.left + ')') - .call(yAxis()) + .call(yAxis().tickFormat(function(d) { return parseInt(d) }) + ) svg.append('g') .attr('class', 'grid') diff --git a/app/profile/subtrack/develop/develop.jade b/app/profile/subtrack/develop/develop.jade index 74502cf83..89b3801ad 100644 --- a/app/profile/subtrack/develop/develop.jade +++ b/app/profile/subtrack/develop/develop.jade @@ -44,9 +44,9 @@ .stats(ng-show="vm.viewing == 'stats' && profileVm.status.stats === 'ready'") .graphs - distribution-graph(promise="vm.distributionPromise", rating="vm.typeStats.rank.rating") + distribution-graph(promise="vm.distributionPromise", rating="vm.typeStats.rank.rating", graph-state="vm.graphState") - history-graph(promise="vm.historyPromise", rating="vm.typeStats.rank.rating") + history-graph(promise="vm.historyPromise", rating="vm.typeStats.rank.rating", graph-state="vm.graphState") h2.detailed Detailed Stats diff --git a/app/profile/subtrack/subtrack.controller.js b/app/profile/subtrack/subtrack.controller.js index 212f0cdc0..891247df7 100644 --- a/app/profile/subtrack/subtrack.controller.js +++ b/app/profile/subtrack/subtrack.controller.js @@ -8,6 +8,7 @@ function ProfileSubtrackController($scope, ProfileService, $q, $stateParams, ChallengeService, CONSTANTS, $state, $window) { var vm = this; + vm.graphState = { show: 'history' }; vm.subTrack = decodeURIComponent($stateParams.subTrack || '') || ''; vm.track = $stateParams.track; vm.viewing = 'challenges'; diff --git a/assets/css/directives/distribution-graph.scss b/assets/css/directives/distribution-graph.scss index 0a0c6c8cd..70fb5fea6 100644 --- a/assets/css/directives/distribution-graph.scss +++ b/assets/css/directives/distribution-graph.scss @@ -80,6 +80,11 @@ .label { color: white; } + margin-bottom: 20px; + } + + .compare { + } } } diff --git a/assets/css/directives/history-graph.scss b/assets/css/directives/history-graph.scss index 6ca29463a..163d4830f 100644 --- a/assets/css/directives/history-graph.scss +++ b/assets/css/directives/history-graph.scss @@ -29,7 +29,7 @@ opacity: 0.7; } - .tick text { + .y.axis .tick text { font-size: 10px; } @@ -72,7 +72,7 @@ padding: 0 5px; text-align: center; } - .compare { + .lower { } } } From 7b246e7d1b83a1774607df56418c00a99c230d06 Mon Sep 17 00:00:00 2001 From: Tom Ladendorf Date: Fri, 4 Sep 2015 11:49:11 -0500 Subject: [PATCH 3/8] Adjusted padding on distribution graph --- .../distribution-graph.directive.js | 49 ++++++++++--------- assets/css/directives/distribution-graph.scss | 1 + 2 files changed, 28 insertions(+), 22 deletions(-) diff --git a/app/directives/distribution-graph/distribution-graph.directive.js b/app/directives/distribution-graph/distribution-graph.directive.js index 303cb9ed0..3c0e0e0f2 100644 --- a/app/directives/distribution-graph/distribution-graph.directive.js +++ b/app/directives/distribution-graph/distribution-graph.directive.js @@ -56,9 +56,11 @@ 'end': Infinity } ]; - var w = 700, - h = 400, - padding = 100; + var w = 600, + h = 300, + padding = { top: 10, left: 100, bottom: 100, right: 0 }; + var totalW = w + padding.left + padding.right; + var totalH = h + padding.top + padding.bottom; activate(); @@ -72,45 +74,48 @@ removeTrailingZeroes(ranges); var xScale = d3.scale.ordinal() .domain(d3.range(ranges.length)) - .rangeRoundBands([padding, w], 0.05); + .rangeRoundBands([padding.left, padding.left + w], 0.05); var yScale = d3.scale.linear() .domain([0, d3.max(ranges, function(range) { return range.number }) + 1]) - .range([h - padding, 0]); + .range([totalH - padding.bottom, padding.top]); var xScale2 = d3.scale.linear() .domain([ranges[0].start, d3.max(ranges, function(range) { return range.end })]) - .range([padding, w]); + .range([padding.left, totalW - padding.right]); var svg = d3.select('div.distribution-graph') .append('svg') - .attr('width', w) - .attr('height', h); + .attr('width', totalW) + .attr('height', totalH); svg.append('rect') - .attr('x', padding) - .attr('y', 0) + .attr('x', padding.left) + .attr('y', padding.top) .attr('width', w) - .attr('height', h - padding) + .attr('height', h) .attr('fill', '#eeeeee') svg.append('g') .attr('class', 'grid') - .attr('transform', 'translate(' + padding + ',0)') + .attr('transform', 'translate(' + padding.left + ',0)') .call( - yAxis(5).tickSize(-w, 0, 0) + yAxis(5).tickSize(-totalW, 0, 0) .tickFormat('') ) svg.append('g') .attr('class', 'axis') - .attr('transform', 'translate(' + padding + ',0)') + .attr('transform', 'translate(' + padding.left + ', 0)') .call(yAxis(5)) + function logr(x) { + console.log(x); return x; + } svg.append('line') .attr('x1', xScale2($scope.rating)) - .attr('y1', h - padding) + .attr('y1', totalH - padding.bottom) .attr('x2', xScale2($scope.rating)) - .attr('y2', 0) + .attr('y2', padding.top) .attr('class', 'my-rating') .attr('stroke-width', 2) .attr('stroke', ratingToColor($scope.colors, $scope.rating)); @@ -128,7 +133,7 @@ }) .attr('width', xScale.rangeBand()) .attr('height', function(d) { - return h - padding - yScale(d.number); + return totalH - padding.bottom - yScale(d.number); }) .attr('fill', function(d) { return ratingToColor($scope.colors, d.start); @@ -154,20 +159,20 @@ .attr('class', 'xaxis') .attr('x1', function(d, i) { if (i === 0) { - return padding; + return padding.left; } else { return xScale(i) - .5; } }) .attr('x2', function(d, i) { if (i === ranges.length - 1) { - return w; + return totalW - padding.right; } else { return xScale(i) + xScale.rangeBand() + .5; } }) - .attr('y1', h - padding + .5) - .attr('y2', h - padding + .5) + .attr('y1', h + padding.top + .5) + .attr('y2', h + padding.top + .5) .attr('stroke', function(d) { return ratingToColor($scope.colors, d.start); }) @@ -186,7 +191,7 @@ svg.append('g') .attr('class', 'axis') - .attr('transform', 'translate(0,' + (h - padding) + ')') + .attr('transform', 'translate(0,' + (h + padding.top) + ')') .call(xAxis) .selectAll('text') .attr('x', 9) diff --git a/assets/css/directives/distribution-graph.scss b/assets/css/directives/distribution-graph.scss index 70fb5fea6..c9281b3dd 100644 --- a/assets/css/directives/distribution-graph.scss +++ b/assets/css/directives/distribution-graph.scss @@ -52,6 +52,7 @@ } .info-port { margin-left: 2px; + margin-top: 10px; background: #eeeeee; height: 300px; width: 250px; From 7a1e63a2c1366c1a91b86fe9eb5ad8533a98fba8 Mon Sep 17 00:00:00 2001 From: Tom Ladendorf Date: Fri, 4 Sep 2015 11:55:29 -0500 Subject: [PATCH 4/8] Adjusted graphs to have similar dimensions --- .../distribution-graph/distribution-graph.directive.js | 6 +++--- assets/css/directives/distribution-graph.scss | 6 +++--- assets/css/directives/history-graph.scss | 2 ++ assets/css/profile/subtrack.scss | 5 +---- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/app/directives/distribution-graph/distribution-graph.directive.js b/app/directives/distribution-graph/distribution-graph.directive.js index 3c0e0e0f2..f891d2b5b 100644 --- a/app/directives/distribution-graph/distribution-graph.directive.js +++ b/app/directives/distribution-graph/distribution-graph.directive.js @@ -57,8 +57,8 @@ } ]; var w = 600, - h = 300, - padding = { top: 10, left: 100, bottom: 100, right: 0 }; + h = 400, + padding = { top: 20, left: 100, bottom: 100, right: 0 }; var totalW = w + padding.left + padding.right; var totalH = h + padding.top + padding.bottom; @@ -92,7 +92,7 @@ .attr('y', padding.top) .attr('width', w) .attr('height', h) - .attr('fill', '#eeeeee') + .attr('fill', '#f6f6f6') svg.append('g') .attr('class', 'grid') diff --git a/assets/css/directives/distribution-graph.scss b/assets/css/directives/distribution-graph.scss index c9281b3dd..7841fac22 100644 --- a/assets/css/directives/distribution-graph.scss +++ b/assets/css/directives/distribution-graph.scss @@ -52,9 +52,9 @@ } .info-port { margin-left: 2px; - margin-top: 10px; - background: #eeeeee; - height: 300px; + margin-top: 20px; + background: #f6f6f6; + height: 400px; width: 250px; display: flex; flex-direction: column; diff --git a/assets/css/directives/history-graph.scss b/assets/css/directives/history-graph.scss index 163d4830f..dcbf51325 100644 --- a/assets/css/directives/history-graph.scss +++ b/assets/css/directives/history-graph.scss @@ -3,6 +3,8 @@ flex-direction: row; .history-graph { + margin-left: 40px; + .axis path, .axis line { fill: none; diff --git a/assets/css/profile/subtrack.scss b/assets/css/profile/subtrack.scss index 8e3279e83..5efa31a5d 100644 --- a/assets/css/profile/subtrack.scss +++ b/assets/css/profile/subtrack.scss @@ -17,15 +17,12 @@ } } .develop, .design { - + .stats { .graphs { display: flex; flex-direction: row; justify-content: center; - img { - width: 700px; - } } h2.detailed { margin: 50px auto 25px auto; From d074f763927aa761468bedd88b7757134fb078ee Mon Sep 17 00:00:00 2001 From: Tom Ladendorf Date: Fri, 4 Sep 2015 12:57:28 -0500 Subject: [PATCH 5/8] adjust padding --- .../history-graph/history-graph.directive.js | 37 ++++++++++++++++++- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/app/directives/history-graph/history-graph.directive.js b/app/directives/history-graph/history-graph.directive.js index 8404e556c..806495af1 100644 --- a/app/directives/history-graph/history-graph.directive.js +++ b/app/directives/history-graph/history-graph.directive.js @@ -60,6 +60,9 @@ h = 400, padding = { top: 20, right: 5, bottom: 30, left: 50 }; + var totalH = h + padding.top + padding.bottom; + var totalW = w + padding.left + padding.right; + activate(); function activate() { @@ -71,11 +74,11 @@ }); var x = d3.time.scale() - .range([0 + padding.left, w + padding.left]) + .range([padding.left + 5, w + padding.left - 5]) .domain(d3.extent(history, function(d) { return d.ratingDate; })); var y = d3.scale.linear() - .range([h + padding.top, padding.top]) + .range([h + padding.top - 5, padding.top + 5]) .domain(d3.extent(history, function(d) { return d.newRating; })); @@ -151,6 +154,36 @@ .attr('class', 'line') .attr('d', line) + + svg.append('g') + .selectAll('line') + .data($scope.colors) + .enter() + .append('line') + .attr('x1', totalW - 3) + .attr('x2', totalW - 3) + .attr('y1', function(d) { + return processRatingStripePoint(y(d.start)); + }) + .attr('y2', function(d) { + return processRatingStripePoint(y(d.end)); + }) + .attr('stroke', function(d) { + return d.color; + }) + .attr('stroke-width', 3) + + function processRatingStripePoint(y) { + console.log('y:' + y) + if (y < padding.top) { + return padding.top; + } else if (y > totalH - padding.bottom) { + return padding.bottom; + } else { + return y; + } + } + svg.selectAll('circle') .data(history) .enter() From 6010bb3c643d9853bd1900f55c943064b6f5e68a Mon Sep 17 00:00:00 2001 From: Tom Ladendorf Date: Fri, 4 Sep 2015 12:57:38 -0500 Subject: [PATCH 6/8] index --- app/index.jade | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/index.jade b/app/index.jade index 442147c79..0a35cfe06 100644 --- a/app/index.jade +++ b/app/index.jade @@ -54,6 +54,7 @@ html link(rel="stylesheet", href="assets/css/directives/tc-pager.css") link(rel="stylesheet", href="assets/css/directives/srm-tile.css") link(rel="stylesheet", href="assets/css/directives/profile-widget.css") + link(rel="stylesheet", href="assets/css/directives/history-graph.css") link(rel="stylesheet", href="assets/css/directives/distribution-graph.css") link(rel="stylesheet", href="assets/css/directives/challenge-tiles.css") link(rel="stylesheet", href="assets/css/directives/badge-tooltip.css") @@ -90,7 +91,6 @@ html script(src='../bower_components/angular-filter/dist/angular-filter.min.js') script(src='../bower_components/angular-img-fallback/angular.dcb-img-fallback.js') script(src='../bower_components/angular-jwt/dist/angular-jwt.js') - script(src='../bower_components/angular-mocks/angular-mocks.js') script(src='../bower_components/angular-sanitize/angular-sanitize.js') script(src='../bower_components/angular-ui-router/release/angular-ui-router.js') script(src='../bower_components/x2js/xml2json.min.js') @@ -131,6 +131,7 @@ html script(src="directives/challenge-tiles/challenge-tile.directive.js") script(src="directives/distribution-graph/distribution-graph.directive.js") script(src="directives/focus-on.directive.js") + script(src="directives/history-graph/history-graph.directive.js") script(src="directives/on-file-change.directive.js") script(src="directives/profile-widget/profile-widget.directive.js") script(src="directives/right-placeholder.directive.js") From 49e4ad5eaa6f3f48b90a0a1060a63bcd41daa8c6 Mon Sep 17 00:00:00 2001 From: Tom Ladendorf Date: Fri, 4 Sep 2015 13:16:25 -0500 Subject: [PATCH 7/8] Hid broken part of graph --- .../history-graph/history-graph.directive.js | 35 ++++++++++--------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/app/directives/history-graph/history-graph.directive.js b/app/directives/history-graph/history-graph.directive.js index 806495af1..61218dd30 100644 --- a/app/directives/history-graph/history-graph.directive.js +++ b/app/directives/history-graph/history-graph.directive.js @@ -155,23 +155,24 @@ .attr('d', line) - svg.append('g') - .selectAll('line') - .data($scope.colors) - .enter() - .append('line') - .attr('x1', totalW - 3) - .attr('x2', totalW - 3) - .attr('y1', function(d) { - return processRatingStripePoint(y(d.start)); - }) - .attr('y2', function(d) { - return processRatingStripePoint(y(d.end)); - }) - .attr('stroke', function(d) { - return d.color; - }) - .attr('stroke-width', 3) + // FIXME !!! +// svg.append('g') +// .selectAll('line') +// .data($scope.colors) +// .enter() +// .append('line') +// .attr('x1', totalW - 3) +// .attr('x2', totalW - 3) +// .attr('y1', function(d) { +// return processRatingStripePoint(y(d.start)); +// }) +// .attr('y2', function(d) { +// return processRatingStripePoint(y(d.end)); +// }) +// .attr('stroke', function(d) { +// return d.color; +// }) +// .attr('stroke-width', 3) function processRatingStripePoint(y) { console.log('y:' + y) From ce8bedf1bafcf6b177b47874be73b630a1ac267f Mon Sep 17 00:00:00 2001 From: Tom Ladendorf Date: Fri, 4 Sep 2015 13:17:00 -0500 Subject: [PATCH 8/8] fixed broken tests --- app/profile/subtrack/subtrack.controller.js | 6 +- app/profile/subtrack/subtrack.spec.js | 12 ++++ .../update-password/update-password.spec.js | 4 ++ app/skill-picker/skill-picker.spec.js | 7 +-- tests/test-helpers/mock-data.js | 63 +++++++++++++++++++ 5 files changed, 84 insertions(+), 8 deletions(-) diff --git a/app/profile/subtrack/subtrack.controller.js b/app/profile/subtrack/subtrack.controller.js index 891247df7..b9e5e2283 100644 --- a/app/profile/subtrack/subtrack.controller.js +++ b/app/profile/subtrack/subtrack.controller.js @@ -43,8 +43,10 @@ var historyDeferred = $q.defer(); vm.historyPromise = historyDeferred.promise; ProfileService.getHistoryStats(profileVm.profile.handle).then(function(data) { - vm.history = ProfileService.getChallengeTypeStats(data, vm.track, vm.subTrack).history; - historyDeferred.resolve(vm.history); + if (data.handle) { + vm.history = ProfileService.getChallengeTypeStats(data, vm.track, vm.subTrack).history; + historyDeferred.resolve(vm.history); + } }); profileVm.statsPromise.then(function(data) { vm.typeStats = ProfileService.getChallengeTypeStats( diff --git a/app/profile/subtrack/subtrack.spec.js b/app/profile/subtrack/subtrack.spec.js index a65d7e571..6db061c75 100644 --- a/app/profile/subtrack/subtrack.spec.js +++ b/app/profile/subtrack/subtrack.spec.js @@ -6,6 +6,7 @@ describe('SubTrack Controller', function() { var mockStats = mockData.getMockStats(); var mockSkills = mockData.getMockSkills(); var mockChallenges = mockData.getMockiOSChallenges(); + var mockHistory = mockData.getMockHistory(); var apiUrl; var track = 'develop', subTrack = 'development'; var profileScope, scope; @@ -57,6 +58,10 @@ describe('SubTrack Controller', function() { .when('GET', apiUrl + '/members/rakesh/stats/') .respond(200, {result: {content: mockStats}}); // mock skills + $httpBackend + .when('GET', apiUrl + '/members/albertwang/stats/history/') + .respond(200, mockHistory); + // mock history $httpBackend .when('GET', apiUrl + '/members/rakesh/skills/') .respond(200, {result: {content: mockSkills}}); @@ -67,6 +72,13 @@ describe('SubTrack Controller', function() { deferred.resolve(resp); return deferred.promise; }); + + sinon.stub(profileService, 'getHistoryStats', function(handle) { + var deferred = $q.defer(); + var resp = {}; + deferred.resolve(resp); + return deferred.promise; + }); }); afterEach(function() { diff --git a/app/settings/update-password/update-password.spec.js b/app/settings/update-password/update-password.spec.js index 5d567f42b..0713d7901 100644 --- a/app/settings/update-password/update-password.spec.js +++ b/app/settings/update-password/update-password.spec.js @@ -12,6 +12,10 @@ describe('Update Password Controller', function() { }; vm = $controller('UpdatePasswordController', { + userData: { + handle: 'foo', + email: 'bar' + }, UserService: { getUserIdentity: function() { return { diff --git a/app/skill-picker/skill-picker.spec.js b/app/skill-picker/skill-picker.spec.js index a7154bc20..bcc3b535f 100644 --- a/app/skill-picker/skill-picker.spec.js +++ b/app/skill-picker/skill-picker.spec.js @@ -3,11 +3,10 @@ describe('Skill Picker Controller', function() { var vm; beforeEach(function() { - bard.appModule('tc.settings'); + bard.appModule('tc.skill-picker'); bard.inject(this, '$controller', '$rootScope', '$q'); vm = $controller('SkillPickerController', { - userData: userData }); }); @@ -17,8 +16,4 @@ describe('Skill Picker Controller', function() { expect(vm).to.exist; }); - describe('user data', function() { - - }); - }); diff --git a/tests/test-helpers/mock-data.js b/tests/test-helpers/mock-data.js index 9f8531149..b9d332cfb 100644 --- a/tests/test-helpers/mock-data.js +++ b/tests/test-helpers/mock-data.js @@ -14,6 +14,7 @@ var mockData = (function() { getMockUserProfile: getMockUserProfile, getMockMarathons: getMockMarathons, getMockProfile: getMockProfile, + getMockHistory: getMockHistory, getMockStats: getMockStats, getMockSkills: getMockSkills, getMockSRMs: getMockSRMs, @@ -1291,6 +1292,68 @@ var mockData = (function() { }; } + function getMockHistory() { + return { + "id": "-306aafb8:14f65e30765:-8000", + "result": { + "success": true, + "status": 200, + "metadata": null, + "content": { + "updatedAt": null, + "createdAt": null, + "createdBy": null, + "updatedBy": null, + "userId": 151743, + "handle": "Ghostar", + "DEVELOP": { + "subTracks": [ + { + "id": 112, + "name": "DESIGN", + "history": [ + { + "challengeId": 30009817, + "challengeName": "Disney Marine Munch - Flash Game Module Architecture", + "ratingDate": "2010-02-28T13:00:00.000Z", + "newRating": 1172 + } + ] + }, + { + "id": 125, + "name": "ASSEMBLY_COMPETITION", + "history": [ + { + "challengeId": 30007872, + "challengeName": "Best Buy Blackberry Web Application Wrapper Assembly", + "ratingDate": "2009-10-18T23:30:00.000Z", + "newRating": 1515 + }, + { + "challengeId": 30008010, + "challengeName": "Best Buy Android Web Application Wrapper Assembly", + "ratingDate": "2009-10-24T01:00:00.000Z", + "newRating": 1566 + } + ] + } + ] + }, + "DATA_SCIENCE": { + "SRM": { + "history": [] + }, + "MARATHON_MATCH": { + "history": [] + } + } + } + }, + "version": "v3" + } + } + function getMockStats() { return { "updatedAt": null,