Merge branch 'master' into utf8

This commit is contained in:
nikolark committed 2016-11-16 22:06:43 +01:00
commit e9b4b82d7e
3 files changed
+281 -150

No files matched your search

+55 -150
View File
@@ -1,5 +1,14 @@
<?php
function is_valid_start_param() {
return isset($_GET['start']) && strlen($_GET['start']) > 0 && date_create($_GET['start']);
}
$semester_start = date_create('first day of august');
if($semester_start > date_create()) {
$semester_start = date_modify($semester_start, '-1 year');
}
$start = is_valid_start_param() ? date_create($_GET['start']) : $semester_start;
?>
<!DOCTYPE html>
<html>
@@ -7,163 +16,59 @@
<meta charset="utf-8">
<title>Medlemsstatistikk - Det Norske Studentersamfund</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" media="all" href="../snapporder/css/style.css" />
<script src="https://code.jquery.com/jquery-2.1.4.js"></script>
<script src="https://code.highcharts.com/highcharts.src.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.10.6/moment.js"></script>
<script>
var barSales;
var appSales;
var smsSales;
var salesChart;
var salesChartToday;
var urls = {
cards: 'https://kassa.neuf.no/stats/card-sales/',
tekstmelding: 'https://tekstmelding.neuf.no/stats/memberships/',
snapporder: '/stats/snapporder.php'
};
function sumSales(memo, num) {
return memo + num.sales;
}
function toHighchartsSeries(memberships) {
return _.map(memberships, function (el) {
return [moment.utc(el.date).valueOf(), el.sales]
});
}
function getBarSales() {
return $.getJSON(urls.cards, function(data) {
barSales = data.memberships;
salesChart.addSeries({name: 'Bar-salg', data: toHighchartsSeries(barSales)});
});
}
function getSmsSales() {
return $.getJSON(urls.tekstmelding, function(data) {
smsSales = data.memberships;
salesChart.addSeries({name: 'SMS-salg', data: toHighchartsSeries(smsSales)});
});
}
function getAppSales() {
return $.getJSON(urls.snapporder, function (data) {
appSales = data.memberships;
salesChart.addSeries({name: 'App-salg', data: toHighchartsSeries(appSales)});
});
}
$(document).ready(function() {
Highcharts.setOptions({
credits: {enabled: false}
});
salesChart = new Highcharts.Chart({
chart: {
renderTo: 'sales-chart'
},
title: {
text: false
},
xAxis: {
type: "datetime"
},
yAxis: {
title: {
text: "Salg"
},
min: 0
},
plotOptions: {
series: {
marker: {
radius: 4
}
}
},
series: []
});
$.when(getSmsSales(), getAppSales(), getBarSales()).done(function() {
/* Totals */
var barTotal = _.reduce(barSales, sumSales, 0);
$('.bar').html(barTotal);
var smsTotal = _.reduce(smsSales, sumSales, 0);
$('.sms').html(smsTotal);
var appTotal = _.reduce(appSales, sumSales, 0);
$('.app').html(appTotal);
$('.sum').html(barTotal + smsTotal + appTotal);
/* Today */
var today = moment.utc().format('YYYY-MM-DD');
$('.today-date-wrap').text(today);
var todayBarSales = _.findWhere(barSales, {date:today}) || {sales: 0};
$('.bar-today').html(todayBarSales.sales);
var todaySmsSales = _.findWhere(smsSales, {date:today}) || {sales: 0};
$('.sms-today').html(todaySmsSales.sales);
var todayAppSales = _.findWhere(appSales, {date:today}) || {sales: 0};
$('.app-today').html(todayAppSales.sales);
$('.sum-today').html(todayBarSales.sales + todaySmsSales.sales + todayAppSales.sales);
salesChartToday = new Highcharts.Chart({
chart: {
renderTo: 'sales-chart-today',
plotBackgroundColor: null,
plotBorderWidth: null,
plotShadow: false,
type: 'pie'
},
title: {
text: false
},
series: [{
name: 'Salg', data: [
{name: 'Bar-salg', y: todayBarSales.sales},
{name: 'SMS-salg', y: todaySmsSales.sales},
{name: 'App-salg', y: todayAppSales.sales}
]}
]
});
});
});
</script>
<style>
.big-number {
font-weight: bold;
font-size: 1.5em;
}
</style>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<link rel="stylesheet" href="stats.css">
</head>
<body>
<div class="container">
<h2>Salg per dag</h2>
<em>Fra 1. august 2015</em>
<div id="sales-chart"></div>
<h2>Salg totalt</h2>
<div id="sums">
<div>SMS: <span class="sms big-number"></span></div>
<div>App: <span class="app big-number"></span></div>
<div>Bar: <span class="bar big-number"></span></div>
<div>Totalt: <span class="sum big-number"></span></div>
<div class="row">
<div class="col-xs-12">
<h1>Medlemskapsstatistikk for DNS</h1>
<div class="disclaimer"><em>Disse tallene kan avvike fra faktiske salgtall.</em></div>
</div>
</div>
<h2>Salg idag</h2>
<em>Dato: <span class="today-date-wrap"></span></em>
<div id="sales-chart-today" style="min-width: 310px; height: 400px; max-width: 600px;"></div>
<div id="sums">
<div>SMS: <span class="sms-today big-number"></span></div>
<div>App: <span class="app-today big-number"></span></div>
<div>Bar: <span class="bar-today big-number"></span></div>
<div>Totalt: <span class="sum-today big-number"></span></div>
<div class="row">
<div class="col-xs-12 col-md-6">
<h2>Salg per dag</h2>
<label for="start">Fra</label> <input id="start" name="start" type="date" value="<?php echo date_format($start, 'Y-m-d'); ?>" />
<div id="sales-chart"></div>
<h3>Salg totalt</h3>
<div id="sums">
<div>SMS: <span class="sms big-number"></span></div>
<div>App: <span class="app big-number"></span></div>
<div>Bar: <span class="bar big-number"></span></div>
<div>Totalt: <span class="sum big-number"></span></div>
</div>
<hr>
<h2>Salg idag</h2>
<em>Dato: <span class="today-date-wrap"></span></em>
<div id="sales-chart-today" style="min-width: 310px; height: 400px; max-width: 600px;"></div>
<div id="sums">
<div>SMS: <span class="sms-today big-number"></span></div>
<div>App: <span class="app-today big-number"></span></div>
<div>Bar: <span class="bar-today big-number"></span></div>
<div>Totalt: <span class="sum-today big-number"></span></div>
</div>
</div>
<div class="col-xs-12 col-md-6">
<h2>Salg per dag</h2>
<button class="export-data-btn btn btn-default btn-sm"><span class="glyphicon glyphicon-download-alt"></span> Eksporter til CSV</button>
<table id="sales-table" class="table table-striped"></table>
</div>
</div>
<!--<div class="credits-wrap">
<div class="credits">Laget med <span class="love" title="kærlighed">♥</span> av <a href="http://kak.studentersamfundet.no/" title="Kommunikasjonsavdelingen">KAK</a></div>
</div>-->
<div class="disclaimer"><br><br><br><em>Disse tallene kan avvike fra faktiske salgtall.</em></div>
</div>
<script src="https://code.jquery.com/jquery-2.1.4.js"></script>
<script src="https://code.highcharts.com/highcharts.src.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.10.6/moment.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<script src="stats.js"></script>
</body>
</html>
+4
View File
@@ -0,0 +1,4 @@
.big-number {
font-weight: bold;
font-size: 1.5em;
}
+222
View File
@@ -0,0 +1,222 @@
/* FIXME: Make this more generic */
var saleTypes = ['bar', 'sms', 'app'];
var salesData = {};
var salesChart;
var salesChartToday;
var urls = {
cards: 'https://kassa.neuf.no/stats/card-sales/',
tekstmelding: 'https://tekstmelding.neuf.no/stats/memberships/',
snapporder: '/stats/snapporder.php'
};
function sumSales(memo, num) {
return memo + num.sales;
}
function toHighchartsSeries(memberships) {
memberships = _.sortBy(memberships, 'date');
return _.map(memberships, function (el) {
return [moment.utc(el.date).valueOf(), el.sales]
});
}
function getBarSales(start) {
return $.getJSON(urls.cards + '?start=' + start, function(data) {
salesData['bar'] = data.memberships;
salesChart.addSeries({name: 'Bar-salg', data: toHighchartsSeries(salesData['bar'])});
});
}
function getSmsSales(start) {
return $.getJSON(urls.tekstmelding + '?start=' + start, function(data) {
salesData['sms'] = data.memberships;
salesChart.addSeries({name: 'SMS-salg', data: toHighchartsSeries(salesData['sms'])});
});
}
function getAppSales(start) {
return $.getJSON(urls.snapporder + '?start=' + start, function (data) {
salesData['app'] = data.memberships;
salesChart.addSeries({name: 'App-salg', data: toHighchartsSeries(salesData['app'])});
});
}
function totals() {
var sum = 0;
_.each(saleTypes, function(type) {
var total = _.reduce(salesData[type], sumSales, 0);
$('.'+ type).html(total);
sum += total;
}) ;
$('.sum').html(sum);
}
function today() {
var today = moment.utc().format('YYYY-MM-DD');
$('.today-date-wrap').text(today);
var todayBarSales = _.findWhere(salesData['bar'], {date: today}) || {sales: 0};
$('.bar-today').html(todayBarSales.sales);
var todaySmsSales = _.findWhere(salesData['sms'], {date: today}) || {sales: 0};
$('.sms-today').html(todaySmsSales.sales);
var todayAppSales = _.findWhere(salesData['app'], {date: today}) || {sales: 0};
$('.app-today').html(todayAppSales.sales);
$('.sum-today').html(todayBarSales.sales + todaySmsSales.sales + todayAppSales.sales);
salesChartToday = new Highcharts.Chart({
chart: {
renderTo: 'sales-chart-today',
plotBackgroundColor: null,
plotBorderWidth: null,
plotShadow: false,
type: 'pie'
},
title: {
text: false
},
series: [{
name: 'Salg', data: [
{name: 'Bar-salg', y: todayBarSales.sales},
{name: 'SMS-salg', y: todaySmsSales.sales},
{name: 'App-salg', y: todayAppSales.sales}
]
}
]
});
}
function groupSalesByDate() {
var salesByDate = {};
_.each(saleTypes, function (type) {
_.each(salesData[type], function (el) {
var d = {};
d[el.date] = {};
d[el.date][type]= el.sales;
$.extend(true, salesByDate, d);
});
});
/* add zeros */
_.each(salesByDate, function (sales, date) {
_.each(saleTypes, function (type) {
if(typeof sales[type] == 'undefined') {
salesByDate[date][type] = 0;
}
});
});
var table_friendly = [];
_.each(salesByDate, function (sales, date) {
sales.date = date;
table_friendly.push(sales);
});
table_friendly = _.sortBy(table_friendly, 'date').reverse();
return table_friendly;
}
function salesTable() {
var html = '<thead><tr><th>Dato</th><th>Bar</th><th>SMS</th><th>App</th></tr></thead>';
html += '<tbody>';
salesData = groupSalesByDate();
_.each(salesData, function(el) {
html += '<tr><td>' + el.date + '</td>';
_.each(saleTypes, function(type) {
html += '<td>' + el[type] + '</td>';
});
html += '</tr>';
});
html += '</tbody>';
$('#sales-table').html(html);
}
function toCSV(data) {
var csvLines = data.map(function(d){
return d.date + ',' + saleTypes.map(function(t) { return d[t]; }).join(',');
});
var csvHeader = 'date,' +saleTypes.join(',') + '\n';
return csvHeader + csvLines.join('\n')
}
function downloadCSVFile(csvData, fileName) {
csvData = 'data:text/csv;charset=utf-8,' + csvData;
var encodedUri = encodeURI(csvData);
var link = document.createElement("a");
link.setAttribute("href", encodedUri);
link.setAttribute("download", fileName);
document.body.appendChild(link); // Required for FF
link.click();
}
function recalc(start, cb) {
salesChart = new Highcharts.Chart({
chart: {
renderTo: 'sales-chart'
},
title: {
text: false
},
xAxis: {
type: "datetime"
},
yAxis: {
title: {
text: "Salg"
},
min: 0
},
plotOptions: {
series: {
marker: {
radius: 4
}
}
},
series: []
});
$.when(getSmsSales(start), getAppSales(start), getBarSales(start)).done(function() {
totals();
salesTable();
if(cb) {
cb();
}
});
}
$(document).ready(function() {
Highcharts.setOptions({
credits: {enabled: false}
});
var $exportBtn = $('.export-data-btn');
var $startInput = $('#start');
var start = $startInput.val();
recalc(start, function() {
today();
});
/* Dynamic date change */
$startInput.on('input', function(e) {
start = $(e.target).val();
history.replaceState(null, null, '?start=' + start);
recalc(start);
});
/* Export to CSV */
$exportBtn.on('click', function (e) {
e.preventDefault();
var fileName = 'medlemskapsstats-' + $startInput.val() + '.csv';
var csvData = toCSV(salesData);
downloadCSVFile(csvData, fileName);
});
});