Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
0c1aef2
Add graph
kyungmin Jun 9, 2014
4eccc2a
Add more properties
kyungmin Jun 10, 2014
b18fc62
Change ChartComponent to ChartView
kyungmin Jun 12, 2014
125489b
Add bar chart
kyungmin Jun 12, 2014
52d759d
Add horizontal/vertical graph
kyungmin Jun 12, 2014
25a9bc9
Merge branch 'master' of https://github.com/balanced/balanced-dashboa…
kyungmin Jun 12, 2014
aed418b
Add triangle bar chart
kyungmin Jun 12, 2014
e5e0784
Move charts to overview page
kyungmin Jun 12, 2014
bd6b29e
Redirect to overview page
kyungmin Jun 13, 2014
a199a44
Merge branch 'master' of https://github.com/balanced/balanced-dashboa…
kyungmin Jun 13, 2014
11d62a4
Beautify
kyungmin Jun 13, 2014
7bd9c9a
Beautify
kyungmin Jun 13, 2014
81be0a5
Add overview title and date filter
kyungmin Jun 13, 2014
98c503e
Set color to line graphs
kyungmin Jun 13, 2014
66d7126
Beautify
kyungmin Jun 16, 2014
72329c7
Customize graph style
kyungmin Jun 16, 2014
819c2d0
Update hover point size
kyungmin Jun 16, 2014
3fd8af3
Customize tooltip
kyungmin Jun 17, 2014
bed9e43
Merge branch 'master' of https://github.com/balanced/balanced-dashboa…
kyungmin Jun 17, 2014
05f08c5
Customize chart style
kyungmin Jun 18, 2014
1eb199c
Merge branch 'master' of https://github.com/balanced/balanced-dashboa…
kyungmin Jun 18, 2014
bd59526
Format overview page
kyungmin Jun 19, 2014
14d43bc
Fix activity redirect route and more
kyungmin Jun 19, 2014
21ef7bf
Add list table in the side panel
kyungmin Jun 19, 2014
6edf76c
Add list table to the overview page
kyungmin Jun 19, 2014
2634325
Add tab navigation
kyungmin Jun 19, 2014
a3925c2
Merge branch 'master' of https://github.com/balanced/balanced-dashboa…
kyungmin Aug 24, 2014
cf0ef6e
Use fixture data
kyungmin Aug 26, 2014
0e398b9
Merge branch 'master' of https://github.com/balanced/balanced-dashboa…
kyungmin Aug 26, 2014
57ec74a
Use body panel view
kyungmin Aug 27, 2014
aa68272
Extract data from analytics response
kyungmin Aug 28, 2014
dd2f973
Merge branch 'master' of https://github.com/balanced/balanced-dashboa…
kyungmin Aug 28, 2014
30a2429
Update property names
kyungmin Aug 28, 2014
7a9818e
Display a line graph from fixture data
kyungmin Sep 3, 2014
32358ec
Add crossfilter
kyungmin Sep 3, 2014
b66f1b4
Render dates correctly
kyungmin Sep 4, 2014
22d5a2d
Add c3
kyungmin Sep 10, 2014
9859bfd
Merge branch 'master' of https://github.com/balanced/balanced-dashboa…
kyungmin Sep 12, 2014
70a6533
Switch to c3.js and use real fixture data
kyungmin Sep 12, 2014
7bdd0b5
Remove files deleted in master
kyungmin Sep 12, 2014
6f5423b
Display transaction volumn and count using crossfilter
kyungmin Sep 15, 2014
9c8d15e
Add c3 chart stylesheet
kyungmin Sep 15, 2014
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 11 additions & 4 deletions Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ module.exports = function(grunt) {
'static/javascripts/lodash/dist/lodash.underscore.js',
'static/javascripts/mixpanel/mixpanel.js',
'static/javascripts/google-code-prettify/src/prettify.js',
'static/javascripts/strftime/index.js',
'static/javascripts/crossfilter/index.js',
'static/javascripts/jquery-hotkeys/jquery.hotkeys.js',
'static/javascripts/jquery.cookie/jquery.cookie.js',
'static/javascripts/bootstrap-modal/js/bootstrap-modalmanager.js',
Expand All @@ -104,7 +104,10 @@ module.exports = function(grunt) {
'static/javascripts/moment/moment.js',
'static/lib/moment-business-days.js',
'static/lib/daterangepicker.js',
'static/javascripts/timepicker/jquery.timepicker.js'
'static/javascripts/timepicker/jquery.timepicker.js',
'static/javascripts/d3/d3.min.js',
'static/javascripts/c3/c3.min.js',
'static/javascripts/strftime/index.js'
],
dest: 'build/js/lib-dev.js'
},
Expand All @@ -131,7 +134,10 @@ module.exports = function(grunt) {
'static/javascripts/moment/min/moment.min.js',
'static/lib/moment-business-days.js',
'static/lib/daterangepicker.js',
'static/javascripts/timepicker/jquery.timepicker.min.js'
'static/javascripts/timepicker/jquery.timepicker.min.js',
'static/javascripts/d3/d3.min.js',
'static/javascripts/c3/c3.min.js',
'static/javascripts/strftime/index.js'
],
dest: 'build/js/lib-prod.js'
},
Expand Down Expand Up @@ -646,7 +652,8 @@ module.exports = function(grunt) {
js: {
files: [
'app/**/*.js',
'static/lib/**/*.js'
'static/lib/**/*.js',
'static/javascripts/**/*.js'
],
tasks: ['format', '_buildJSAfterTemplates'],
options: {
Expand Down
146 changes: 146 additions & 0 deletions app/controllers/overview.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
Balanced.MarketplaceOverviewController = Balanced.ObjectController.extend(
Ember.Evented,
Balanced.ResultsTable, {
needs: ['marketplace'],
baseClassSelector: '#overview',
pageTitle: 'Overview',

init: function() {
this._super();
this.loadAnalytics();
},

totalVolume: [],
transactionsCount: [],

loadAnalytics: function() {
var connection = Balanced.Connections.ApiConnection.create();
var self = this;

connection.ajax({
uri: "/analytics?type=volume"
}).then(function(response) {
var transactions = response.analytics.map(function(day) {
return day.transactions.map(function(transaction) {
return _.extend({}, transaction, {
start_at: day.start_at
});
});
});
transactions = _.flatten(transactions);
self.formatTransactions(transactions);
});
},

formatTransactions: function(data) {
var cf = crossfilter(data);

var debitCount = ['debits'];
var creditCount = ['credits'];
var refundCount = ['refunds'];
var reversalCount = ['reversals'];

var debitAmount = ['debits'];
var creditAmount = ['credits'];
var refundAmount = ['refunds'];
var reversalAmount = ['reversals'];

function reduceAdd(type) {
return function(p, v) {
if (v["type"] === type) {
p.count += v.count;
p.amount += v.amount;
}
return p;
};
}

function reduceRemove(type) {
return function(p, v) {
if (v["type"] === type) {
p.count -= v.count;
p.amount -= v.amount;
}
return p;
};
}

function reduceInitial() {
return {
count: 0,
amount: 0
};
}

// group transactions by date
var transactionsByDate = cf.dimension(function(p) {
return p.start_at;
});

var dates = transactionsByDate.group().all().map(function(transaction) {
return Date.parseISO8601(transaction.key);
});
dates = ['x'].concat(dates);

var debits = transactionsByDate.group().reduce(reduceAdd('debit'), reduceRemove('debit'), reduceInitial).all();

debitAmount = debitAmount.concat(_.map(debits, function(debit) {
return debit.value.amount
}));

debitCount = debitCount.concat(_.map(debits, function(debit) {
return debit.value.count
}));

var credits = transactionsByDate.group().reduce(reduceAdd('credit'), reduceRemove('credit'), reduceInitial).all();

creditAmount = creditAmount.concat(_.map(credits, function(credit) {
return credit.value.amount
}));

creditCount = creditCount.concat(_.map(credits, function(credit) {
return credit.value.count
}));

var refunds = transactionsByDate.group().reduce(reduceAdd('refund'), reduceRemove('refund'), reduceInitial).all();

refundAmount = refundAmount.concat(_.map(refunds, function(refund) {
return refund.value.amount
}));

refundCount = refundCount.concat(_.map(refunds, function(refund) {
return refund.value.count
}));

var reversals = transactionsByDate.group().reduce(reduceAdd('reversal'), reduceRemove('reversal'), reduceInitial).all();

reversalAmount = reversalAmount.concat(_.map(reversals, function(reversal) {
return reversal.value.amount
}));

reversalCount = reversalCount.concat(_.map(reversals, function(reversal) {
return reversal.value.count
}));

this.set("totalVolume", {
x: 'x',
columns: [dates, debitAmount, creditAmount, refundAmount, reversalAmount]
});

this.set("transactionsCount", {
x: 'x',
columns: [dates, debitCount, creditCount, refundCount, reversalCount]
});

this.set("verticalBarChartData", {
x: 'x',
columns: [dates, debitCount]
});

this.set("horizontalBarChartData", {
x: 'x',
columns: [dates, debitCount]
});
},

});
1 change: 1 addition & 0 deletions app/routes/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ Balanced.Router.map(function() {
this.resource('marketplace', {
path: '/:marketplace_id'
}, function() {
this.route('overview');
this.route('settings');
this.route('add_customer');
this.route('import_payouts');
Expand Down
35 changes: 35 additions & 0 deletions app/templates/charts/line-chart-with-legend.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<div class="side-panel">
<h3>Total volume</h3>
<table class="list">
<tbody>
<tr {{action toggleLegend "Sine Wave" target=view.lineChartView}}>
<td>
<span>
<div class="checkbox checked"></div>
<div class="legend-color-guide series-1"></div>
Debits
</span>
</td>
<td class="num">
<span>$123.45</span>
</td>
</tr>
<tr {{action toggleLegend "Cosine Wave" target=view.lineChartView}}>
<td>
<span>
<div class="checkbox"></div>
<div class="legend-color-guide series-2"></div>
Credits
</span>
</td>
<td class="num">
<span>$123.45</span>
</td>
</tr>
</tbody>
</table>
</div>

<div class="main-panel">
{{view Balanced.LineChartView data=view.data viewName="lineChartView"}}
</div>
15 changes: 0 additions & 15 deletions app/templates/components/meta.hbs

This file was deleted.

45 changes: 45 additions & 0 deletions app/templates/marketplace/overview.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<div class="page-navigation">
<h1 class="page-title">
{{pageTitle}}
</h1>
</div>
<div id="overview">
{{view Balanced.DateFilterHeaderView}}

<ul class="nav-tabs">
<li {{bind-attr class=":active"}}>Payments</li>
<li {{bind-attr class=""}}>Cards</li>
<li {{bind-attr class=""}}>Disputes</li>
</ul>

<div class="tab-content">
<div class="tab-pane">
{{#view Balanced.BodyPanelView}}
{{view Balanced.LineChartWithLegendView data=controller.totalVolume}}
{{/view}}

{{#view Balanced.BodyPanelView}}
{{view Balanced.LineChartWithLegendView data=controller.transactionsCount}}
{{/view}}

{{#view Balanced.BodyPanelView}}
{{#view Balanced.SidePanelView model=model}}
<h3>Average transaction size</h3>
{{/view}}
{{#view Balanced.MainPanelView}}
{{view Balanced.VerticalBarChartView data=verticalBarChartData}}
{{/view}}
{{/view}}
</div>
<div class="tab-pane">
{{#view Balanced.BodyPanelView}}
{{#view Balanced.SidePanelView model=model}}
<h3>Total card volume</h3>
{{/view}}
{{#view Balanced.MainPanelView}}
{{view Balanced.HorizontalBarChartView data=horizontalBarChartData}}
{{/view}}
{{/view}}
</div>
</div>
</div>
5 changes: 5 additions & 0 deletions app/views/charts/chart-with-legend.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Balanced.ChartWithLegendView = Ember.View.extend({});

Balanced.LineChartWithLegendView = Balanced.ChartWithLegendView.extend({
templateName: 'charts/line-chart-with-legend'
});
89 changes: 89 additions & 0 deletions app/views/charts/chart.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
Balanced.ChartView = Ember.View.extend({
tagName: 'div',
classNames: ['chart'],
data: {},
axis: {},
regions: {},
grid: {},
transition: {},
legend: {},
tooltip: {},
subchart: {},
zoom: {},
size: {},
padding: {},
type: null,
color: {
pattern: ['#639ABD', '#BC8F30', '#9364A8', '#00A08E']
},
// @egyptianBlue80, @turmericYellow80, @byzantiumPurple80, @forestGreen80

spline: {},
bar: {},

_chart: undefined,

chart: function() {
var self = this;
if (Ember.isEqual(self.get('_chart'), undefined)) {
// Empty, create it.
var container = self.get('element');
if (Ember.isEqual(container, undefined)) {
return undefined;
} else {
var config = self.get('_config');
var chart = c3.generate(config);
self.set('_chart', chart);
return chart;
}
} else {
// Editor is already created and cached.
return self.get('_chart');
}
}.property('element', '_config'),

_config: function() {
var c = this.getProperties([
'data',
'axis',
'regions',
'bar',
'grid',
'legend',
'tooltip',
'subchart',
'zoom',
'size',
'padding',
'color',
'transition'
]);
c.data.type = this.get('type');
c.bindto = this.get('element');
return c;
}.property('element', 'data', 'type', 'axis', 'regions', 'bar', 'grid', 'legend', 'tooltip', 'subchart', 'zoom', 'size', 'padding', 'color', 'transition'),

dataDidChange: function() {
var chart = this.get('chart');
chart.load(this.get('data'));
}.observes('data').on('didInsertElement'),

actions: {
toggleLegend: function(seriesKey) {
var chart = this.get('chart');
var data = this.get('data');

data.filterBy('key', seriesKey).forEach(function(series) {
series.disabled = !series.disabled;
});

if (data.isEvery('disabled')) {
data.forEach(function(series) {
series.disabled = false;
});
}

chart.update();
}
}
});
Loading