mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2026-01-09 20:11:22 +00:00
Code cleanup.
This commit is contained in:
87
public/js/ff/accounts/show.js
Normal file
87
public/js/ff/accounts/show.js
Normal file
@@ -0,0 +1,87 @@
|
||||
/* global $, lineChart, accountID, token */
|
||||
|
||||
|
||||
// Return a helper with preserved width of cells
|
||||
var fixHelper = function (e, tr) {
|
||||
"use strict";
|
||||
var $originals = tr.children();
|
||||
var $helper = tr.clone();
|
||||
$helper.children().each(function (index) {
|
||||
// Set helper cell sizes to match the original sizes
|
||||
$(this).width($originals.eq(index).width());
|
||||
});
|
||||
return $helper;
|
||||
};
|
||||
|
||||
$(function () {
|
||||
"use strict";
|
||||
if (typeof(lineChart) === "function" && typeof accountID !== 'undefined') {
|
||||
|
||||
lineChart('chart/account/' + accountID, 'overview-chart');
|
||||
}
|
||||
|
||||
// sortable!
|
||||
if (typeof $(".sortable-table tbody").sortable !== "undefined") {
|
||||
$(".sortable-table tbody").sortable(
|
||||
{
|
||||
helper: fixHelper,
|
||||
items: 'tr:not(.ignore)',
|
||||
stop: sortStop,
|
||||
handle: '.handle',
|
||||
start: function (event, ui) {
|
||||
// Build a placeholder cell that spans all the cells in the row
|
||||
var cellCount = 0;
|
||||
$('td, th', ui.helper).each(function () {
|
||||
// For each TD or TH try and get it's colspan attribute, and add that or 1 to the total
|
||||
var colspan = 1;
|
||||
var colspanAttr = $(this).attr('colspan');
|
||||
if (colspanAttr > 1) {
|
||||
colspan = colspanAttr;
|
||||
}
|
||||
cellCount += colspan;
|
||||
});
|
||||
|
||||
// Add the placeholder UI - note that this is the item's content, so TD rather than TR
|
||||
ui.placeholder.html('<td colspan="' + cellCount + '"> </td>');
|
||||
}
|
||||
}
|
||||
).disableSelection();
|
||||
} else {
|
||||
console.log('its null');
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
function sortStop(event, ui) {
|
||||
"use strict";
|
||||
var current = $(ui.item);
|
||||
console.log('sort stop');
|
||||
var thisDate = current.data('date');
|
||||
var originalBG = current.css('backgroundColor');
|
||||
|
||||
|
||||
if (current.prev().data('date') !== thisDate && current.next().data('date') !== thisDate) {
|
||||
// animate something with color:
|
||||
current.animate({backgroundColor: "#d9534f"}, 200, function () {
|
||||
$(this).animate({backgroundColor: originalBG}, 200);
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// do update
|
||||
var list = $('tr[data-date="' + thisDate + '"]');
|
||||
var submit = [];
|
||||
$.each(list, function (i, v) {
|
||||
var row = $(v);
|
||||
var id = row.data('id');
|
||||
submit.push(id);
|
||||
});
|
||||
|
||||
// do extra animation when done?
|
||||
$.post('transaction/reorder', {items: submit, date: thisDate, _token: token});
|
||||
|
||||
current.animate({backgroundColor: "#5cb85c"}, 200, function () {
|
||||
$(this).animate({backgroundColor: originalBG}, 200);
|
||||
});
|
||||
}
|
||||
9
public/js/ff/bills/show.js
Normal file
9
public/js/ff/bills/show.js
Normal file
@@ -0,0 +1,9 @@
|
||||
/* global comboChart, billID */
|
||||
|
||||
$(function () {
|
||||
"use strict";
|
||||
if (typeof(columnChart) === 'function' && typeof(billID) !== 'undefined') {
|
||||
columnChart('chart/bill/' + billID, 'bill-overview');
|
||||
}
|
||||
}
|
||||
);
|
||||
117
public/js/ff/budgets/index.js
Normal file
117
public/js/ff/budgets/index.js
Normal file
@@ -0,0 +1,117 @@
|
||||
/* globals $, budgeted:true, currencySymbol, budgetIncomeTotal, columnChart, budgetedMuch, budgetedPercentage, token, budgetID, repetitionID, spent, lineChart */
|
||||
|
||||
function drawSpentBar() {
|
||||
"use strict";
|
||||
if ($('.spentBar').length > 0) {
|
||||
var overspent = spent > budgeted;
|
||||
var pct;
|
||||
|
||||
if (overspent) {
|
||||
// draw overspent bar
|
||||
pct = (budgeted / spent) * 100;
|
||||
$('.spentBar .progress-bar-warning').css('width', pct + '%');
|
||||
$('.spentBar .progress-bar-danger').css('width', (100 - pct) + '%');
|
||||
} else {
|
||||
// draw normal bar:
|
||||
pct = (spent / budgeted) * 100;
|
||||
$('.spentBar .progress-bar-info').css('width', pct + '%');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function drawBudgetedBar() {
|
||||
"use strict";
|
||||
|
||||
if ($('.budgetedBar').length > 0) {
|
||||
var budgetedMuch = budgeted > budgetIncomeTotal;
|
||||
|
||||
// recalculate percentage:
|
||||
|
||||
var pct;
|
||||
if (budgetedMuch) {
|
||||
// budgeted too much.
|
||||
pct = (budgetIncomeTotal / budgeted) * 100;
|
||||
$('.budgetedBar .progress-bar-warning').css('width', pct + '%');
|
||||
$('.budgetedBar .progress-bar-danger').css('width', (100 - pct) + '%');
|
||||
$('.budgetedBar .progress-bar-info').css('width', 0);
|
||||
} else {
|
||||
pct = (budgeted / budgetIncomeTotal) * 100;
|
||||
$('.budgetedBar .progress-bar-warning').css('width', 0);
|
||||
$('.budgetedBar .progress-bar-danger').css('width', 0);
|
||||
$('.budgetedBar .progress-bar-info').css('width', pct + '%');
|
||||
}
|
||||
|
||||
$('#budgetedAmount').html(currencySymbol + ' ' + budgeted.toFixed(2));
|
||||
}
|
||||
}
|
||||
|
||||
function updateBudgetedAmounts(e) {
|
||||
"use strict";
|
||||
var target = $(e.target);
|
||||
var id = target.data('id');
|
||||
var value = target.val();
|
||||
var original = target.data('original');
|
||||
var difference = value - original;
|
||||
if (difference !== 0) {
|
||||
// add difference to 'budgeted' var
|
||||
budgeted = budgeted + difference;
|
||||
|
||||
// update original:
|
||||
target.data('original', value);
|
||||
// run drawBudgetedBar() again:
|
||||
drawBudgetedBar();
|
||||
|
||||
// send a post to Firefly to update the amount:
|
||||
$.post('budgets/amount/' + id, {amount: value, _token: token}).done(function (data) {
|
||||
// update the link if relevant:
|
||||
if (data.repetition > 0) {
|
||||
$('.budget-link[data-id="' + id + '"]').attr('href', 'budgets/show/' + id + '/' + data.repetition);
|
||||
} else {
|
||||
$('.budget-link[data-id="' + id + '"]').attr('href', 'budgets/show/' + id);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
console.log('Budget id is ' + id);
|
||||
console.log('Difference = ' + (value - original ));
|
||||
|
||||
}
|
||||
|
||||
$(function () {
|
||||
"use strict";
|
||||
|
||||
$('.updateIncome').on('click', updateIncome);
|
||||
|
||||
/*
|
||||
On start, fill the "spent"-bar using the content from the page.
|
||||
*/
|
||||
drawSpentBar();
|
||||
drawBudgetedBar();
|
||||
|
||||
/*
|
||||
When the input changes, update the percentages for the budgeted bar:
|
||||
*/
|
||||
$('input[type="number"]').on('input', updateBudgetedAmounts);
|
||||
|
||||
|
||||
/*
|
||||
Draw the charts, if necessary:
|
||||
*/
|
||||
if (typeof budgetID !== 'undefined' && typeof repetitionID === 'undefined') {
|
||||
columnChart('chart/budget/' + budgetID, 'budgetOverview');
|
||||
}
|
||||
if (typeof budgetID !== 'undefined' && typeof repetitionID !== 'undefined') {
|
||||
lineChart('chart/budget/' + budgetID + '/' + repetitionID, 'budgetOverview');
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
function updateIncome() {
|
||||
"use strict";
|
||||
$('#defaultModal').empty().load('budgets/income', function () {
|
||||
$('#defaultModal').modal('show');
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
117
public/js/ff/budgets/show.js
Normal file
117
public/js/ff/budgets/show.js
Normal file
@@ -0,0 +1,117 @@
|
||||
/* globals $, budgeted:true, currencySymbol, budgetIncomeTotal, columnChart, budgetedMuch, budgetedPercentage, token, budgetID, repetitionID, spent, lineChart */
|
||||
|
||||
function drawSpentBar() {
|
||||
"use strict";
|
||||
if ($('.spentBar').length > 0) {
|
||||
var overspent = spent > budgeted;
|
||||
var pct;
|
||||
|
||||
if (overspent) {
|
||||
// draw overspent bar
|
||||
pct = (budgeted / spent) * 100;
|
||||
$('.spentBar .progress-bar-warning').css('width', pct + '%');
|
||||
$('.spentBar .progress-bar-danger').css('width', (100 - pct) + '%');
|
||||
} else {
|
||||
// draw normal bar:
|
||||
pct = (spent / budgeted) * 100;
|
||||
$('.spentBar .progress-bar-info').css('width', pct + '%');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function drawBudgetedBar() {
|
||||
"use strict";
|
||||
|
||||
if ($('.budgetedBar').length > 0) {
|
||||
var budgetedMuch = budgeted > budgetIncomeTotal;
|
||||
|
||||
// recalculate percentage:
|
||||
|
||||
var pct;
|
||||
if (budgetedMuch) {
|
||||
// budgeted too much.
|
||||
pct = (budgetIncomeTotal / budgeted) * 100;
|
||||
$('.budgetedBar .progress-bar-warning').css('width', pct + '%');
|
||||
$('.budgetedBar .progress-bar-danger').css('width', (100 - pct) + '%');
|
||||
$('.budgetedBar .progress-bar-info').css('width', 0);
|
||||
} else {
|
||||
pct = (budgeted / budgetIncomeTotal) * 100;
|
||||
$('.budgetedBar .progress-bar-warning').css('width', 0);
|
||||
$('.budgetedBar .progress-bar-danger').css('width', 0);
|
||||
$('.budgetedBar .progress-bar-info').css('width', pct + '%');
|
||||
}
|
||||
|
||||
$('#budgetedAmount').html(currencySymbol + ' ' + budgeted.toFixed(2));
|
||||
}
|
||||
}
|
||||
|
||||
function updateBudgetedAmounts(e) {
|
||||
"use strict";
|
||||
var target = $(e.target);
|
||||
var id = target.data('id');
|
||||
var value = target.val();
|
||||
var original = target.data('original');
|
||||
var difference = value - original;
|
||||
if (difference !== 0) {
|
||||
// add difference to 'budgeted' var
|
||||
budgeted = budgeted + difference;
|
||||
|
||||
// update original:
|
||||
target.data('original', value);
|
||||
// run drawBudgetedBar() again:
|
||||
drawBudgetedBar();
|
||||
|
||||
// send a post to Firefly to update the amount:
|
||||
$.post('budgets/amount/' + id, {amount: value, _token: token}).done(function (data) {
|
||||
// update the link if relevant:
|
||||
if (data.repetition > 0) {
|
||||
$('.budget-link[data-id="' + id + '"]').attr('href', 'budgets/show/' + id + '/' + data.repetition);
|
||||
} else {
|
||||
$('.budget-link[data-id="' + id + '"]').attr('href', 'budgets/show/' + id);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
console.log('Budget id is ' + id);
|
||||
console.log('Difference = ' + (value - original ));
|
||||
|
||||
}
|
||||
|
||||
$(function () {
|
||||
"use strict";
|
||||
|
||||
$('.updateIncome').on('click', updateIncome);
|
||||
|
||||
/*
|
||||
On start, fill the "spent"-bar using the content from the page.
|
||||
*/
|
||||
drawSpentBar();
|
||||
drawBudgetedBar();
|
||||
|
||||
/*
|
||||
When the input changes, update the percentages for the budgeted bar:
|
||||
*/
|
||||
$('input[type="number"]').on('input', updateBudgetedAmounts);
|
||||
|
||||
|
||||
/*
|
||||
Draw the charts, if necessary:
|
||||
*/
|
||||
if (typeof budgetID !== 'undefined' && typeof repetitionID === 'undefined') {
|
||||
columnChart('chart/budget/' + budgetID, 'budgetOverview');
|
||||
}
|
||||
if (typeof budgetID !== 'undefined' && typeof repetitionID !== 'undefined') {
|
||||
lineChart('chart/budget/' + budgetID + '/' + repetitionID, 'budgetOverview');
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
function updateIncome() {
|
||||
"use strict";
|
||||
$('#defaultModal').empty().load('budgets/income', function () {
|
||||
$('#defaultModal').modal('show');
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
19
public/js/ff/categories/index.js
Normal file
19
public/js/ff/categories/index.js
Normal file
@@ -0,0 +1,19 @@
|
||||
/* globals $, categoryID, columnChart, categoryDate */
|
||||
$(function () {
|
||||
"use strict";
|
||||
if (typeof categoryID !== 'undefined') {
|
||||
// more splits:
|
||||
if ($('#all').length > 0) {
|
||||
columnChart('chart/category/' + categoryID + '/all', 'all');
|
||||
}
|
||||
if ($('#period').length > 0) {
|
||||
columnChart('chart/category/' + categoryID + '/period', 'period');
|
||||
}
|
||||
|
||||
}
|
||||
if (typeof categoryID !== 'undefined' && typeof categoryDate !== undefined) {
|
||||
columnChart('chart/category/' + categoryID + '/period/' + categoryDate, 'period-specific-period');
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
19
public/js/ff/categories/show.js
Normal file
19
public/js/ff/categories/show.js
Normal file
@@ -0,0 +1,19 @@
|
||||
/* globals $, categoryID, columnChart, categoryDate */
|
||||
$(function () {
|
||||
"use strict";
|
||||
if (typeof categoryID !== 'undefined') {
|
||||
// more splits:
|
||||
if ($('#all').length > 0) {
|
||||
columnChart('chart/category/' + categoryID + '/all', 'all');
|
||||
}
|
||||
if ($('#period').length > 0) {
|
||||
columnChart('chart/category/' + categoryID + '/period', 'period');
|
||||
}
|
||||
|
||||
}
|
||||
if (typeof categoryID !== 'undefined' && typeof categoryDate !== undefined) {
|
||||
columnChart('chart/category/' + categoryID + '/period/' + categoryDate, 'period-specific-period');
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
19
public/js/ff/categories/show_with_date.js
Normal file
19
public/js/ff/categories/show_with_date.js
Normal file
@@ -0,0 +1,19 @@
|
||||
/* globals $, categoryID, columnChart, categoryDate */
|
||||
$(function () {
|
||||
"use strict";
|
||||
if (typeof categoryID !== 'undefined') {
|
||||
// more splits:
|
||||
if ($('#all').length > 0) {
|
||||
columnChart('chart/category/' + categoryID + '/all', 'all');
|
||||
}
|
||||
if ($('#period').length > 0) {
|
||||
columnChart('chart/category/' + categoryID + '/period', 'period');
|
||||
}
|
||||
|
||||
}
|
||||
if (typeof categoryID !== 'undefined' && typeof categoryDate !== undefined) {
|
||||
columnChart('chart/category/' + categoryID + '/period/' + categoryDate, 'period-specific-period');
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
393
public/js/ff/charts.js
Normal file
393
public/js/ff/charts.js
Normal file
@@ -0,0 +1,393 @@
|
||||
/*
|
||||
* charts.js
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
/* globals $, Chart, currencySymbol,mon_decimal_point ,accounting, mon_thousands_sep, frac_digits */
|
||||
|
||||
/*
|
||||
Make some colours:
|
||||
*/
|
||||
var colourSet = [
|
||||
[53, 124, 165],
|
||||
[0, 141, 76],
|
||||
[219, 139, 11],
|
||||
[202, 25, 90],
|
||||
[85, 82, 153],
|
||||
[66, 133, 244],
|
||||
[219, 68, 55],
|
||||
[244, 180, 0],
|
||||
[15, 157, 88],
|
||||
[171, 71, 188],
|
||||
[0, 172, 193],
|
||||
[255, 112, 67],
|
||||
[158, 157, 36],
|
||||
[92, 107, 192],
|
||||
[240, 98, 146],
|
||||
[0, 121, 107],
|
||||
[194, 24, 91]
|
||||
|
||||
];
|
||||
|
||||
// Settings object that controls default parameters for library methods:
|
||||
accounting.settings = {
|
||||
currency: {
|
||||
symbol: currencySymbol, // default currency symbol is '$'
|
||||
format: "%s %v", // controls output: %s = symbol, %v = value/number (can be object: see below)
|
||||
decimal: mon_decimal_point, // decimal point separator
|
||||
thousand: mon_thousands_sep, // thousands separator
|
||||
precision: frac_digits // decimal places
|
||||
},
|
||||
number: {
|
||||
precision: 0, // default precision on numbers is 0
|
||||
thousand: ",",
|
||||
decimal: "."
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
var fillColors = [];
|
||||
var strokePointHighColors = [];
|
||||
|
||||
|
||||
for (var i = 0; i < colourSet.length; i++) {
|
||||
fillColors.push("rgba(" + colourSet[i][0] + ", " + colourSet[i][1] + ", " + colourSet[i][2] + ", 0.2)");
|
||||
strokePointHighColors.push("rgba(" + colourSet[i][0] + ", " + colourSet[i][1] + ", " + colourSet[i][2] + ", 0.9)");
|
||||
}
|
||||
|
||||
Chart.defaults.global.legend.display = false;
|
||||
Chart.defaults.global.animation.duration = 0;
|
||||
Chart.defaults.global.responsive = true;
|
||||
Chart.defaults.global.maintainAspectRatio = false;
|
||||
|
||||
/*
|
||||
Set default options:
|
||||
*/
|
||||
var defaultAreaOptions = {
|
||||
scales: {
|
||||
xAxes: [
|
||||
{
|
||||
gridLines: {
|
||||
display: false
|
||||
}
|
||||
}
|
||||
],
|
||||
yAxes: [{
|
||||
display: true,
|
||||
ticks: {
|
||||
callback: function (tickValue, index, ticks) {
|
||||
"use strict";
|
||||
return accounting.formatMoney(tickValue);
|
||||
|
||||
}
|
||||
}
|
||||
}]
|
||||
},
|
||||
tooltips: {
|
||||
mode: 'label',
|
||||
callbacks: {
|
||||
label: function (tooltipItem, data) {
|
||||
"use strict";
|
||||
return data.datasets[tooltipItem.datasetIndex].label + ': ' + accounting.formatMoney(tooltipItem.yLabel);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
var defaultPieOptions = {
|
||||
tooltips: {
|
||||
callbacks: {
|
||||
label: function (tooltipItem, data) {
|
||||
"use strict";
|
||||
return data.labels[tooltipItem.datasetIndex] + ': ' + accounting.formatMoney(tooltipItem.yLabel);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
var defaultLineOptions = {
|
||||
scales: {
|
||||
xAxes: [
|
||||
{
|
||||
gridLines: {
|
||||
display: false
|
||||
}
|
||||
}
|
||||
],
|
||||
yAxes: [{
|
||||
display: true,
|
||||
ticks: {
|
||||
callback: function (tickValue, index, ticks) {
|
||||
"use strict";
|
||||
return accounting.formatMoney(tickValue);
|
||||
|
||||
}
|
||||
}
|
||||
}]
|
||||
},
|
||||
tooltips: {
|
||||
mode: 'label',
|
||||
callbacks: {
|
||||
label: function (tooltipItem, data) {
|
||||
"use strict";
|
||||
return data.datasets[tooltipItem.datasetIndex].label + ': ' + accounting.formatMoney(tooltipItem.yLabel);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var defaultColumnOptions = {
|
||||
scales: {
|
||||
xAxes: [
|
||||
{
|
||||
gridLines: {
|
||||
display: false
|
||||
}
|
||||
}
|
||||
],
|
||||
yAxes: [{
|
||||
ticks: {
|
||||
callback: function (tickValue, index, ticks) {
|
||||
"use strict";
|
||||
return accounting.formatMoney(tickValue);
|
||||
|
||||
}
|
||||
}
|
||||
}]
|
||||
},
|
||||
elements: {
|
||||
line: {
|
||||
fill: false
|
||||
}
|
||||
},
|
||||
tooltips: {
|
||||
mode: 'label',
|
||||
callbacks: {
|
||||
label: function (tooltipItem, data) {
|
||||
"use strict";
|
||||
return data.datasets[tooltipItem.datasetIndex].label + ': ' + accounting.formatMoney(tooltipItem.yLabel);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var defaultStackedColumnOptions = {
|
||||
stacked: true,
|
||||
scales: {
|
||||
xAxes: [{
|
||||
stacked: true,
|
||||
gridLines: {
|
||||
display: false
|
||||
}
|
||||
}],
|
||||
yAxes: [{
|
||||
stacked: true,
|
||||
ticks: {
|
||||
callback: function (tickValue, index, ticks) {
|
||||
"use strict";
|
||||
return accounting.formatMoney(tickValue);
|
||||
|
||||
}
|
||||
}
|
||||
}]
|
||||
},
|
||||
tooltips: {
|
||||
mode: 'label',
|
||||
callbacks: {
|
||||
label: function (tooltipItem, data) {
|
||||
"use strict";
|
||||
return data.datasets[tooltipItem.datasetIndex].label + ': ' + accounting.formatMoney(tooltipItem.yLabel);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Function to draw a line chart:
|
||||
* @param URL
|
||||
* @param container
|
||||
* @param options
|
||||
*/
|
||||
function lineChart(URL, container, options) {
|
||||
"use strict";
|
||||
$.getJSON(URL).done(function (data) {
|
||||
|
||||
var ctx = document.getElementById(container).getContext("2d");
|
||||
var newData = {};
|
||||
newData.datasets = [];
|
||||
|
||||
for (var i = 0; i < data.count; i++) {
|
||||
newData.labels = data.labels;
|
||||
var dataset = data.datasets[i];
|
||||
dataset.backgroundColor = fillColors[i];
|
||||
newData.datasets.push(dataset);
|
||||
}
|
||||
|
||||
new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: data,
|
||||
options: defaultLineOptions
|
||||
});
|
||||
|
||||
}).fail(function () {
|
||||
$('#' + container).addClass('general-chart-error');
|
||||
});
|
||||
console.log('URL for line chart : ' + URL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to draw an area chart:
|
||||
*
|
||||
* @param URL
|
||||
* @param container
|
||||
* @param options
|
||||
*/
|
||||
function areaChart(URL, container, options) {
|
||||
"use strict";
|
||||
|
||||
$.getJSON(URL).done(function (data) {
|
||||
var ctx = document.getElementById(container).getContext("2d");
|
||||
var newData = {};
|
||||
newData.datasets = [];
|
||||
|
||||
for (var i = 0; i < data.count; i++) {
|
||||
newData.labels = data.labels;
|
||||
var dataset = data.datasets[i];
|
||||
dataset.backgroundColor = fillColors[i];
|
||||
newData.datasets.push(dataset);
|
||||
}
|
||||
|
||||
new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: newData,
|
||||
options: defaultAreaOptions
|
||||
});
|
||||
|
||||
}).fail(function () {
|
||||
$('#' + container).addClass('general-chart-error');
|
||||
});
|
||||
|
||||
console.log('URL for area chart: ' + URL);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param URL
|
||||
* @param container
|
||||
* @param options
|
||||
*/
|
||||
function columnChart(URL, container, options) {
|
||||
"use strict";
|
||||
|
||||
options = options || {};
|
||||
|
||||
$.getJSON(URL).done(function (data) {
|
||||
|
||||
var result = true;
|
||||
if (options.beforeDraw) {
|
||||
result = options.beforeDraw(data, {url: URL, container: container});
|
||||
}
|
||||
if (result === false) {
|
||||
return;
|
||||
}
|
||||
console.log('Will draw columnChart(' + URL + ')');
|
||||
|
||||
var ctx = document.getElementById(container).getContext("2d");
|
||||
var newData = {};
|
||||
newData.datasets = [];
|
||||
|
||||
for (var i = 0; i < data.count; i++) {
|
||||
newData.labels = data.labels;
|
||||
var dataset = data.datasets[i];
|
||||
dataset.backgroundColor = fillColors[i];
|
||||
newData.datasets.push(dataset);
|
||||
}
|
||||
new Chart(ctx, {
|
||||
type: 'bar',
|
||||
data: data,
|
||||
options: defaultColumnOptions
|
||||
});
|
||||
|
||||
}).fail(function () {
|
||||
$('#' + container).addClass('general-chart-error');
|
||||
});
|
||||
console.log('URL for column chart : ' + URL);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param URL
|
||||
* @param container
|
||||
* @param options
|
||||
*/
|
||||
function stackedColumnChart(URL, container, options) {
|
||||
"use strict";
|
||||
|
||||
options = options || {};
|
||||
|
||||
|
||||
$.getJSON(URL).done(function (data) {
|
||||
|
||||
var result = true;
|
||||
if (options.beforeDraw) {
|
||||
result = options.beforeDraw(data, {url: URL, container: container});
|
||||
}
|
||||
if (result === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
var ctx = document.getElementById(container).getContext("2d");
|
||||
var newData = {};
|
||||
newData.datasets = [];
|
||||
|
||||
for (var i = 0; i < data.count; i++) {
|
||||
newData.labels = data.labels;
|
||||
var dataset = data.datasets[i];
|
||||
dataset.backgroundColor = fillColors[i];
|
||||
newData.datasets.push(dataset);
|
||||
}
|
||||
new Chart(ctx, {
|
||||
type: 'bar',
|
||||
data: data,
|
||||
options: defaultStackedColumnOptions
|
||||
});
|
||||
|
||||
|
||||
}).fail(function () {
|
||||
$('#' + container).addClass('general-chart-error');
|
||||
});
|
||||
console.log('URL for stacked column chart : ' + URL);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param URL
|
||||
* @param container
|
||||
* @param options
|
||||
*/
|
||||
function pieChart(URL, container, options) {
|
||||
"use strict";
|
||||
|
||||
$.getJSON(URL).done(function (data) {
|
||||
|
||||
var ctx = document.getElementById(container).getContext("2d");
|
||||
new Chart(ctx, {
|
||||
type: 'pie',
|
||||
data: data,
|
||||
options: defaultPieOptions
|
||||
});
|
||||
|
||||
}).fail(function () {
|
||||
$('#' + container).addClass('general-chart-error');
|
||||
});
|
||||
|
||||
|
||||
console.log('URL for pie chart : ' + URL);
|
||||
|
||||
}
|
||||
126
public/js/ff/export/index.js
Normal file
126
public/js/ff/export/index.js
Normal file
@@ -0,0 +1,126 @@
|
||||
/* globals token, jobKey */
|
||||
|
||||
/*
|
||||
* index.js
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
var intervalId = 0;
|
||||
|
||||
$(function () {
|
||||
"use strict";
|
||||
// on click of export button:
|
||||
// - hide form
|
||||
// - post export command
|
||||
// - start polling progress.
|
||||
// - return false,
|
||||
|
||||
$('#export').submit(startExport);
|
||||
}
|
||||
);
|
||||
|
||||
function startExport() {
|
||||
"use strict";
|
||||
console.log('Start export...');
|
||||
hideForm();
|
||||
showLoading();
|
||||
hideError();
|
||||
|
||||
// do export
|
||||
callExport();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function hideError() {
|
||||
"use strict";
|
||||
$('#export-error').hide();
|
||||
}
|
||||
|
||||
function hideForm() {
|
||||
"use strict";
|
||||
$('#form-body').hide();
|
||||
$('#do-export-button').hide();
|
||||
}
|
||||
|
||||
function showForm() {
|
||||
"use strict";
|
||||
$('#form-body').show();
|
||||
$('#do-export-button').show();
|
||||
}
|
||||
|
||||
function showLoading() {
|
||||
"use strict";
|
||||
$('#export-loading').show();
|
||||
}
|
||||
|
||||
function hideLoading() {
|
||||
"use strict";
|
||||
$('#export-loading').hide();
|
||||
}
|
||||
|
||||
function showDownload() {
|
||||
"use strict";
|
||||
$('#export-download').show();
|
||||
}
|
||||
|
||||
function showError(text) {
|
||||
"use strict";
|
||||
$('#export-error').show();
|
||||
$('#export-error>p').text(text);
|
||||
}
|
||||
|
||||
function callExport() {
|
||||
"use strict";
|
||||
console.log('Start callExport()...')
|
||||
var data = $('#export').serialize();
|
||||
|
||||
// call status, keep calling it until response is "finished"?
|
||||
intervalId = window.setInterval(checkStatus, 500);
|
||||
|
||||
$.post('export/submit', data).done(function (data) {
|
||||
console.log('Export hath succeeded!');
|
||||
|
||||
// stop polling:
|
||||
window.clearTimeout(intervalId);
|
||||
|
||||
// call it one last time:
|
||||
window.setTimeout(checkStatus, 500);
|
||||
|
||||
// somewhere here is a download link.
|
||||
|
||||
// keep the loading thing, for debug.
|
||||
hideLoading();
|
||||
|
||||
// show download
|
||||
showDownload();
|
||||
|
||||
}).fail(function () {
|
||||
// show error.
|
||||
// show form again.
|
||||
showError('The export failed. Please check the log files to find out why.');
|
||||
|
||||
// stop polling:
|
||||
window.clearTimeout(intervalId);
|
||||
|
||||
hideLoading();
|
||||
showForm();
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
function checkStatus() {
|
||||
"use strict";
|
||||
console.log('get status...');
|
||||
$.getJSON('export/status/' + jobKey).done(function (data) {
|
||||
putStatusText(data.status);
|
||||
});
|
||||
}
|
||||
|
||||
function putStatusText(status) {
|
||||
"use strict";
|
||||
$('#status-message').text(status);
|
||||
}
|
||||
114
public/js/ff/firefly.js
Normal file
114
public/js/ff/firefly.js
Normal file
@@ -0,0 +1,114 @@
|
||||
/* globals token, dateRangeConfig, $, */
|
||||
$(function () {
|
||||
"use strict";
|
||||
|
||||
// when you click on a currency, this happens:
|
||||
$('.currency-option').click(currencySelect);
|
||||
|
||||
var ranges = {};
|
||||
// range for the current month:
|
||||
ranges[dateRangeConfig.currentMonth] = [moment().startOf('month'), moment().endOf('month')];
|
||||
|
||||
// range for the previous month:
|
||||
ranges[dateRangeConfig.previousMonth] = [moment().subtract(1, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')];
|
||||
|
||||
// range for the next month:
|
||||
ranges[dateRangeConfig.nextMonth] = [moment().add(1, 'month').startOf('month'), moment().add(1, 'month').endOf('month')];
|
||||
|
||||
// range for everything:
|
||||
ranges[dateRangeConfig.everything] = [dateRangeConfig.firstDate, moment()];
|
||||
|
||||
|
||||
// build the data range:
|
||||
$('#daterange').text(dateRangeConfig.linkTitle).daterangepicker(
|
||||
{
|
||||
ranges: ranges,
|
||||
opens: 'left',
|
||||
locale: {
|
||||
applyLabel: dateRangeConfig.applyLabel,
|
||||
cancelLabel: dateRangeConfig.cancelLabel,
|
||||
fromLabel: dateRangeConfig.fromLabel,
|
||||
toLabel: dateRangeConfig.toLabel,
|
||||
weekLabel: 'W',
|
||||
customRangeLabel: dateRangeConfig.customRangeLabel,
|
||||
daysOfWeek: moment.weekdaysMin(),
|
||||
monthNames: moment.monthsShort(),
|
||||
firstDay: moment.localeData()._week.dow
|
||||
},
|
||||
format: 'YYYY-MM-DD',
|
||||
startDate: dateRangeConfig.startDate,
|
||||
endDate: dateRangeConfig.endDate
|
||||
},
|
||||
function (start, end, label) {
|
||||
|
||||
// send post.
|
||||
$.post(dateRangeConfig.URL, {
|
||||
start: start.format('YYYY-MM-DD'),
|
||||
end: end.format('YYYY-MM-DD'),
|
||||
label: label,
|
||||
_token: token
|
||||
}).done(function () {
|
||||
console.log('Succesfully sent new date range.');
|
||||
window.location.reload(true);
|
||||
}).fail(function () {
|
||||
console.log('Could not send new date range.');
|
||||
alert('Could not change date range');
|
||||
|
||||
});
|
||||
|
||||
//alert('A date range was chosen: ' + start.format('YYYY-MM-DD') + ' to ' + end.format('YYYY-MM-DD'));
|
||||
}
|
||||
);
|
||||
|
||||
});
|
||||
|
||||
function currencySelect(e) {
|
||||
"use strict";
|
||||
// clicked on
|
||||
var target = $(e.target); // target is the <A> tag.
|
||||
|
||||
// name of the field in question:
|
||||
var name = target.data('name');
|
||||
|
||||
// id of menu button (used later on):
|
||||
var menuID = 'currency_dropdown_' + name;
|
||||
|
||||
// the hidden input with the actual value of the selected currency:
|
||||
var hiddenInputName = 'amount_currency_id_' + target.data('name');
|
||||
|
||||
// span with the current selection (next to the caret):
|
||||
var spanId = 'currency_select_symbol_' + target.data('name');
|
||||
|
||||
// the selected currency symbol:
|
||||
var symbol = target.data('symbol');
|
||||
|
||||
// id of the selected currency.
|
||||
var id = target.data('id');
|
||||
|
||||
// update the hidden input:
|
||||
$('input[name="' + hiddenInputName + '"]').val(id);
|
||||
|
||||
// update the symbol:
|
||||
$('#' + spanId).text(symbol);
|
||||
|
||||
// close the menu (hack hack)
|
||||
$('#' + menuID).click();
|
||||
|
||||
|
||||
return false;
|
||||
|
||||
//var code = target.data('code');
|
||||
//var fieldType = target.data('field');
|
||||
//var menu = $('.' + fieldType + 'CurrencyDropdown');
|
||||
//
|
||||
//var symbolHolder = $('#' + fieldType + 'CurrentSymbol');
|
||||
//symbolHolder.text(symbol);
|
||||
//$('input[name="' + fieldType + '_currency_id"]').val(id);
|
||||
//
|
||||
// close dropdown (hack hack)
|
||||
//menu.click();
|
||||
|
||||
|
||||
//return false;
|
||||
}
|
||||
|
||||
6
public/js/ff/guest.js
Normal file
6
public/js/ff/guest.js
Normal file
@@ -0,0 +1,6 @@
|
||||
$(function () {
|
||||
"use strict";
|
||||
|
||||
// Focus first visible form element.
|
||||
$("form input:enabled:visible:first").first().select()
|
||||
});
|
||||
27
public/js/ff/help.js
Normal file
27
public/js/ff/help.js
Normal file
@@ -0,0 +1,27 @@
|
||||
$(function () {
|
||||
"use strict";
|
||||
$('#help').click(showHelp);
|
||||
$(function () {
|
||||
|
||||
//$('[data-toggle="tooltip"]').tooltip();
|
||||
});
|
||||
});
|
||||
|
||||
function showHelp(e) {
|
||||
"use strict";
|
||||
var target = $(e.target);
|
||||
var route = target.data('route');
|
||||
//
|
||||
$('#helpBody').html('<i class="fa fa-refresh fa-spin"></i>');
|
||||
$('#helpTitle').html('Please hold...');
|
||||
|
||||
$('#helpModal').modal('show');
|
||||
$.getJSON('help/' + encodeURI(route)).done(function (data) {
|
||||
$('#helpBody').html(data.text);
|
||||
$('#helpTitle').html(data.title);
|
||||
}).fail(function () {
|
||||
$('#helpBody').html('<p class="text-danger">No help text could be found.</p>');
|
||||
$('#helpTitle').html('Sorry...');
|
||||
});
|
||||
return false;
|
||||
}
|
||||
85
public/js/ff/index.js
Normal file
85
public/js/ff/index.js
Normal file
@@ -0,0 +1,85 @@
|
||||
/* globals $, columnChart,showTour, Tour, google, lineChart, pieChart, stackedColumnChart, areaChart */
|
||||
|
||||
$(function () {
|
||||
"use strict";
|
||||
// do chart JS stuff.
|
||||
drawChart();
|
||||
if (showTour) {
|
||||
$.getJSON('json/tour').done(function (data) {
|
||||
var tour = new Tour(
|
||||
{
|
||||
steps: data.steps,
|
||||
template: data.template,
|
||||
onEnd: endTheTour
|
||||
});
|
||||
// Initialize the tour
|
||||
tour.init();
|
||||
// Start the tour
|
||||
tour.start();
|
||||
}).fail(function () {
|
||||
console.log('Already had tour.');
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
|
||||
function endTheTour() {
|
||||
"use strict";
|
||||
$.post('json/end-tour', {_token: token});
|
||||
|
||||
}
|
||||
|
||||
function drawChart() {
|
||||
"use strict";
|
||||
areaChart('chart/account/frontpage', 'accounts-chart');
|
||||
pieChart('chart/bill/frontpage', 'bills-chart');
|
||||
stackedColumnChart('chart/budget/frontpage', 'budgets-chart', {beforeDraw: beforeDrawIsEmpty});
|
||||
columnChart('chart/category/frontpage', 'categories-chart', {beforeDraw: beforeDrawIsEmpty});
|
||||
columnChart('chart/account/expense', 'expense-accounts-chart', {beforeDraw: beforeDrawIsEmpty});
|
||||
|
||||
|
||||
getBoxAmounts();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a chart container if there is nothing for the chart to draw.
|
||||
*
|
||||
* @param data
|
||||
* @param options
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function beforeDrawIsEmpty(data, options) {
|
||||
"use strict";
|
||||
|
||||
// check if chart holds data.
|
||||
if (data.labels.length === 0) {
|
||||
// remove the chart container + parent
|
||||
console.log(options.container + ' appears empty. Removed.');
|
||||
$('#' + options.container).parent().parent().remove();
|
||||
|
||||
// return false so script stops.
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
function getBoxAmounts() {
|
||||
"use strict";
|
||||
var boxes = ['in', 'out', 'bills-unpaid', 'bills-paid'];
|
||||
for (var x in boxes) {
|
||||
var box = boxes[x];
|
||||
$.getJSON('json/box/' + box).done(putData).fail(failData);
|
||||
}
|
||||
}
|
||||
|
||||
function putData(data) {
|
||||
"use strict";
|
||||
$('#box-' + data.box).html(data.amount);
|
||||
}
|
||||
|
||||
function failData() {
|
||||
"use strict";
|
||||
console.log('Failed to get box!');
|
||||
}
|
||||
85
public/js/ff/piggy-banks/index.js
Normal file
85
public/js/ff/piggy-banks/index.js
Normal file
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* index.js
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
/* globals $, lineChart, token, piggyBankID */
|
||||
|
||||
// Return a helper with preserved width of cells
|
||||
var fixHelper = function (e, tr) {
|
||||
"use strict";
|
||||
var $originals = tr.children();
|
||||
var $helper = tr.clone();
|
||||
$helper.children().each(function (index) {
|
||||
// Set helper cell sizes to match the original sizes
|
||||
$(this).width($originals.eq(index).width());
|
||||
});
|
||||
return $helper;
|
||||
};
|
||||
|
||||
$(function () {
|
||||
"use strict";
|
||||
$('.addMoney').on('click', addMoney);
|
||||
$('.removeMoney').on('click', removeMoney);
|
||||
|
||||
$('#sortable tbody').sortable(
|
||||
{
|
||||
helper: fixHelper,
|
||||
stop: stopSorting,
|
||||
handle: '.handle',
|
||||
start: function (event, ui) {
|
||||
// Build a placeholder cell that spans all the cells in the row
|
||||
var cellCount = 0;
|
||||
$('td, th', ui.helper).each(function () {
|
||||
// For each TD or TH try and get it's colspan attribute, and add that or 1 to the total
|
||||
var colspan = 1;
|
||||
var colspanAttr = $(this).attr('colspan');
|
||||
if (colspanAttr > 1) {
|
||||
colspan = colspanAttr;
|
||||
}
|
||||
cellCount += colspan;
|
||||
});
|
||||
|
||||
// Add the placeholder UI - note that this is the item's content, so TD rather than TR
|
||||
ui.placeholder.html('<td colspan="' + cellCount + '"> </td>');
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
function addMoney(e) {
|
||||
"use strict";
|
||||
var pigID = parseInt($(e.target).data('id'));
|
||||
$('#defaultModal').empty().load('piggy-banks/add/' + pigID, function () {
|
||||
$('#defaultModal').modal('show');
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function removeMoney(e) {
|
||||
"use strict";
|
||||
var pigID = parseInt($(e.target).data('id'));
|
||||
$('#defaultModal').empty().load('piggy-banks/remove/' + pigID, function () {
|
||||
$('#defaultModal').modal('show');
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
function stopSorting() {
|
||||
"use strict";
|
||||
$('.loadSpin').addClass('fa fa-refresh fa-spin');
|
||||
var order = [];
|
||||
$.each($('#sortable>tbody>tr'), function (i, v) {
|
||||
var holder = $(v);
|
||||
var id = holder.data('id');
|
||||
order.push(id);
|
||||
});
|
||||
$.post('piggy-banks/sort', {_token: token, order: order}).done(function () {
|
||||
$('.loadSpin').removeClass('fa fa-refresh fa-spin');
|
||||
});
|
||||
}
|
||||
16
public/js/ff/piggy-banks/show.js
Normal file
16
public/js/ff/piggy-banks/show.js
Normal file
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* show.js
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
/* globals $, lineChart, piggyBankID */
|
||||
|
||||
$(function () {
|
||||
"use strict";
|
||||
if (typeof(lineChart) === 'function' && typeof(piggyBankID) !== 'undefined') {
|
||||
lineChart('chart/piggy-bank/' + piggyBankID, 'piggy-bank-history');
|
||||
}
|
||||
});
|
||||
114
public/js/ff/reports/audit/all.js
Normal file
114
public/js/ff/reports/audit/all.js
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* all.js
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
/* globals hideable */
|
||||
|
||||
|
||||
/**
|
||||
* Created by sander on 01/04/16.
|
||||
*/
|
||||
|
||||
$(function () {
|
||||
"use strict";
|
||||
|
||||
// scan current selection of checkboxes and put them in a cookie:
|
||||
var arr;
|
||||
if ((readCookie('audit-option-checkbox') !== null)) {
|
||||
arr = readCookie('audit-option-checkbox').split(',');
|
||||
arr.forEach(function (val) {
|
||||
$('input[type="checkbox"][value="' + val + '"]').prop('checked', true);
|
||||
});
|
||||
console.log('arr from cookie is ' + arr)
|
||||
} else {
|
||||
// no cookie? read list, store in array 'arr'
|
||||
// all account ids:
|
||||
arr = readCheckboxes();
|
||||
}
|
||||
storeCheckboxes(arr);
|
||||
|
||||
|
||||
// process options:
|
||||
showOnlyColumns(arr);
|
||||
|
||||
// respond to click each button:
|
||||
$('.audit-option-checkbox').click(clickColumnOption);
|
||||
|
||||
});
|
||||
|
||||
function clickColumnOption() {
|
||||
"use strict";
|
||||
var newArr = readCheckboxes();
|
||||
showOnlyColumns(newArr);
|
||||
storeCheckboxes(newArr);
|
||||
}
|
||||
|
||||
function storeCheckboxes(checkboxes) {
|
||||
"use strict";
|
||||
// store new cookie with those options:
|
||||
console.log('Store new cookie with those options: ' + checkboxes);
|
||||
createCookie('audit-option-checkbox', checkboxes, 365);
|
||||
}
|
||||
|
||||
function readCheckboxes() {
|
||||
"use strict";
|
||||
var checkboxes = [];
|
||||
$.each($('.audit-option-checkbox'), function (i, v) {
|
||||
var c = $(v);
|
||||
if (c.prop('checked')) {
|
||||
//url += c.val() + ',';
|
||||
checkboxes.push(c.val());
|
||||
}
|
||||
});
|
||||
console.log('arr is now (default): ' + checkboxes);
|
||||
return checkboxes;
|
||||
}
|
||||
|
||||
function showOnlyColumns(checkboxes) {
|
||||
"use strict";
|
||||
|
||||
for (var i = 0; i < hideable.length; i++) {
|
||||
var opt = hideable[i];
|
||||
if(checkboxes.indexOf(opt) > -1) {
|
||||
console.log(opt + ' is in checkboxes');
|
||||
$('td.hide-' + opt).show();
|
||||
$('th.hide-' + opt).show();
|
||||
} else {
|
||||
console.log(opt + ' is NOT in checkboxes');
|
||||
$('th.hide-' + opt).hide();
|
||||
$('td.hide-' + opt).hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function createCookie(name, value, days) {
|
||||
"use strict";
|
||||
var expires;
|
||||
|
||||
if (days) {
|
||||
var date = new Date();
|
||||
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
|
||||
expires = "; expires=" + date.toGMTString();
|
||||
} else {
|
||||
expires = "";
|
||||
}
|
||||
document.cookie = encodeURIComponent(name) + "=" + encodeURIComponent(value) + expires + "; path=/";
|
||||
}
|
||||
|
||||
function readCookie(name) {
|
||||
"use strict";
|
||||
var nameEQ = encodeURIComponent(name) + "=";
|
||||
var ca = document.cookie.split(';');
|
||||
for (var i = 0; i < ca.length; i++) {
|
||||
var c = ca[i];
|
||||
while (c.charAt(0) === ' ') c = c.substring(1, c.length);
|
||||
if (c.indexOf(nameEQ) === 0) return decodeURIComponent(c.substring(nameEQ.length, c.length));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
54
public/js/ff/reports/default/all.js
Normal file
54
public/js/ff/reports/default/all.js
Normal file
@@ -0,0 +1,54 @@
|
||||
/* globals startDate, endDate, reportType, accountIds */
|
||||
/*
|
||||
* all.js
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Created by sander on 01/04/16.
|
||||
*/
|
||||
|
||||
$(function () {
|
||||
"use strict";
|
||||
|
||||
// find the little info buttons and respond to them.
|
||||
$('.firefly-info-button').click(clickInfoButton);
|
||||
|
||||
});
|
||||
|
||||
function clickInfoButton(e) {
|
||||
"use strict";
|
||||
// find all data tags, regardless of what they are:
|
||||
var element = $(e.target);
|
||||
var attributes = element.data();
|
||||
|
||||
// set wait cursor
|
||||
$('body').addClass('waiting');
|
||||
|
||||
// add some more elements:
|
||||
attributes.startDate = startDate;
|
||||
attributes.endDate = endDate;
|
||||
attributes.reportType = reportType;
|
||||
attributes.accounts = accountIds;
|
||||
|
||||
$.getJSON('popup/report', {attributes: attributes}).success(respondInfoButton).fail(errorInfoButton);
|
||||
}
|
||||
|
||||
function errorInfoButton(data) {
|
||||
"use strict";
|
||||
// remove wait cursor
|
||||
$('body').removeClass('waiting');
|
||||
alert('Apologies. The requested data is not (yet) available.');
|
||||
}
|
||||
|
||||
function respondInfoButton(data) {
|
||||
"use strict";
|
||||
// remove wait cursor
|
||||
$('body').removeClass('waiting');
|
||||
$('#defaultModal').empty().html(data.html);
|
||||
$('#defaultModal').modal('show');
|
||||
|
||||
}
|
||||
64
public/js/ff/reports/default/month.js
Normal file
64
public/js/ff/reports/default/month.js
Normal file
@@ -0,0 +1,64 @@
|
||||
/* globals google, startDate ,reportURL, endDate , reportType ,accountIds , picker:true, minDate, expenseRestShow:true, incomeRestShow:true, year, month, hideTheRest, showTheRest, showTheRestExpense, hideTheRestExpense, columnChart, lineChart, stackedColumnChart */
|
||||
|
||||
|
||||
$(function () {
|
||||
"use strict";
|
||||
drawChart();
|
||||
|
||||
// click open the top X income list:
|
||||
$('#showIncomes').click(showIncomes);
|
||||
// click open the top X expense list:
|
||||
$('#showExpenses').click(showExpenses);
|
||||
});
|
||||
|
||||
|
||||
function drawChart() {
|
||||
"use strict";
|
||||
|
||||
// month view:
|
||||
// draw account chart
|
||||
lineChart('chart/account/report/' + reportType + '/' + startDate + '/' + endDate + '/' + accountIds, 'account-balances-chart');
|
||||
}
|
||||
|
||||
|
||||
function showIncomes() {
|
||||
"use strict";
|
||||
if (incomeRestShow) {
|
||||
// hide everything, make button say "show"
|
||||
$('#showIncomes').text(showTheRest);
|
||||
$('.incomesCollapsed').removeClass('in').addClass('out');
|
||||
|
||||
// toggle:
|
||||
incomeRestShow = false;
|
||||
} else {
|
||||
// show everything, make button say "hide".
|
||||
$('#showIncomes').text(hideTheRest);
|
||||
$('.incomesCollapsed').removeClass('out').addClass('in');
|
||||
|
||||
// toggle:
|
||||
incomeRestShow = true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function showExpenses() {
|
||||
"use strict";
|
||||
if (expenseRestShow) {
|
||||
// hide everything, make button say "show"
|
||||
$('#showExpenses').text(showTheRestExpense);
|
||||
$('.expenseCollapsed').removeClass('in').addClass('out');
|
||||
|
||||
// toggle:
|
||||
expenseRestShow = false;
|
||||
} else {
|
||||
// show everything, make button say "hide".
|
||||
$('#showExpenses').text(hideTheRestExpense);
|
||||
$('.expenseCollapsed').removeClass('out').addClass('in');
|
||||
|
||||
// toggle:
|
||||
expenseRestShow = true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
205
public/js/ff/reports/default/multi-year.js
Normal file
205
public/js/ff/reports/default/multi-year.js
Normal file
@@ -0,0 +1,205 @@
|
||||
/* globals google, startDate ,reportURL, endDate , reportType ,accountIds , picker:true, minDate, expenseRestShow:true, incomeRestShow:true, year, month, hideTheRest, showTheRest, showTheRestExpense, hideTheRestExpense, columnChart, lineChart, stackedColumnChart */
|
||||
|
||||
|
||||
$(function () {
|
||||
"use strict";
|
||||
drawChart();
|
||||
|
||||
// click open the top X income list:
|
||||
$('#showIncomes').click(showIncomes);
|
||||
// click open the top X expense list:
|
||||
$('#showExpenses').click(showExpenses);
|
||||
|
||||
});
|
||||
|
||||
|
||||
function drawChart() {
|
||||
"use strict";
|
||||
|
||||
// income and expense over multi year:
|
||||
lineChart('chart/report/net-worth/' + reportType + '/' + startDate + '/' + endDate + '/' + accountIds, 'net-worth');
|
||||
columnChart('chart/report/in-out/' + reportType + '/' + startDate + '/' + endDate + '/' + accountIds, 'income-expenses-chart');
|
||||
columnChart('chart/report/in-out-sum/' + reportType + '/' + startDate + '/' + endDate + '/' + accountIds, 'income-expenses-sum-chart');
|
||||
|
||||
|
||||
$.each($('.account-chart'), function (i, v) {
|
||||
var holder = $(v);
|
||||
console.log('Will draw chart for account #' + holder.data('id'));
|
||||
});
|
||||
|
||||
// draw budget chart based on selected budgets:
|
||||
$('.budget-checkbox').on('change', updateBudgetChart);
|
||||
selectBudgetsByCookie();
|
||||
updateBudgetChart();
|
||||
|
||||
// draw category chart based on selected budgets:
|
||||
$('.category-checkbox').on('change', updateCategoryChart);
|
||||
selectCategoriesByCookie();
|
||||
updateCategoryChart();
|
||||
}
|
||||
|
||||
function selectBudgetsByCookie() {
|
||||
"use strict";
|
||||
var cookie = readCookie('multi-year-budgets');
|
||||
if (cookie !== null) {
|
||||
var cookieArray = cookie.split(',');
|
||||
for (var x in cookieArray) {
|
||||
var budgetId = cookieArray[x];
|
||||
$('.budget-checkbox[value="' + budgetId + '"').prop('checked', true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function selectCategoriesByCookie() {
|
||||
"use strict";
|
||||
var cookie = readCookie('multi-year-categories');
|
||||
if (cookie !== null) {
|
||||
var cookieArray = cookie.split(',');
|
||||
for (var x in cookieArray) {
|
||||
var categoryId = cookieArray[x];
|
||||
$('.category-checkbox[value="' + categoryId + '"').prop('checked', true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function updateBudgetChart() {
|
||||
"use strict";
|
||||
console.log('will update budget chart.');
|
||||
// get all budget ids:
|
||||
var budgets = [];
|
||||
$.each($('.budget-checkbox'), function (i, v) {
|
||||
var current = $(v);
|
||||
if (current.prop('checked')) {
|
||||
budgets.push(current.val());
|
||||
}
|
||||
});
|
||||
|
||||
if (budgets.length > 0) {
|
||||
|
||||
var budgetIds = budgets.join(',');
|
||||
|
||||
// remove old chart:
|
||||
$('#budgets-chart').replaceWith('<canvas id="budgets-chart" class="budgets-chart" style="width:100%;height:400px;"></canvas>');
|
||||
|
||||
// hide message:
|
||||
$('#budgets-chart-message').hide();
|
||||
|
||||
// draw chart. Redraw when exists? Not sure if we support that.
|
||||
columnChart('chart/budget/multi-year/' + reportType + '/' + startDate + '/' + endDate + '/' + accountIds + '/' + budgetIds, 'budgets-chart');
|
||||
createCookie('multi-year-budgets', budgets, 365);
|
||||
} else {
|
||||
// hide canvas, show message:
|
||||
$('#budgets-chart-message').show();
|
||||
$('#budgets-chart').hide();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function updateCategoryChart() {
|
||||
"use strict";
|
||||
console.log('will update category chart.');
|
||||
// get all category ids:
|
||||
var categories = [];
|
||||
$.each($('.category-checkbox'), function (i, v) {
|
||||
var current = $(v);
|
||||
if (current.prop('checked')) {
|
||||
categories.push(current.val());
|
||||
}
|
||||
});
|
||||
|
||||
if (categories.length > 0) {
|
||||
|
||||
var categoryIds = categories.join(',');
|
||||
|
||||
// remove old chart:
|
||||
$('#categories-chart').replaceWith('<canvas id="categories-chart" class="budgets-chart" style="width:100%;height:400px;"></canvas>');
|
||||
|
||||
// hide message:
|
||||
$('#categories-chart-message').hide();
|
||||
|
||||
// draw chart. Redraw when exists? Not sure if we support that.
|
||||
columnChart('chart/category/multi-year/' + reportType + '/' + startDate + '/' + endDate + '/' + accountIds + '/' + categoryIds, 'categories-chart');
|
||||
createCookie('multi-year-categories', categories, 365);
|
||||
} else {
|
||||
// hide canvas, show message:
|
||||
$('#categories-chart-message').show();
|
||||
$('#categories-chart').hide();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function createCookie(name, value, days) {
|
||||
"use strict";
|
||||
var expires;
|
||||
|
||||
if (days) {
|
||||
var date = new Date();
|
||||
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
|
||||
expires = "; expires=" + date.toGMTString();
|
||||
} else {
|
||||
expires = "";
|
||||
}
|
||||
document.cookie = encodeURIComponent(name) + "=" + encodeURIComponent(value) + expires + "; path=/";
|
||||
}
|
||||
|
||||
function readCookie(name) {
|
||||
"use strict";
|
||||
var nameEQ = encodeURIComponent(name) + "=";
|
||||
var ca = document.cookie.split(';');
|
||||
for (var i = 0; i < ca.length; i++) {
|
||||
var c = ca[i];
|
||||
while (c.charAt(0) === ' ') c = c.substring(1, c.length);
|
||||
if (c.indexOf(nameEQ) === 0) return decodeURIComponent(c.substring(nameEQ.length, c.length));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function eraseCookie(name) {
|
||||
createCookie(name, "", -1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
function showIncomes() {
|
||||
"use strict";
|
||||
if (incomeRestShow) {
|
||||
// hide everything, make button say "show"
|
||||
$('#showIncomes').text(showTheRest);
|
||||
$('.incomesCollapsed').removeClass('in').addClass('out');
|
||||
|
||||
// toggle:
|
||||
incomeRestShow = false;
|
||||
} else {
|
||||
// show everything, make button say "hide".
|
||||
$('#showIncomes').text(hideTheRest);
|
||||
$('.incomesCollapsed').removeClass('out').addClass('in');
|
||||
|
||||
// toggle:
|
||||
incomeRestShow = true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function showExpenses() {
|
||||
"use strict";
|
||||
if (expenseRestShow) {
|
||||
// hide everything, make button say "show"
|
||||
$('#showExpenses').text(showTheRestExpense);
|
||||
$('.expenseCollapsed').removeClass('in').addClass('out');
|
||||
|
||||
// toggle:
|
||||
expenseRestShow = false;
|
||||
} else {
|
||||
// show everything, make button say "hide".
|
||||
$('#showExpenses').text(hideTheRestExpense);
|
||||
$('.expenseCollapsed').removeClass('out').addClass('in');
|
||||
|
||||
// toggle:
|
||||
expenseRestShow = true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
68
public/js/ff/reports/default/year.js
Normal file
68
public/js/ff/reports/default/year.js
Normal file
@@ -0,0 +1,68 @@
|
||||
/* globals google, startDate ,reportURL, endDate , reportType ,accountIds , picker:true, minDate, expenseRestShow:true, incomeRestShow:true, year, month, hideTheRest, showTheRest, showTheRestExpense, hideTheRestExpense, columnChart, lineChart, stackedColumnChart */
|
||||
|
||||
|
||||
$(function () {
|
||||
"use strict";
|
||||
drawChart();
|
||||
|
||||
// click open the top X income list:
|
||||
$('#showIncomes').click(showIncomes);
|
||||
// click open the top X expense list:
|
||||
$('#showExpenses').click(showExpenses);
|
||||
});
|
||||
|
||||
|
||||
function drawChart() {
|
||||
"use strict";
|
||||
|
||||
lineChart('chart/report/net-worth/' + reportType + '/' + startDate + '/' + endDate + '/' + accountIds, 'net-worth');
|
||||
columnChart('chart/report/in-out/' + reportType + '/' + startDate + '/' + endDate + '/' + accountIds, 'income-expenses-chart');
|
||||
columnChart('chart/report/in-out-sum/' + reportType + '/' + startDate + '/' + endDate + '/' + accountIds, 'income-expenses-sum-chart');
|
||||
stackedColumnChart('chart/budget/year/' + reportType + '/' + startDate + '/' + endDate + '/' + accountIds, 'budgets');
|
||||
stackedColumnChart('chart/category/spent-in-period/' + reportType + '/' + startDate + '/' + endDate + '/' + accountIds, 'categories-spent-in-period');
|
||||
stackedColumnChart('chart/category/earned-in-period/' + reportType + '/' + startDate + '/' + endDate + '/' + accountIds, 'categories-earned-in-period');
|
||||
|
||||
}
|
||||
|
||||
|
||||
function showIncomes() {
|
||||
"use strict";
|
||||
if (incomeRestShow) {
|
||||
// hide everything, make button say "show"
|
||||
$('#showIncomes').text(showTheRest);
|
||||
$('.incomesCollapsed').removeClass('in').addClass('out');
|
||||
|
||||
// toggle:
|
||||
incomeRestShow = false;
|
||||
} else {
|
||||
// show everything, make button say "hide".
|
||||
$('#showIncomes').text(hideTheRest);
|
||||
$('.incomesCollapsed').removeClass('out').addClass('in');
|
||||
|
||||
// toggle:
|
||||
incomeRestShow = true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function showExpenses() {
|
||||
"use strict";
|
||||
if (expenseRestShow) {
|
||||
// hide everything, make button say "show"
|
||||
$('#showExpenses').text(showTheRestExpense);
|
||||
$('.expenseCollapsed').removeClass('in').addClass('out');
|
||||
|
||||
// toggle:
|
||||
expenseRestShow = false;
|
||||
} else {
|
||||
// show everything, make button say "hide".
|
||||
$('#showExpenses').text(hideTheRestExpense);
|
||||
$('.expenseCollapsed').removeClass('out').addClass('in');
|
||||
|
||||
// toggle:
|
||||
expenseRestShow = true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
122
public/js/ff/reports/index.js
Normal file
122
public/js/ff/reports/index.js
Normal file
@@ -0,0 +1,122 @@
|
||||
/* globals google, startDate ,reportURL, endDate , reportType ,accountIds , picker:true, minDate, expenseRestShow:true, incomeRestShow:true, year, month, hideTheRest, showTheRest, showTheRestExpense, hideTheRestExpense, columnChart, lineChart, stackedColumnChart */
|
||||
|
||||
|
||||
$(function () {
|
||||
"use strict";
|
||||
|
||||
if ($('#inputDateRange').length > 0) {
|
||||
|
||||
picker = $('#inputDateRange').daterangepicker(
|
||||
{
|
||||
locale: {
|
||||
format: 'YYYY-MM-DD',
|
||||
firstDay: 1,
|
||||
},
|
||||
minDate: minDate,
|
||||
drops: 'up',
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
// set values from cookies, if any:
|
||||
if (readCookie('report-type') !== null) {
|
||||
$('select[name="report_type"]').val(readCookie('report-type'));
|
||||
}
|
||||
|
||||
if ((readCookie('report-accounts') !== null)) {
|
||||
var arr = readCookie('report-accounts').split(',');
|
||||
arr.forEach(function (val) {
|
||||
$('input[type="checkbox"][value="' + val + '"]').prop('checked', true);
|
||||
});
|
||||
}
|
||||
|
||||
// set date:
|
||||
var startStr = readCookie('report-start');
|
||||
var endStr = readCookie('report-end');
|
||||
if (startStr !== null && endStr !== null && startStr.length == 8 && endStr.length == 8) {
|
||||
var startDate = moment(startStr, "YYYY-MM-DD");
|
||||
var endDate = moment(endStr, "YYYY-MM-DD");
|
||||
var datePicker = $('#inputDateRange').data('daterangepicker');
|
||||
datePicker.setStartDate(startDate);
|
||||
datePicker.setEndDate(endDate);
|
||||
}
|
||||
}
|
||||
|
||||
$('.date-select').on('click', preSelectDate);
|
||||
$('#report-form').on('submit', catchSubmit);
|
||||
|
||||
});
|
||||
|
||||
function catchSubmit() {
|
||||
"use strict";
|
||||
// default;20141201;20141231;4;5
|
||||
// report name:
|
||||
var url = '' + $('select[name="report_type"]').val() + '/';
|
||||
|
||||
// date, processed:
|
||||
var picker = $('#inputDateRange').data('daterangepicker');
|
||||
url += moment(picker.startDate).format("YYYYMMDD") + '/';
|
||||
url += moment(picker.endDate).format("YYYYMMDD") + '/';
|
||||
|
||||
// all account ids:
|
||||
var count = 0;
|
||||
var accounts = [];
|
||||
$.each($('.account-checkbox'), function (i, v) {
|
||||
var c = $(v);
|
||||
if (c.prop('checked')) {
|
||||
url += c.val() + ',';
|
||||
accounts.push(c.val());
|
||||
count++;
|
||||
}
|
||||
});
|
||||
if (count > 0) {
|
||||
// set cookie to remember choices.
|
||||
createCookie('report-type', $('select[name="report_type"]').val(), 365);
|
||||
createCookie('report-accounts', accounts, 365);
|
||||
createCookie('report-start', moment(picker.startDate).format("YYYYMMDD"), 365);
|
||||
createCookie('report-end', moment(picker.endDate).format("YYYYMMDD"), 365);
|
||||
|
||||
window.location.href = reportURL + "/" + url;
|
||||
}
|
||||
//console.log(url);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function preSelectDate(e) {
|
||||
"use strict";
|
||||
var link = $(e.target);
|
||||
var picker = $('#inputDateRange').data('daterangepicker');
|
||||
picker.setStartDate(moment(link.data('start'), "YYYY-MM-DD"));
|
||||
picker.setEndDate(moment(link.data('end'), "YYYY-MM-DD"));
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
function createCookie(name, value, days) {
|
||||
"use strict";
|
||||
var expires;
|
||||
|
||||
if (days) {
|
||||
var date = new Date();
|
||||
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
|
||||
expires = "; expires=" + date.toGMTString();
|
||||
} else {
|
||||
expires = "";
|
||||
}
|
||||
document.cookie = encodeURIComponent(name) + "=" + encodeURIComponent(value) + expires + "; path=/";
|
||||
}
|
||||
|
||||
function readCookie(name) {
|
||||
"use strict";
|
||||
var nameEQ = encodeURIComponent(name) + "=";
|
||||
var ca = document.cookie.split(';');
|
||||
for (var i = 0; i < ca.length; i++) {
|
||||
var c = ca[i];
|
||||
while (c.charAt(0) === ' ') c = c.substring(1, c.length);
|
||||
if (c.indexOf(nameEQ) === 0) return decodeURIComponent(c.substring(nameEQ.length, c.length));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
114
public/js/ff/rules/create-edit.js
Normal file
114
public/js/ff/rules/create-edit.js
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* create-edit.js
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
var triggerCount = 0;
|
||||
var actionCount = 0;
|
||||
|
||||
$(function () {
|
||||
"use strict";
|
||||
console.log('edit-create');
|
||||
});
|
||||
|
||||
|
||||
function addNewTrigger() {
|
||||
"use strict";
|
||||
triggerCount++;
|
||||
|
||||
$.getJSON('json/trigger', {count: triggerCount}).done(function (data) {
|
||||
$('tbody.rule-trigger-tbody').append(data.html);
|
||||
|
||||
$('.remove-trigger').unbind('click').click(function (e) {
|
||||
removeTrigger(e);
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
}).fail(function () {
|
||||
alert('Cannot get a new trigger.');
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function addNewAction() {
|
||||
"use strict";
|
||||
actionCount++;
|
||||
|
||||
$.getJSON('json/action', {count: actionCount}).done(function (data) {
|
||||
//console.log(data.html);
|
||||
$('tbody.rule-action-tbody').append(data.html);
|
||||
|
||||
// add action things.
|
||||
$('.remove-action').unbind('click').click(function (e) {
|
||||
removeAction(e);
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
}).fail(function () {
|
||||
alert('Cannot get a new action.');
|
||||
});
|
||||
}
|
||||
|
||||
function removeTrigger(e) {
|
||||
"use strict";
|
||||
var target = $(e.target);
|
||||
if(target.prop("tagName") == "I") {
|
||||
target = target.parent();
|
||||
}
|
||||
// remove grand parent:
|
||||
target.parent().parent().remove();
|
||||
|
||||
// if now at zero, immediatly add one again:
|
||||
if($('.rule-trigger-tbody tr').length == 0) {
|
||||
addNewTrigger();
|
||||
}
|
||||
}
|
||||
|
||||
function removeAction(e) {
|
||||
"use strict";
|
||||
var target = $(e.target);
|
||||
if(target.prop("tagName") == "I") {
|
||||
target = target.parent();
|
||||
}
|
||||
// remove grand parent:
|
||||
target.parent().parent().remove();
|
||||
|
||||
// if now at zero, immediatly add one again:
|
||||
if($('.rule-action-tbody tr').length == 0) {
|
||||
addNewAction();
|
||||
}
|
||||
}
|
||||
|
||||
function testRuleTriggers() {
|
||||
"use strict";
|
||||
|
||||
// Serialize all trigger data
|
||||
var triggerData = $( ".rule-trigger-tbody" ).find( "input[type=text], input[type=checkbox], select" ).serializeArray();
|
||||
|
||||
// Find a list of existing transactions that match these triggers
|
||||
$.get('rules/test', triggerData).done(function (data) {
|
||||
var modal = $( "#testTriggerModal" );
|
||||
var numTriggers = $( ".rule-trigger-body > tr" ).length;
|
||||
|
||||
// Set title and body
|
||||
modal.find( ".transactions-list" ).html(data.html);
|
||||
|
||||
// Show warning if appropriate
|
||||
if( data.warning ) {
|
||||
modal.find( ".transaction-warning .warning-contents" ).text(data.warning);
|
||||
modal.find( ".transaction-warning" ).show();
|
||||
} else {
|
||||
modal.find( ".transaction-warning" ).hide();
|
||||
}
|
||||
|
||||
// Show the modal dialog
|
||||
$( "#testTriggerModal" ).modal();
|
||||
}).fail(function () {
|
||||
alert('Cannot get transactions for given triggers.');
|
||||
});
|
||||
}
|
||||
40
public/js/ff/rules/create.js
Normal file
40
public/js/ff/rules/create.js
Normal file
@@ -0,0 +1,40 @@
|
||||
/* global $, addNewTrigger, addNewAction, actionCount, triggerCount */
|
||||
/*
|
||||
* edit.js
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
// make a line.
|
||||
|
||||
$(function () {
|
||||
"use strict";
|
||||
console.log("create");
|
||||
if (triggerCount === 0) {
|
||||
addNewTrigger();
|
||||
}
|
||||
if (actionCount === 0) {
|
||||
addNewAction();
|
||||
}
|
||||
|
||||
|
||||
$('.add_rule_trigger').click(function () {
|
||||
addNewTrigger();
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
$('.add_rule_action').click(function () {
|
||||
addNewAction();
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
$('.test_rule_triggers').click(function () {
|
||||
testRuleTriggers();
|
||||
|
||||
return false;
|
||||
});
|
||||
});
|
||||
51
public/js/ff/rules/edit.js
Normal file
51
public/js/ff/rules/edit.js
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* edit.js
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
$(function () {
|
||||
"use strict";
|
||||
console.log("edit");
|
||||
|
||||
if (triggerCount === 0) {
|
||||
addNewTrigger();
|
||||
}
|
||||
if (actionCount === 0) {
|
||||
addNewAction();
|
||||
}
|
||||
|
||||
|
||||
$('.add_rule_trigger').click(function () {
|
||||
addNewTrigger();
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
$('.test_rule_triggers').click(function () {
|
||||
testRuleTriggers();
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
$('.add_rule_action').click(function () {
|
||||
addNewAction();
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
$('.remove-trigger').unbind('click').click(function (e) {
|
||||
removeTrigger(e);
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
// add action things.
|
||||
$('.remove-action').unbind('click').click(function (e) {
|
||||
removeAction(e);
|
||||
|
||||
return false;
|
||||
});
|
||||
});
|
||||
71
public/js/ff/rules/index.js
Normal file
71
public/js/ff/rules/index.js
Normal file
@@ -0,0 +1,71 @@
|
||||
/* global comboChart,token, billID */
|
||||
/*
|
||||
* index.js
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
// Return a helper with preserved width of cells
|
||||
var fixHelper = function (e, tr) {
|
||||
"use strict";
|
||||
var $originals = tr.children();
|
||||
var $helper = tr.clone();
|
||||
$helper.children().each(function (index) {
|
||||
// Set helper cell sizes to match the original sizes
|
||||
$(this).width($originals.eq(index).width());
|
||||
});
|
||||
return $helper;
|
||||
};
|
||||
|
||||
$(function () {
|
||||
"use strict";
|
||||
$('.rule-triggers').sortable(
|
||||
{
|
||||
helper: fixHelper,
|
||||
stop: sortStop,
|
||||
cursor: "move",
|
||||
}
|
||||
);
|
||||
|
||||
$('.rule-actions').sortable(
|
||||
{
|
||||
helper: fixHelper,
|
||||
stop: sortStop,
|
||||
cursor: "move"
|
||||
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
function sortStop(event, ui) {
|
||||
"use strict";
|
||||
var current = $(ui.item);
|
||||
var parent = current.parent();
|
||||
var ruleId = current.parent().data('id');
|
||||
var entries = [];
|
||||
// who am i?
|
||||
console.log('Rule: #' + current.parent().data('id'));
|
||||
|
||||
$.each(parent.children(), function (i, v) {
|
||||
var trigger = $(v);
|
||||
var id = trigger.data('id');
|
||||
var order = i + 1;
|
||||
entries.push(id);
|
||||
|
||||
});
|
||||
if (parent.hasClass('rule-triggers')) {
|
||||
$.post('rules/rules/trigger/reorder/' + ruleId, {_token: token, triggers: entries}).fail(function () {
|
||||
alert('Could not re-order rule triggers. Please refresh the page.');
|
||||
});
|
||||
} else {
|
||||
$.post('rules/rules/action/reorder/' + ruleId, {_token: token, actions: entries}).fail(function () {
|
||||
alert('Could not re-order rule actions. Please refresh the page.');
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
104
public/js/ff/tags/create.js
Normal file
104
public/js/ff/tags/create.js
Normal file
@@ -0,0 +1,104 @@
|
||||
/* globals zoomLevel, token, google, latitude, longitude, doPlaceMarker */
|
||||
$(function () {
|
||||
"use strict";
|
||||
|
||||
$('#clearLocation').click(clearLocation);
|
||||
|
||||
});
|
||||
|
||||
/*
|
||||
Some vars as prep for the map:
|
||||
*/
|
||||
var map;
|
||||
var markers = [];
|
||||
var setTag = false;
|
||||
|
||||
var mapOptions = {
|
||||
zoom: zoomLevel,
|
||||
center: new google.maps.LatLng(latitude, longitude),
|
||||
disableDefaultUI: true
|
||||
};
|
||||
|
||||
/*
|
||||
Clear location and reset zoomLevel.
|
||||
*/
|
||||
function clearLocation() {
|
||||
"use strict";
|
||||
deleteMarkers();
|
||||
$('input[name="latitude"]').val("");
|
||||
$('input[name="longitude"]').val("");
|
||||
$('input[name="zoomLevel"]').val("6");
|
||||
setTag = false;
|
||||
$('input[name="setTag"]').val('false');
|
||||
return false;
|
||||
}
|
||||
|
||||
function initialize() {
|
||||
"use strict";
|
||||
/*
|
||||
Create new map:
|
||||
*/
|
||||
map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
|
||||
|
||||
/*
|
||||
Respond to click event.
|
||||
*/
|
||||
google.maps.event.addListener(map, 'rightclick', function (event) {
|
||||
placeMarker(event);
|
||||
});
|
||||
|
||||
/*
|
||||
Respond to zoom event.
|
||||
*/
|
||||
google.maps.event.addListener(map, 'zoom_changed', function () {
|
||||
saveZoomLevel(event);
|
||||
});
|
||||
/*
|
||||
Maybe place marker?
|
||||
*/
|
||||
if(doPlaceMarker) {
|
||||
var myLatlng = new google.maps.LatLng(latitude,longitude);
|
||||
var fakeEvent = {};
|
||||
fakeEvent.latLng = myLatlng;
|
||||
placeMarker(fakeEvent);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* save zoom level of map into hidden input.
|
||||
*/
|
||||
function saveZoomLevel() {
|
||||
"use strict";
|
||||
$('input[name="zoomLevel"]').val(map.getZoom());
|
||||
}
|
||||
|
||||
/**
|
||||
* Place marker on map.
|
||||
* @param event
|
||||
*/
|
||||
function placeMarker(event) {
|
||||
"use strict";
|
||||
deleteMarkers();
|
||||
var marker = new google.maps.Marker({position: event.latLng, map: map});
|
||||
$('input[name="latitude"]').val(event.latLng.lat());
|
||||
$('input[name="longitude"]').val(event.latLng.lng());
|
||||
markers.push(marker);
|
||||
setTag = true;
|
||||
$('input[name="setTag"]').val('true');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deletes all markers in the array by removing references to them.
|
||||
*/
|
||||
function deleteMarkers() {
|
||||
"use strict";
|
||||
for (var i = 0; i < markers.length; i++) {
|
||||
markers[i].setMap(null);
|
||||
}
|
||||
markers = [];
|
||||
}
|
||||
|
||||
|
||||
google.maps.event.addDomListener(window, 'load', initialize);
|
||||
104
public/js/ff/tags/edit.js
Normal file
104
public/js/ff/tags/edit.js
Normal file
@@ -0,0 +1,104 @@
|
||||
/* globals zoomLevel, token, google, latitude, longitude, doPlaceMarker */
|
||||
$(function () {
|
||||
"use strict";
|
||||
|
||||
$('#clearLocation').click(clearLocation);
|
||||
|
||||
});
|
||||
|
||||
/*
|
||||
Some vars as prep for the map:
|
||||
*/
|
||||
var map;
|
||||
var markers = [];
|
||||
var setTag = false;
|
||||
|
||||
var mapOptions = {
|
||||
zoom: zoomLevel,
|
||||
center: new google.maps.LatLng(latitude, longitude),
|
||||
disableDefaultUI: true
|
||||
};
|
||||
|
||||
/*
|
||||
Clear location and reset zoomLevel.
|
||||
*/
|
||||
function clearLocation() {
|
||||
"use strict";
|
||||
deleteMarkers();
|
||||
$('input[name="latitude"]').val("");
|
||||
$('input[name="longitude"]').val("");
|
||||
$('input[name="zoomLevel"]').val("6");
|
||||
setTag = false;
|
||||
$('input[name="setTag"]').val('false');
|
||||
return false;
|
||||
}
|
||||
|
||||
function initialize() {
|
||||
"use strict";
|
||||
/*
|
||||
Create new map:
|
||||
*/
|
||||
map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
|
||||
|
||||
/*
|
||||
Respond to click event.
|
||||
*/
|
||||
google.maps.event.addListener(map, 'rightclick', function (event) {
|
||||
placeMarker(event);
|
||||
});
|
||||
|
||||
/*
|
||||
Respond to zoom event.
|
||||
*/
|
||||
google.maps.event.addListener(map, 'zoom_changed', function () {
|
||||
saveZoomLevel(event);
|
||||
});
|
||||
/*
|
||||
Maybe place marker?
|
||||
*/
|
||||
if(doPlaceMarker) {
|
||||
var myLatlng = new google.maps.LatLng(latitude,longitude);
|
||||
var fakeEvent = {};
|
||||
fakeEvent.latLng = myLatlng;
|
||||
placeMarker(fakeEvent);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* save zoom level of map into hidden input.
|
||||
*/
|
||||
function saveZoomLevel() {
|
||||
"use strict";
|
||||
$('input[name="zoomLevel"]').val(map.getZoom());
|
||||
}
|
||||
|
||||
/**
|
||||
* Place marker on map.
|
||||
* @param event
|
||||
*/
|
||||
function placeMarker(event) {
|
||||
"use strict";
|
||||
deleteMarkers();
|
||||
var marker = new google.maps.Marker({position: event.latLng, map: map});
|
||||
$('input[name="latitude"]').val(event.latLng.lat());
|
||||
$('input[name="longitude"]').val(event.latLng.lng());
|
||||
markers.push(marker);
|
||||
setTag = true;
|
||||
$('input[name="setTag"]').val('true');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deletes all markers in the array by removing references to them.
|
||||
*/
|
||||
function deleteMarkers() {
|
||||
"use strict";
|
||||
for (var i = 0; i < markers.length; i++) {
|
||||
markers[i].setMap(null);
|
||||
}
|
||||
markers = [];
|
||||
}
|
||||
|
||||
|
||||
google.maps.event.addDomListener(window, 'load', initialize);
|
||||
104
public/js/ff/tags/index.js
Normal file
104
public/js/ff/tags/index.js
Normal file
@@ -0,0 +1,104 @@
|
||||
/* globals zoomLevel, token, google, latitude, longitude, doPlaceMarker */
|
||||
$(function () {
|
||||
"use strict";
|
||||
|
||||
$('#clearLocation').click(clearLocation);
|
||||
|
||||
});
|
||||
|
||||
/*
|
||||
Some vars as prep for the map:
|
||||
*/
|
||||
var map;
|
||||
var markers = [];
|
||||
var setTag = false;
|
||||
|
||||
var mapOptions = {
|
||||
zoom: zoomLevel,
|
||||
center: new google.maps.LatLng(latitude, longitude),
|
||||
disableDefaultUI: true
|
||||
};
|
||||
|
||||
/*
|
||||
Clear location and reset zoomLevel.
|
||||
*/
|
||||
function clearLocation() {
|
||||
"use strict";
|
||||
deleteMarkers();
|
||||
$('input[name="latitude"]').val("");
|
||||
$('input[name="longitude"]').val("");
|
||||
$('input[name="zoomLevel"]').val("6");
|
||||
setTag = false;
|
||||
$('input[name="setTag"]').val('false');
|
||||
return false;
|
||||
}
|
||||
|
||||
function initialize() {
|
||||
"use strict";
|
||||
/*
|
||||
Create new map:
|
||||
*/
|
||||
map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
|
||||
|
||||
/*
|
||||
Respond to click event.
|
||||
*/
|
||||
google.maps.event.addListener(map, 'rightclick', function (event) {
|
||||
placeMarker(event);
|
||||
});
|
||||
|
||||
/*
|
||||
Respond to zoom event.
|
||||
*/
|
||||
google.maps.event.addListener(map, 'zoom_changed', function () {
|
||||
saveZoomLevel(event);
|
||||
});
|
||||
/*
|
||||
Maybe place marker?
|
||||
*/
|
||||
if(doPlaceMarker) {
|
||||
var myLatlng = new google.maps.LatLng(latitude,longitude);
|
||||
var fakeEvent = {};
|
||||
fakeEvent.latLng = myLatlng;
|
||||
placeMarker(fakeEvent);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* save zoom level of map into hidden input.
|
||||
*/
|
||||
function saveZoomLevel() {
|
||||
"use strict";
|
||||
$('input[name="zoomLevel"]').val(map.getZoom());
|
||||
}
|
||||
|
||||
/**
|
||||
* Place marker on map.
|
||||
* @param event
|
||||
*/
|
||||
function placeMarker(event) {
|
||||
"use strict";
|
||||
deleteMarkers();
|
||||
var marker = new google.maps.Marker({position: event.latLng, map: map});
|
||||
$('input[name="latitude"]').val(event.latLng.lat());
|
||||
$('input[name="longitude"]').val(event.latLng.lng());
|
||||
markers.push(marker);
|
||||
setTag = true;
|
||||
$('input[name="setTag"]').val('true');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deletes all markers in the array by removing references to them.
|
||||
*/
|
||||
function deleteMarkers() {
|
||||
"use strict";
|
||||
for (var i = 0; i < markers.length; i++) {
|
||||
markers[i].setMap(null);
|
||||
}
|
||||
markers = [];
|
||||
}
|
||||
|
||||
|
||||
google.maps.event.addDomListener(window, 'load', initialize);
|
||||
47
public/js/ff/transactions/create-edit.js
Normal file
47
public/js/ff/transactions/create-edit.js
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* create-edit.js
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
/* globals what:true, $, doSwitch, txt, middleCrumbName, title,button, middleCrumbUrl, piggiesLength, breadcrumbs */
|
||||
$(document).ready(function () {
|
||||
"use strict";
|
||||
if ($('input[name="expense_account"]').length > 0) {
|
||||
$.getJSON('json/expense-accounts').done(function (data) {
|
||||
$('input[name="expense_account"]').typeahead({source: data});
|
||||
});
|
||||
}
|
||||
|
||||
if ($('input[name="tags"]').length > 0) {
|
||||
$.getJSON('json/tags').done(function (data) {
|
||||
var opt = {
|
||||
typeahead: {
|
||||
source: data
|
||||
}
|
||||
};
|
||||
$('input[name="tags"]').tagsinput(
|
||||
opt
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
if ($('input[name="revenue_account"]').length > 0) {
|
||||
$.getJSON('json/revenue-accounts').done(function (data) {
|
||||
$('input[name="revenue_account"]').typeahead({source: data});
|
||||
});
|
||||
}
|
||||
|
||||
if ($('input[name="description"]').length > 0 && what !== undefined) {
|
||||
$.getJSON('json/transaction-journals/' + what).done(function (data) {
|
||||
$('input[name="description"]').typeahead({source: data});
|
||||
});
|
||||
}
|
||||
|
||||
if ($('input[name="category"]').length > 0) {
|
||||
$.getJSON('json/categories').done(function (data) {
|
||||
$('input[name="category"]').typeahead({source: data});
|
||||
});
|
||||
}
|
||||
});
|
||||
114
public/js/ff/transactions/create.js
Normal file
114
public/js/ff/transactions/create.js
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* create.js
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
/* globals what:true, $, doSwitch, txt, middleCrumbName, title,button, middleCrumbUrl, piggiesLength, breadcrumbs */
|
||||
$(document).ready(function () {
|
||||
"use strict";
|
||||
|
||||
// respond to switch buttons when
|
||||
// creating stuff:
|
||||
if (doSwitch) {
|
||||
updateButtons();
|
||||
updateForm();
|
||||
updateLayout();
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
|
||||
function updateLayout() {
|
||||
"use strict";
|
||||
$('#subTitle').text(title[what]);
|
||||
$('.breadcrumb .active').text(breadcrumbs[what]);
|
||||
$('.breadcrumb li:nth-child(2)').html('<a href="' + middleCrumbUrl[what] + '">' + middleCrumbName[what] + '</a>');
|
||||
$('#transaction-btn').text(button[what]);
|
||||
}
|
||||
|
||||
function updateForm() {
|
||||
"use strict";
|
||||
|
||||
$('input[name="what"]').val(what);
|
||||
|
||||
switch (what) {
|
||||
case 'withdrawal':
|
||||
$('#account_id_holder').show();
|
||||
$('#expense_account_holder').show();
|
||||
$('#revenue_account_holder').hide();
|
||||
$('#account_from_id_holder').hide();
|
||||
$('#account_to_id_holder').hide();
|
||||
$('#budget_id_holder').show();
|
||||
$('#piggy_bank_id_holder').hide();
|
||||
|
||||
|
||||
if ($('#ffInput_revenue_account').val().length > 0) {
|
||||
$('#ffInput_expense_account').val($('#ffInput_revenue_account').val());
|
||||
}
|
||||
|
||||
break;
|
||||
case 'deposit':
|
||||
$('#account_id_holder').show();
|
||||
$('#expense_account_holder').hide();
|
||||
$('#revenue_account_holder').show();
|
||||
$('#account_from_id_holder').hide();
|
||||
$('#account_to_id_holder').hide();
|
||||
$('#budget_id_holder').hide();
|
||||
$('#piggy_bank_id_holder').hide();
|
||||
|
||||
if ($('#ffInput_expense_account').val().length > 0) {
|
||||
$('#ffInput_revenue_account').val($('#ffInput_expense_account').val());
|
||||
}
|
||||
|
||||
break;
|
||||
case 'transfer':
|
||||
$('#account_id_holder').hide();
|
||||
$('#expense_account_holder').hide();
|
||||
$('#revenue_account_holder').hide();
|
||||
$('#account_from_id_holder').show();
|
||||
$('#account_to_id_holder').show();
|
||||
$('#budget_id_holder').hide();
|
||||
if (piggiesLength === 0) {
|
||||
$('#piggy_bank_id_holder').hide();
|
||||
} else {
|
||||
$('#piggy_bank_id_holder').show();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function updateButtons() {
|
||||
"use strict";
|
||||
$('.switch').each(function (i, v) {
|
||||
var button = $(v);
|
||||
|
||||
// remove click event:
|
||||
button.unbind('click');
|
||||
// new click event:
|
||||
button.bind('click', clickButton);
|
||||
|
||||
if (button.data('what') == what) {
|
||||
button.removeClass('btn-default').addClass('btn-info').html('<i class="fa fa-fw fa-check"></i> ' + txt[button.data('what')]);
|
||||
console.log('Now displaying form for ' + what);
|
||||
} else {
|
||||
button.removeClass('btn-info').addClass('btn-default').text(txt[button.data('what')]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function clickButton(e) {
|
||||
"use strict";
|
||||
var button = $(e.target);
|
||||
var newWhat = button.data('what');
|
||||
if (newWhat != what) {
|
||||
what = newWhat;
|
||||
updateButtons();
|
||||
updateForm();
|
||||
updateLayout();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
13
public/js/ff/transactions/edit.js
Normal file
13
public/js/ff/transactions/edit.js
Normal file
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* edit.js
|
||||
* Copyright (C) 2016 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This software may be modified and distributed under the terms
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
/* globals $ */
|
||||
$(document).ready(function () {
|
||||
"use strict";
|
||||
// no special JS for edit transaction.
|
||||
});
|
||||
Reference in New Issue
Block a user