Skip to content

Commit

Permalink
Merge branch 'develop' into feature/album-directive
Browse files Browse the repository at this point in the history
Conflicts:
	app/less/main.less
  • Loading branch information
edoparearyee committed Jul 27, 2015
2 parents ac77bc9 + 89f75c5 commit cc0ebab
Show file tree
Hide file tree
Showing 17 changed files with 653 additions and 34 deletions.
3 changes: 3 additions & 0 deletions app/index.html
Expand Up @@ -143,6 +143,9 @@
<script src="js/stats/services/DateUtils.js"></script>
<script src="js/stats/services/StatsResolver.js"></script>

<script src="js/users/users.js"></script>
<script src="js/users/controllers/UserStatsCtrl.js"></script>

<script src="js/app.js"></script>
<!-- /build -->
<!--<![endif]-->
Expand Down
6 changes: 6 additions & 0 deletions app/js/api/factories/UsersResource.js
Expand Up @@ -25,6 +25,12 @@ angular.module("FM.api.UsersResource",[
// Default values for url parameters.
{
id: "@id"
},
{
stats: {
method: "GET",
url: env.FM_API_SERVER_ADDRESS + "users" + "/:id/stats"
}
}
);

Expand Down
1 change: 1 addition & 0 deletions app/js/app.js
Expand Up @@ -19,6 +19,7 @@ angular.module("FM", [
"FM.loadingScreen",
"FM.nav",
"FM.stats",
"FM.users",
"ngRoute",
"notification",
"config"
Expand Down
25 changes: 1 addition & 24 deletions app/js/stats/controllers/StatsCtrl.js
Expand Up @@ -142,30 +142,7 @@ angular.module("FM.stats.StatsCtrl", [
*/
$scope.loadHistoricData = function loadHistoricData (startDate, endDate) {

startDate = new Date(startDate);
endDate = endDate ? new Date(endDate) : new Date();

/**
* Difference in days between filter start and end dates
* @property {Number} diff
*/
var diff = (startDate.getTime() - endDate.getTime()) / (24 * 60 * 60 * 1000);

/**
* Calculated dates for historic data, based on filter dates
* Eg. if the filter period is 1 week this will be 1 week before, 2 weeks before and 3 weeks before
* @property {Array} dates
*/
var dates = [{
from: $filter("date")(new Date().setDate(startDate.getDate() + diff), "yyyy-MM-dd"),
to: $filter("date")(new Date().setDate(startDate.getDate() - 1), "yyyy-MM-dd"),
},{
from: $filter("date")(new Date().setDate(startDate.getDate() + (diff * 2)), "yyyy-MM-dd"),
to: $filter("date")(new Date().setDate(startDate.getDate() + (diff) - 1), "yyyy-MM-dd"),
},{
from: $filter("date")(new Date().setDate(startDate.getDate() + (diff * 3)), "yyyy-MM-dd"),
to: $filter("date")(new Date().setDate(startDate.getDate() + (diff * 2) - 1), "yyyy-MM-dd"),
}];
var dates = DateUtils.historicDatePeriods(startDate, endDate, 3);

// request historic data from API using calculated date ranges
$q.all([
Expand Down
40 changes: 39 additions & 1 deletion app/js/stats/services/DateUtils.js
Expand Up @@ -26,8 +26,9 @@ angular.module("FM.stats.DateUtils", [
* @returns {Object}
*/
.service("DateUtils", [
"$filter",
"LAST_WEEK",
function (LAST_WEEK) {
function ($filter, LAST_WEEK) {

/**
* Return last occurence of a day in the week
Expand All @@ -42,5 +43,42 @@ angular.module("FM.stats.DateUtils", [
}
};

/**
* Return previous date periods from date range
* E.g. given this week as a date range this will return last week, two weeks ago, three weeks ago etc
* @method historicDatePeriods
* @param {Date} startDate
* @param {Date} endDate
* @param {Number} numberOfPeriods
*/
this.historicDatePeriods = function historicDatePeriods (startDate, endDate, numberOfPeriods) {

startDate = new Date(startDate);
endDate = endDate ? new Date(endDate) : new Date();

/**
* Difference in days between filter start and end dates
* @property {Number} diff
*/
var diff = (startDate.getTime() - endDate.getTime()) / (24 * 60 * 60 * 1000);

/**
* Calculated dates for historic data, based on filter dates
* Eg. if the filter period is 1 week this will be 1 week before, 2 weeks before and 3 weeks before
* @property {Array} dates
*/
var dates = [];

for (var i = 1; i <= numberOfPeriods; i++) {
dates.push({
from: $filter("date")(new Date().setDate(startDate.getDate() + (diff * i)), "yyyy-MM-dd"),
to: $filter("date")(new Date().setDate(startDate.getDate() + (diff * (i - 1)) - 1), "yyyy-MM-dd"),
});
}

return dates;

};

}
]);
193 changes: 193 additions & 0 deletions app/js/users/controllers/UserStatsCtrl.js
@@ -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();

}
]);
8 changes: 8 additions & 0 deletions app/js/users/users.js
@@ -0,0 +1,8 @@
"use strict";
/**
* @module FM.users
* @author SOON_
*/
angular.module("FM.users", [
"FM.users.UserStatsCtrl"
]);
13 changes: 13 additions & 0 deletions app/less/default/core/variables.less
Expand Up @@ -187,6 +187,19 @@
//** Element ID within SVG icon file.
@icon-font-svg-id: "icomoon";

//== Navs
//
//##

//=== Shared nav styles
@nav-link-hover-bg: @lighter-black;

//== Tabs
@nav-tabs-border-color: @lighter-black;
@nav-tabs-link-hover-border-color: @lighter-black;
@nav-tabs-active-link-hover-bg: @lighter-black;
@nav-tabs-active-link-hover-color: @lighter-black;

//== Popovers
//
//##
Expand Down
21 changes: 21 additions & 0 deletions app/less/default/modules/navs.less
@@ -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;
}
33 changes: 33 additions & 0 deletions app/less/default/modules/profile.less
@@ -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;
}
}
}

0 comments on commit cc0ebab

Please sign in to comment.