Separate charts in different controllers.
This commit is contained in:
parent
a23d653738
commit
803b2baeab
@ -24,21 +24,298 @@ accountantApp
|
||||
);
|
||||
}])
|
||||
|
||||
.controller(
|
||||
"CategoryChartController", [
|
||||
"$rootScope", "$scope", "$http", "$routeParams",
|
||||
function($rootScope, $scope, $http, $routeParams) {
|
||||
|
||||
var colors = Highcharts.getOptions().colors;
|
||||
$scope.revenueColor = colors[2];
|
||||
$scope.expenseColor = colors[3];
|
||||
|
||||
// Configure pie chart for categories.
|
||||
$scope.config = {
|
||||
options: {
|
||||
chart: {
|
||||
type: 'pie',
|
||||
animation: {
|
||||
duration: 500
|
||||
}
|
||||
},
|
||||
plotOptions: {
|
||||
pie: {
|
||||
startAngle: -90
|
||||
},
|
||||
series: {
|
||||
allowPointSelect: 0
|
||||
}
|
||||
},
|
||||
tooltip: {
|
||||
valueDecimals: 2,
|
||||
valueSuffix: '€'
|
||||
}
|
||||
},
|
||||
yAxis: {
|
||||
title: {
|
||||
text: "Categories"
|
||||
}
|
||||
},
|
||||
title: {
|
||||
text: "Répartition dépenses/recettes"
|
||||
},
|
||||
series: [{
|
||||
name: "Value",
|
||||
data: [],
|
||||
innerSize: '33%',
|
||||
size: '60%',
|
||||
dataLabels: {
|
||||
formatter: function() {
|
||||
return this.point.name;
|
||||
},
|
||||
distance: -40
|
||||
}
|
||||
}, {
|
||||
name: "Value",
|
||||
data: [],
|
||||
innerSize: '66%',
|
||||
size: '60%',
|
||||
dataLabels: {
|
||||
formatter: function() {
|
||||
return this.point.name !== null && this.percentage >= 2.5 ? this.point.name : null;
|
||||
},
|
||||
}
|
||||
}]
|
||||
};
|
||||
|
||||
$scope.brightenColor = function(color) {
|
||||
brightness = 0.2;
|
||||
|
||||
return Highcharts.Color(color).brighten(brightness).get()
|
||||
};
|
||||
|
||||
// Load categories, mainly to populate the pie chart.
|
||||
$scope.load = function(begin, end) {
|
||||
$scope.config.loading = true;
|
||||
|
||||
$http.get("/api/categories", {
|
||||
params: {
|
||||
account: $routeParams.accountId,
|
||||
begin: begin.format('YYYY-MM-DD'),
|
||||
end: end.format('YYYY-MM-DD')
|
||||
}
|
||||
}).success(function(data) {
|
||||
var expenses = [], revenues = [];
|
||||
|
||||
var expenseColor = $scope.brightenColor($scope.expenseColor);
|
||||
var revenueColor = $scope.brightenColor($scope.revenueColor);
|
||||
|
||||
angular.forEach(angular.fromJson(data), function(category) {
|
||||
expenses.push({
|
||||
name: category.category,
|
||||
y: -category.expenses,
|
||||
color: expenseColor
|
||||
});
|
||||
|
||||
revenues.push({
|
||||
name: category.category,
|
||||
y: category.revenues,
|
||||
color: revenueColor
|
||||
});
|
||||
});
|
||||
|
||||
// Note: expenses and revenues must be in the same order than in series[0].
|
||||
$scope.config.series[1].data = revenues.concat(expenses);
|
||||
|
||||
$scope.config.loading = false;
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* Get account status.
|
||||
*/
|
||||
$scope.getAccountStatus = function(begin, end) {
|
||||
$http.get("/api/accounts/" + $routeParams.accountId, {
|
||||
params: {
|
||||
begin: begin.format('YYYY-MM-DD'),
|
||||
end: end.format('YYYY-MM-DD')
|
||||
}
|
||||
}).success(function(account) {
|
||||
// Emit accountLoadedEvent.
|
||||
$scope.$emit("accountLoadedEvent", account);
|
||||
|
||||
// Update pie chart subtitle with Balance.
|
||||
$scope.config.subtitle = {
|
||||
text: "Balance: " + account.balance
|
||||
};
|
||||
|
||||
$scope.config.series[0].data = [{
|
||||
name: "Revenues",
|
||||
y: account.revenues,
|
||||
color: $scope.revenueColor
|
||||
}, {
|
||||
name: "Expenses",
|
||||
y: -account.expenses,
|
||||
color: $scope.expenseColor,
|
||||
}];
|
||||
});
|
||||
};
|
||||
|
||||
// Reload categories and account status on range selection.
|
||||
$rootScope.$on("rangeSelectedEvent", function(e, args) {
|
||||
$scope.load(args.begin, args.end);
|
||||
$scope.getAccountStatus(args.begin, args.end);
|
||||
});
|
||||
}])
|
||||
|
||||
.controller(
|
||||
"SoldChartController", [
|
||||
"$rootScope", "$scope", "$http", "$routeParams",
|
||||
function($rootScope, $scope, $http, $routeParams) {
|
||||
|
||||
$scope.setExtremes = function(e) {
|
||||
begin = moment.utc(e.min);
|
||||
end = moment.utc(e.max);
|
||||
|
||||
$scope.selectRange(begin, end);
|
||||
};
|
||||
|
||||
// Configure chart for entries.
|
||||
$scope.config = {
|
||||
options: {
|
||||
chart: {
|
||||
zoomType: 'x'
|
||||
},
|
||||
rangeSelector: {
|
||||
buttons: [{
|
||||
type: 'month',
|
||||
count: 1,
|
||||
text: "1m"
|
||||
}, {
|
||||
type: "month",
|
||||
count: 3,
|
||||
text: "3m"
|
||||
}, {
|
||||
type: "month",
|
||||
count: 6,
|
||||
text: "6m"
|
||||
}, {
|
||||
type: "year",
|
||||
count: 1,
|
||||
text: "1y"
|
||||
}, {
|
||||
type: "all",
|
||||
text: "All"
|
||||
}],
|
||||
selected: 0,
|
||||
},
|
||||
navigator: {
|
||||
enabled: true
|
||||
},
|
||||
tooltip: {
|
||||
crosshairs: true,
|
||||
shared: true,
|
||||
valueDecimals: 2,
|
||||
valueSuffix: '€'
|
||||
},
|
||||
scrollbar: {
|
||||
liveRedraw: false
|
||||
}
|
||||
},
|
||||
series: [{
|
||||
type: "ohlc",
|
||||
name: "Sold",
|
||||
data: [],
|
||||
dataGrouping : {
|
||||
units : [[
|
||||
'week', // unit name
|
||||
[1] // allowed multiples
|
||||
], [
|
||||
'month',
|
||||
[1, 2, 3, 4, 6]
|
||||
]]
|
||||
}
|
||||
}],
|
||||
title: {
|
||||
text: "Sold evolution"
|
||||
},
|
||||
xAxis: {
|
||||
type: "datetime",
|
||||
dateTimeLabelFormats: {
|
||||
month: "%e. %b",
|
||||
year: "%Y"
|
||||
},
|
||||
minRange: 3600 * 1000 * 24 * 14, // 2 weeks
|
||||
events: {
|
||||
afterSetExtremes: $scope.setExtremes
|
||||
},
|
||||
currentMin: moment.utc().startOf('month'),
|
||||
currentMax: moment.utc().endOf('month')
|
||||
},
|
||||
yAxis: {
|
||||
plotLines: [{
|
||||
color: "orange",
|
||||
width: 2,
|
||||
value: 0.0
|
||||
}, {
|
||||
color: "red",
|
||||
width: 2,
|
||||
value: 0.0
|
||||
}]
|
||||
},
|
||||
useHighStocks: true
|
||||
};
|
||||
|
||||
$scope.selectRange = function(begin, end) {
|
||||
$scope.$emit("rangeSelectedEvent", {begin: begin, end: end});
|
||||
};
|
||||
|
||||
$scope.loadSolds = function() {
|
||||
$scope.config.loading = true;
|
||||
|
||||
$http.get("/api/solds", {
|
||||
params: {
|
||||
account: $routeParams.accountId,
|
||||
}
|
||||
}).success(function(data) {
|
||||
$scope.config.series[0].data = [];
|
||||
|
||||
angular.forEach(data, function(entry) {
|
||||
$scope.config.series[0].data.push([
|
||||
moment.utc(entry.operation_date).valueOf(),
|
||||
entry.open, entry.high, entry.low, entry.close
|
||||
]);
|
||||
});
|
||||
|
||||
$scope.$emit("rangeSelectedEvent", {
|
||||
begin: $scope.config.xAxis.currentMin,
|
||||
end: $scope.config.xAxis.currentMax
|
||||
});
|
||||
|
||||
$scope.config.loading = false;
|
||||
});
|
||||
};
|
||||
|
||||
// Reload solds when an entry is saved.
|
||||
$rootScope.$on("entrySavedEvent", function(e, entry) {
|
||||
$scope.loadSolds();
|
||||
});
|
||||
|
||||
// Update authorized overdraft on account loading.
|
||||
$rootScope.$on("accountLoadedEvent", function(e, account) {
|
||||
$scope.config.yAxis.plotLines[1].value = account.authorized_overdraft;
|
||||
});
|
||||
|
||||
// Select beginning and end of month.
|
||||
$scope.loadSolds();
|
||||
}])
|
||||
|
||||
.controller(
|
||||
"EntryController", [
|
||||
"$scope", "$http", "$rootScope", "$filter", "$routeParams", "notificationService", "Entries",
|
||||
function($scope, $http, $rootScope, $filter, $routeParams, notificationService, Entries) {
|
||||
// Range for entries.
|
||||
$scope.begin = moment.utc().startOf('month');
|
||||
$scope.end = moment.utc().endOf('month');
|
||||
|
||||
// Entry store and selection
|
||||
$scope.entries = [];
|
||||
|
||||
$scope.categories = [];
|
||||
|
||||
$scope.account = null;
|
||||
|
||||
// Function to reset the new entry.
|
||||
$scope.addEntry = function() {
|
||||
if(!$scope.inserted) {
|
||||
@ -48,291 +325,16 @@ accountantApp
|
||||
}
|
||||
};
|
||||
|
||||
$scope.setExtremes = function(e) {
|
||||
begin = moment.utc(e.min);
|
||||
end = moment.utc(e.max);
|
||||
|
||||
$scope.selectRange(begin, end);
|
||||
};
|
||||
|
||||
$scope.selectRange = function(begin, end) {
|
||||
$scope.begin = begin;
|
||||
$scope.end = end;
|
||||
|
||||
$scope.$emit("rangeSelectedEvent", {begin: begin, end: end});
|
||||
};
|
||||
|
||||
// Configure pie chart for categories.
|
||||
$scope.categoriesChartConfig = {
|
||||
options: {
|
||||
chart: {
|
||||
type: 'pie',
|
||||
animation: {
|
||||
duration: 500
|
||||
}
|
||||
},
|
||||
plotOptions: {
|
||||
pie: {
|
||||
startAngle: -90
|
||||
},
|
||||
series: {
|
||||
allowPointSelect: 0
|
||||
}
|
||||
},
|
||||
tooltip: {
|
||||
valueDecimals: 2,
|
||||
valueSuffix: '€'
|
||||
}
|
||||
},
|
||||
yAxis: {
|
||||
title: {
|
||||
text: "Categories"
|
||||
}
|
||||
},
|
||||
title: {
|
||||
text: "Répartition dépenses/recettes"
|
||||
},
|
||||
series: [{
|
||||
name: "Value",
|
||||
data: [],
|
||||
innerSize: '33%',
|
||||
size: '60%',
|
||||
dataLabels: {
|
||||
formatter: function() {
|
||||
return this.point.name;
|
||||
},
|
||||
distance: -40
|
||||
}
|
||||
}, {
|
||||
name: "Value",
|
||||
data: [],
|
||||
innerSize: '66%',
|
||||
size: '60%',
|
||||
dataLabels: {
|
||||
formatter: function() {
|
||||
return this.point.name !== null && this.percentage >= 2.5 ? this.point.name : null;
|
||||
},
|
||||
}
|
||||
}]
|
||||
};
|
||||
|
||||
// Configure chart for entries.
|
||||
$scope.soldChartConfig = {
|
||||
options: {
|
||||
chart: {
|
||||
zoomType: 'x'
|
||||
},
|
||||
rangeSelector: {
|
||||
buttons: [{
|
||||
type: 'month',
|
||||
count: 1,
|
||||
text: "1m"
|
||||
}, {
|
||||
type: "month",
|
||||
count: 3,
|
||||
text: "3m"
|
||||
}, {
|
||||
type: "month",
|
||||
count: 6,
|
||||
text: "6m"
|
||||
}, {
|
||||
type: "year",
|
||||
count: 1,
|
||||
text: "1y"
|
||||
}, {
|
||||
type: "all",
|
||||
text: "All"
|
||||
}],
|
||||
selected: 0,
|
||||
},
|
||||
navigator: {
|
||||
enabled: true
|
||||
},
|
||||
tooltip: {
|
||||
crosshairs: true,
|
||||
shared: true,
|
||||
valueDecimals: 2,
|
||||
valueSuffix: '€'
|
||||
},
|
||||
scrollbar: {
|
||||
liveRedraw: false
|
||||
}
|
||||
},
|
||||
series: [{
|
||||
type: "ohlc",
|
||||
name: "Sold",
|
||||
data: [],
|
||||
dataGrouping : {
|
||||
units : [[
|
||||
'week', // unit name
|
||||
[1] // allowed multiples
|
||||
], [
|
||||
'month',
|
||||
[1, 2, 3, 4, 6]
|
||||
]]
|
||||
}
|
||||
}],
|
||||
title: {
|
||||
text: "Sold evolution"
|
||||
},
|
||||
xAxis: {
|
||||
type: "datetime",
|
||||
dateTimeLabelFormats: {
|
||||
month: "%e. %b",
|
||||
year: "%Y"
|
||||
},
|
||||
minRange: 3600 * 1000 * 24 * 14, // 2 weeks
|
||||
events: {
|
||||
afterSetExtremes: $scope.setExtremes
|
||||
},
|
||||
currentMin: $scope.begin,
|
||||
currentMax: $scope.end
|
||||
},
|
||||
yAxis: {
|
||||
plotLines: [{
|
||||
color: "orange",
|
||||
width: 2,
|
||||
value: 0.0
|
||||
}, {
|
||||
color: "red",
|
||||
width: 2,
|
||||
value: 0.0
|
||||
}]
|
||||
},
|
||||
useHighStocks: true
|
||||
};
|
||||
|
||||
// Load categories, mainly to populate the pie chart.
|
||||
$scope.loadCategories = function() {
|
||||
$scope.categoriesChartConfig.loading = true;
|
||||
|
||||
$http.get("/api/categories", {
|
||||
params: {
|
||||
account: $scope.account.id,
|
||||
begin: $scope.begin.format('YYYY-MM-DD'),
|
||||
end: $scope.end.format('YYYY-MM-DD')
|
||||
}
|
||||
}).success(function(data) {
|
||||
var expenses = [], revenues = [];
|
||||
var colors = Highcharts.getOptions().colors;
|
||||
|
||||
var config = $scope.categoriesChartConfig;
|
||||
|
||||
angular.forEach(angular.fromJson(data), function(category) {
|
||||
brightness = 0.2;
|
||||
|
||||
expenses.push({
|
||||
name: category.category,
|
||||
y: -category.expenses,
|
||||
color: Highcharts.Color(config.series[0].data[1].color).brighten(brightness).get()
|
||||
});
|
||||
|
||||
revenues.push({
|
||||
name: category.category,
|
||||
y: category.revenues,
|
||||
color: Highcharts.Color(config.series[0].data[0].color).brighten(brightness).get()
|
||||
});
|
||||
});
|
||||
|
||||
// Note: expenses and revenues must be in the same order than in series[0].
|
||||
config.series[1].data = revenues.concat(expenses);
|
||||
|
||||
$scope.categoriesChartConfig.loading = false;
|
||||
|
||||
$scope.loadSolds();
|
||||
});
|
||||
};
|
||||
|
||||
$scope.loadSolds = function() {
|
||||
$scope.soldChartConfig.loading = true;
|
||||
|
||||
$http.get("/api/solds", {
|
||||
params: {
|
||||
account: $scope.account.id,
|
||||
}
|
||||
}).success(function(data) {
|
||||
var config = $scope.soldChartConfig;
|
||||
|
||||
config.series[0].data = [];
|
||||
|
||||
angular.forEach(data, function(entry) {
|
||||
config.series[0].data.push([
|
||||
moment.utc(entry.operation_date).valueOf(),
|
||||
entry.open, entry.high, entry.low, entry.close
|
||||
]);
|
||||
});
|
||||
|
||||
$scope.soldChartConfig.loading = false;
|
||||
|
||||
$scope.loadEntries();
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* Hook on account selected event to display account status.
|
||||
*/
|
||||
$rootScope.$on("accountSelectedEvent", function(event, args) {
|
||||
$scope.getAccountStatus($routeParams.accountId);
|
||||
});
|
||||
|
||||
$rootScope.$on("rangeSelectedEvent", function(event, args) {
|
||||
$scope.getAccountStatus($routeParams.accountId);
|
||||
});
|
||||
|
||||
/*
|
||||
* Get account status.
|
||||
*/
|
||||
$scope.getAccountStatus = function(accountId) {
|
||||
$scope.categoriesChartConfig.loading = true;
|
||||
|
||||
$http.get("/api/accounts/" + accountId, {
|
||||
params: {
|
||||
begin: $scope.begin.format('YYYY-MM-DD'),
|
||||
end: $scope.end.format('YYYY-MM-DD')
|
||||
}
|
||||
}).success(function(account) {
|
||||
$scope.account = account;
|
||||
$scope.categoriesChartConfig.loading = false;
|
||||
|
||||
$scope.$emit("accountLoadedEvent", account);
|
||||
});
|
||||
};
|
||||
|
||||
$rootScope.$on("accountLoadedEvent", $scope.loadCategories);
|
||||
|
||||
$rootScope.$on("accountLoadedEvent", function(e, account) {
|
||||
var colors = Highcharts.getOptions().colors;
|
||||
|
||||
var config = $scope.categoriesChartConfig;
|
||||
|
||||
// Update pie chart subtitle with Balance.
|
||||
config.subtitle = {
|
||||
text: "Balance: " + account.balance
|
||||
};
|
||||
|
||||
config.series[0].data = [{
|
||||
name: "Revenues",
|
||||
y: account.revenues,
|
||||
color: colors[2]
|
||||
}, {
|
||||
name: "Expenses",
|
||||
y: -account.expenses,
|
||||
color: colors[3],
|
||||
}];
|
||||
|
||||
$scope.soldChartConfig.yAxis.plotLines[1].value = account.authorized_overdraft;
|
||||
});
|
||||
|
||||
// Function to load entries from server for a specific account and month.
|
||||
$scope.loadEntries = function() {
|
||||
$scope.loadEntries = function(begin, end) {
|
||||
// Clean up selected entry.
|
||||
$scope.selectedItem = null;
|
||||
$scope.savedItem = null;
|
||||
|
||||
$scope.entries = Entries.query({
|
||||
account: $scope.account.id,
|
||||
begin: $scope.begin.format('YYYY-MM-DD'),
|
||||
end: $scope.end.format('YYYY-MM-DD')
|
||||
account: $routeParams.accountId,
|
||||
begin: begin.format('YYYY-MM-DD'),
|
||||
end: end.format('YYYY-MM-DD')
|
||||
}, function(data) {
|
||||
$scope.$emit("entriesLoadedEvent", {entries: data});
|
||||
});
|
||||
@ -369,7 +371,7 @@ accountantApp
|
||||
};
|
||||
|
||||
/*
|
||||
* Save an entry and emit entrySavedEvent, or entryCreatedEvent.
|
||||
* Save an entry and emit entrySavedEvent.
|
||||
*/
|
||||
$scope.saveEntry = function($data, $index) {
|
||||
// Check if $data is already a resource.
|
||||
@ -390,60 +392,20 @@ accountantApp
|
||||
promise = promise.then(function(data) {
|
||||
$scope.inserted = false;
|
||||
|
||||
notificationService.success("Entry #" + data.id + " created.");
|
||||
});
|
||||
} else {
|
||||
promise = promise.then(function(data) {
|
||||
notificationService.success("Entry #" + data.id + " saved.");
|
||||
return data;
|
||||
});
|
||||
}
|
||||
|
||||
promise = promise.then(function(data) {
|
||||
$scope.getAccountStatus($routeParams.accountId);
|
||||
return promise.then(function(data) {
|
||||
notificationService.success("Entry #" + data.id + " saved.");
|
||||
$scope.$emit("entrySavedEvent", data);
|
||||
|
||||
return data;
|
||||
});
|
||||
|
||||
return promise;
|
||||
};
|
||||
|
||||
$scope.removeEntry = function(entry) {
|
||||
$scope.removingEntry = entry;
|
||||
$("#remove_entry").modal({
|
||||
keyboard: false,
|
||||
});
|
||||
};
|
||||
|
||||
$scope.hideRemoveEntryPopup = function() {
|
||||
$scope.removingEntry = null;
|
||||
$("#remove_entry").modal("hide");
|
||||
};
|
||||
|
||||
// Removes an entry.
|
||||
$scope.confirmRemoveEntry = function() {
|
||||
// Cancel current editing.
|
||||
if ($scope.removingEntry) {
|
||||
$scope.removingEntry.$delete(function (result) {
|
||||
// Send the "entry removed" event.
|
||||
$scope.$emit("entryRemovedEvent", $scope.removingEntry);
|
||||
|
||||
$scope.hideRemoveEntryPopup();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
$rootScope.$on("entryRemovedEvent", function(e, entry) {
|
||||
new PNotify({
|
||||
type: "success",
|
||||
title: "Delete",
|
||||
text: "Entry #" + entry.id + " deleted."
|
||||
});
|
||||
// Reload entries on range selection.
|
||||
$rootScope.$on("rangeSelectedEvent", function(e, args) {
|
||||
$scope.loadEntries(args.begin, args.end);
|
||||
});
|
||||
|
||||
$scope.closeModal = function(modalScope) {
|
||||
// Close the modal dialog
|
||||
if(modalScope && modalScope.dismiss) {
|
||||
modalScope.dismiss();
|
||||
}
|
||||
};
|
||||
|
||||
$scope.getAccountStatus($routeParams.accountId);
|
||||
}]);
|
||||
|
@ -19,10 +19,14 @@
|
||||
<!-- Chart row -->
|
||||
<div class="row">
|
||||
<!-- Sold evolution chart placeholder -->
|
||||
<highchart id="sold-chart" config="soldChartConfig" class="col-md-8"></highchart>
|
||||
<div class="col-md-8" ng-controller="SoldChartController">
|
||||
<highchart id="sold-chart" config="config"></highchart>
|
||||
</div>
|
||||
|
||||
<!-- Category piechart -->
|
||||
<highchart id="categories-chart" config="categoriesChartConfig" class="col-md-4"></highchart>
|
||||
<div class="col-md-4" ng-controller="CategoryChartController">
|
||||
<highchart id="categories-chart" config="config"></highchart>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
|
Loading…
Reference in New Issue
Block a user