diff --git a/app/controllers/main.controller.js b/app/controllers/main.controller.js index 943bb0e..fe5603a 100644 --- a/app/controllers/main.controller.js +++ b/app/controllers/main.controller.js @@ -1,151 +1,154 @@ var pageviewChartModel = require('../models/pageviewchart.model'); module.exports = function($scope, pageViews, searchService, chartService) { chart = chartService.createChart('myChart', new pageviewChartModel()); + + chart.setDateRange( + new Date(Date.parse("2016-01-01")), + new Date(Date.parse("2016-04-01")) + ); + $scope.groups = []; $scope.search = { str: "", list: [] }; $scope.chart = { selected: "Line" }; $scope.addNewArticle = function (name) { pageViews.query({ project: "sv.wikipedia", article: name, from: "20160101", to: "20160401", }).$promise.then(function(result) { result.article.name = name; $scope.groups.push({ articles:[result.article], name: name }); chart.addDataset(name, result.article.views); - chart.setDateRange( - new Date(Date.parse("2016-01-01")), - new Date(Date.parse("2016-04-01")) - ); + }); $scope.search = { str: "", list: [] }; }; $scope.projects = [ // TODO: Proper externalization and language checking {name: "Wikipedia", url: "$lang$.wikipedia", multilang: true}, {name: "Wikiversity", url: "$lang$.wikiversity", multilang: true}, {name: "Wikisource", url: "$lang$.wikisource", multilang: true}, {name: "Wikinews", url: "$lang$.wikinews", multilang: true}, {name: "Wikibooks", url: "$lang$.wikibooks", multilang: true}, {name: "Wikiquote", url: "$lang$.wikiquote", multilang: true}, {name: "Wikispecies", url: "species.wikimedia", multilang: false}, {name: "Wikivoyage", url: "$lang$.wikivoyage", multilang: true}, {name: "Wikidata", url: "www.wikidata", multilang: false}, {name: "Wikicommons", url: "commons.wikimedia", multilang: false}, {name: "Metawiki", url: "meta.wikimedia", multilang: false} ]; $scope.chosen = { proj: $scope.projects[0].name, lang: "Svenska" }; $scope.changeChosen = function(name, dropdown){ $scope.chosen[dropdown] = name; }; $scope.$watch('search.str.length', function () { var searchstr = $scope.search.str; if(searchstr.length <= 0) { $scope.search.list = []; return; } searchService.query({ namespace: 'sv.wikipedia', //TODO str: searchstr }).then(function(data) { if($scope.search.str == searchstr) $scope.search.list = data.data; }); }); // DATEPICKER // TODO: Move everything related to bottom bar date pickers // to separate controller $scope.today = function() { $scope.dt = new Date(); }; $scope.today(); $scope.clear = function() { $scope.dt = null; }; $scope.inlineOptions = { customClass: getDayClass, minDate: new Date(), showWeeks: true }; $scope.dateOptions = { formatYear: 'yy', maxDate: new Date(), minDate: new Date(), startingDay: 1 }; $scope.toggleMin = function() { $scope.inlineOptions.minDate = $scope.inlineOptions.minDate ? null : new Date(); $scope.dateOptions.minDate = $scope.inlineOptions.minDate; }; $scope.toggleMin(); $scope.openFrom = function() { $scope.popupFrom.opened = true; }; $scope.openTo = function() { $scope.popupTo.opened = true; }; $scope.setDate = function (year, month, day) { $scope.dt = new Date(year, month, day); }; $scope.popupFrom = { opened: false }; $scope.popupTo = { opened: false }; function getDayClass(data) { var date = data.date, mode = data.mode; if (mode === 'day') { var dayToCheck = new Date(date).setHours(0, 0, 0, 0); for (var i = 0; i < $scope.events.length; i++) { var currentDay = new Date($scope.events[i].date).setHours(0, 0, 0, 0); if (dayToCheck === currentDay) { return $scope.events[i].status; } } } return ''; } }; diff --git a/app/directives/highchart.directive.js b/app/directives/highchart.directive.js index 38c2754..ffa3cb4 100644 --- a/app/directives/highchart.directive.js +++ b/app/directives/highchart.directive.js @@ -1,50 +1,49 @@ module.exports = function(chartService) { return { restrict: 'E', link: function(scope, element, attrs) { - function updateChart() - { - var series = []; - var datasets = scope.chartModel.getDatasets(); - - for (var name in datasets) - { - series.push({animation: false, name: name, data: datasets[name]}); - } - - // will running this again and again properly (no leaks) replace the stuff - // that existed previously? are there more effecient ways to control - // highcharts? ("restarting" is probably the least efficient way!) - $(function () { + scope.chartModel = chartService.getChart(attrs.chartName); + // will running this again and again properly (no leaks) replace the stuff + // that existed previously? are there more effecient ways to control + // highcharts? ("restarting" is probably the least efficient way!) + $(function () { $(element).highcharts({ chart: { type: 'line', animation: true, }, credits: { enabled: false }, title: { text: 'Page Views' }, xAxis: { categories: scope.chartModel.getXAxisValues() }, yAxis: { title: { text: 'Views' }, }, - series: series + series: [] }); + }); + + function addSeries() { + var set = scope.chartModel.getLatest(); + $(element).highcharts().addSeries({ + data: set.values, + name: set.name }); + } scope.chartModel = chartService.getChart(attrs.chartName); - scope.$watch('chartModel', updateChart, true); + scope.$watch('chartModel', addSeries, true); } }; }; diff --git a/app/models/pageviewchart.model.js b/app/models/pageviewchart.model.js index 0f069ac..bcce92e 100644 --- a/app/models/pageviewchart.model.js +++ b/app/models/pageviewchart.model.js @@ -1,118 +1,125 @@ /** * Pageviews chart data model. * * @author Mikael Forsberg * @version 20160421T0822 */ module.exports = function() { /** * Date range starting date. */ this.dateRangeFrom = new Date(); /** * Date range ending date. */ this.dateRangeTo = new Date(); /** * Y-value data sets. */ this.datasets = {}; + this.latest = null; // "constructor" begins this.dateRangeFrom.setUTCHours(0); this.dateRangeFrom.setUTCMinutes(0); this.dateRangeFrom.setUTCSeconds(0); this.dateRangeFrom.setUTCMilliseconds(0); this.dateRangeTo.setUTCHours(0); this.dateRangeTo.setUTCMinutes(0); this.dateRangeTo.setUTCSeconds(0); this.dateRangeTo.setUTCMilliseconds(0); // default date range is one week ending at today's date this.dateRangeFrom.setDate(this.dateRangeFrom.getDate() - 7); // "constructor" ends /** * Set the date range. The starting date must be an earlier date * than the ending date for the range to be considered valid. * * @param Date from Start of date range * @param Date to End of date range * @return Boolean True if given a valid range, False otherwise. */ this.setDateRange = function(from, to) { if (from.getTime() >= to.getTime()) { return false; } this.dateRangeFrom = from; this.dateRangeTo = to; return true; }; /** * Add a Y-value dataset. There must be one numeric value in yValues * for each distinct date contained in the current date range, and the * values must be in chronological order. * * @param String name Name of new dataset * @param Array yValues Array of numeric Y-values * @return void */ this.addDataset = function(name, yValues) { + this.latest = {name: name, values: yValues}; this.datasets[name] = yValues; }; + + this.getLatest = function() + { + return this.latest; + }; /** * Remove a dataset. * * @param String name Name of dataset to remove * @return void */ this.removeDataset = function(name) { delete this.datasets[name]; }; /** * Retrieve all datasets. * * @return Object */ this.getDatasets = function() { return this.datasets; }; /** * Retrieve the X-axis "values" or "tick labels", i.e. the * distinct dates contained in the current date range. * * @return Date[] */ this.getXAxisValues = function() { var values = []; var at = new Date(this.dateRangeFrom); var stop = this.dateRangeTo.getTime(); while (at.getTime() < stop) { values.push(new Date(at).toISOString().slice(0, 10)); at.setDate(at.getDate() + 1); } return values; }; };