Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'develop' into feature/album-directive
Conflicts: app/less/main.less
- Loading branch information
Showing
17 changed files
with
653 additions
and
34 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,193 @@ | ||
"use strict"; | ||
/** | ||
* @module FM.users.UserStatsCtrl | ||
* @author SOON_ | ||
*/ | ||
angular.module("FM.users.UserStatsCtrl", [ | ||
"FM.api.UsersResource", | ||
"FM.stats", | ||
"ngRoute", | ||
"chart.js", | ||
"ui.bootstrap.datepicker" | ||
]) | ||
/** | ||
* @method config | ||
* @param {Provider} $routeProvider | ||
*/ | ||
.config([ | ||
"$routeProvider", | ||
function ($routeProvider) { | ||
|
||
$routeProvider | ||
.when("/users/:id", { | ||
templateUrl: "partials/user-stats.html", | ||
controller: "UserStatsCtrl", | ||
resolve: { | ||
stats: ["UsersResource", "$route", function (UsersResource, $route){ | ||
return UsersResource.stats($route.current.params).$promise; | ||
}], | ||
user: ["UsersResource", "$route", function (UsersResource, $route){ | ||
return UsersResource.get($route.current.params).$promise; | ||
}] | ||
} | ||
}); | ||
|
||
} | ||
]) | ||
/** | ||
* @constructor | ||
* @class UserStatsCtrl | ||
* @param {Object} $scope Scoped application data | ||
* @param {Service} $q Angular promise service | ||
* @param {Service} $filter Angular filter service | ||
* @param {Service} $location Angular URL service | ||
* @param {Service} DateUtils Date helper functions | ||
* @param {Array} CHART_COLOURS List of global chart colours | ||
* @param {Object} CHART_OPTIONS ChartJS config options | ||
* @param {Resource} StatsResource Provides communication with stats API endpoint | ||
* @param {Object} stats User's stats resolved from API | ||
* @param {Object} user User object resolved from API | ||
*/ | ||
.controller("UserStatsCtrl", [ | ||
"$scope", | ||
"$q", | ||
"$filter", | ||
"$location", | ||
"DateUtils", | ||
"CHART_COLOURS", | ||
"CHART_OPTIONS", | ||
"UsersResource", | ||
"stats", | ||
"user", | ||
function ($scope, $q, $filter, $location, DateUtils, CHART_COLOURS, CHART_OPTIONS, UsersResource, stats, user) { | ||
|
||
/** | ||
* User | ||
* @property {Object} user | ||
*/ | ||
$scope.user = user; | ||
|
||
/** | ||
* User's stats resolved from API | ||
* @property {Object} stats | ||
*/ | ||
$scope.stats = stats; | ||
|
||
/** | ||
* Current search params | ||
* @property {Object} search | ||
*/ | ||
$scope.search = $location.search(); | ||
|
||
/** | ||
* @property {Object} filter | ||
*/ | ||
$scope.filter = {}; | ||
|
||
/** | ||
* Track open status of datepickers | ||
* @property {Object} datepickerOpened | ||
*/ | ||
$scope.datepickerOpened = { | ||
from: "", | ||
to: "" | ||
}; | ||
|
||
/** | ||
* List of colours to use for charts | ||
* @property {Array} chartColours | ||
*/ | ||
$scope.chartColours = CHART_COLOURS; | ||
|
||
/** | ||
* ChartJS config for play time line graph | ||
* @property {Object} playTime | ||
*/ | ||
$scope.playTime = { | ||
data: [[]], | ||
series: [user.display_name], // jshint ignore:line | ||
labels: [], | ||
options: CHART_OPTIONS | ||
}; | ||
|
||
/** | ||
* Load historic play time statistics for line chart based on filter start/end dates | ||
* @method loadHistoricData | ||
* @param {String} startDate Filter start date | ||
* @param {String} endDate Filter end date | ||
*/ | ||
$scope.loadHistoricData = function loadHistoricData (startDate, endDate) { | ||
|
||
var dates = DateUtils.historicDatePeriods(startDate, endDate, 3); | ||
|
||
// request historic data from API using calculated date ranges | ||
$q.all([ | ||
UsersResource.stats({ from: dates[0].from, to: dates[0].to, id: user.id }).$promise, | ||
UsersResource.stats({ from: dates[1].from, to: dates[1].to, id: user.id }).$promise, | ||
UsersResource.stats({ from: dates[2].from, to: dates[2].to, id: user.id }).$promise | ||
]).then(function (responses) { | ||
responses.forEach(function (response, index) { | ||
// add data to play time chart dataset | ||
$scope.playTime.labels.unshift($filter("date")(dates[index].from, "dd-MM-yyyy")); | ||
// convert milliseconds to minutes | ||
$scope.playTime.data[0].unshift(Math.round(response.total_play_time / 1000 / 60)); // jshint ignore:line | ||
}); | ||
}); | ||
}; | ||
|
||
/** | ||
* Filter stats by dates | ||
* @method updateFilter | ||
*/ | ||
$scope.updateFilter = function updateFilter () { | ||
if ($scope.filter.to) { | ||
$scope.search.to = $scope.filter.to.toISOString ? $filter("date")($scope.filter.to.toISOString(), "yyyy-MM-dd") : $scope.filter.to; | ||
} else { | ||
$scope.search.to = undefined; | ||
} | ||
if ($scope.filter.from) { | ||
$scope.search.from = $scope.filter.from.toISOString ? $filter("date")($scope.filter.from.toISOString(), "yyyy-MM-dd") : $scope.filter.from; | ||
} else { | ||
$scope.search.from = undefined; | ||
$scope.search.all = true; | ||
} | ||
$location.search($scope.search); | ||
}; | ||
|
||
/** | ||
* Open datepicker | ||
* @method updateFilter | ||
*/ | ||
$scope.openDatepicker = function openDatepicker($event, id) { | ||
$event.preventDefault(); | ||
$event.stopPropagation(); | ||
$scope.datepickerOpened[id] = !$scope.datepickerOpened[id] ; | ||
}; | ||
|
||
/** | ||
* Set current filter params and load historic data on initalise | ||
* @method init | ||
*/ | ||
$scope.init = function init () { | ||
|
||
$scope.filter.from = $scope.search.from || undefined; | ||
$scope.filter.to = $scope.search.to || undefined; | ||
|
||
// set max datepicker date to today | ||
$scope.datepickerMaxDate = new Date(); | ||
|
||
if ($scope.filter.from) { | ||
// Format total play time per user stats for charts | ||
$scope.playTime.labels.unshift($filter("date")($scope.filter.from, "dd-MM-yyyy")); | ||
// convert milliseconds to minutes | ||
$scope.playTime.data[0].unshift(Math.round(stats.total_play_time / 1000 / 60)); // jshint ignore:line | ||
|
||
// Load additional data for play time line chart | ||
$scope.loadHistoricData($scope.filter.from, $scope.filter.to); | ||
} | ||
}; | ||
|
||
$scope.init(); | ||
|
||
} | ||
]); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
"use strict"; | ||
/** | ||
* @module FM.users | ||
* @author SOON_ | ||
*/ | ||
angular.module("FM.users", [ | ||
"FM.users.UserStatsCtrl" | ||
]); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
// | ||
// Navs | ||
// -------------------------------------------------- | ||
|
||
|
||
// Tabs | ||
.nav-tabs { | ||
margin-bottom: 20px; | ||
} | ||
|
||
.nav-tabs > li > a { | ||
border-radius: 0; | ||
} | ||
|
||
.nav-tabs > li.active > a, | ||
.nav-tabs > li.active > a:hover, | ||
.nav-tabs > li.active > a:focus { | ||
border: none; | ||
border-bottom: 2px solid @brand-primary; | ||
color: @white; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
// | ||
// Profile | ||
// -------------------------------------------------- | ||
|
||
.profile { | ||
.flex-box(); | ||
.align-items(stretch); | ||
.flex-direction(row); | ||
.flex-wrap(nowrap); | ||
.justify-content(flex-start); | ||
margin-top: 20px; | ||
margin-bottom: 40px; | ||
|
||
.avatar { | ||
.flex(3); | ||
.align-self(center); | ||
|
||
img { | ||
.img-responsive(); | ||
.img-circle(); | ||
} | ||
} | ||
|
||
.name { | ||
.flex(9); | ||
.align-self(center); | ||
margin-left: @grid-gutter-width * 2; | ||
|
||
h1 { | ||
margin: 0; | ||
} | ||
} | ||
} |
Oops, something went wrong.