diff --git a/app/controllers/main.controller.js b/app/controllers/main.controller.js index 3388baa..510e9de 100644 --- a/app/controllers/main.controller.js +++ b/app/controllers/main.controller.js @@ -1,170 +1,174 @@ var pageviewChartModel = require('../models/pageviewchart.model'); module.exports = function($scope, pageViews, searchService, chartService) { chart = chartService.createChart('myChart', new pageviewChartModel()); $scope.dateFrom = new Date(Date.parse("2016-01-01")); $scope.dateTo = new Date(Date.parse("2016-04-01")); - chart.setDateRange($scope.dateFrom, $scope.dateTo); - + chart.getModel().setDateRange($scope.dateFrom, $scope.dateTo); $scope.groups = []; $scope.search = { str: "", list: [] }; $scope.chart = { - selected: "Line" + selected: 'line' }; - + + $scope.$watch('chart.selected', function() + { + chart.setType($scope.chart.selected); + }); + $scope.dateToStr = function(date) { var day = date.getDate() + ''; var month = date.getMonth() + 1 + ''; var year = date.getFullYear() + ''; var month = month < 10 ? '0' + month: month; var day = day < 10 ? '0' + day: day; return year+month+day; }; $scope.addNewArticle = function (name) { pageViews.query({ project: "sv.wikipedia", article: name, from: $scope.dateToStr($scope.dateFrom), to: $scope.dateToStr($scope.dateTo), }).$promise.then(function(result) { result.article.name = name; $scope.groups.push({ articles:[result.article], name: name }); - chart.addDataset(name, result.article.views); + chart.getModel().addDataset(name, result.article.views); }); $scope.search = { str: "", list: [] }; }; function reloadAll() { var g = angular.copy($scope.groups, g); $scope.groups = []; - chart.clearDataset(); + chart.getModel().clearDatasets(); angular.forEach(g, function (val, key) { $scope.addNewArticle(val.name); }); - chart.setDateRange($scope.dateFrom, $scope.dateTo); + chart.getModel().setDateRange($scope.dateFrom, $scope.dateTo); } $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.searchArticle = function (str) { var searchstr = str; return searchService.query({ namespace: 'sv.wikipedia', //TODO str: searchstr }).then(function(response) { return response.data.url; }); }; // 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 }; $scope.$watch('dateFrom', reloadAll); $scope.$watch('dateTo', reloadAll); 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 d15eeab..7ba7d66 100644 --- a/app/directives/highchart.directive.js +++ b/app/directives/highchart.directive.js @@ -1,56 +1,181 @@ module.exports = function(chartService) { return { restrict: 'E', - + scope: {}, // isolate scope link: function(scope, element, attrs) { - 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 () { + // var seriesAdapterInterface = { + // type: 'string' // passed to highcharts as chart type, + // init: function(chart); // initialize the chart + // add: function(chart, datasets, name); // add a data series to the chart + // setXAxis: function(chart); // configure the x-axis + // }; + + var lineSeriesAdapter = { + type: 'line', + + init: function(chart) + { + chart.xAxis[0].setCategories(scope.chartModel.getXAxisValues()); + }, + + add: function(chart, datasets, name) + { + chart.addSeries({ + name: name, + data: datasets[name] + }); + }, + + setXAxis: function(chart) + { + chart.xAxis[0].setCategories(scope.chartModel.getXAxisValues()); + } + }; + + var pieSeriesAdapter = { + type: 'pie', + + init: function(chart) + { + chart.xAxis[0].setCategories([]); + chart.addSeries({name: 'Total Views', data: []}); + }, + + add: function(chart, datasets, name) + { + chart.series[0].addPoint({ + name: name, + y: datasets[name].reduce(function(a, b) { return a + b; }, 0) + }); + }, + + setXAxis: function(chart) { } + }; + + var columnSeriesAdapter = { + type: 'column', + + init: function(chart) + { + chart.xAxis[0].setCategories([]); + chart.addSeries({name: 'Total Views'}); + }, + + add: function(chart, datasets, name) + { + console.log(name); + chart.series[0].addPoint({ + name: name, + y: datasets[name].reduce(function(a, b) { return a + b; }, 0) + }); + }, + + setXAxis: function(chart) { } + }; + + scope.chart = chartService.getChart(attrs.chartName); + scope.chartModel = chart.getModel(); + + if (attrs.chartType == 'pie') + { + scope.chart.setType('pie'); + scope.chartSeriesAdapter = pieSeriesAdapter; + } + else if (attrs.chartType == 'column') + { + scope.chart.setType('column'); + scope.chartSeriesAdapter = columnSeriesAdapter; + } + else + { + scope.chart.setType('line'); + scope.chartSeriesAdapter = lineSeriesAdapter; + } + + $(function () + { + var initchart = function() + { $(element).highcharts({ chart: { - type: 'line', - animation: true, + type: scope.chartSeriesAdapter.type, + animation: true }, credits: { enabled: false }, + plotOptions: { + pie: { + dataLabels: { + format: '{point.name}: {point.percentage:.1f} %' + } + } + }, + tooltip: { + shared: true, + crosshairs: { + width: 1, + color: 'rgba(0,0,0,0.2)' + } + }, title: { text: 'Page Views' }, - xAxis: { - categories: scope.chartModel.getXAxisValues() - }, + xAxis: {}, // configured a bit later by chartSeriesAdapter.init yAxis: { title: { text: 'Views' - }, - }, - series: [] + } + } + // series: configured a bit later by chartSeriesAdapter.init/add }); - }); - - function addSeries() { - var set = scope.chartModel.getLatest(); - var chart = $(element).highcharts(); - if(set == null) { - while(chart.series.length > 0) - chart.series[0].remove(true); - return; - } - chart.addSeries({ - data: set.values, - name: set.name + + var chart = $(element).highcharts(); + var datasets = scope.chartModel.getDatasets(); + var setnames = Object.keys(datasets); + + scope.chartSeriesAdapter.init(chart); + + for (var i in setnames) + { + scope.chartSeriesAdapter.add(chart, datasets, setnames[i]); + } + }; + + initchart(); + + scope.chartModel.addEventListener('datasetadded', function(name) + { + scope.chartSeriesAdapter.add($(element).highcharts(), scope.chartModel.getDatasets(), name); }); - chart.xAxis[0].setCategories( scope.chartModel.getXAxisValues()); - - } - - scope.chartModel = chartService.getChart(attrs.chartName); - scope.$watch('chartModel', addSeries, true); + + scope.chartModel.addEventListener('daterangechanged', function() + { + console.log('date change'); + scope.chartSeriesAdapter.setXAxis($(element).highcharts()); + initchart(); + }); + + scope.$watch('chart.getType()', function(type) + { + if (type == 'pie') + { + scope.chartSeriesAdapter = pieSeriesAdapter; + } + else if (type == 'column') + { + scope.chartSeriesAdapter = columnSeriesAdapter; + } + else + { + scope.chartSeriesAdapter = lineSeriesAdapter; + } + + initchart(); + }); + }); } }; }; diff --git a/app/index.html b/app/index.html index 68b0f4f..676ab10 100644 --- a/app/index.html +++ b/app/index.html @@ -1,154 +1,154 @@