mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-12-12 01:42:32 +00:00
First attempt at "create transaction"-form for v2 users.
This commit is contained in:
@@ -259,7 +259,7 @@ export default () => ({
|
||||
|
||||
init() {
|
||||
// console.log('accounts init');
|
||||
Promise.all([getVariable('viewRange', '1M'), getVariable('autoConversion', false), getVariable('language', 'en-US')]).then((values) => {
|
||||
Promise.all([getVariable('viewRange', '1M'), getVariable('autoConversion', false), getVariable('language', 'en_US')]).then((values) => {
|
||||
//console.log('accounts after promises');
|
||||
this.autoConversion = values[1];
|
||||
afterPromises = true;
|
||||
|
||||
@@ -175,11 +175,12 @@ export default () => ({
|
||||
|
||||
init() {
|
||||
// console.log('budgets init');
|
||||
Promise.all([getVariable('autoConversion', false), getVariable('language', 'en-US')]).then((values) => {
|
||||
Promise.all([getVariable('autoConversion', false), getVariable('language', 'en_US')]).then((values) => {
|
||||
|
||||
i18n = new I18n();
|
||||
i18n.locale = values[1];
|
||||
loadTranslations(i18n, values[1]).then(() => {
|
||||
const locale = values[1].replace('-', '_');
|
||||
i18n.locale = locale;
|
||||
loadTranslations(i18n, locale).then(() => {
|
||||
this.autoConversion = values[0];
|
||||
afterPromises = true;
|
||||
if (false === this.loading) {
|
||||
|
||||
@@ -130,11 +130,12 @@ export default () => ({
|
||||
init() {
|
||||
// console.log('piggies init');
|
||||
apiData = [];
|
||||
Promise.all([getVariable('autoConversion', false), getVariable('language', 'en-US')]).then((values) => {
|
||||
Promise.all([getVariable('autoConversion', false), getVariable('language', 'en_US')]).then((values) => {
|
||||
|
||||
i18n = new I18n();
|
||||
i18n.locale = values[1];
|
||||
loadTranslations(i18n, values[1]).then(() => {
|
||||
const locale = values[1].replace('-', '_');
|
||||
i18n.locale = locale;
|
||||
loadTranslations(i18n, locale).then(() => {
|
||||
// console.log('piggies after promises');
|
||||
afterPromises = true;
|
||||
this.autoConversion = values[0];
|
||||
|
||||
@@ -350,12 +350,13 @@ export default () => ({
|
||||
init() {
|
||||
// console.log('sankey init');
|
||||
transactions = [];
|
||||
Promise.all([getVariable('autoConversion', false), getVariable('language', 'en-US')]).then((values) => {
|
||||
Promise.all([getVariable('autoConversion', false), getVariable('language', 'en_US')]).then((values) => {
|
||||
this.autoConversion = values[0];
|
||||
autoConversion = values[0];
|
||||
i18n = new I18n();
|
||||
i18n.locale = values[1];
|
||||
loadTranslations(i18n, values[1]).then(() => {
|
||||
const locale = values[1].replace('-', '_');
|
||||
i18n.locale = locale;
|
||||
loadTranslations(i18n, locale).then(() => {
|
||||
// some translations:
|
||||
translations.all_money = i18n.t('firefly.all_money');
|
||||
translations.category = i18n.t('firefly.category');
|
||||
|
||||
@@ -274,14 +274,15 @@ export default () => ({
|
||||
|
||||
init() {
|
||||
console.log('subscriptions init');
|
||||
Promise.all([getVariable('autoConversion', false), getVariable('language', 'en-US')]).then((values) => {
|
||||
Promise.all([getVariable('autoConversion', false), getVariable('language', 'en_US')]).then((values) => {
|
||||
console.log('subscriptions after promises');
|
||||
this.autoConversion = values[0];
|
||||
afterPromises = true;
|
||||
|
||||
i18n = new I18n();
|
||||
i18n.locale = values[1];
|
||||
loadTranslations(i18n, values[1]).then(() => {
|
||||
const locale = values[1].replace('-', '_');
|
||||
i18n.locale = locale;
|
||||
loadTranslations(i18n, locale).then(() => {
|
||||
if (false === this.loading) {
|
||||
this.startSubscriptions();
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ export default () => ({
|
||||
defaultRange: {
|
||||
start: null, end: null
|
||||
},
|
||||
language: 'en-US',
|
||||
language: 'en_US',
|
||||
|
||||
init() {
|
||||
// console.log('Dates init');
|
||||
|
||||
@@ -25,14 +25,135 @@ import {parseFromEntries} from "./shared/parse-from-entries.js";
|
||||
import formatMoney from "../../util/format-money.js";
|
||||
import Autocomplete from "bootstrap5-autocomplete";
|
||||
import Post from "../../api/v2/model/transaction/post.js";
|
||||
import {getVariable} from "../../store/get-variable.js";
|
||||
import {I18n} from "i18n-js";
|
||||
import {loadTranslations} from "../../support/load-translations.js";
|
||||
|
||||
let i18n;
|
||||
|
||||
const urls = {
|
||||
description: '/api/v2/autocomplete/transaction-descriptions',
|
||||
account: '/api/v2/autocomplete/accounts',
|
||||
};
|
||||
|
||||
let transactions = function () {
|
||||
return {
|
||||
count: 0,
|
||||
totalAmount: 0,
|
||||
transactionType: 'unknown',
|
||||
showSuccessMessage: false,
|
||||
showErrorMessage: false,
|
||||
entries: [],
|
||||
filters: {
|
||||
source: [],
|
||||
destination: [],
|
||||
},
|
||||
detectTransactionType() {
|
||||
const sourceType = this.entries[0].source_account.type ?? 'unknown';
|
||||
const destType = this.entries[0].destination_account.type ?? 'unknown';
|
||||
if ('unknown' === sourceType && 'unknown' === destType) {
|
||||
this.transactionType = 'unknown';
|
||||
console.warn('Cannot infer transaction type from two unknown accounts.');
|
||||
return;
|
||||
}
|
||||
// transfer: both are the same and in strict set of account types
|
||||
if (sourceType === destType && ['Asset account', 'Loan', 'Debt', 'Mortgage'].includes(sourceType)) {
|
||||
this.transactionType = 'transfer';
|
||||
console.log('Transaction type is detected to be "' + this.transactionType + '".');
|
||||
return;
|
||||
}
|
||||
// withdrawals:
|
||||
if ('Asset account' === sourceType && ['Expense account', 'Debt', 'Loan', 'Mortgage'].includes(destType)) {
|
||||
this.transactionType = 'withdrawal';
|
||||
console.log('Transaction type is detected to be "' + this.transactionType + '".');
|
||||
return;
|
||||
}
|
||||
if ('Asset account' === sourceType && 'unknown' === destType) {
|
||||
this.transactionType = 'withdrawal';
|
||||
console.log('Transaction type is detected to be "' + this.transactionType + '".');
|
||||
return;
|
||||
}
|
||||
if (['Debt', 'Loan', 'Mortgage'].includes(sourceType) && 'Expense account' === destType) {
|
||||
this.transactionType = 'withdrawal';
|
||||
console.log('Transaction type is detected to be "' + this.transactionType + '".');
|
||||
return;
|
||||
}
|
||||
|
||||
// deposits:
|
||||
if ('Revenue account' === sourceType && ['Asset account', 'Debt', 'Loan', 'Mortgage'].includes(destType)) {
|
||||
this.transactionType = 'deposit';
|
||||
console.log('Transaction type is detected to be "' + this.transactionType + '".');
|
||||
return;
|
||||
}
|
||||
if (['Debt', 'Loan', 'Mortgage'].includes(sourceType) && 'Asset account' === destType) {
|
||||
this.transactionType = 'deposit';
|
||||
console.log('Transaction type is detected to be "' + this.transactionType + '".');
|
||||
return;
|
||||
}
|
||||
console.warn('Unknown account combination between "' + sourceType + '" and "' + destType + '".');
|
||||
},
|
||||
selectSourceAccount(item, ac) {
|
||||
const index = parseInt(ac._searchInput.attributes['data-index'].value);
|
||||
document.querySelector('#form')._x_dataStack[0].$data.entries[index].source_account =
|
||||
{
|
||||
id: item.id,
|
||||
name: item.name,
|
||||
type: item.type,
|
||||
};
|
||||
console.log('Changed source account into a known ' + item.type.toLowerCase());
|
||||
},
|
||||
changedAmount(e) {
|
||||
const index = parseInt(e.target.dataset.index);
|
||||
this.entries[index].amount = parseFloat(e.target.value);
|
||||
this.totalAmount = 0;
|
||||
for (let i in this.entries) {
|
||||
if (this.entries.hasOwnProperty(i)) {
|
||||
this.totalAmount = this.totalAmount + parseFloat(this.entries[i].amount);
|
||||
}
|
||||
}
|
||||
console.log('Changed amount to ' + this.totalAmount);
|
||||
},
|
||||
selectDestAccount(item, ac) {
|
||||
const index = parseInt(ac._searchInput.attributes['data-index'].value);
|
||||
document.querySelector('#form')._x_dataStack[0].$data.entries[index].destination_account =
|
||||
{
|
||||
id: item.id,
|
||||
name: item.name,
|
||||
type: item.type,
|
||||
};
|
||||
console.log('Changed destination account into a known ' + item.type.toLowerCase());
|
||||
},
|
||||
changeSourceAccount(item, ac) {
|
||||
if (typeof item === 'undefined') {
|
||||
const index = parseInt(ac._searchInput.attributes['data-index'].value);
|
||||
let source = document.querySelector('#form')._x_dataStack[0].$data.entries[index].source_account;
|
||||
if (source.name === ac._searchInput.value) {
|
||||
console.warn('Ignore hallucinated source account name change to "' + ac._searchInput.value + '"');
|
||||
return;
|
||||
}
|
||||
document.querySelector('#form')._x_dataStack[0].$data.entries[index].source_account =
|
||||
{
|
||||
name: ac._searchInput.value,
|
||||
};
|
||||
console.log('Changed source account into a unknown account called "' + ac._searchInput.value + '"');
|
||||
}
|
||||
},
|
||||
changeDestAccount(item, ac) {
|
||||
if (typeof item === 'undefined') {
|
||||
const index = parseInt(ac._searchInput.attributes['data-index'].value);
|
||||
let destination = document.querySelector('#form')._x_dataStack[0].$data.entries[index].destination_account;
|
||||
if (destination.name === ac._searchInput.value) {
|
||||
console.warn('Ignore hallucinated destination account name change to "' + ac._searchInput.value + '"');
|
||||
return;
|
||||
}
|
||||
document.querySelector('#form')._x_dataStack[0].$data.entries[index].destination_account =
|
||||
{
|
||||
name: ac._searchInput.value,
|
||||
};
|
||||
console.log('Changed destination account into a unknown account called "' + ac._searchInput.value + '"');
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
// error and success messages:
|
||||
showError: false,
|
||||
@@ -40,62 +161,85 @@ let transactions = function () {
|
||||
|
||||
addedSplit() {
|
||||
console.log('addedSplit');
|
||||
const opts = {
|
||||
onSelectItem: console.log,
|
||||
};
|
||||
var src = [];
|
||||
for (let i = 0; i < 50; i++) {
|
||||
src.push({
|
||||
title: "Option " + i,
|
||||
id: "opt" + i,
|
||||
data: {
|
||||
key: i,
|
||||
},
|
||||
});
|
||||
}
|
||||
Autocomplete.init("input.ac-source", {
|
||||
server: urls.account,
|
||||
serverParams: {
|
||||
types: this.filters.source,
|
||||
},
|
||||
fetchOptions: {
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': document.head.querySelector('meta[name="csrf-token"]').content
|
||||
}
|
||||
},
|
||||
hiddenInput: true,
|
||||
preventBrowserAutocomplete: true,
|
||||
highlightTyped: true,
|
||||
liveServer: true,
|
||||
onChange: this.changeSourceAccount,
|
||||
onSelectItem: this.selectSourceAccount,
|
||||
onRenderItem: function (item, b, c) {
|
||||
return item.name_with_balance + '<br><small class="text-muted">' + i18n.t('firefly.account_type_' + item.type) + '</small>';
|
||||
}
|
||||
});
|
||||
|
||||
Autocomplete.init("input.autocomplete", {
|
||||
items: src,
|
||||
Autocomplete.init("input.ac-dest", {
|
||||
server: urls.account,
|
||||
serverParams: {
|
||||
types: this.filters.destination,
|
||||
},
|
||||
fetchOptions: {
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': document.head.querySelector('meta[name="csrf-token"]').content
|
||||
}
|
||||
},
|
||||
hiddenInput: true,
|
||||
preventBrowserAutocomplete: true,
|
||||
liveServer: true,
|
||||
highlightTyped: true,
|
||||
onSelectItem: this.selectDestAccount,
|
||||
onChange: this.changeDestAccount,
|
||||
onRenderItem: function (item, b, c) {
|
||||
return item.name_with_balance + '<br><small class="text-muted">' + i18n.t('firefly.account_type_' + item.type) + '</small>';
|
||||
}
|
||||
});
|
||||
this.filters.destination = [];
|
||||
Autocomplete.init('input.ac-description', {
|
||||
server: urls.description,
|
||||
fetchOptions: {
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': document.head.querySelector('meta[name="csrf-token"]').content
|
||||
}
|
||||
},
|
||||
valueField: "id",
|
||||
labelField: "title",
|
||||
labelField: "description",
|
||||
highlightTyped: true,
|
||||
onSelectItem: console.log,
|
||||
});
|
||||
|
||||
|
||||
// setTimeout(() => {
|
||||
// console.log('timed out');
|
||||
// console.log(document.querySelector('input.autocomplete'));
|
||||
|
||||
// }, 1500);
|
||||
|
||||
},
|
||||
|
||||
init() {
|
||||
console.log('init()');
|
||||
this.addSplit();
|
||||
Promise.all([getVariable('language', 'en_US')]).then((values) => {
|
||||
i18n = new I18n();
|
||||
const locale = values[0].replace('-', '_');
|
||||
i18n.locale = locale;
|
||||
loadTranslations(i18n, locale).then(() => {
|
||||
this.addSplit();
|
||||
});
|
||||
|
||||
// // We can use regular objects as source and customize label
|
||||
// new Autocomplete(document.getElementById("autocompleteRegularInput"), {
|
||||
// items: {
|
||||
// opt_some: "Some",
|
||||
// opt_value: "Value",
|
||||
// opt_here: "Here is a very long element that should be truncated",
|
||||
// opt_dia: "çaça"
|
||||
// },
|
||||
// onRenderItem: (item, label) => {
|
||||
// return label + " (" + item.value + ")";
|
||||
// },
|
||||
// });
|
||||
// new Autocomplete(document.getElementById("autocompleteDatalist"), opts);
|
||||
//new Autocomplete(document.getElementById("autocompleteRemote"), opts);
|
||||
// new Autocomplete(document.getElementById("autocompleteLiveRemote"), opts);
|
||||
});
|
||||
|
||||
// source can never be expense account
|
||||
this.filters.source = ['Asset account', 'Loan', 'Debt', 'Mortgage', 'Revenue account'];
|
||||
// destination can never be revenue account
|
||||
this.filters.destination = ['Expense account', 'Loan', 'Debt', 'Mortgage', 'Asset account'];
|
||||
},
|
||||
submitTransaction() {
|
||||
this.detectTransactionType();
|
||||
// todo disable buttons
|
||||
|
||||
let transactions = parseFromEntries(this.entries);
|
||||
let transactions = parseFromEntries(this.entries, this.transactionType);
|
||||
let submission = {
|
||||
// todo process all options
|
||||
group_title: null,
|
||||
|
||||
@@ -32,7 +32,7 @@ export function createEmptySplit() {
|
||||
let now = new Date();
|
||||
let formatted = format(now, 'yyyy-MM-dd HH:mm');
|
||||
return {
|
||||
description: 'OK then',
|
||||
description: '',
|
||||
amount: '',
|
||||
source_account: getAccount(),
|
||||
destination_account: getAccount(),
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
*
|
||||
* @param entries
|
||||
*/
|
||||
export function parseFromEntries(entries) {
|
||||
export function parseFromEntries(entries, transactionType) {
|
||||
let returnArray = [];
|
||||
for (let i in entries) {
|
||||
if (entries.hasOwnProperty(i)) {
|
||||
@@ -36,8 +36,16 @@ export function parseFromEntries(entries) {
|
||||
current.amount = entry.amount;
|
||||
current.date = entry.date;
|
||||
|
||||
// if ID is set:
|
||||
if ('' !== entry.source_account.id.toString()) {
|
||||
current.source_id = entry.source_account.id;
|
||||
}
|
||||
if ('' !== entry.destination_account.id.toString()) {
|
||||
current.destination_id = entry.destination_account.id;
|
||||
}
|
||||
|
||||
// TODO transaction type is hard coded:
|
||||
current.type = 'withdrawal';
|
||||
current.type = transactionType;
|
||||
|
||||
|
||||
returnArray.push(current);
|
||||
|
||||
@@ -22,6 +22,7 @@ let loaded = false;
|
||||
|
||||
async function loadTranslations(i18n, locale) {
|
||||
if (false === loaded) {
|
||||
locale = locale.replace('-', '_');
|
||||
const response = await fetch(`./v2/i18n/${locale}.json`);
|
||||
const translations = await response.json();
|
||||
i18n.store(translations);
|
||||
|
||||
Reference in New Issue
Block a user