Added category, added pie chart on categories, removed buggy ba-resize plugin.
This commit is contained in:
parent
6f36d7970f
commit
868cf3138a
@ -17,7 +17,7 @@ class EntryAPI extends RestAPI {
|
|||||||
|
|
||||||
$account=$this->_request['account'];
|
$account=$this->_request['account'];
|
||||||
|
|
||||||
$statement=$connection->prepare("select id, value_date, operation_date, label, value, account_id, sold, pointedSold from (select *, sum(value) over(order by value_date, operation_date, label desc, value desc) as sold, sum(value) over(partition by operation_date is not null order by value_date, operation_date, label desc, value desc) as pointedSold from entry where account_id=:account order by value_date desc, operation_date desc, label, value) as e where date_trunc('month', e.value_date) = :day ");
|
$statement=$connection->prepare("select id, value_date, operation_date, label, value, account_id, sold, pointedsold, category from (select *, sum(value) over(order by value_date, operation_date, label desc, value desc) as sold, sum(value) over(partition by operation_date is not null order by value_date, operation_date, label desc, value desc) as pointedSold from entry where account_id=:account order by value_date desc, operation_date desc, label, value) as e where date_trunc('month', e.value_date) = :day ");
|
||||||
$statement->bindParam("day", $day);
|
$statement->bindParam("day", $day);
|
||||||
$statement->bindParam("account", $account);
|
$statement->bindParam("account", $account);
|
||||||
|
|
||||||
@ -36,9 +36,9 @@ class EntryAPI extends RestAPI {
|
|||||||
$connection=$this->get_db_connection();
|
$connection=$this->get_db_connection();
|
||||||
|
|
||||||
if($entry['id'] != null) {
|
if($entry['id'] != null) {
|
||||||
$statement=$connection->prepare("update entry set value_date=:value_date, operation_date=:operation_date, label=:label, value=:value, account_id=:account where id=:id");
|
$statement=$connection->prepare("update entry set value_date=:value_date, operation_date=:operation_date, label=:label, value=:value, account_id=:account, category=:category where id=:id");
|
||||||
} else {
|
} else {
|
||||||
$statement=$connection->prepare("insert into entry (value_date, operation_date, label, value, account_id) values (:value_date, :operation_date, :label, :value, :account)");
|
$statement=$connection->prepare("insert into entry (value_date, operation_date, label, value, account_id) values (:value_date, :operation_date, :label, :value, :account, :category)");
|
||||||
}
|
}
|
||||||
|
|
||||||
$statement->bindParam("value_date", $entry['value_date']);
|
$statement->bindParam("value_date", $entry['value_date']);
|
||||||
@ -47,6 +47,7 @@ class EntryAPI extends RestAPI {
|
|||||||
$statement->bindParam("value", $entry['value']);
|
$statement->bindParam("value", $entry['value']);
|
||||||
$statement->bindParam("account", $entry['account']);
|
$statement->bindParam("account", $entry['account']);
|
||||||
$statement->bindParam("id", $entry['id']);
|
$statement->bindParam("id", $entry['id']);
|
||||||
|
$statement->bindParam("category", $entry['category']);
|
||||||
|
|
||||||
$return=$statement->execute();
|
$return=$statement->execute();
|
||||||
|
|
||||||
|
@ -33,20 +33,28 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="content" style="margin-top: 116px; margin-bottom: 41px">
|
<div class="row" style="margin-top: 116px"></div>
|
||||||
|
|
||||||
<div class="container-fluid">
|
<div class="row">
|
||||||
<div class="span8">
|
<div class="span8">
|
||||||
<div id="chart-placeholder" data-bind="chart: $root.entriesChart"></div>
|
<div id="entries-chart-placeholder" data-bind="chart: $root.entriesChart"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="span4"></div>
|
<div class="span4">
|
||||||
|
<div id="categories-chart-placeholder" data-bind="pieChart: $root.categoriesChart"></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
<div id="message-placeholder"></div>
|
<div id="message-placeholder"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
<a class="btn btn-primary" data-bind="click: $root.add" href="#" title="Add entry"><i class="icon-plus"></i> Ajouter une entrée</a>
|
<a class="btn btn-primary" data-bind="click: $root.add" href="#" title="Add entry"><i class="icon-plus"></i> Ajouter une entrée</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
<table class="table table-striped table-condensed table-hover">
|
<table class="table table-striped table-condensed table-hover">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
@ -56,6 +64,7 @@
|
|||||||
<th style="width: 50px">Montant</th>
|
<th style="width: 50px">Montant</th>
|
||||||
<th style="width: 50px">Solde</th>
|
<th style="width: 50px">Solde</th>
|
||||||
<th style="width: 50px">Solde pointé</th>
|
<th style="width: 50px">Solde pointé</th>
|
||||||
|
<th style="width: 100px">Catégorie</th>
|
||||||
<th style="width: 60px">Actions</th>
|
<th style="width: 60px">Actions</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
@ -64,6 +73,8 @@
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div style="margin-bottom: 21px"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -89,6 +100,7 @@
|
|||||||
<td data-bind="text: value, css: {'text-error': value() < 0 }"></td>
|
<td data-bind="text: value, css: {'text-error': value() < 0 }"></td>
|
||||||
<td data-bind="text: sold, css: {'text-error': sold() < 0 }"></td>
|
<td data-bind="text: sold, css: {'text-error': sold() < 0 }"></td>
|
||||||
<td data-bind="text: pointedSold, css: {'text-error': pointedSold() < 0 }"></td>
|
<td data-bind="text: pointedSold, css: {'text-error': pointedSold() < 0 }"></td>
|
||||||
|
<td data-bind="text: category"></td>
|
||||||
<td class="buttons">
|
<td class="buttons">
|
||||||
<a class="btn btn-mini" data-bind="click: $root.edit" href="#" title="edit"><i class="icon-edit"></i></a>
|
<a class="btn btn-mini" data-bind="click: $root.edit" href="#" title="edit"><i class="icon-edit"></i></a>
|
||||||
<a class="btn btn-mini" data-bind="click: $root.remove" href="#" title="remove"><i class="icon-trash"></i></a>
|
<a class="btn btn-mini" data-bind="click: $root.remove" href="#" title="remove"><i class="icon-trash"></i></a>
|
||||||
@ -104,6 +116,7 @@
|
|||||||
<td><input type="text" class="input-mini" data-bind="value: value"/></td>
|
<td><input type="text" class="input-mini" data-bind="value: value"/></td>
|
||||||
<td data-bind="text: sold"></td>
|
<td data-bind="text: sold"></td>
|
||||||
<td data-bind="text: pointedSold"></td>
|
<td data-bind="text: pointedSold"></td>
|
||||||
|
<td><input type="text" class="input-small" data-bind="value: category"/></td>
|
||||||
<td class="buttons">
|
<td class="buttons">
|
||||||
<a class="btn btn-mini btn-success" data-bind="click: $root.save" href="#" title="save"><i class="icon-ok"></i></a>
|
<a class="btn btn-mini btn-success" data-bind="click: $root.save" href="#" title="save"><i class="icon-ok"></i></a>
|
||||||
<a class="btn btn-mini" data-bind="click: $root.cancel" href="#" title="cancel"><i class="icon-ban-circle"></i></a>
|
<a class="btn btn-mini" data-bind="click: $root.cancel" href="#" title="cancel"><i class="icon-ban-circle"></i></a>
|
||||||
@ -112,7 +125,6 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script type="text/javascript" src="jquery/jquery.js"></script>
|
<script type="text/javascript" src="jquery/jquery.js"></script>
|
||||||
<script type="text/javascript" src="jquery/jquery.ba-resize.min.js"></script>
|
|
||||||
<script type="text/javascript" src="bootstrap/js/bootstrap.min.js"></script>
|
<script type="text/javascript" src="bootstrap/js/bootstrap.min.js"></script>
|
||||||
<script type="text/javascript" src="datepicker/js/bootstrap-datepicker.js"></script>
|
<script type="text/javascript" src="datepicker/js/bootstrap-datepicker.js"></script>
|
||||||
<script type="text/javascript" src="knockout/knockout.js"></script>
|
<script type="text/javascript" src="knockout/knockout.js"></script>
|
||||||
@ -122,6 +134,7 @@
|
|||||||
<script type="text/javascript" src="jqplot/plugins/jqplot.canvasTextRenderer.min.js"></script>
|
<script type="text/javascript" src="jqplot/plugins/jqplot.canvasTextRenderer.min.js"></script>
|
||||||
<script type="text/javascript" src="jqplot/plugins/jqplot.canvasAxisTickRenderer.min.js"></script>
|
<script type="text/javascript" src="jqplot/plugins/jqplot.canvasAxisTickRenderer.min.js"></script>
|
||||||
<script type="text/javascript" src="jqplot/plugins/jqplot.ohlcRenderer.min.js"></script>
|
<script type="text/javascript" src="jqplot/plugins/jqplot.ohlcRenderer.min.js"></script>
|
||||||
|
<script type="text/javascript" src="jqplot/plugins/jqplot.pieRenderer.min.js"></script>
|
||||||
<script type="text/javascript" src="jqplot/plugins/jqplot.highlighter.min.js"></script>
|
<script type="text/javascript" src="jqplot/plugins/jqplot.highlighter.min.js"></script>
|
||||||
|
|
||||||
<script type="text/javascript" src="js/entries.js"></script>
|
<script type="text/javascript" src="js/entries.js"></script>
|
||||||
|
9
src/html/jquery/jquery.ba-resize.min.js
vendored
9
src/html/jquery/jquery.ba-resize.min.js
vendored
@ -1,9 +0,0 @@
|
|||||||
/*
|
|
||||||
* jQuery resize event - v1.1 - 3/14/2010
|
|
||||||
* http://benalman.com/projects/jquery-resize-plugin/
|
|
||||||
*
|
|
||||||
* Copyright (c) 2010 "Cowboy" Ben Alman
|
|
||||||
* Dual licensed under the MIT and GPL licenses.
|
|
||||||
* http://benalman.com/about/license/
|
|
||||||
*/
|
|
||||||
(function($,h,c){var a=$([]),e=$.resize=$.extend($.resize,{}),i,k="setTimeout",j="resize",d=j+"-special-event",b="delay",f="throttleWindow";e[b]=250;e[f]=true;$.event.special[j]={setup:function(){if(!e[f]&&this[k]){return false}var l=$(this);a=a.add(l);$.data(this,d,{w:l.width(),h:l.height()});if(a.length===1){g()}},teardown:function(){if(!e[f]&&this[k]){return false}var l=$(this);a=a.not(l);l.removeData(d);if(!a.length){clearTimeout(i)}},add:function(l){if(!e[f]&&this[k]){return false}var n;function m(s,o,p){var q=$(this),r=$.data(this,d);r.w=o!==c?o:q.width();r.h=p!==c?p:q.height();n.apply(this,arguments)}if($.isFunction(l)){n=l;return m}else{n=l.handler;l.handler=m}}};function g(){i=h[k](function(){a.each(function(){var n=$(this),m=n.width(),l=n.height(),o=$.data(this,d);if(m!==o.w||l!==o.h){n.trigger(j,[o.w=m,o.h=l])}});g()},e[b])}})(jQuery,this);
|
|
@ -7,6 +7,7 @@ function entry(data){
|
|||||||
var account = ko.utils.unwrapObservable(data.account);
|
var account = ko.utils.unwrapObservable(data.account);
|
||||||
var sold = ko.utils.unwrapObservable(data.sold);
|
var sold = ko.utils.unwrapObservable(data.sold);
|
||||||
var pointedSold = ko.utils.unwrapObservable(data.pointedSold);
|
var pointedSold = ko.utils.unwrapObservable(data.pointedSold);
|
||||||
|
var category = ko.utils.unwrapObservable(data.category);
|
||||||
|
|
||||||
this.id=ko.observable(id ? id : null);
|
this.id=ko.observable(id ? id : null);
|
||||||
this.value_date=ko.observable(value_date ? value_date : null);
|
this.value_date=ko.observable(value_date ? value_date : null);
|
||||||
@ -16,6 +17,7 @@ function entry(data){
|
|||||||
this.account=ko.observable(account ? account : null);
|
this.account=ko.observable(account ? account : null);
|
||||||
this.sold=ko.observable(sold ? sold : null);
|
this.sold=ko.observable(sold ? sold : null);
|
||||||
this.pointedSold=ko.observable(pointedSold ? pointedSold : null);
|
this.pointedSold=ko.observable(pointedSold ? pointedSold : null);
|
||||||
|
this.category=ko.observable(category ? category : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
function message(alertType, title, message) {
|
function message(alertType, title, message) {
|
||||||
@ -34,17 +36,41 @@ var ListViewModel = function() {
|
|||||||
self.months = ko.observableArray();
|
self.months = ko.observableArray();
|
||||||
self.month = ko.observable();
|
self.month = ko.observable();
|
||||||
|
|
||||||
self.pointedSold = ko.observable();
|
|
||||||
self.futureSold = ko.observable();
|
|
||||||
self.currentSold = ko.observable();
|
|
||||||
|
|
||||||
self.selectedItem = ko.observable();
|
self.selectedItem = ko.observable();
|
||||||
self.savedItem = ko.observable();
|
self.savedItem = ko.observable();
|
||||||
self.itemToRemove = ko.observable();
|
self.itemToRemove = ko.observable();
|
||||||
self.chart = null;
|
self.chart = null;
|
||||||
|
|
||||||
|
self.categoriesChart = ko.computed(function() {
|
||||||
|
var entries=ko.utils.unwrapObservable(self.entries);
|
||||||
|
|
||||||
|
var chartValues = [];
|
||||||
|
var chartValuesTmp = {};
|
||||||
|
|
||||||
|
$.each(entries, function(index, entry) {
|
||||||
|
var category = entry.category();
|
||||||
|
var value = entry.value() ? Number(entry.value()) : null;
|
||||||
|
|
||||||
|
if(category && value) {
|
||||||
|
var oldValue = 0.0;
|
||||||
|
|
||||||
|
if(chartValuesTmp[category]) {
|
||||||
|
oldValue = chartValuesTmp[category];
|
||||||
|
}
|
||||||
|
|
||||||
|
chartValuesTmp[category] = oldValue - value
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$.each(chartValuesTmp, function(key, value) {
|
||||||
|
chartValues.push([key, value]);
|
||||||
|
});
|
||||||
|
|
||||||
|
return chartValues;
|
||||||
|
});
|
||||||
|
|
||||||
self.entriesChart = ko.computed(function() {
|
self.entriesChart = ko.computed(function() {
|
||||||
var entries = self.entries().slice().reverse();
|
var entries = ko.utils.unwrapObservable(self.entries).slice().reverse();
|
||||||
|
|
||||||
var chartValues = [];
|
var chartValues = [];
|
||||||
var chartValuesTmp = {};
|
var chartValuesTmp = {};
|
||||||
@ -113,7 +139,8 @@ var ListViewModel = function() {
|
|||||||
value: element.value,
|
value: element.value,
|
||||||
account: element.account_id,
|
account: element.account_id,
|
||||||
sold: element.sold,
|
sold: element.sold,
|
||||||
pointedSold: element.operation_date ? element.pointedsold : ''
|
pointedSold: element.operation_date ? element.pointedsold : '',
|
||||||
|
category: element.category
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -357,29 +384,25 @@ ko.bindingHandlers.dateValue = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
drawChart = function(entries, element) {
|
drawChart = function(entries, element) {
|
||||||
if(entries && entries.length > 0) {
|
// clear previous chart
|
||||||
var firstDate, lastDate;
|
$(element).html("");
|
||||||
var chartValues = [[], []];
|
|
||||||
|
|
||||||
|
if(entries && entries.length > 0) {
|
||||||
var day = 24 * 60 * 60 * 1000;
|
var day = 24 * 60 * 60 * 1000;
|
||||||
|
|
||||||
lastDate = new Date(Date.parse(entries[entries.length -1][0]).valueOf() + 1 * day);
|
var lastDate = new Date(Date.parse(entries[entries.length -1][0]).valueOf() + 1 * day);
|
||||||
firstDate = new Date(Date.parse(entries[0][0]).valueOf() - 1 * day);
|
var firstDate = new Date(Date.parse(entries[0][0]).valueOf() - 1 * day);
|
||||||
|
var chartValues = [[], []];
|
||||||
|
|
||||||
// For the '0' line.
|
// For the '0' line.
|
||||||
chartValues[0].push(
|
chartValues[0].push(
|
||||||
[new Date(firstDate.valueOf()).toString(), 0],
|
[new Date(firstDate.valueOf()).toString(), 0],
|
||||||
[new Date(lastDate.valueOf()).toString(), 0]);
|
[new Date(lastDate.valueOf()).toString(), 0]);
|
||||||
|
|
||||||
// Push last entry
|
|
||||||
chartValues[1] = entries;
|
chartValues[1] = entries;
|
||||||
|
|
||||||
// clear previous chart
|
|
||||||
$(element).html("");
|
|
||||||
$(element).resize();
|
|
||||||
|
|
||||||
// plot chart
|
// plot chart
|
||||||
jqplot = $.jqplot(element.id, chartValues, {
|
window.chart = $.jqplot(element.id, chartValues, {
|
||||||
axes:{
|
axes:{
|
||||||
xaxis:{
|
xaxis:{
|
||||||
renderer:$.jqplot.DateAxisRenderer,
|
renderer:$.jqplot.DateAxisRenderer,
|
||||||
@ -387,12 +410,10 @@ drawChart = function(entries, element) {
|
|||||||
},
|
},
|
||||||
yaxis: {
|
yaxis: {
|
||||||
autoscale: true,
|
autoscale: true,
|
||||||
//tickOptions: {formatString: "%f"}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
highlighter: {
|
highlighter: {
|
||||||
show:true,
|
show:true,
|
||||||
//tooltipAxes: 'y',
|
|
||||||
yvalues: 4,
|
yvalues: 4,
|
||||||
formatString:'<table class="jqplot-highlighter"><tr><td>date:</td><td>%s</td></tr><tr><td>open:</td><td>%s</td></tr><tr><td>hi:</td><td>%s</td></tr><tr><td>low:</td><td>%s</td></tr><tr><td>close:</td><td>%s</td></tr></table>'
|
formatString:'<table class="jqplot-highlighter"><tr><td>date:</td><td>%s</td></tr><tr><td>open:</td><td>%s</td></tr><tr><td>hi:</td><td>%s</td></tr><tr><td>low:</td><td>%s</td></tr><tr><td>close:</td><td>%s</td></tr></table>'
|
||||||
},
|
},
|
||||||
@ -407,12 +428,38 @@ drawChart = function(entries, element) {
|
|||||||
color: "blue",
|
color: "blue",
|
||||||
lineWidth: 3,
|
lineWidth: 3,
|
||||||
rendererOptions:{
|
rendererOptions:{
|
||||||
//candleStick: true
|
|
||||||
}}],
|
}}],
|
||||||
});//*/
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
$(element).resize(function() {
|
drawPieChart = function(entries, element) {
|
||||||
jqplot.replot({resetAxes: true});
|
// clear previous chart
|
||||||
|
$(element).html("");
|
||||||
|
|
||||||
|
if(entries && entries.length > 0) {
|
||||||
|
var chartValues = [[]];
|
||||||
|
|
||||||
|
chartValues[0] = entries;
|
||||||
|
|
||||||
|
// plot chart
|
||||||
|
window.pieChart = $.jqplot(element.id, chartValues, {
|
||||||
|
seriesDefaults: {
|
||||||
|
renderer: $.jqplot.PieRenderer,
|
||||||
|
rendererOptions: {
|
||||||
|
showDataLabels: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
show: true,
|
||||||
|
location: 'e'
|
||||||
|
},
|
||||||
|
highlighter: {
|
||||||
|
show: true,
|
||||||
|
formatString:'%s: %s',
|
||||||
|
tooltipLocation:'sw',
|
||||||
|
useAxesFormatters:false
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -432,10 +479,35 @@ ko.bindingHandlers.chart = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ko.bindingHandlers.pieChart = {
|
||||||
|
init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
|
||||||
|
// empty - left as placeholder if needed later
|
||||||
|
},
|
||||||
|
|
||||||
|
update: function (element, valueAccessor, allBindingsAccessor, viewModel) {
|
||||||
|
var unwrap = ko.utils.unwrapObservable;
|
||||||
|
var dataSource = valueAccessor();
|
||||||
|
|
||||||
|
//var entries = dataSource ? unwrap(dataSource) : null;
|
||||||
|
var entries = dataSource ? unwrap(dataSource) : null;
|
||||||
|
drawPieChart(entries, element);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
$(document).ajaxError(function(event, xhr, settings) {
|
$(document).ajaxError(function(event, xhr, settings) {
|
||||||
message("error", "Error.", xhr.statusText);
|
message("error", "Error.", xhr.statusText);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$(window).resize(function() {
|
||||||
|
if(window.chart) {
|
||||||
|
window.chart.replot({resetAxes: true});
|
||||||
|
}
|
||||||
|
|
||||||
|
if(window.chart) {
|
||||||
|
window.pieChart.replot({resetAxes: true});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
var viewModel = new ListViewModel();
|
var viewModel = new ListViewModel();
|
||||||
ko.applyBindings(viewModel);
|
ko.applyBindings(viewModel);
|
||||||
|
|
||||||
|
@ -12,7 +12,8 @@ CREATE TABLE "entry" (
|
|||||||
"label" VARCHAR(500) NOT NULL,
|
"label" VARCHAR(500) NOT NULL,
|
||||||
"comment" VARCHAR(500),
|
"comment" VARCHAR(500),
|
||||||
"value" NUMERIC(15,4) NOT NULL,
|
"value" NUMERIC(15,4) NOT NULL,
|
||||||
"account_id" INTEGER NOT NULL REFERENCES "account"("id")
|
"account_id" INTEGER NOT NULL REFERENCES "account"("id"),
|
||||||
|
"category" VARCHAR(100),
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE INDEX on entry(value_date);
|
CREATE INDEX on entry(value_date);
|
||||||
|
Loading…
Reference in New Issue
Block a user