Rebuild frontend, first working edit form (no feedback)

This commit is contained in:
James Cole 2021-03-21 18:48:47 +01:00
parent e0d0f49bfd
commit 1088a43866
No known key found for this signature in database
GPG Key ID: B5669F9493CDE38D
16 changed files with 2243 additions and 851 deletions

View File

@ -26,6 +26,7 @@ namespace FireflyIII\Api\V1\Controllers\Autocomplete;
use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest;
use FireflyIII\Models\ObjectGroup;
use FireflyIII\Models\PiggyBank;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
@ -37,7 +38,7 @@ use Illuminate\Http\JsonResponse;
*/
class PiggyBankController extends Controller
{
private AccountRepositoryInterface $accountRepository;
private AccountRepositoryInterface $accountRepository;
private PiggyBankRepositoryInterface $piggyRepository;
/**
@ -75,9 +76,19 @@ class PiggyBankController extends Controller
/** @var PiggyBank $piggy */
foreach ($piggies as $piggy) {
$currency = $this->accountRepository->getAccountCurrency($piggy->account) ?? $defaultCurrency;
$groupTitle = null;
$groupId = null;
/** @var ObjectGroup $group */
$group = $piggy->objectGroups()->first();
if (null !== $group) {
$groupTitle = $group->title;
$groupId = (string)$group->id;
}
$response[] = [
'id' => (string)$piggy->id,
'name' => $piggy->name,
'object_group_id' => $groupId,
'object_group_title' => $groupTitle,
'currency_id' => $currency->id,
'currency_name' => $currency->name,
'currency_code' => $currency->code,
@ -103,13 +114,23 @@ class PiggyBankController extends Controller
foreach ($piggies as $piggy) {
$currency = $this->accountRepository->getAccountCurrency($piggy->account) ?? $defaultCurrency;
$currentAmount = $this->piggyRepository->getRepetition($piggy)->currentamount ?? '0';
$response[] = [
$groupTitle = null;
$groupId = null;
/** @var ObjectGroup $group */
$group = $piggy->objectGroups()->first();
if (null !== $group) {
$groupTitle = $group->title;
$groupId = (string)$group->id;
}
$response[] = [
'id' => (string)$piggy->id,
'name' => $piggy->name,
'name_with_balance' => sprintf(
'%s (%s / %s)', $piggy->name, app('amount')->formatAnything($currency, $currentAmount, false),
app('amount')->formatAnything($currency, $piggy->targetamount, false),
),
'object_group_id' => $groupId,
'object_group_title' => $groupTitle,
'currency_id' => $currency->id,
'currency_name' => $currency->name,
'currency_code' => $currency->code,

View File

@ -387,6 +387,7 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface
/**
* @inheritDoc
* TODO need to sort by group order as well.
*/
public function searchPiggyBank(string $query, int $limit): Collection
{

View File

@ -136,19 +136,19 @@ export default {
groupTitle: '',
originalGroupTitle: '',
transactionType: 'any',
groudId: 0,
groupId: 0,
// errors in the group title:
groupTitleErrors: [],
// which custom fields to show TODO
// which custom fields to show
customFields: {},
// group ID + title once submitted:
returnedGroupId: 0,
returnedGroupTitle: '',
// date and time of the transaction, TODO
// date and time of the transaction,
date: new Date,
time: new Date,
originalDate: new Date,
@ -252,7 +252,7 @@ export default {
// meta data
result.category = array.category_name;
result.budget_id = array.budget_id;
result.bill_id = array.bill_id;
result.bill_id = array.bill_id ?? 0;
result.tags = array.tags;
@ -287,7 +287,7 @@ export default {
* Get the links of this transaction group from the API.
*/
parseLinks: function (journalId, index) {
axios.get('./api/v1/transactions/' + journalId + '/links')
axios.get('./api/v1/transaction-journals/' + journalId + '/links')
.then(response => {
let links = response.data.data;
for (let i in links) {
@ -342,6 +342,7 @@ export default {
let direction = responses[0].direction;
let linkTypeId = responses[2].data.data.id;
let object = {
id: link.id,
link_type_id: linkTypeId + '-' + direction,
transaction_group_id: responses[1].data.data.id,
transaction_journal_id: journal.transaction_journal_id,
@ -355,12 +356,13 @@ export default {
});
},
/**
* TODO same method as Create
* Get API value.
*/
getAllowedOpposingTypes: function () {
axios.get('./api/v1/configuration/static/firefly.allowed_opposing_types')
axios.get('./api/v1/configuration/firefly.allowed_opposing_types')
.then(response => {
this.allowedOpposingTypes = response.data['firefly.allowed_opposing_types'];
this.allowedOpposingTypes = response.data.data.value;
// console.log('Set allowedOpposingTypes');
});
},
@ -439,6 +441,7 @@ export default {
submission.group_title = this.groupTitle;
shouldSubmit = true;
}
let transactionCount = this.originalTransactions.length;
for (let i in this.transactions) {
if (this.transactions.hasOwnProperty(i) && /^0$|^[1-9]\d*$/.test(i) && i <= 4294967294) {
// original transaction present?
@ -467,17 +470,20 @@ export default {
// console.log(originalTransaction[fieldName]);
// console.log(currentTransaction[fieldName]);
diff[fieldName] = currentTransaction[fieldName];
shouldSubmit = true;
}
}
}
if (0 !== currentTransaction.piggy_bank_id) {
diff.piggy_bank_id = currentTransaction.piggy_bank_id;
shouldSubmit = true;
}
if (JSON.stringify(currentTransaction.tags) !== JSON.stringify(originalTransaction.tags)) {
// console.log('tags are different');
// console.log(currentTransaction.tags);
// console.log(originalTransaction.tags);
diff.tags = currentTransaction.tags;
shouldSubmit = true;
}
// compare links:
@ -515,10 +521,13 @@ export default {
dateStr = toW3CString(theDate);
submission.date = dateStr;
}
if (Object.keys(diff).length !== 0) {
if (Object.keys(diff).length === 0 && transactionCount > 1) {
diff.transaction_journal_id = originalTransaction.transaction_journal_id;
submission.transactions.push(diff);
submission.transactions.push(lodashClonedeep(diff));
shouldSubmit = true;
} else if (Object.keys(diff).length !== 0) {
diff.transaction_journal_id = originalTransaction.transaction_journal_id;
submission.transactions.push(lodashClonedeep(diff));
shouldSubmit = true;
}
}
@ -529,8 +538,12 @@ export default {
console.log(shouldLinks);
console.log(shouldSubmit);
if (shouldSubmit) {
this.submitUpdate(submission);
this.submitUpdate(submission, shouldLinks, shouldUpload);
}
if (!shouldSubmit && shouldLinks) {
this.submitTransactionLinks();
}
//console.log(submission);
},
compareLinks: function (array) {
@ -553,17 +566,24 @@ export default {
// console.log(compare);
return JSON.stringify(compare);
},
submitUpdate: function (submission) {
submitUpdate: function (submission, shouldLinks, shouldUpload) {
console.log('submitUpdate');
const url = './api/v1/transactions/' + this.groupId;
console.log(submission);
axios.put(url, submission)
.then(response => {
// console.log('Response is OK!');
console.log('Response is OK!');
// report the transaction is submitted.
this.submittedTransaction = true;
// // submit links and attachments (can only be done when the transaction is created)
// this.submitTransactionLinks(data, response);
// submit links and attachments (can only be done when the transaction is created)
if (shouldLinks) {
console.log('Need to update links.');
this.submitTransactionLinks();
}
if (!shouldLinks) {
console.log('No need to update links.');
}
// this.submitAttachments(data, response);
//
// // meanwhile, store the ID and the title in some easy to access variables.
@ -678,6 +698,116 @@ export default {
resetErrors(payload) {
this.transactions[payload.index].errors = lodashClonedeep(getDefaultErrors());
},
deleteOriginalLinks: function (transaction) {
console.log(transaction.links);
for (let i in transaction.links) {
if (transaction.links.hasOwnProperty(i) && /^0$|^[1-9]\d*$/.test(i) && i <= 4294967294) {
let current = transaction.links[i];
let url = '/api/v1/transaction_links/' + current.id;
axios.delete(url).then(response => {
// TODO response
});
}
}
},
/**
* Submit transaction links.
* TODO same method as CREATE
*/
submitTransactionLinks() {
let total = 0;
let promises = [];
console.log('submitTransactionLinks()');
for (let i in this.transactions) {
if (this.transactions.hasOwnProperty(i) && /^0$|^[1-9]\d*$/.test(i) && i <= 4294967294) {
// original transaction present?
let currentTransaction = this.transactions[i];
let originalTransaction = this.originalTransactions.hasOwnProperty(i) ? this.originalTransactions[i] : {};
// compare links:
let newLinks = this.compareLinks(currentTransaction.links);
let originalLinks = this.compareLinks(originalTransaction.links);
if (newLinks !== originalLinks) {
if ('[]' !== originalLinks) {
this.deleteOriginalLinks(originalTransaction);
}
console.log('links are different!');
// console.log(newLinks);
// console.log(originalLinks);
for (let ii in currentTransaction.links) {
if (currentTransaction.links.hasOwnProperty(ii) && /^0$|^[1-9]\d*$/.test(ii) && ii <= 4294967294) {
let currentLink = currentTransaction.links[ii];
let linkObject = {
inward_id: currentTransaction.transaction_journal_id,
outward_id: currentTransaction.transaction_journal_id,
link_type_id: 'something'
};
let parts = currentLink.link_type_id.split('-');
linkObject.link_type_id = parts[0];
if ('inward' === parts[1]) {
linkObject.inward_id = currentLink.transaction_journal_id;
}
if ('outward' === parts[1]) {
linkObject.outward_id = currentLink.transaction_journal_id;
}
console.log(linkObject);
total++;
// submit transaction link:
promises.push(axios.post('./api/v1/transaction_links', linkObject).then(response => {
// TODO error handling.
}));
}
}
// shouldLinks = true;
}
}
}
return;
let result = response.data.data.attributes.transactions;
// for (let i in data.transactions) {
// if (data.transactions.hasOwnProperty(i) && /^0$|^[1-9]\d*$/.test(i) && i <= 4294967294) {
// let submitted = data.transactions[i];
// if (result.hasOwnProperty(i)) {
// // found matching created transaction.
// let received = result[i];
// // grab ID from received, loop "submitted" transaction links
// for (let ii in submitted.links) {
// if (submitted.links.hasOwnProperty(ii) && /^0$|^[1-9]\d*$/.test(ii) && ii <= 4294967294) {
// let currentLink = submitted.links[ii];
// total++;
// if (0 === currentLink.outward_id) {
// currentLink.outward_id = received.transaction_journal_id;
// }
// if (0 === currentLink.inward_id) {
// currentLink.inward_id = received.transaction_journal_id;
// }
// // submit transaction link:
// promises.push(axios.post('./api/v1/transaction_links', currentLink).then(response => {
// // TODO error handling.
// }));
// }
// }
// }
// }
// }
if (0 === total) {
this.submittedLinks = true;
return;
}
Promise.all(promises).then(function () {
this.submittedLinks = true;
});
},
}
}
</script>

View File

@ -27,7 +27,9 @@
<div class="row">
<div class="col">
<p v-if="links.length === 0">
<button class="btn btn-default btn-xs" data-target="#linkModal" @click="resetModal" data-toggle="modal"><i class="fas fa-plus"></i> Add transaction link</button>
<button class="btn btn-default btn-xs" :data-target="'#linkModal' + index" @click="resetModal" data-toggle="modal"><i class="fas fa-plus"></i> Add transaction
link
</button>
</p>
<ul v-if="links.length > 0" class="list-group">
<li v-for="(transaction, index) in links" class="list-group-item" v-bind:key="index">
@ -64,13 +66,13 @@
</li>
</ul>
<div v-if="links.length > 0" class="form-text">
<button class="btn btn-default" @click="resetModal" data-target="#linkModal" data-toggle="modal"><i class="fas fa-plus"></i></button>
<button class="btn btn-default" @click="resetModal" :data-target="'#linkModal' + index" data-toggle="modal"><i class="fas fa-plus"></i></button>
</div>
</div>
</div>
</div>
<!-- modal -->
<div id="linkModal" class="modal" tabindex="-1" ref="linkModal">
<div :id="'linkModal' + index" class="modal" tabindex="-1" :ref="'linkModal' + index">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
@ -305,7 +307,7 @@ export default {
}
);
},
resetModal: function() {
resetModal: function () {
this.search();
},
parseLinkTypes: function (data) {
@ -332,7 +334,7 @@ export default {
}
},
search: function () {
if('' === this.query) {
if ('' === this.query) {
this.searchResults = [];
return;
}
@ -351,11 +353,28 @@ export default {
for (let ii in data.data[i].attributes.transactions) {
if (data.data[i].attributes.transactions.hasOwnProperty(ii) && /^0$|^[1-9]\d*$/.test(ii) && ii <= 4294967294) {
let current = data.data[i].attributes.transactions[ii];
current.transaction_group_id = parseInt(data.data[i].id);
current.selected = this.isJournalSelected(current.transaction_journal_id);
current.link_type_id = this.getJournalLinkType(current.transaction_journal_id);
current.link_type_text = '';
this.searchResults.push(current);
let copied = {
transaction_journal_id: current.transaction_journal_id,
transaction_group_id: parseInt(data.data[i].id),
description: current.description,
type: current.type,
amount: current.amount,
currency_code: current.currency_code,
source_id: current.source_id,
source_name: current.source_name,
destination_id: current.destination_id,
destination_name: current.destination_name,
selected: this.isJournalSelected(current.transaction_journal_id),
link_type_id: this.getJournalLinkType(current.transaction_journal_id),
link_type_text: '',
};
// current.transaction_group_id = parseInt(data.data[i].id);
// current.selected = this.isJournalSelected(current.transaction_journal_id);
// current.link_type_id = this.getJournalLinkType(current.transaction_journal_id);
// current.link_type_text = '';
this.searchResults.push(copied);
}
}
}

View File

@ -43,7 +43,6 @@ export default {
return {
notes: this.value,
availableFields: this.customFields,
emitEvent: true
}
},
computed: {
@ -56,17 +55,13 @@ export default {
},
watch: {
value: function (value) {
this.emitEvent = false;
this.notes = value;
},
customFields: function (value) {
this.availableFields = value;
},
notes: function (value) {
if (true === this.emitEvent) {
this.$emit('set-field', {field: 'notes', index: this.index, value: value});
}
this.emitEvent = true;
this.$emit('set-field', {field: 'notes', index: this.index, value: value});
}
}
}

View File

@ -33,9 +33,16 @@
name="piggy_bank_id[]"
v-on:submit.prevent
>
<option v-for="piggy in this.piggyList" :label="piggy.name_with_balance" :value="piggy.id">{{ piggy.name_with_balance }}</option>
<optgroup v-for="group in this.piggyGroups" v-bind:key="group.title" :label="group.title">
<option v-for="piggy in group.piggies" :label="piggy.name_with_balance" :value="piggy.id">{{ piggy.name_with_balance }}</option>
</optgroup>
</select>
<!--
<span v-for="group in this.piggyList">"{{ group.title }}"<br>
</span>
-->
</div>
<span v-if="errors.length > 0">
<span v-for="error in errors" class="text-danger small">{{ error }}<br/></span>
@ -50,7 +57,8 @@ export default {
name: "TransactionPiggyBank",
data() {
return {
piggyList: [],
piggyGroups: [],
piggyList: {},
piggy_bank_id: this.value,
emitEvent: true
}
@ -60,12 +68,33 @@ export default {
},
methods: {
collectData() {
this.piggyList.push(
// add empty group:
this.piggyGroups.push(
{
id: 0,
name_with_balance: this.$t('firefly.no_piggy_bank'),
title: this.$t('firefly.default_group_title_name'),
piggies: []
}
);
// empty piggy list:
// this.piggyList['0'] = {
// title: this.$t('firefly.default_group_title_name'),
// piggies: [
// {
// id: 0,
// name_with_balance: this.$t('firefly.no_piggy_bank'),
// }
// ]
// };
// this.piggyList.push(
// {
// id: 0,
// name_with_balance: this.$t('firefly.no_piggy_bank'),
// }
// );
this.getPiggies();
},
getPiggies() {
@ -75,18 +104,67 @@ export default {
}
);
},
groupExists: function (title) {
for (let i in this.piggyGroups) {
if (this.piggyGroups.hasOwnProperty(i) && /^0$|^[1-9]\d*$/.test(i) && i <= 4294967294) {
let current = this.piggyGroups[i];
if (current.title === title) {
return true;
}
}
}
return false;
},
getGroupIndex: function (groupId) {
for (let i in this.piggyGroups) {
if (this.piggyGroups.hasOwnProperty(i) && /^0$|^[1-9]\d*$/.test(i) && i <= 4294967294) {
let current = this.piggyGroups[i];
if (current.id === groupId) {
return i;
}
}
}
return 0;
},
parsePiggies(data) {
for (let key in data) {
if (data.hasOwnProperty(key) && /^0$|^[1-9]\d*$/.test(key) && key <= 4294967294) {
let current = data[key];
this.piggyList.push(
{
id: parseInt(current.id),
name_with_balance: current.name_with_balance
}
);
let groupId = current.object_group_id ?? '0';
if ('0' !== groupId) {
if (this.groupExists(current.object_group_title)) {
let currentGroup = this.getGroupIndex(parseInt(current.object_group_id));
this.piggyGroups[currentGroup].piggies.push(current);
}
if (!this.groupExists(current.object_group_title)) {
this.piggyGroups.push(
{
id: parseInt(current.object_group_id),
title: current.object_group_title,
piggies: [current]
}
);
}
}
if ('0' === groupId) {
this.piggyGroups[0].piggies.push(current);
}
// //console.log('group id is ' + groupId);
// if ('0' !== groupId) {
// this.piggyList[groupId] = this.piggyList[groupId] ? this.piggyList[groupId] : {title: current.object_group_title, piggies: []};
// }
// this.piggyList[groupId].piggies.push(
// {
// id: parseInt(current.id),
// name_with_balance: current.name_with_balance
// }
// );
}
}
//console.log(this.piggyList);
},
},
watch: {

View File

@ -20,4 +20,7 @@
// slightly darker blue to match the logo:
$blue: #1E6581 !default;
$blue: #1E6581 !default;
// other green to match the logo:
$green: #64B624 !default;

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,23 @@
{% extends './v2/layout/default' %}
{% block breadcrumbs %}
{{ Breadcrumbs.render }}
{% endblock %}
{% block content %}
<!-- Small boxes (Stat box) -->
<!-- Main row -->
<div id="transactions_edit"></div>
<!-- /.row (main row) -->
{% endblock %}
{% block styles %}
{% endblock %}
{% block scripts %}
<script type="text/javascript">
// this is a terrible hack.
var previousURL = '{{ previousUri }}';
</script>
<script src="v2/js/transactions/edit.js" nonce="{{ JS_NONCE }}"></script>
{% endblock %}