mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-02-25 18:45:27 -06:00
Lots of new code for new transaction screen.
This commit is contained in:
parent
912fe99981
commit
d5c5fa4fad
@ -45,7 +45,7 @@ echo "Discover packages..."
|
||||
php artisan package:discover
|
||||
|
||||
echo "Run various artisan commands..."
|
||||
. $FIREFLY_PATH/.env
|
||||
#. $FIREFLY_PATH/.env
|
||||
if [[ -z "$DB_PORT" ]]; then
|
||||
if [[ $DB_CONNECTION == "pgsql" ]]; then
|
||||
DB_PORT=5432
|
||||
|
@ -543,6 +543,15 @@ return [
|
||||
TransactionTypeModel::OPENING_BALANCE => [AccountType::INITIAL_BALANCE, AccountType::ASSET, AccountType::LOAN, AccountType::DEBT,
|
||||
AccountType::MORTGAGE],
|
||||
TransactionTypeModel::RECONCILIATION => [AccountType::RECONCILIATION, AccountType::ASSET],
|
||||
// in case no transaction type is known yet, it could be anything.
|
||||
'none' => [
|
||||
AccountType::ASSET,
|
||||
AccountType::EXPENSE,
|
||||
AccountType::REVENUE,
|
||||
AccountType::LOAN,
|
||||
AccountType::DEBT,
|
||||
AccountType::MORTGAGE,
|
||||
],
|
||||
],
|
||||
'destination' => [
|
||||
TransactionTypeModel::WITHDRAWAL => [AccountType::EXPENSE, AccountType::CASH, AccountType::LOAN, AccountType::DEBT,
|
||||
@ -554,6 +563,127 @@ return [
|
||||
TransactionTypeModel::RECONCILIATION => [AccountType::RECONCILIATION, AccountType::ASSET],
|
||||
],
|
||||
],
|
||||
'allowed_opposing_types' => [
|
||||
'source' => [
|
||||
AccountType::ASSET => [AccountType::ASSET, AccountType::CASH, AccountType::DEBT, AccountType::EXPENSE, AccountType::INITIAL_BALANCE,
|
||||
AccountType::LOAN, AccountType::RECONCILIATION],
|
||||
AccountType::CASH => [AccountType::ASSET],
|
||||
AccountType::DEBT => [AccountType::ASSET, AccountType::DEBT, AccountType::EXPENSE, AccountType::INITIAL_BALANCE, AccountType::LOAN,
|
||||
AccountType::MORTGAGE],
|
||||
AccountType::EXPENSE => [], // is not allowed as a source.
|
||||
AccountType::INITIAL_BALANCE => [AccountType::ASSET, AccountType::DEBT, AccountType::LOAN, AccountType::MORTGAGE],
|
||||
AccountType::LOAN => [AccountType::ASSET, AccountType::DEBT, AccountType::EXPENSE, AccountType::INITIAL_BALANCE, AccountType::LOAN,
|
||||
AccountType::MORTGAGE],
|
||||
AccountType::MORTGAGE => [AccountType::ASSET, AccountType::DEBT, AccountType::EXPENSE, AccountType::INITIAL_BALANCE, AccountType::LOAN,
|
||||
AccountType::MORTGAGE],
|
||||
AccountType::RECONCILIATION => [AccountType::ASSET],
|
||||
AccountType::REVENUE => [AccountType::ASSET, AccountType::DEBT, AccountType::LOAN, AccountType::MORTGAGE],
|
||||
|
||||
],
|
||||
'destination' => [
|
||||
AccountType::ASSET => [AccountType::ASSET, AccountType::CASH, AccountType::DEBT, AccountType::INITIAL_BALANCE, AccountType::LOAN,
|
||||
AccountType::MORTGAGE, AccountType::RECONCILIATION, AccountType::REVENUE],
|
||||
AccountType::CASH => [AccountType::ASSET],
|
||||
AccountType::DEBT => [AccountType::ASSET, AccountType::DEBT, AccountType::INITIAL_BALANCE, AccountType::LOAN, AccountType::MORTGAGE,
|
||||
AccountType::REVENUE],
|
||||
AccountType::EXPENSE => [AccountType::ASSET, AccountType::DEBT, AccountType::LOAN, AccountType::MORTGAGE],
|
||||
AccountType::INITIAL_BALANCE => [AccountType::ASSET, AccountType::DEBT, AccountType::LOAN, AccountType::MORTGAGE],
|
||||
AccountType::LOAN => [AccountType::ASSET, AccountType::DEBT, AccountType::INITIAL_BALANCE, AccountType::LOAN, AccountType::MORTGAGE,
|
||||
AccountType::REVENUE],
|
||||
AccountType::MORTGAGE => [AccountType::ASSET, AccountType::DEBT, AccountType::INITIAL_BALANCE, AccountType::LOAN, AccountType::MORTGAGE,
|
||||
AccountType::REVENUE],
|
||||
AccountType::RECONCILIATION => [AccountType::ASSET],
|
||||
AccountType::REVENUE => [], // is not allowed as a destination
|
||||
],
|
||||
],
|
||||
// depending on the account type, return the allowed transaction types:
|
||||
'allowed_transaction_types' => [
|
||||
'source' => [
|
||||
AccountType::ASSET => [TransactionTypeModel::WITHDRAWAL, TransactionTypeModel::TRANSFER, TransactionTypeModel::OPENING_BALANCE,
|
||||
TransactionTypeModel::RECONCILIATION],
|
||||
AccountType::EXPENSE => [], // is not allowed as a source.
|
||||
AccountType::REVENUE => [TransactionTypeModel::DEPOSIT],
|
||||
AccountType::LOAN => [TransactionTypeModel::WITHDRAWAL, TransactionTypeModel::DEPOSIT, TransactionTypeModel::TRANSFER,
|
||||
TransactionTypeModel::OPENING_BALANCE],
|
||||
AccountType::DEBT => [TransactionTypeModel::WITHDRAWAL, TransactionTypeModel::DEPOSIT, TransactionTypeModel::TRANSFER,
|
||||
TransactionTypeModel::OPENING_BALANCE],
|
||||
AccountType::MORTGAGE => [TransactionTypeModel::WITHDRAWAL, TransactionTypeModel::DEPOSIT, TransactionTypeModel::TRANSFER,
|
||||
TransactionTypeModel::OPENING_BALANCE],
|
||||
AccountType::INITIAL_BALANCE => [], // todo fill me in.
|
||||
AccountType::RECONCILIATION => [], // todo fill me in.
|
||||
],
|
||||
'destination' => [
|
||||
AccountType::ASSET => [TransactionTypeModel::DEPOSIT, TransactionTypeModel::TRANSFER, TransactionTypeModel::OPENING_BALANCE,
|
||||
TransactionTypeModel::RECONCILIATION],
|
||||
AccountType::EXPENSE => [TransactionTypeModel::WITHDRAWAL],
|
||||
AccountType::REVENUE => [], // is not allowed as destination.
|
||||
AccountType::LOAN => [TransactionTypeModel::WITHDRAWAL, TransactionTypeModel::DEPOSIT, TransactionTypeModel::TRANSFER,
|
||||
TransactionTypeModel::OPENING_BALANCE],
|
||||
AccountType::DEBT => [TransactionTypeModel::WITHDRAWAL, TransactionTypeModel::DEPOSIT, TransactionTypeModel::TRANSFER,
|
||||
TransactionTypeModel::OPENING_BALANCE],
|
||||
AccountType::MORTGAGE => [TransactionTypeModel::WITHDRAWAL, TransactionTypeModel::DEPOSIT, TransactionTypeModel::TRANSFER,
|
||||
TransactionTypeModel::OPENING_BALANCE],
|
||||
AccountType::INITIAL_BALANCE => [], // todo fill me in.
|
||||
AccountType::RECONCILIATION => [], // todo fill me in.
|
||||
],
|
||||
|
||||
],
|
||||
|
||||
// having the source + dest will tell you the transaction type.
|
||||
'account_to_transaction' => [
|
||||
AccountType::ASSET => [
|
||||
AccountType::ASSET => TransactionTypeModel::TRANSFER,
|
||||
AccountType::CASH => TransactionTypeModel::WITHDRAWAL,
|
||||
AccountType::DEBT => TransactionTypeModel::WITHDRAWAL,
|
||||
AccountType::EXPENSE => TransactionTypeModel::WITHDRAWAL,
|
||||
AccountType::INITIAL_BALANCE => TransactionTypeModel::OPENING_BALANCE,
|
||||
AccountType::LOAN => TransactionTypeModel::WITHDRAWAL,
|
||||
AccountType::MORTGAGE => TransactionTypeModel::WITHDRAWAL,
|
||||
AccountType::RECONCILIATION => TransactionTypeModel::RECONCILIATION,
|
||||
],
|
||||
AccountType::CASH => [
|
||||
AccountType::ASSET => TransactionTypeModel::DEPOSIT,
|
||||
],
|
||||
AccountType::DEBT => [
|
||||
AccountType::ASSET => TransactionTypeModel::DEPOSIT,
|
||||
AccountType::DEBT => TransactionTypeModel::TRANSFER,
|
||||
AccountType::EXPENSE => TransactionTypeModel::WITHDRAWAL,
|
||||
AccountType::INITIAL_BALANCE => TransactionTypeModel::OPENING_BALANCE,
|
||||
AccountType::LOAN => TransactionTypeModel::TRANSFER,
|
||||
AccountType::MORTGAGE => TransactionTypeModel::TRANSFER,
|
||||
],
|
||||
AccountType::INITIAL_BALANCE => [
|
||||
AccountType::ASSET => TransactionTypeModel::OPENING_BALANCE,
|
||||
AccountType::DEBT => TransactionTypeModel::OPENING_BALANCE,
|
||||
AccountType::LOAN => TransactionTypeModel::OPENING_BALANCE,
|
||||
AccountType::MORTGAGE => TransactionTypeModel::OPENING_BALANCE,
|
||||
],
|
||||
AccountType::LOAN => [
|
||||
AccountType::ASSET => TransactionTypeModel::DEPOSIT,
|
||||
AccountType::DEBT => TransactionTypeModel::TRANSFER,
|
||||
AccountType::EXPENSE => TransactionTypeModel::WITHDRAWAL,
|
||||
AccountType::INITIAL_BALANCE => TransactionTypeModel::OPENING_BALANCE,
|
||||
AccountType::LOAN => TransactionTypeModel::TRANSFER,
|
||||
AccountType::MORTGAGE => TransactionTypeModel::TRANSFER,
|
||||
],
|
||||
AccountType::MORTGAGE => [
|
||||
AccountType::ASSET => TransactionTypeModel::DEPOSIT,
|
||||
AccountType::DEBT => TransactionTypeModel::TRANSFER,
|
||||
AccountType::EXPENSE => TransactionTypeModel::WITHDRAWAL,
|
||||
AccountType::INITIAL_BALANCE => TransactionTypeModel::OPENING_BALANCE,
|
||||
AccountType::LOAN => TransactionTypeModel::TRANSFER,
|
||||
AccountType::MORTGAGE => TransactionTypeModel::TRANSFER,
|
||||
],
|
||||
AccountType::RECONCILIATION => [
|
||||
AccountType::ASSET => TransactionTypeModel::RECONCILIATION,
|
||||
],
|
||||
AccountType::REVENUE => [
|
||||
AccountType::ASSET => TransactionTypeModel::DEPOSIT,
|
||||
AccountType::DEBT => TransactionTypeModel::DEPOSIT,
|
||||
AccountType::LOAN => TransactionTypeModel::DEPOSIT,
|
||||
AccountType::MORTGAGE => TransactionTypeModel::DEPOSIT,
|
||||
],
|
||||
],
|
||||
|
||||
// allowed source / destination accounts.
|
||||
'source_dests' => [
|
||||
|
@ -13,12 +13,14 @@
|
||||
"axios": "^0.17",
|
||||
"bootstrap-sass": "^3.3.7",
|
||||
"cross-env": "^5.1",
|
||||
"jquery": "^3.1.1",
|
||||
"laravel-mix": "^1.0",
|
||||
"lodash": "^4.17.4",
|
||||
"vue": "^2.5.7"
|
||||
},
|
||||
"dependencies": {
|
||||
"font-awesome": "^4.7.0"
|
||||
"@johmun/vue-tags-input": "^2.0.1",
|
||||
"font-awesome": "^4.7.0",
|
||||
"jquery": "^3.1.1",
|
||||
"uiv": "^0.31.5"
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,3 @@
|
||||
{
|
||||
"/v2/js/index.js": "/v2/js/index.js",
|
||||
"/v2/js/manifest.js": "/v2/js/manifest.js",
|
||||
"/v2/js/vendor.js": "/v2/js/vendor.js",
|
||||
"/undefined.js": "/undefined.js",
|
||||
"/v2/css/app.css": "/v2/css/app.css"
|
||||
"/v1/js/app.js": "/v1/js/app.js"
|
||||
}
|
2
public/v1/css/app.css
vendored
Normal file
2
public/v1/css/app.css
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
/* TODO REMOVE ME */
|
||||
|
15
public/v1/css/firefly.css
vendored
15
public/v1/css/firefly.css
vendored
@ -18,6 +18,14 @@
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
input.ti-new-tag-input {
|
||||
font-size: 14px !important;
|
||||
line-height: 1.42857143;
|
||||
color: #555;
|
||||
font-family:"Source Sans Pro", "Helvetica Neue",Helvetica,Arial,sans-serif !important;
|
||||
}
|
||||
|
||||
.split_amount_input {
|
||||
width: 40%;
|
||||
border-radius: 0;
|
||||
@ -36,6 +44,13 @@
|
||||
|
||||
}
|
||||
|
||||
.autocomplete-suggestions { border: 1px solid #999; background: #FFF; overflow: auto; }
|
||||
.autocomplete-suggestion { padding: 2px 5px; white-space: nowrap; overflow: hidden; }
|
||||
.autocomplete-selected { background: #F0F0F0; }
|
||||
.autocomplete-suggestions strong { font-weight: normal; color: #3399FF; }
|
||||
.autocomplete-group { padding: 2px 5px; font-weight: bold;}
|
||||
.autocomplete-group strong { display: block; border-bottom: 1px solid #000; }
|
||||
|
||||
.split_amount_input:focus {
|
||||
border-color: #98cbe8;
|
||||
outline: 0;
|
||||
|
53455
public/v1/js/app.js
vendored
53455
public/v1/js/app.js
vendored
File diff suppressed because one or more lines are too long
225
public/v1/js/ff/transactions/create.js
vendored
Normal file
225
public/v1/js/ff/transactions/create.js
vendored
Normal file
@ -0,0 +1,225 @@
|
||||
/*
|
||||
* create.js
|
||||
* Copyright (c) 2019 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
* Firefly III is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Firefly III is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/** global: autoCompleteUri */
|
||||
|
||||
$(function () {
|
||||
"use strict";
|
||||
initPage();
|
||||
|
||||
});
|
||||
function initPage() {
|
||||
// recreate buttons and auto-complete things
|
||||
autoComplete();
|
||||
makeButtons();
|
||||
runModernizer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset all click triggers.
|
||||
*/
|
||||
function makeButtons() {
|
||||
$('.clearDestination').unbind('click').on('click', clearDestination);
|
||||
$('.clearSource').unbind('click').on('click', clearSource);
|
||||
$('#addSplitButton').unbind('click').on('click', addSplit);
|
||||
}
|
||||
|
||||
function addSplit() {
|
||||
// clone the latest
|
||||
var latest =$($('#transactions').children()[$('#transactions').children().length - 1]);
|
||||
latest.clone(true).appendTo('#transactions');
|
||||
|
||||
initPage();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Code to handle clearing the source account.
|
||||
* @param e
|
||||
*/
|
||||
function clearSource(e) {
|
||||
console.log('Now clearing source.');
|
||||
var button = $(e.currentTarget);
|
||||
// empty value.
|
||||
$(button.parent().parent().find('input').get(0)).val('');
|
||||
|
||||
// reset source account
|
||||
setSourceAccount(null);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Code to handle clearing the destination account.
|
||||
* @param e
|
||||
*/
|
||||
function clearDestination(e) {
|
||||
console.log('Now clearing destination.');
|
||||
var button = $(e.currentTarget);
|
||||
// empty value.
|
||||
$(button.parent().parent().find('input').get(0)).val('');
|
||||
|
||||
// reset destination account
|
||||
setDestinationAccount(null);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the new source account (from a suggestion).
|
||||
*
|
||||
* @param newAccount
|
||||
*/
|
||||
function setSourceAccount(newAccount) {
|
||||
if (null === newAccount) {
|
||||
console.log('New source account is now null.');
|
||||
sourceAccount = null;
|
||||
setAllowedDestinationAccounts(newAccount);
|
||||
return;
|
||||
}
|
||||
console.log('The new source account is now ' + newAccount.value + 'of type ' + newAccount.data.type);
|
||||
setAllowedDestinationAccounts(newAccount);
|
||||
|
||||
sourceAccount = newAccount;
|
||||
|
||||
setTransactionType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the new destination account (from a suggestion).
|
||||
*
|
||||
* @param newAccount
|
||||
*/
|
||||
function setDestinationAccount(newAccount) {
|
||||
if (null === newAccount) {
|
||||
console.log('New destination account is now null.');
|
||||
destinationAccount = null;
|
||||
setAllowedSourceAccounts(newAccount);
|
||||
return;
|
||||
}
|
||||
console.log('The new destination account is now ' + newAccount.value + 'of type ' + newAccount.data.type);
|
||||
setAllowedSourceAccounts(newAccount);
|
||||
|
||||
sourceAccount = newAccount;
|
||||
|
||||
setTransactionType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a new limit on the allowed destination account.
|
||||
*
|
||||
* @param newAccount
|
||||
*/
|
||||
function setAllowedDestinationAccounts(newAccount) {
|
||||
if (null === newAccount) {
|
||||
console.log('Allowed type for destination account is anything.');
|
||||
destAllowedAccountTypes = [];
|
||||
return;
|
||||
}
|
||||
destAllowedAccountTypes = allowedOpposingTypes.source[newAccount.data.type];
|
||||
console.log('The destination account must be of type: ', destAllowedAccountTypes);
|
||||
|
||||
// todo if the current destination account is not of this type, reset it.
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a new limit on the allowed destination account.
|
||||
*
|
||||
* @param newAccount
|
||||
*/
|
||||
function setAllowedSourceAccounts(newAccount) {
|
||||
if (null === newAccount) {
|
||||
console.log('Allowed type for source account is anything.');
|
||||
sourceAllowedAccountTypes = [];
|
||||
return;
|
||||
}
|
||||
sourceAllowedAccountTypes = allowedOpposingTypes.source[newAccount.data.type];
|
||||
console.log('The source account must be of type: ', sourceAllowedAccountTypes);
|
||||
|
||||
// todo if the current destination account is not of this type, reset it.
|
||||
}
|
||||
|
||||
/**
|
||||
* Create auto complete.
|
||||
*/
|
||||
function autoComplete() {
|
||||
var options = {
|
||||
serviceUrl: getSourceAutoCompleteURI,
|
||||
groupBy: 'type',
|
||||
onSelect: function (suggestion) {
|
||||
setSourceAccount(suggestion);
|
||||
}
|
||||
};
|
||||
$('.sourceAccountAC').autocomplete(options);
|
||||
|
||||
// also select destination account.
|
||||
var destinationOptions = {
|
||||
serviceUrl: getDestinationAutoCompleteURI,
|
||||
groupBy: 'type',
|
||||
onSelect: function (suggestion) {
|
||||
setDestinationAccount(suggestion);
|
||||
}
|
||||
};
|
||||
|
||||
$('.destinationAccountAC').autocomplete(destinationOptions);
|
||||
}
|
||||
|
||||
function setTransactionType() {
|
||||
if (sourceAccount === undefined || destinationAccount === undefined || sourceAccount === null || destinationAccount === null) {
|
||||
$('.transactionTypeIndicator').text('');
|
||||
$('.transactionTypeIndicatorBlock').hide();
|
||||
console.warn('Not both accounts are known yet.');
|
||||
return;
|
||||
}
|
||||
$('.transactionTypeIndicatorBlock').show();
|
||||
var expectedType = accountToTypes[sourceAccount.data.type][destinationAccount.data.type];
|
||||
$('.transactionTypeIndicator').html(creatingTypes[expectedType]);
|
||||
console.log('Expected transaction type is ' + expectedType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the auto complete URI for source accounts.
|
||||
* @returns {string}
|
||||
*/
|
||||
function getSourceAutoCompleteURI() {
|
||||
console.log('Will filter source accounts', sourceAllowedAccountTypes);
|
||||
return accountAutoCompleteURI + '?types=' + encodeURI(sourceAllowedAccountTypes.join(','));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the auto complete URI for destination accounts.
|
||||
* @returns {string}
|
||||
*/
|
||||
function getDestinationAutoCompleteURI() {
|
||||
console.log('Will filter destination accounts', destAllowedAccountTypes);
|
||||
return accountAutoCompleteURI + '?types=' + encodeURI(destAllowedAccountTypes.join(','));
|
||||
}
|
||||
|
||||
/**
|
||||
* Give date a datepicker if not natively supported.
|
||||
*/
|
||||
function runModernizer() {
|
||||
if (!Modernizr.inputtypes.date) {
|
||||
$('input[type="date"]').datepicker(
|
||||
{
|
||||
dateFormat: 'yy-mm-dd'
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
8
public/v1/js/lib/jquery.autocomplete.min.js
vendored
Executable file
8
public/v1/js/lib/jquery.autocomplete.min.js
vendored
Executable file
File diff suppressed because one or more lines are too long
19
resources/assets/js/app.js
vendored
19
resources/assets/js/app.js
vendored
@ -3,10 +3,26 @@
|
||||
* includes Vue and other libraries. It is a great starting point when
|
||||
* building robust, powerful web applications using Vue and Laravel.
|
||||
*/
|
||||
/* TODO REMOVE ME */
|
||||
|
||||
require('./bootstrap');
|
||||
window.Vue = require('vue');
|
||||
import * as uiv from 'uiv';
|
||||
|
||||
Vue.use(uiv);
|
||||
// components for create and edit transactions.
|
||||
Vue.component('budget', require('./components/transactions/Budget.vue'));
|
||||
Vue.component('custom-transaction-fields', require('./components/transactions/CustomTransactionFields.vue'));
|
||||
Vue.component('piggy-bank', require('./components/transactions/PiggyBank.vue'));
|
||||
Vue.component('tags', require('./components/transactions/Tags.vue'));
|
||||
Vue.component('category', require('./components/transactions/Category.vue'));
|
||||
Vue.component('amount', require('./components/transactions/Amount.vue'));
|
||||
Vue.component('foreign-amount', require('./components/transactions/ForeignAmountSelect.vue'));
|
||||
Vue.component('transaction-type', require('./components/transactions/TransactionType.vue'));
|
||||
Vue.component('account-select', require('./components/transactions/AccountSelect.vue'));
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Components for OAuth2 tokens.
|
||||
@ -14,6 +30,7 @@ window.Vue = require('vue');
|
||||
Vue.component('passport-clients', require('./components/passport/Clients.vue'));
|
||||
Vue.component('passport-authorized-clients', require('./components/passport/AuthorizedClients.vue'));
|
||||
Vue.component('passport-personal-access-tokens', require('./components/passport/PersonalAccessTokens.vue'));
|
||||
Vue.component('create-transaction', require('./components/transactions/CreateTransaction'));
|
||||
|
||||
|
||||
const app = new Vue({
|
||||
|
160
resources/assets/js/components/transactions/AccountSelect.vue
Normal file
160
resources/assets/js/components/transactions/AccountSelect.vue
Normal file
@ -0,0 +1,160 @@
|
||||
<!--
|
||||
- AccountSelect.vue
|
||||
- Copyright (c) 2019 thegrumpydictator@gmail.com
|
||||
-
|
||||
- This file is part of Firefly III.
|
||||
-
|
||||
- Firefly III is free software: you can redistribute it and/or modify
|
||||
- it under the terms of the GNU General Public License as published by
|
||||
- the Free Software Foundation, either version 3 of the License, or
|
||||
- (at your option) any later version.
|
||||
-
|
||||
- Firefly III is distributed in the hope that it will be useful,
|
||||
- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
- GNU General Public License for more details.
|
||||
-
|
||||
- You should have received a copy of the GNU General Public License
|
||||
- along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
<template>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<div class="input-group">
|
||||
<input
|
||||
ref="input"
|
||||
type="text"
|
||||
:placeholder="title"
|
||||
:data-index="index"
|
||||
autocomplete="off"
|
||||
data-role="input"
|
||||
v-on:keypress="handleEnter"
|
||||
:disabled="inputDisabled"
|
||||
class="form-control"
|
||||
v-on:submit.prevent
|
||||
:name="inputName"
|
||||
:title="title">
|
||||
<span class="input-group-btn">
|
||||
<button
|
||||
v-on:click="clearSource"
|
||||
class="btn btn-default"
|
||||
type="button"><i class="fa fa-trash-o"></i></button>
|
||||
</span>
|
||||
</div>
|
||||
<typeahead
|
||||
:open-on-empty=true
|
||||
:open-on-focus=true
|
||||
v-on:input="selectedItem"
|
||||
:async-src="accountAutoCompleteURI"
|
||||
v-model="name"
|
||||
:target="target"
|
||||
item-key="name"
|
||||
></typeahead>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
inputName: String,
|
||||
title: String,
|
||||
index: Number,
|
||||
transactionType: String,
|
||||
accountName: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
accountTypeFilters: {
|
||||
type: Array,
|
||||
default: function () {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
accountAutoCompleteURI: null,
|
||||
name: null,
|
||||
trType: this.transactionType,
|
||||
target: null,
|
||||
inputDisabled: false,
|
||||
allowedTypes: this.accountTypeFilters
|
||||
}
|
||||
},
|
||||
ready() {
|
||||
this.name = this.accountName;
|
||||
},
|
||||
mounted() {
|
||||
this.target = this.$refs.input;
|
||||
let types = this.allowedTypes.join(',');
|
||||
this.name = this.accountName;
|
||||
this.accountAutoCompleteURI = document.getElementsByTagName('base')[0].href + "json/accounts?types=" + types + "&query=";
|
||||
this.triggerTransactionType();
|
||||
},
|
||||
|
||||
watch: {
|
||||
transactionType() {
|
||||
this.triggerTransactionType();
|
||||
},
|
||||
accountTypeFilters() {
|
||||
let types = this.accountTypeFilters.join(',');
|
||||
console.log(this.inputName + '[' + this.index + '] is now searching for: ' + types);
|
||||
this.accountAutoCompleteURI = document.getElementsByTagName('base')[0].href + "json/accounts?types=" + types + "&query=";
|
||||
}
|
||||
},
|
||||
methods:
|
||||
{
|
||||
triggerTransactionType: function () {
|
||||
if (null === this.transactionType) {
|
||||
return;
|
||||
}
|
||||
this.inputDisabled = false;
|
||||
if (this.transactionType.toString() !== '' && this.index > 0) {
|
||||
if (this.transactionType.toString() === 'Transfer') {
|
||||
this.inputDisabled = true;
|
||||
// todo: needs to copy value from very first input
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.transactionType.toString() === 'Withdrawal' && this.inputName.substr(0, 6).toLowerCase() === 'source') {
|
||||
// todo also clear value?
|
||||
this.inputDisabled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.transactionType.toString() === 'Deposit' && this.inputName.substr(0, 11).toLowerCase() === 'destination') {
|
||||
// todo also clear value?
|
||||
this.inputDisabled = true;
|
||||
}
|
||||
}
|
||||
},
|
||||
selectedItem: function (e) {
|
||||
if (typeof this.name === 'undefined') {
|
||||
return;
|
||||
}
|
||||
// emit the fact that the user selected a type of account
|
||||
// (influencing the destination)
|
||||
this.$emit('select:account', this.name);
|
||||
},
|
||||
clearSource: function (e) {
|
||||
//props.value = '';
|
||||
this.name = '';
|
||||
// some event?
|
||||
this.$emit('clear:value')
|
||||
},
|
||||
handleEnter: function (e) {
|
||||
// todo feels sloppy
|
||||
if (e.keyCode === 13) {
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
76
resources/assets/js/components/transactions/Amount.vue
Normal file
76
resources/assets/js/components/transactions/Amount.vue
Normal file
@ -0,0 +1,76 @@
|
||||
<!--
|
||||
- Amount.vue
|
||||
- Copyright (c) 2019 thegrumpydictator@gmail.com
|
||||
-
|
||||
- This file is part of Firefly III.
|
||||
-
|
||||
- Firefly III is free software: you can redistribute it and/or modify
|
||||
- it under the terms of the GNU General Public License as published by
|
||||
- the Free Software Foundation, either version 3 of the License, or
|
||||
- (at your option) any later version.
|
||||
-
|
||||
- Firefly III is distributed in the hope that it will be useful,
|
||||
- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
- GNU General Public License for more details.
|
||||
-
|
||||
- You should have received a copy of the GNU General Public License
|
||||
- along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
<template>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-4 control-label" ref="cur"></label>
|
||||
<div class="col-sm-8">
|
||||
<input type="number" step="any" class="form-control" name="amount[]"
|
||||
title="amount" autocomplete="off" placeholder="Amount">
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "Amount",
|
||||
props: ['source', 'destination', 'transactionType'],
|
||||
data() {
|
||||
return {
|
||||
sourceAccount: this.source,
|
||||
destinationAccount: this.destination,
|
||||
type: this.transactionType,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
changeData: function () {
|
||||
if ('' === this.transactionType) {
|
||||
$(this.$refs.cur).text(this.sourceAccount.currency_name);
|
||||
return;
|
||||
}
|
||||
if (this.transactionType === 'Withdrawal' || this.transactionType === 'Transfer') {
|
||||
$(this.$refs.cur).text(this.sourceAccount.currency_name);
|
||||
return;
|
||||
}
|
||||
if (this.transactionType === 'Deposit') {
|
||||
$(this.$refs.cur).text(this.destinationAccount.currency_name);
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
source: function () {
|
||||
this.changeData();
|
||||
},
|
||||
destination: function () {
|
||||
this.changeData();
|
||||
},
|
||||
transactionType: function () {
|
||||
this.changeData();
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.changeData();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
66
resources/assets/js/components/transactions/Budget.vue
Normal file
66
resources/assets/js/components/transactions/Budget.vue
Normal file
@ -0,0 +1,66 @@
|
||||
<!--
|
||||
- Budget.vue
|
||||
- Copyright (c) 2019 thegrumpydictator@gmail.com
|
||||
-
|
||||
- This file is part of Firefly III.
|
||||
-
|
||||
- Firefly III is free software: you can redistribute it and/or modify
|
||||
- it under the terms of the GNU General Public License as published by
|
||||
- the Free Software Foundation, either version 3 of the License, or
|
||||
- (at your option) any later version.
|
||||
-
|
||||
- Firefly III is distributed in the hope that it will be useful,
|
||||
- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
- GNU General Public License for more details.
|
||||
-
|
||||
- You should have received a copy of the GNU General Public License
|
||||
- along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
<template>
|
||||
<div class="form-group" v-if="typeof this.transactionType !== 'undefined' && this.transactionType === 'Withdrawal'">
|
||||
<div class="col-sm-12">
|
||||
<select name="budget[]" class="form-control" v-if="this.budgets.length > 0">
|
||||
<option v-for="budget in this.budgets">{{budget.name}}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "Budget",
|
||||
props: ['transactionType'],
|
||||
mounted() {
|
||||
this.loadBudgets();
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
budgets: [],
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
loadBudgets: function () {
|
||||
let URI = document.getElementsByTagName('base')[0].href + "json/budgets";
|
||||
axios.get(URI, {}).then((res) => {
|
||||
this.budgets = [
|
||||
{
|
||||
name: '(no budget)',
|
||||
id: 0,
|
||||
}
|
||||
];
|
||||
for (const key in res.data) {
|
||||
if (res.data.hasOwnProperty(key) && /^0$|^[1-9]\d*$/.test(key) && key <= 4294967294) {
|
||||
this.budgets.push(res.data[key]);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
108
resources/assets/js/components/transactions/Category.vue
Normal file
108
resources/assets/js/components/transactions/Category.vue
Normal file
@ -0,0 +1,108 @@
|
||||
<!--
|
||||
- Category.vue
|
||||
- Copyright (c) 2019 thegrumpydictator@gmail.com
|
||||
-
|
||||
- This file is part of Firefly III.
|
||||
-
|
||||
- Firefly III is free software: you can redistribute it and/or modify
|
||||
- it under the terms of the GNU General Public License as published by
|
||||
- the Free Software Foundation, either version 3 of the License, or
|
||||
- (at your option) any later version.
|
||||
-
|
||||
- Firefly III is distributed in the hope that it will be useful,
|
||||
- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
- GNU General Public License for more details.
|
||||
-
|
||||
- You should have received a copy of the GNU General Public License
|
||||
- along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
<template>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<div class="input-group">
|
||||
<input
|
||||
ref="input"
|
||||
type="text"
|
||||
placeholder="Category"
|
||||
autocomplete="off"
|
||||
data-role="input"
|
||||
v-on:keypress="handleEnter"
|
||||
class="form-control"
|
||||
v-on:submit.prevent
|
||||
name="category[]"
|
||||
title="Category">
|
||||
<span class="input-group-btn">
|
||||
<button
|
||||
v-on:click="clearCategory"
|
||||
class="btn btn-default"
|
||||
type="button"><i class="fa fa-trash-o"></i></button>
|
||||
</span>
|
||||
</div>
|
||||
<typeahead
|
||||
:open-on-empty=true
|
||||
:open-on-focus=true
|
||||
v-on:input="selectedItem"
|
||||
:async-src="categoryAutoCompleteURI"
|
||||
v-model="name"
|
||||
:target="target"
|
||||
item-key="name"
|
||||
></typeahead>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "Category",
|
||||
props: {
|
||||
inputName: String,
|
||||
accountName: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
categoryAutoCompleteURI: null,
|
||||
name: null,
|
||||
target: null,
|
||||
}
|
||||
},
|
||||
ready() {
|
||||
this.name = this.accountName;
|
||||
},
|
||||
mounted() {
|
||||
this.target = this.$refs.input;
|
||||
this.categoryAutoCompleteURI = document.getElementsByTagName('base')[0].href + "json/categories?query=";
|
||||
//this.triggerTransactionType();
|
||||
},
|
||||
methods: {
|
||||
clearCategory: function () {
|
||||
//props.value = '';
|
||||
this.name = '';
|
||||
// some event?
|
||||
this.$emit('clear:category')
|
||||
},
|
||||
selectedItem: function (e) {
|
||||
if (typeof this.name === 'undefined') {
|
||||
return;
|
||||
}
|
||||
// emit the fact that the user selected a type of account
|
||||
// (influencing the destination)
|
||||
this.$emit('select:category', this.name);
|
||||
},
|
||||
handleEnter: function (e) {
|
||||
// todo feels sloppy
|
||||
if (e.keyCode === 13) {
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
@ -0,0 +1,301 @@
|
||||
<!--
|
||||
- CreateTransaction.vue
|
||||
- Copyright (c) 2019 thegrumpydictator@gmail.com
|
||||
-
|
||||
- This file is part of Firefly III.
|
||||
-
|
||||
- Firefly III is free software: you can redistribute it and/or modify
|
||||
- it under the terms of the GNU General Public License as published by
|
||||
- the Free Software Foundation, either version 3 of the License, or
|
||||
- (at your option) any later version.
|
||||
-
|
||||
- Firefly III is distributed in the hope that it will be useful,
|
||||
- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
- GNU General Public License for more details.
|
||||
-
|
||||
- You should have received a copy of the GNU General Public License
|
||||
- along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
<template>
|
||||
<form method="POST" action="xxxx" accept-charset="UTF-8" class="form-horizontal" id="store" enctype="multipart/form-data">
|
||||
<input name="_token" type="hidden" value="xxx">
|
||||
|
||||
<div class="row" v-if="transactions.transactions.length > 1">
|
||||
<div class="col-lg-6">
|
||||
<div class="box">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">
|
||||
Description of the split transaction
|
||||
</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<input type="text" class="form-control" name="group_title"
|
||||
v-model="transactions.group_title"
|
||||
title="Description of the split transaction" autocomplete="off" placeholder="Description of the split transaction">
|
||||
|
||||
|
||||
<p class="help-block">
|
||||
If you create a split transaction, there must be a global description for all splits of the transaction.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-for="(transaction, index) in transactions.transactions">
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<div class="box">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title splitTitle">
|
||||
<span v-if="transactions.transactions.length > 1">Split {{ index+1 }} / {{ transactions.transactions.length }}</span>
|
||||
<span v-if="transactions.transactions.length === 1">Transaction information</span>
|
||||
</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<div class="row">
|
||||
<div class="col-lg-4">
|
||||
<account-select
|
||||
inputName="source[]"
|
||||
title="Source account"
|
||||
:accountName="transaction.source_account.name"
|
||||
:accountTypeFilters="transaction.source_account.allowed_types"
|
||||
:transactionType="transactionType"
|
||||
:index="index"
|
||||
v-on:clear:value="clearSource(index)"
|
||||
v-on:select:account="selectedSourceAccount(index, $event)"
|
||||
></account-select>
|
||||
<account-select
|
||||
inputName="destination[]"
|
||||
title="Destination account"
|
||||
:accountName="transaction.destination_account.name"
|
||||
:accountTypeFilters="transaction.destination_account.allowed_types"
|
||||
:transactionType="transactionType"
|
||||
:index="index"
|
||||
v-on:clear:value="clearDestination(index)"
|
||||
v-on:select:account="selectedDestinationAccount(index, $event)"
|
||||
></account-select>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<input type="text" class="form-control" name="description[]"
|
||||
:value="transaction.description"
|
||||
title="Description" autocomplete="off" placeholder="Description">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<input type="date" class="form-control" name="date[]"
|
||||
title="Date" value="" autocomplete="off"
|
||||
:value="transaction.date"
|
||||
:disabled="index > 0"
|
||||
placeholder="Date">
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="index===0">
|
||||
<transaction-type
|
||||
:source="transaction.source_account.type"
|
||||
:destination="transaction.destination_account.type"
|
||||
v-on:set:transactionType="setTransactionType($event)"
|
||||
v-on:act:limitSourceType="limitSourceType($event)"
|
||||
v-on:act:limitDestinationType="limitDestinationType($event)"
|
||||
></transaction-type>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-4">
|
||||
<amount
|
||||
:source="transaction.source_account"
|
||||
:destination="transaction.destination_account"
|
||||
:transactionType="transactionType"
|
||||
></amount>
|
||||
<foreign-amount
|
||||
:source="transaction.source_account"
|
||||
:destination="transaction.destination_account"
|
||||
:transactionType="transactionType"
|
||||
></foreign-amount>
|
||||
</div>
|
||||
<div class="col-lg-4">
|
||||
<budget :transactionType="transactionType"></budget>
|
||||
<category :transactionType="transactionType"></category>
|
||||
<piggy-bank :transactionType="transactionType"></piggy-bank>
|
||||
<tags></tags>
|
||||
<!-- custom string fields -->
|
||||
<custom-transaction-fields></custom-transaction-fields>
|
||||
|
||||
<!-- custom date fields -->
|
||||
|
||||
<!-- custom other fields -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<p>
|
||||
<button class="btn btn-primary" v-on:click="addTransaction">Add another split</button>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "CreateTransaction",
|
||||
components: {
|
||||
|
||||
},
|
||||
mounted() {
|
||||
// not sure if something needs to happen here.
|
||||
},
|
||||
ready() {
|
||||
},
|
||||
methods: {
|
||||
addTransaction: function (e) {
|
||||
let latest = this.transactions.transactions[this.transactions.transactions.length - 1];
|
||||
this.transactions.transactions.push(latest);
|
||||
e.preventDefault();
|
||||
},
|
||||
setTransactionType: function (type) {
|
||||
this.transactionType = type;
|
||||
},
|
||||
limitSourceType: function (type) {
|
||||
let i;
|
||||
for (i = 0; i < this.transactions.transactions.length; i++) {
|
||||
this.transactions.transactions[i].source_account.allowed_types = [type];
|
||||
}
|
||||
},
|
||||
limitDestinationType: function (type) {
|
||||
let i;
|
||||
for (i = 0; i < this.transactions.transactions.length; i++) {
|
||||
this.transactions.transactions[i].destination_account.allowed_types = [type];
|
||||
}
|
||||
},
|
||||
|
||||
selectedSourceAccount: function (index, model) {
|
||||
if (typeof model === 'string') {
|
||||
// cant change types, only name.
|
||||
this.transactions.transactions[index].source_account.name = model;
|
||||
} else {
|
||||
|
||||
// todo maybe replace the entire model?
|
||||
this.transactions.transactions[index].source_account.id = model.id;
|
||||
this.transactions.transactions[index].source_account.name = model.name;
|
||||
this.transactions.transactions[index].source_account.type = model.type;
|
||||
|
||||
this.transactions.transactions[index].source_account.currency_id = model.currency_id;
|
||||
this.transactions.transactions[index].source_account.currency_name = model.currency_name;
|
||||
this.transactions.transactions[index].source_account.currency_code = model.currency_code;
|
||||
this.transactions.transactions[index].source_account.currency_decimal_places = model.currency_decimal_places;
|
||||
// force types on destination selector.
|
||||
this.transactions.transactions[index].destination_account.allowed_types = window.allowedOpposingTypes.source[model.type];
|
||||
}
|
||||
},
|
||||
selectedDestinationAccount: function (index, model) {
|
||||
if (typeof model === 'string') {
|
||||
// cant change types, only name.
|
||||
this.transactions.transactions[index].destination_account.name = model;
|
||||
} else {
|
||||
|
||||
// todo maybe replace the entire model?
|
||||
this.transactions.transactions[index].destination_account.id = model.id;
|
||||
this.transactions.transactions[index].destination_account.name = model.name;
|
||||
this.transactions.transactions[index].destination_account.type = model.type;
|
||||
|
||||
this.transactions.transactions[index].destination_account.currency_id = model.currency_id;
|
||||
this.transactions.transactions[index].destination_account.currency_name = model.currency_name;
|
||||
this.transactions.transactions[index].destination_account.currency_code = model.currency_code;
|
||||
this.transactions.transactions[index].destination_account.currency_decimal_places = model.currency_decimal_places;
|
||||
|
||||
// force types on destination selector.
|
||||
this.transactions.transactions[index].source_account.allowed_types = window.allowedOpposingTypes.destination[model.type];
|
||||
}
|
||||
},
|
||||
clearSource: function (index) {
|
||||
this.transactions.transactions[index].source_account.id = 0;
|
||||
this.transactions.transactions[index].source_account.name = "";
|
||||
this.transactions.transactions[index].source_account.type = "";
|
||||
this.transactions.transactions[index].destination_account.allowed_types = [];
|
||||
|
||||
// if there is a destination model, reset the types of the source
|
||||
// by pretending we selected it again.
|
||||
if (this.transactions.transactions[index].destination_account) {
|
||||
console.log('There is a destination account.');
|
||||
this.selectedDestinationAccount(index, this.transactions.transactions[index].destination_account);
|
||||
}
|
||||
},
|
||||
clearDestination: function (index) {
|
||||
this.transactions.transactions[index].destination_account.id = 0;
|
||||
this.transactions.transactions[index].destination_account.name = "";
|
||||
this.transactions.transactions[index].destination_account.type = "";
|
||||
this.transactions.transactions[index].source_account.allowed_types = [];
|
||||
|
||||
// if there is a source model, reset the types of the destination
|
||||
// by pretending we selected it again.
|
||||
if (this.transactions.transactions[index].source_account) {
|
||||
console.log('There is a source account.');
|
||||
this.selectedSourceAccount(index, this.transactions.transactions[index].source_account);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/*
|
||||
* The component's data.
|
||||
*/
|
||||
data() {
|
||||
return {
|
||||
transactionType: null,
|
||||
transactions: {
|
||||
group_title: "",
|
||||
transactions: [
|
||||
{
|
||||
description: "",
|
||||
date: "",
|
||||
amount: "",
|
||||
foreign_amount: "",
|
||||
source_account: {
|
||||
id: 0,
|
||||
name: "",
|
||||
type: "",
|
||||
//currency_id: window.defaultCurrency.id,
|
||||
//currency_name: window.defaultCurrency.name,
|
||||
//currency_code: window.defaultCurrency.code,
|
||||
//currency_decimal_places: window.defaultCurrency.decimal_places,
|
||||
currency_id: 0,
|
||||
currency_name: '',
|
||||
currency_code: '',
|
||||
currency_decimal_places: 2,
|
||||
allowed_types: []
|
||||
},
|
||||
destination_account: {
|
||||
id: 0,
|
||||
name: "",
|
||||
type: "",
|
||||
//currency_id: window.defaultCurrency.id,
|
||||
//currency_name: window.defaultCurrency.name,
|
||||
//currency_code: window.defaultCurrency.code,
|
||||
//currency_decimal_places: window.defaultCurrency.decimal_places,
|
||||
currency_id: 0,
|
||||
currency_name: '',
|
||||
currency_code: '',
|
||||
currency_decimal_places: 2,
|
||||
allowed_types: []
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
@ -0,0 +1,46 @@
|
||||
<!--
|
||||
- CustomTransactionFields.vue
|
||||
- Copyright (c) 2019 thegrumpydictator@gmail.com
|
||||
-
|
||||
- This file is part of Firefly III.
|
||||
-
|
||||
- Firefly III is free software: you can redistribute it and/or modify
|
||||
- it under the terms of the GNU General Public License as published by
|
||||
- the Free Software Foundation, either version 3 of the License, or
|
||||
- (at your option) any later version.
|
||||
-
|
||||
- Firefly III is distributed in the hope that it will be useful,
|
||||
- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
- GNU General Public License for more details.
|
||||
-
|
||||
- You should have received a copy of the GNU General Public License
|
||||
- along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
<template>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "CustomTransactionFields",
|
||||
mounted() {
|
||||
this.getPreference();
|
||||
},
|
||||
methods: {
|
||||
getPreference() {
|
||||
|
||||
const url = document.getElementsByTagName('base')[0].href + 'api/v1/preferences/transaction_journal_optional_fields';
|
||||
|
||||
axios.get(url).then(response => {
|
||||
console.log(response.data.data.attributes);
|
||||
}).catch(() => console.warn('Oh. Something went wrong'));
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
@ -0,0 +1,127 @@
|
||||
<!--
|
||||
- ForeignAmountSelect.vue
|
||||
- Copyright (c) 2019 thegrumpydictator@gmail.com
|
||||
-
|
||||
- This file is part of Firefly III.
|
||||
-
|
||||
- Firefly III is free software: you can redistribute it and/or modify
|
||||
- it under the terms of the GNU General Public License as published by
|
||||
- the Free Software Foundation, either version 3 of the License, or
|
||||
- (at your option) any later version.
|
||||
-
|
||||
- Firefly III is distributed in the hope that it will be useful,
|
||||
- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
- GNU General Public License for more details.
|
||||
-
|
||||
- You should have received a copy of the GNU General Public License
|
||||
- along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
<template>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-4">
|
||||
<select class="form-control" name="foreign_currency[]" v-if="this.enabledCurrencies.length > 0">
|
||||
<option v-for="currency in this.enabledCurrencies" v-if="currency.enabled">{{ currency.name }}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-sm-8">
|
||||
<input type="number" step="any" class="form-control" name="foreign_amount[]" v-if="this.enabledCurrencies.length > 0"
|
||||
title="Foreign amount" autocomplete="off" placeholder="Foreign amount">
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "ForeignAmountSelect",
|
||||
props: ['source', 'destination', 'transactionType'],
|
||||
mounted() {
|
||||
this.loadCurrencies();
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
currencies: [],
|
||||
enabledCurrencies: [],
|
||||
exclude: null
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
source: function () {
|
||||
this.changeData();
|
||||
},
|
||||
destination: function () {
|
||||
this.changeData();
|
||||
},
|
||||
transactionType: function () {
|
||||
this.changeData();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
changeData: function () {
|
||||
this.enabledCurrencies = [];
|
||||
if (this.transactionType === 'Transfer') {
|
||||
// lock source on currencyID of destination
|
||||
for (const key in this.currencies) {
|
||||
if (this.currencies.hasOwnProperty(key) && /^0$|^[1-9]\d*$/.test(key) && key <= 4294967294) {
|
||||
if (this.currencies[key].id === this.destination.currency_id) {
|
||||
this.enabledCurrencies.push(this.currencies[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
// if type is withdrawal, list all but skip the source account ID.
|
||||
if (this.transactionType === 'Withdrawal' && this.source) {
|
||||
for (const key in this.currencies) {
|
||||
if (this.currencies.hasOwnProperty(key) && /^0$|^[1-9]\d*$/.test(key) && key <= 4294967294) {
|
||||
if (this.source.currency_id !== this.currencies[key].id) {
|
||||
this.enabledCurrencies.push(this.currencies[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// if type is deposit, list all but skip the source account ID.
|
||||
if (this.transactionType === 'Deposit' && this.destination) {
|
||||
for (const key in this.currencies) {
|
||||
if (this.currencies.hasOwnProperty(key) && /^0$|^[1-9]\d*$/.test(key) && key <= 4294967294) {
|
||||
if (this.destination.currency_id !== this.currencies[key].id) {
|
||||
this.enabledCurrencies.push(this.currencies[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
for (const key in this.currencies) {
|
||||
if (this.currencies.hasOwnProperty(key) && /^0$|^[1-9]\d*$/.test(key) && key <= 4294967294) {
|
||||
this.enabledCurrencies.push(this.currencies[key]);
|
||||
}
|
||||
}
|
||||
},
|
||||
loadCurrencies: function () {
|
||||
let URI = document.getElementsByTagName('base')[0].href + "json/currencies";
|
||||
axios.get(URI, {}).then((res) => {
|
||||
this.currencies = [
|
||||
{
|
||||
name: '(none)',
|
||||
id: 0,
|
||||
enabled: true
|
||||
}
|
||||
];
|
||||
for (const key in res.data) {
|
||||
if (res.data.hasOwnProperty(key) && /^0$|^[1-9]\d*$/.test(key) && key <= 4294967294) {
|
||||
this.currencies.push(res.data[key]);
|
||||
this.enabledCurrencies.push(res.data[key]);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
66
resources/assets/js/components/transactions/PiggyBank.vue
Normal file
66
resources/assets/js/components/transactions/PiggyBank.vue
Normal file
@ -0,0 +1,66 @@
|
||||
<!--
|
||||
- PiggyBank.vue
|
||||
- Copyright (c) 2019 thegrumpydictator@gmail.com
|
||||
-
|
||||
- This file is part of Firefly III.
|
||||
-
|
||||
- Firefly III is free software: you can redistribute it and/or modify
|
||||
- it under the terms of the GNU General Public License as published by
|
||||
- the Free Software Foundation, either version 3 of the License, or
|
||||
- (at your option) any later version.
|
||||
-
|
||||
- Firefly III is distributed in the hope that it will be useful,
|
||||
- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
- GNU General Public License for more details.
|
||||
-
|
||||
- You should have received a copy of the GNU General Public License
|
||||
- along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
<template>
|
||||
<div class="form-group" v-if="typeof this.transactionType !== 'undefined' && this.transactionType === 'Transfer'">
|
||||
<div class="col-sm-12">
|
||||
<select name="piggy_bank[]" class="form-control" v-if="this.piggies.length > 0">
|
||||
<option v-for="piggy in this.piggies">{{piggy.name}}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "PiggyBank",
|
||||
props: ['transactionType'],
|
||||
mounted() {
|
||||
this.loadPiggies();
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
piggies: [],
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
loadPiggies: function () {
|
||||
let URI = document.getElementsByTagName('base')[0].href + "json/piggy-banks";
|
||||
axios.get(URI, {}).then((res) => {
|
||||
this.piggies = [
|
||||
{
|
||||
name: '(no piggy bank)',
|
||||
id: 0,
|
||||
}
|
||||
];
|
||||
for (const key in res.data) {
|
||||
if (res.data.hasOwnProperty(key) && /^0$|^[1-9]\d*$/.test(key) && key <= 4294967294) {
|
||||
this.piggies.push(res.data[key]);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
82
resources/assets/js/components/transactions/Tags.vue
Normal file
82
resources/assets/js/components/transactions/Tags.vue
Normal file
@ -0,0 +1,82 @@
|
||||
<!--
|
||||
- Tags.vue
|
||||
- Copyright (c) 2019 thegrumpydictator@gmail.com
|
||||
-
|
||||
- This file is part of Firefly III.
|
||||
-
|
||||
- Firefly III is free software: you can redistribute it and/or modify
|
||||
- it under the terms of the GNU General Public License as published by
|
||||
- the Free Software Foundation, either version 3 of the License, or
|
||||
- (at your option) any later version.
|
||||
-
|
||||
- Firefly III is distributed in the hope that it will be useful,
|
||||
- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
- GNU General Public License for more details.
|
||||
-
|
||||
- You should have received a copy of the GNU General Public License
|
||||
- along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
<template>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<vue-tags-input
|
||||
v-model="tag"
|
||||
:tags="tags"
|
||||
classes="form-input"
|
||||
:autocomplete-items="autocompleteItems"
|
||||
:add-only-from-autocomplete="false"
|
||||
@tags-changed="update"
|
||||
placeholder="Tags"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from 'axios';
|
||||
import VueTagsInput from '@johmun/vue-tags-input';
|
||||
|
||||
export default {
|
||||
name: "Tags",
|
||||
components: {
|
||||
VueTagsInput
|
||||
}, data() {
|
||||
return {
|
||||
tag: '',
|
||||
tags: [],
|
||||
autocompleteItems: [],
|
||||
debounce: null,
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
'tag': 'initItems',
|
||||
},
|
||||
methods: {
|
||||
update(newTags) {
|
||||
this.autocompleteItems = [];
|
||||
this.tags = newTags;
|
||||
},
|
||||
initItems() {
|
||||
if (this.tag.length < 2) {
|
||||
return;
|
||||
}
|
||||
const url = document.getElementsByTagName('base')[0].href + `json/tags?query=${this.tag}`;
|
||||
|
||||
clearTimeout(this.debounce);
|
||||
this.debounce = setTimeout(() => {
|
||||
axios.get(url).then(response => {
|
||||
this.autocompleteItems = response.data.map(a => {
|
||||
return {text: a.tag};
|
||||
});
|
||||
}).catch(() => console.warn('Oh. Something went wrong'));
|
||||
}, 600);
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
@ -0,0 +1,90 @@
|
||||
<!--
|
||||
- TransactionType.vue
|
||||
- Copyright (c) 2019 thegrumpydictator@gmail.com
|
||||
-
|
||||
- This file is part of Firefly III.
|
||||
-
|
||||
- Firefly III is free software: you can redistribute it and/or modify
|
||||
- it under the terms of the GNU General Public License as published by
|
||||
- the Free Software Foundation, either version 3 of the License, or
|
||||
- (at your option) any later version.
|
||||
-
|
||||
- Firefly III is distributed in the hope that it will be useful,
|
||||
- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
- GNU General Public License for more details.
|
||||
-
|
||||
- You should have received a copy of the GNU General Public License
|
||||
- along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
<template>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<label v-if="sentence !== ''" class="control-label text-info">
|
||||
{{ sentence }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
source: String,
|
||||
destination: String,
|
||||
type: String
|
||||
},
|
||||
methods: {
|
||||
changeValue: function () {
|
||||
if (this.source && this.destination) {
|
||||
let transactionType = '';
|
||||
if (window.accountToTypes[this.source]) {
|
||||
if (window.accountToTypes[this.source][this.destination]) {
|
||||
transactionType = window.accountToTypes[this.source][this.destination];
|
||||
} else {
|
||||
console.warn('User selected an impossible destination.');
|
||||
}
|
||||
} else {
|
||||
console.warn('User selected an impossible source.');
|
||||
}
|
||||
if ('' !== transactionType) {
|
||||
this.transactionType = transactionType;
|
||||
this.sentence = 'You\'re creating a ' + this.transactionType;
|
||||
|
||||
// Must also emit a change to set ALL sources and destinations to this particular type.
|
||||
this.$emit('act:limitSourceType', this.source);
|
||||
this.$emit('act:limitDestinationType', this.destination);
|
||||
}
|
||||
} else {
|
||||
this.sentence = '';
|
||||
this.transactionType = '';
|
||||
}
|
||||
// emit event how cool is that.
|
||||
this.$emit('set:transactionType', this.transactionType);
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
transactionType: this.type,
|
||||
sentence: ''
|
||||
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
source() {
|
||||
this.changeValue();
|
||||
},
|
||||
destination() {
|
||||
this.changeValue();
|
||||
}
|
||||
},
|
||||
name: "TransactionType"
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
@ -46,6 +46,7 @@ return [
|
||||
'create_withdrawal' => 'Create new withdrawal',
|
||||
'create_deposit' => 'Create new deposit',
|
||||
'create_transfer' => 'Create new transfer',
|
||||
'create_new_transaction' => 'Create a new transaction',
|
||||
'edit_journal' => 'Edit transaction ":description"',
|
||||
'edit_reconciliation' => 'Edit ":description"',
|
||||
'delete_journal' => 'Delete transaction ":description"',
|
||||
|
@ -1177,7 +1177,7 @@ return [
|
||||
'store_configuration' => 'Store configuration',
|
||||
'single_user_administration' => 'User administration for :email',
|
||||
'edit_user' => 'Edit user :email',
|
||||
'hidden_fields_preferences' => 'Not all fields are visible right now. You must enable them in your <a href=":link">settings</a>.',
|
||||
'hidden_fields_preferences' => 'You can enable more transaction options in your <a href=":link">settings</a>.',
|
||||
'user_data_information' => 'User data',
|
||||
'user_information' => 'User information',
|
||||
'total_size' => 'total size',
|
||||
@ -1202,6 +1202,14 @@ return [
|
||||
'send_message' => 'Send message',
|
||||
'send_test_triggered' => 'Test was triggered. Check your inbox and the log files.',
|
||||
|
||||
'split_transaction_title' => 'Description of the split transaction',
|
||||
'split_title_help' => 'If you create a split transaction, there must be a global description for all splits of the transaction.',
|
||||
'transaction_information' => 'Transaction information',
|
||||
'you_create_transfer' => 'You\'re creating a <strong>transfer</strong>.',
|
||||
'you_create_withdrawal' => 'You\'re creating a <strong>withdrawal</strong>.',
|
||||
'you_create_deposit' => 'You\'re creating a <strong>deposit</strong>.',
|
||||
|
||||
|
||||
// links
|
||||
'journal_link_configuration' => 'Transaction links configuration',
|
||||
'create_new_link_type' => 'Create new link type',
|
||||
|
@ -57,6 +57,7 @@ return [
|
||||
'asset_source_account' => 'Source account',
|
||||
'journal_description' => 'Description',
|
||||
'note' => 'Notes',
|
||||
'store_new_transaction' => 'Store new transaction',
|
||||
'split_journal' => 'Split this transaction',
|
||||
'split_journal_explanation' => 'Split this transaction in multiple parts',
|
||||
'currency' => 'Currency',
|
||||
|
@ -31,18 +31,4 @@
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if type == 'create' and name == 'transaction' %}
|
||||
<div class="form-group">
|
||||
<label for="{{ name }}_split" class="col-sm-4 control-label">
|
||||
{{ trans('form.split_journal') }}
|
||||
</label>
|
||||
|
||||
<div class="col-sm-8">
|
||||
<div class="checkbox"><label>
|
||||
{{ Form.checkbox('split_journal', '1', old('split_journal') == '1', {'id': name ~ 'split'}) }}
|
||||
{{ trans('form.split_journal_explanation') }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
@ -193,8 +193,8 @@
|
||||
{% if not shownDemo %}
|
||||
<script type="text/javascript">
|
||||
var routeForTour = "{{ current_route_name }}";
|
||||
var routeStepsUri = "{{ route('json.intro', [current_route_name, what|default("")]) }}";
|
||||
var routeForFinishedTour = "{{ route('json.intro.finished', [current_route_name, what|default("")]) }}";
|
||||
var routeStepsUri = "{{ route('json.intro', [current_route_name, objectType|default("")]) }}";
|
||||
var routeForFinishedTour = "{{ route('json.intro.finished', [current_route_name, objectType|default("")]) }}";
|
||||
</script>
|
||||
<script type="text/javascript" src="v1/lib/intro/intro.min.js?v={{ FF_VERSION }}"></script>
|
||||
<script type="text/javascript" src="v1/js/ff/intro/intro.js?v={{ FF_VERSION }}"></script>
|
||||
|
@ -1,7 +1,9 @@
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>X</th>
|
||||
<th>
|
||||
{{ groups.render }}
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
@ -12,22 +12,22 @@
|
||||
</span>
|
||||
</a>
|
||||
<ul class="treeview-menu">
|
||||
<li class="{{ activeRoutePartialWhat('accounts', 'asset') }}">
|
||||
<li class="{{ activeRoutePartialObjectType('accounts', 'asset') }}">
|
||||
<a href="{{ route('accounts.index','asset') }}">
|
||||
<i class="fa fa-money fa-fw"></i> {{ 'asset_accounts'|_ }}
|
||||
</a>
|
||||
</li>
|
||||
<li class="{{ activeRoutePartialWhat('accounts', 'expense') }}">
|
||||
<li class="{{ activeRoutePartialObjectType('accounts', 'expense') }}">
|
||||
<a href="{{ route('accounts.index','expense') }}">
|
||||
<i class="fa fa-shopping-cart fa-fw"></i> {{ 'expense_accounts'|_ }}
|
||||
</a>
|
||||
</li>
|
||||
<li class="{{ activeRoutePartialWhat('accounts', 'revenue') }}">
|
||||
<li class="{{ activeRoutePartialObjectType('accounts', 'revenue') }}">
|
||||
<a href="{{ route('accounts.index','revenue') }}">
|
||||
<i class="fa fa-download fa-fw"></i> {{ 'revenue_accounts'|_ }}
|
||||
</a>
|
||||
</li>
|
||||
<li class="{{ activeRoutePartialWhat('accounts', 'liabilities') }}">
|
||||
<li class="{{ activeRoutePartialObjectType('accounts', 'liabilities') }}">
|
||||
<a href="{{ route('accounts.index','liabilities') }}">
|
||||
<i class="fa fa-ticket fa-fw"></i> {{ 'liabilities_accounts'|_ }}
|
||||
</a>
|
||||
@ -67,15 +67,15 @@
|
||||
</span>
|
||||
</a>
|
||||
<ul class="treeview-menu">
|
||||
<li class="{{ activeRoutePartialWhat('transactions','withdrawal') }}">
|
||||
<li class="{{ activeRoutePartialObjectType('transactions','withdrawal') }}">
|
||||
<a href="{{ route('transactions.index','withdrawal') }}">
|
||||
<i class="fa fa-long-arrow-left fa-fw"></i> {{ 'expenses'|_ }}</a>
|
||||
</li>
|
||||
<li class="{{ activeRoutePartialWhat('transactions','deposit') }}">
|
||||
<li class="{{ activeRoutePartialObjectType('transactions','deposit') }}">
|
||||
<a href="{{ route('transactions.index','deposit') }}"><i
|
||||
class="fa fa-long-arrow-right fa-fw"></i> {{ 'income'|_ }}</a>
|
||||
</li>
|
||||
<li class="{{ activeRoutePartialWhat('transactions','transfers') }}">
|
||||
<li class="{{ activeRoutePartialObjectType('transactions','transfers') }}">
|
||||
<a href="{{ route('transactions.index','transfers') }}">
|
||||
<i class="fa fa-fw fa-exchange"></i> {{ 'transfers'|_ }}</a>
|
||||
</li>
|
||||
|
288
resources/views/v1/transactions/create.twig
Normal file
288
resources/views/v1/transactions/create.twig
Normal file
@ -0,0 +1,288 @@
|
||||
{% extends "./layout/default" %}
|
||||
|
||||
{% block breadcrumbs %}
|
||||
{{ Breadcrumbs.render(Route.getCurrentRoute.getName, objectType) }}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<create-transaction></create-transaction>
|
||||
|
||||
|
||||
{#
|
||||
<form method="POST" action="{{ route('transactions.store') }}" accept-charset="UTF-8" class="form-horizontal" id="store" enctype="multipart/form-data">
|
||||
<input name="_token" type="hidden" value="{{ csrf_token() }}">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-6">
|
||||
<div class="box">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">
|
||||
{{ 'split_transaction_title'|_ }}
|
||||
</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<input type="text" class="form-control" name="group_title"
|
||||
title="{{ 'split_transaction_title'|_ }}" autocomplete="off" placeholder="{{ 'split_transaction_title'|_ }}">
|
||||
<p class="help-block">
|
||||
{{ 'split_title_help'|_ }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="transactions">
|
||||
<div class="row transactionRow">
|
||||
<div class="col-lg-12">
|
||||
<div class="box">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title splitTitle">
|
||||
{{ 'transaction_information'|_ }}
|
||||
</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<div class="row">
|
||||
<div class="col-lg-4">
|
||||
<div class="form-group transactionTypeIndicatorBlock" style="display:none;">
|
||||
<div class="col-sm-12">
|
||||
<label class="control-label transactionTypeIndicator text-info"></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
|
||||
<div class="input-group">
|
||||
<input type="text" data-index="0" class="form-control indexField sourceAccountAC" name="source[]"
|
||||
title="{{ trans('form.source_account') }}" autocomplete="off"
|
||||
placeholder="{{ trans('form.source_account') }}">
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-default clearSource" type="button"><i class="fa fa-trash-o"></i></button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<div class="input-group">
|
||||
<input data-index="0" type="text" class="form-control indexField destinationAccountAC" name="destination[]"
|
||||
title="{{ trans('form.destination_account') }}" autocomplete="off"
|
||||
placeholder="{{ trans('form.destination_account') }}">
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-default clearDestination" type="button"><i class="fa fa-trash-o"></i></button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<input type="text" class="form-control" name="description[]"
|
||||
title="{{ trans('form.description') }}" autocomplete="off" placeholder="{{ trans('form.description') }}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<input type="date" class="form-control" name="date[]"
|
||||
title="{{ trans('form.date') }}" value="{{ phpdate('Y-m-d') }}" autocomplete="off"
|
||||
placeholder="{{ trans('form.date') }}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-4">
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label">$</label>
|
||||
<div class="col-sm-9">
|
||||
<input type="number" step="any" class="form-control" name="amount[]"
|
||||
title="{{ trans('form.amount') }}" autocomplete="off" placeholder="{{ trans('form.amount') }}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-3">
|
||||
<select name="foreign_amount">
|
||||
<option>none</option>
|
||||
<option>USD</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-sm-9">
|
||||
<input type="number" step="any" class="form-control" name="amount[]"
|
||||
title="Foreign amount" autocomplete="off" placeholder="Foreign amount">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-4">
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<select name="budget">
|
||||
<option>budget</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<input type="text" class="form-control" name="category[]"
|
||||
title="Category" autocomplete="off" placeholder="Category">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<input type="text" class="form-control" name="tags[]"
|
||||
title="Tags" autocomplete="off" placeholder="Tags">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<select name="piggy">
|
||||
<option>Piggy</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{% if
|
||||
optionalFields.interest_date or optionalFields.book_date or optionalFields.process_date
|
||||
or optionalFields.due_date or optionalFields.payment_date
|
||||
or optionalFields.invoice_date %}
|
||||
{% for field in ['interest_date','book_date','process_date','due_date','payment_date','invoice_date'] %}
|
||||
{% if optionalFields[field] %}
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<input type="text" class="form-control" name="{{ field }}[]"
|
||||
title="{{ field }}" autocomplete="off" placeholder="{{ field }}">
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% if optionalFields.internal_reference or optionalFields.notes %}
|
||||
|
||||
{% if optionalFields.internal_reference %}
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<input type="text" class="form-control" name="internal_reference[]"
|
||||
title="internal_reference" autocomplete="off" placeholder="internal_reference">
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% if optionalFields.notes %}
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<textarea></textarea>
|
||||
<br>
|
||||
{{ trans('firefly.field_supports_markdown')|raw }}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% if optionalFields.attachments %}
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
|
||||
<input multiple="multiple" class="form-control"
|
||||
autocomplete="off" placeholder="Attachments" name="attachments[]" type="file">
|
||||
<p class="help-block">
|
||||
{{ trans('firefly.upload_max_file_size', {'size': uploadSize|filesize}) }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% if
|
||||
not optionalFields.interest_date or
|
||||
not optionalFields.book_date or
|
||||
not optionalFields.process_date or
|
||||
not optionalFields.due_date or
|
||||
not optionalFields.payment_date or
|
||||
not optionalFields.invoice_date or
|
||||
not optionalFields.internal_reference or
|
||||
not optionalFields.notes or
|
||||
not optionalFields.attachments %}
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<p class="text-success"><i class="fa fa-info-circle"></i>
|
||||
<em>{{ trans('firefly.hidden_fields_preferences', {link: route('preferences.index')})|raw }}</em></p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<p>
|
||||
<button id="addSplitButton" class="btn btn-primary">Add another split</button>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-6">
|
||||
|
||||
<div class="box">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">{{ 'options'|_ }}</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
{{ ExpandedForm.optionsList('create','transaction') }}
|
||||
</div>
|
||||
<div class="box-footer">
|
||||
<button type="submit" class="transaction-btn btn btn-success pull-right">
|
||||
{{ trans('form.store_new_transaction') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
#}
|
||||
{% endblock %}
|
||||
{% block scripts %}
|
||||
<script type="text/javascript">
|
||||
var allowedOpposingTypes = {{ allowedOpposingTypes|json_encode|raw }};
|
||||
var accountToTypes = {{ accountToTypes|json_encode|raw }};
|
||||
var defaultCurrency = {{ defaultCurrency.toArray()|json_encode|raw }};
|
||||
</script>
|
||||
<!--
|
||||
<script type="text/javascript">
|
||||
var transactionType = 'none';
|
||||
|
||||
var accountToTypes = {{ accountToTypes|json_encode|raw }};
|
||||
|
||||
var creatingTypes = {
|
||||
Transfer: "{{ 'you_create_transfer'|_ }}",
|
||||
Withdrawal: "{{ 'you_create_withdrawal'|_ }}",
|
||||
Deposit: "{{ 'you_create_deposit'|_ }}",
|
||||
};
|
||||
|
||||
// options for source account selection.
|
||||
var sourceAccount = null;
|
||||
var sourceAllowedAccountTypes = [];
|
||||
|
||||
// options for destination account selection.
|
||||
var destinationAccount = null;
|
||||
var destAllowedAccountTypes = [];
|
||||
|
||||
</script>
|
||||
|
||||
<script type="text/javascript" src="v1/js/lib/modernizr-custom.js?v={{ FF_VERSION }}"></script>
|
||||
<script type="text/javascript" src="v1/js/lib/jquery.autocomplete.min.js?v={{ FF_VERSION }}"></script>
|
||||
<script type="text/javascript" src="v1/js/ff/transactions/create.js?v={{ FF_VERSION }}"></script>
|
||||
-->
|
||||
{% endblock %}
|
||||
|
||||
{% block styles %}
|
||||
{% endblock %}
|
@ -31,7 +31,7 @@
|
||||
{% endif %}
|
||||
</div>
|
||||
{# actual list #}
|
||||
{% include 'list.transactions' %}
|
||||
{% include 'list.groups' %}
|
||||
</div>
|
||||
<div class="box-footer">
|
||||
{# links for other views #}
|
||||
|
@ -1022,9 +1022,9 @@ try {
|
||||
|
||||
Breadcrumbs::register(
|
||||
'transactions.create',
|
||||
function (BreadcrumbsGenerator $breadcrumbs, string $what) {
|
||||
$breadcrumbs->parent('transactions.index', $what);
|
||||
$breadcrumbs->push(trans('breadcrumbs.create_' . e($what)), route('transactions.create', [$what]));
|
||||
function (BreadcrumbsGenerator $breadcrumbs, string $objectType) {
|
||||
$breadcrumbs->parent('transactions.index', $objectType);
|
||||
$breadcrumbs->push(trans('breadcrumbs.create_new_transaction'), route('transactions.create', [$objectType]));
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -546,14 +546,20 @@ Route::group(
|
||||
['middleware' => 'user-full-auth', 'namespace' => 'FireflyIII\Http\Controllers', 'prefix' => 'json', 'as' => 'json.'], function () {
|
||||
|
||||
// for auto complete
|
||||
Route::get('accounts', ['uses' => 'Json\AutoCompleteController@accounts', 'as' => 'autocomplete.accounts']);
|
||||
Route::get('currencies', ['uses' => 'Json\AutoCompleteController@currencies', 'as' => 'autocomplete.currencies']);
|
||||
Route::get('budgets', ['uses' => 'Json\AutoCompleteController@budgets', 'as' => 'autocomplete.budgets']);
|
||||
Route::get('categories', ['uses' => 'Json\AutoCompleteController@categories', 'as' => 'autocomplete.categories']);
|
||||
Route::get('piggy-banks', ['uses' => 'Json\AutoCompleteController@piggyBanks', 'as' => 'autocomplete.piggy-banks']);
|
||||
Route::get('tags', ['uses' => 'Json\AutoCompleteController@tags', 'as' => 'autocomplete.tags']);
|
||||
|
||||
|
||||
|
||||
// TODO improve 3 routes:
|
||||
Route::get('transaction-journals/all', ['uses' => 'Json\AutoCompleteController@allTransactionJournals', 'as' => 'all-transaction-journals']);
|
||||
Route::get('transaction-journals/with-id/{tj}', ['uses' => 'Json\AutoCompleteController@journalsWithId', 'as' => 'journals-with-id']);
|
||||
Route::get('transaction-journals/{what}', ['uses' => 'Json\AutoCompleteController@transactionJournals', 'as' => 'transaction-journals']);
|
||||
//Route::get('transaction-journals/all', ['uses' => 'Json\AutoCompleteController@allTransactionJournals', 'as' => 'all-transaction-journals']);
|
||||
//Route::get('transaction-journals/with-id/{tj}', ['uses' => 'Json\AutoCompleteController@journalsWithId', 'as' => 'journals-with-id']);
|
||||
//Route::get('transaction-journals/{what}', ['uses' => 'Json\AutoCompleteController@transactionJournals', 'as' => 'transaction-journals']);
|
||||
// TODO end of improvement
|
||||
|
||||
Route::get('transaction-types', ['uses' => 'Json\AutoCompleteController@transactionTypes', 'as' => 'transaction-types']);
|
||||
|
||||
// boxes
|
||||
@ -577,7 +583,7 @@ Route::group(
|
||||
Route::post('intro/enable/{route}/{specificPage?}', ['uses' => 'Json\IntroController@postEnable', 'as' => 'intro.enable']);
|
||||
Route::get('intro/{route}/{specificPage?}', ['uses' => 'Json\IntroController@getIntroSteps', 'as' => 'intro']);
|
||||
|
||||
Route::get('/{subject}', ['uses' => 'Json\AutoCompleteController@autoComplete', 'as' => 'autocomplete']);
|
||||
//Route::get('/{subject}', ['uses' => 'Json\AutoCompleteController@autoComplete', 'as' => 'autocomplete']);
|
||||
|
||||
}
|
||||
);
|
||||
@ -873,11 +879,13 @@ Route::group(
|
||||
Route::group(
|
||||
['middleware' => 'user-full-auth', 'namespace' => 'FireflyIII\Http\Controllers', 'prefix' => 'transactions', 'as' => 'transactions.'], function () {
|
||||
|
||||
|
||||
// show groups:
|
||||
Route::get('{what}/{start_date?}/{end_date?}', ['uses' => 'Transaction\IndexController@index', 'as' => 'index'])->where(
|
||||
['what' => 'withdrawal|deposit|transfers|transfer']
|
||||
);
|
||||
|
||||
// create group:
|
||||
Route::get('create/{objectType}', ['uses' => 'Transaction\CreateController@create', 'as' => 'create'])->where(['objectType' => 'withdrawal|deposit|transfer']);
|
||||
|
||||
|
||||
// TODO improve these routes
|
||||
@ -903,7 +911,7 @@ Route::group(
|
||||
['middleware' => 'user-full-auth', 'namespace' => 'FireflyIII\Http\Controllers\Transaction', 'prefix' => 'transactions', 'as' => 'transactions.'],
|
||||
function () {
|
||||
// TODO improve these routes
|
||||
Route::get('create/{what}', ['uses' => 'SingleController@create', 'as' => 'create'])->where(['what' => 'withdrawal|deposit|transfer']);
|
||||
|
||||
Route::get('edit/{tj}', ['uses' => 'SingleController@edit', 'as' => 'edit']);
|
||||
Route::get('delete/{tj}', ['uses' => 'SingleController@delete', 'as' => 'delete']);
|
||||
Route::post('store', ['uses' => 'SingleController@store', 'as' => 'store'])->where(['what' => 'withdrawal|deposit|transfer']);
|
||||
|
24
yarn.lock
24
yarn.lock
@ -2,6 +2,13 @@
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@johmun/vue-tags-input@^2.0.1":
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@johmun/vue-tags-input/-/vue-tags-input-2.0.1.tgz#5ca22a573858c8df6c05788e3ffabe92e1baa1df"
|
||||
integrity sha512-1LUsINr6iBROfG31C05qf+XpoM4jLstpLzTmfu+57fxErgP2gGnVB41oz1qVxjKe1gdpOaAZSByhoAm2h0cO3w==
|
||||
dependencies:
|
||||
vue "^2.5.16"
|
||||
|
||||
"@types/q@^1.5.1":
|
||||
version "1.5.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.1.tgz#48fd98c1561fe718b61733daed46ff115b496e18"
|
||||
@ -7974,6 +7981,13 @@ uglifyjs-webpack-plugin@^1.0.0:
|
||||
webpack-sources "^1.1.0"
|
||||
worker-farm "^1.5.2"
|
||||
|
||||
uiv@^0.31.5:
|
||||
version "0.31.5"
|
||||
resolved "https://registry.yarnpkg.com/uiv/-/uiv-0.31.5.tgz#bfb87833b9abb59d8f0bb4f630943449b053b733"
|
||||
integrity sha512-VcizUxkJCr4XhnFJ3KWCuiVaDvU3H5yDLX4F1yhrmK5hz+2+OIuCShJd6Is366oJdJagoh42sjWQqZL74uMEmw==
|
||||
dependencies:
|
||||
vue-functional-data-merge "^2.0.3"
|
||||
|
||||
unbzip2-stream@^1.0.9:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.3.1.tgz#7854da51622a7e63624221196357803b552966a1"
|
||||
@ -8252,6 +8266,11 @@ vm-browserify@0.0.4:
|
||||
dependencies:
|
||||
indexof "0.0.1"
|
||||
|
||||
vue-functional-data-merge@^2.0.3:
|
||||
version "2.0.7"
|
||||
resolved "https://registry.yarnpkg.com/vue-functional-data-merge/-/vue-functional-data-merge-2.0.7.tgz#bdee655181eacdcb1f96ce95a4cc14e75313d1da"
|
||||
integrity sha512-pvLc+H+x2prwBj/uSEIITyxjz/7ZUVVK8uYbrYMmhDvMXnzh9OvQvVEwcOSBQjsubd4Eq41/CSJaWzy4hemMNQ==
|
||||
|
||||
vue-hot-reload-api@^2.2.0:
|
||||
version "2.3.1"
|
||||
resolved "https://registry.yarnpkg.com/vue-hot-reload-api/-/vue-hot-reload-api-2.3.1.tgz#b2d3d95402a811602380783ea4f566eb875569a2"
|
||||
@ -8297,6 +8316,11 @@ vue-template-es2015-compiler@^1.6.0:
|
||||
resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.6.0.tgz#dc42697133302ce3017524356a6c61b7b69b4a18"
|
||||
integrity sha512-x3LV3wdmmERhVCYy3quqA57NJW7F3i6faas++pJQWtknWT+n7k30F4TVdHvCLn48peTJFRvCpxs3UuFPqgeELg==
|
||||
|
||||
vue@^2.5.16:
|
||||
version "2.6.10"
|
||||
resolved "https://registry.yarnpkg.com/vue/-/vue-2.6.10.tgz#a72b1a42a4d82a721ea438d1b6bf55e66195c637"
|
||||
integrity sha512-ImThpeNU9HbdZL3utgMCq0oiMzAkt1mcgy3/E6zWC/G6AaQoeuFdsl9nDhTDU3X1R6FK7nsIUuRACVcjI+A2GQ==
|
||||
|
||||
vue@^2.5.7:
|
||||
version "2.5.21"
|
||||
resolved "https://registry.yarnpkg.com/vue/-/vue-2.5.21.tgz#3d33dcd03bb813912ce894a8303ab553699c4a85"
|
||||
|
Loading…
Reference in New Issue
Block a user