Expand view with several new options. Move cache to api endpoints.

This commit is contained in:
James Cole
2024-04-28 13:30:42 +02:00
parent c1c0afa40b
commit 7992b810fd
10 changed files with 226 additions and 82 deletions

View File

@@ -43,6 +43,7 @@ store.addPlugin(observePlugin);
window.bootstrapped = false;
window.store = store;
window.bootstrap = bootstrap;

View File

@@ -32,7 +32,6 @@ import {showWizardButton} from "../../support/page-settings/show-wizard-button.j
import {setVariable} from "../../store/set-variable.js";
import {getVariables} from "../../store/get-variables.js";
import pageNavigation from "../../support/page-navigation.js";
import {getCacheKey} from "../../support/get-cache-key.js";
// set type from URL
@@ -144,10 +143,36 @@ let index = function () {
},
editors: {},
accounts: [],
lastClickedFilter: '',
lastFilterInput: '',
goToPage(page) {
this.page = page;
this.loadAccounts();
},
applyFilter() {
this.filters[this.lastClickedFilter] = this.lastFilterInput;
this.page = 1;
setVariable(this.getPreferenceKey('filters'), this.filters);
// hide modal
window.bootstrap.Modal.getInstance(document.getElementById('filterModal')).hide();
this.loadAccounts();
},
removeFilter(field) {
this.filters[field] = null;
this.page = 1;
setVariable(this.getPreferenceKey('filters'), this.filters);
this.loadAccounts();
},
hasFilters() {
return this.filters.name !== null;
},
showFilterDialog(field) {
this.lastFilterInput = this.filters[field] ?? '';
this.lastClickedFilter = field;
document.getElementById('filterInput').focus();
},
accountRole(roleName) {
return i18next.t('firefly.account_role_' + roleName);
},
@@ -159,7 +184,7 @@ let index = function () {
},
sort(column) {
this.page =1;
this.page = 1;
this.pageOptions.sortingColumn = column;
this.pageOptions.sortDirection = this.pageOptions.sortDirection === 'asc' ? 'desc' : 'asc';
@@ -179,7 +204,7 @@ let index = function () {
},
generatePageUrl(includePageNr) {
let url = './accounts/' + type + '?column=' + this.pageOptions.sortingColumn + '&direction=' + this.pageOptions.sortDirection + '&page=';
if(includePageNr) {
if (includePageNr) {
return url + this.page
}
return url;
@@ -204,6 +229,15 @@ let index = function () {
},
init() {
// modal filter thing
const myModalEl = document.getElementById('filterModal')
myModalEl.addEventListener('shown.bs.modal', event => {
document.getElementById('filterInput').focus();
})
// some opts
this.pageOptions.isLoading = true;
this.notifications.wait.show = true;
this.page = page;
@@ -230,7 +264,7 @@ let index = function () {
this.pageOptions.sortDirection = '' === this.pageOptions.sortDirection ? res[2] : this.pageOptions.sortDirection;
// filters
for(let k in res[3]) {
for (let k in res[3]) {
if (res[3].hasOwnProperty(k) && this.filters.hasOwnProperty(k)) {
this.filters[k] = res[3][k];
}
@@ -241,13 +275,13 @@ let index = function () {
},
saveActiveFilter(e) {
this.page = 1;
if('both' === e.currentTarget.value) {
if ('both' === e.currentTarget.value) {
this.filters.active = null;
}
if('active' === e.currentTarget.value) {
if ('active' === e.currentTarget.value) {
this.filters.active = true;
}
if('inactive' === e.currentTarget.value) {
if ('inactive' === e.currentTarget.value) {
this.filters.active = false;
}
setVariable(this.getPreferenceKey('filters'), this.filters);
@@ -301,8 +335,8 @@ let index = function () {
// filter instructions
let filters = [];
for(let k in this.filters) {
if(this.filters.hasOwnProperty(k) && null !== this.filters[k]) {
for (let k in this.filters) {
if (this.filters.hasOwnProperty(k) && null !== this.filters[k]) {
filters.push({column: k, filter: this.filters[k]});
}
}
@@ -351,7 +385,12 @@ let index = function () {
native_currency_code: current.attributes.native_currency_code,
last_activity: null === current.attributes.last_activity ? '' : format(new Date(current.attributes.last_activity), i18next.t('config.month_and_day_fns')),
balance_difference: current.attributes.balance_difference,
native_balance_difference: current.attributes.native_balance_difference
native_balance_difference: current.attributes.native_balance_difference,
liability_type: current.attributes.liability_type,
liability_direction: current.attributes.liability_direction,
interest: current.attributes.interest,
interest_period: current.attributes.interest_period,
current_debt: current.attributes.current_debt,
};
this.accounts.push(account);
}

View File

@@ -2327,6 +2327,15 @@ return [
'no_tags' => '(no tags)',
'nothing_found' => '(nothing found)',
// page settings and wizard dialogs
'page_settings_header' => 'Page settings',
'visible_columns' => 'Visible columns',
'accounts_to_show' => 'Accounts to show',
'active_accounts_only' => 'Active accounts only',
'in_active_accounts_only' => 'Inactive accounts only',
'show_all_accounts' => 'Show all accounts',
// piggy banks:
'event_history' => 'Event history',
'add_money_to_piggy' => 'Add money to piggy bank ":name"',

View File

@@ -28,6 +28,7 @@ return [
// new user:
'bank_name' => 'Bank name',
'bank_balance' => 'Balance',
'current_balance' => 'Current balance',
'savings_balance' => 'Savings balance',
'credit_card_limit' => 'Credit card limit',
'automatch' => 'Match automatically',

View File

@@ -7,30 +7,30 @@
<div class="col-xl-4 col-lg-6 col-md-12 col-sm-12 col-xs-12">
<div class="card">
<div class="card-header">
<h3 class="card-title">Net worth</h3>
<h3 class="card-title">{{ __('firefly.net_worth') }}</h3>
</div>
<div class="card-body">
some chart
TODO
</div>
</div>
</div>
<div class="col-xl-4 col-lg-6 col-md-12 col-sm-12 col-xs-12">
<div class="card">
<div class="card-header">
<h3 class="card-title">In + out this period</h3>
<h3 class="card-title">{{ __('firefly.in_out_period') }}</h3>
</div>
<div class="card-body">
Same
TODO
</div>
</div>
</div>
<div class="col-xl-4 col-lg-6 col-md-12 col-sm-12 col-xs-12">
<div class="card">
<div class="card-header">
<h3 class="card-title">Something else</h3>
<h3 class="card-title">TODO</h3>
</div>
<div class="card-body">
Same
TODO
</div>
</div>
</div>
@@ -46,7 +46,7 @@
<div class="card-header">
<div class="row">
<div class="col">
<h3 class="card-title">Accounts (ungrouped)</h3>
<h3 class="card-title">{{ __('firefly.undefined_accounts') }}</h3>
</div>
<div class="col text-end">
</div>
@@ -55,13 +55,14 @@
<div class="card-body p-0">
<table class="table">
<thead>
<tr>
<tr x-show="hasFilters()">
<td x-show="tableColumns.drag_and_drop.visible && tableColumns.drag_and_drop.enabled">
&nbsp;
</td>
<td x-show="tableColumns.active.visible && tableColumns.active.enabled">&nbsp;</td>
<td x-show="tableColumns.name.visible && tableColumns.name.enabled">
<em>"Filtered"</em>
<em x-show="'' !== filters.name && null !== filters.name">"<span x-text="filters.name"></span>"</em>
<a href="#" @click.prevent="removeFilter('name')"><em class="text-danger fa fa-trash-can"></em></a>
</td>
<td x-show="tableColumns.type.visible && tableColumns.type.enabled">&nbsp;</td>
<td x-show="tableColumns.liability_type.visible && tableColumns.liability_type.enabled">
@@ -95,60 +96,69 @@
&nbsp;
</th>
<th x-show="tableColumns.active.visible && tableColumns.active.enabled">
<a href="#" x-on:click.prevent="sort('active')">Active?</a>
<a href="#" x-on:click.prevent="sort('active')">{{ __('list.active') }}</a>
<em x-show="pageOptions.sortingColumn === 'active' && pageOptions.sortDirection === 'asc'"
class="fa-solid fa-arrow-down-short-wide"></em>
<em x-show="pageOptions.sortingColumn === 'active' && pageOptions.sortDirection === 'desc'"
class="fa-solid fa-arrow-down-wide-short"></em>
</th>
<th x-show="tableColumns.name.visible && tableColumns.name.enabled">
<a href="#" x-on:click.prevent="sort('name')">Name</a>
<a href="#" x-on:click.prevent="sort('name')">{{ __('list.name') }}</a>
<em x-show="pageOptions.sortingColumn === 'name' && pageOptions.sortDirection === 'asc'"
class="fa-solid fa-arrow-down-a-z"></em>
<em x-show="pageOptions.sortingColumn === 'name' && pageOptions.sortDirection === 'desc'"
class="fa-solid fa-arrow-down-z-a"></em>
<em x-show="pageOptions.sortingColumn === 'name' && pageOptions.sortDirection === 'desc'" class="fa-solid fa-arrow-down-z-a"></em>
<a @click.prevent="showFilterDialog('name')" href="#" data-bs-toggle="modal" data-bs-target="#filterModal"><em class="fa-solid fa-magnifying-glass"></em></a>
</th>
<th x-show="tableColumns.type.visible && tableColumns.type.enabled">Type</th>
<th x-show="tableColumns.type.visible && tableColumns.type.enabled">{{ __('list.type') }}</th>
<th x-show="tableColumns.liability_type.visible && tableColumns.liability_type.enabled">
Liability type
{{ __('list.liability_type') }}
</th>
<th x-show="tableColumns.liability_direction.visible && tableColumns.liability_direction.enabled">
Liability direction
{{ __('list.liability_direction') }}
</th>
<th x-show="tableColumns.liability_interest.visible && tableColumns.liability_interest.enabled">
Liability interest
{{ __('list.interest') }}
</th>
<th x-show="tableColumns.number.visible && tableColumns.number.enabled">
<a href="#" x-on:click.prevent="sort('iban')">Account number</a>
<a href="#" x-on:click.prevent="sort('iban')">
{{ __('list.account_number') }}
</a>
<em x-show="pageOptions.sortingColumn === 'iban' && pageOptions.sortDirection === 'asc'"
class="fa-solid fa-arrow-down-a-z"></em>
<em x-show="pageOptions.sortingColumn === 'iban' && pageOptions.sortDirection === 'desc'"
class="fa-solid fa-arrow-down-z-a"></em>
</th>
<th x-show="tableColumns.current_balance.visible && tableColumns.current_balance.enabled">
<a href="#" x-on:click.prevent="sort('balance')">Current balance</a>
<a href="#" x-on:click.prevent="sort('balance')">
{{ __('list.current_balance') }}
</a>
<em x-show="pageOptions.sortingColumn === 'balance' && pageOptions.sortDirection === 'asc'"
class="fa-solid fa-arrow-down-9-1"></em>
<em x-show="pageOptions.sortingColumn === 'balance' && pageOptions.sortDirection === 'desc'"
class="fa-solid fa-arrow-down-1-9"></em>
</th>
<th x-show="tableColumns.amount_due.visible && tableColumns.amount_due.enabled">
<a href="#" x-on:click.prevent="sort('amount_due')">Amount due</a>
<em x-show="pageOptions.sortingColumn === 'amount_due' && pageOptions.sortDirection === 'asc'"
<a href="#" x-on:click.prevent="sort('current_debt')">
{{ __('list.amount_due') }}
</a>
<em x-show="pageOptions.sortingColumn === 'current_debt' && pageOptions.sortDirection === 'asc'"
class="fa-solid fa-arrow-down-wide-short"></em>
<em x-show="pageOptions.sortingColumn === 'amount_due' && pageOptions.sortDirection === 'desc'"
<em x-show="pageOptions.sortingColumn === 'current_debt' && pageOptions.sortDirection === 'desc'"
class="fa-solid fa-arrow-up-wide-short"></em>
</th>
<th x-show="tableColumns.last_activity.visible && tableColumns.last_activity.enabled">
<a href="#" x-on:click.prevent="sort('last_activity')">Last activity</a>
<a href="#" x-on:click.prevent="sort('last_activity')">
{{ __('list.last_activity') }}
</a>
<em x-show="pageOptions.sortingColumn === 'last_activity' && pageOptions.sortDirection === 'asc'"
class="fa-solid fa-arrow-down-wide-short"></em>
<em x-show="pageOptions.sortingColumn === 'last_activity' && pageOptions.sortDirection === 'desc'"
class="fa-solid fa-arrow-up-wide-short"></em>
</th>
<th x-show="tableColumns.balance_difference.visible && tableColumns.balance_difference.enabled">
<a href="#" x-on:click.prevent="sort('balance_difference')">Balance
difference</a>
<a href="#" x-on:click.prevent="sort('balance_difference')">
{{ __('list.balance_difference') }}</a>
<em x-show="pageOptions.sortingColumn === 'balance_difference' && pageOptions.sortDirection === 'asc'"
class="fa-solid fa-arrow-down-wide-short"></em>
<em x-show="pageOptions.sortingColumn === 'balance_difference' && pageOptions.sortDirection === 'desc'"
@@ -220,9 +230,16 @@
<span x-text="accountRole(account.role)"></span>"
</template>
</td>
<td x-show="tableColumns.liability_type.visible && tableColumns.liability_type.enabled"></td>
<td x-show="tableColumns.liability_direction.visible && tableColumns.liability_direction.enabled"></td>
<td x-show="tableColumns.liability_interest.visible && tableColumns.liability_interest.enabled"></td>
<td x-show="tableColumns.liability_type.visible && tableColumns.liability_type.enabled">
<span x-text="$t('firefly.account_type_' + account.liability_type)"></span>
</td>
<td x-show="tableColumns.liability_direction.visible && tableColumns.liability_direction.enabled">
<span x-text="$t('firefly.liability_direction_' + account.liability_direction + '_short')"></span>
</td>
<td x-show="tableColumns.liability_interest.visible && tableColumns.liability_interest.enabled">
<span x-text="account.interest"></span>%
(<span x-text="$t('firefly.interest_calc_' + account.interest_period)"></span>)
</td>
<td x-show="tableColumns.number.visible && tableColumns.number.enabled">
<!-- IBAN and no account nr -->
<template x-if="'' === account.account_number && '' !== account.iban">
@@ -245,7 +262,10 @@
x-text="formatMoney(account.native_current_balance, account.currency_code)"></span>
</td>
<td x-show="tableColumns.amount_due.visible && tableColumns.amount_due.enabled">
TODO
<template x-if="null !== account.current_debt">
<span
x-text="formatMoney(account.current_debt, account.currency_code)"></span>
</template>
</td>
<td x-show="tableColumns.last_activity.visible && tableColumns.last_activity.enabled">
<span x-text="account.last_activity"></span>
@@ -304,12 +324,12 @@
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="internalsModalLabel">TODO Page settings</h1>
<h1 class="modal-title fs-5" id="internalsModalLabel">{{ __('firefly.page_settings_header') }}</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="row mb-3">
<label for="inputEmail3" class="col-sm-4 col-form-label">Visible columns</label>
<label class="col-sm-4 col-form-label">{{ __('firefly.visible_columns') }}</label>
<div class="col-sm-8">
<template x-for="(column, key) in tableColumns" :key="key">
<div class="form-check form-switch form-check-inline" x-show="column.visible">
@@ -323,19 +343,19 @@
</div>
</div>
<div class="row mb-3">
<label for="inputEmail3" class="col-sm-4 col-form-label">Active accounts?</label>
<label class="col-sm-4 col-form-label">{{ __('firefly.accounts_to_show') }}</label>
<div class="col-sm-8">
<select @change="saveActiveFilter" class="form-control">
<option value="active" :selected="true === filters.active" label="Active accounts">Active accounts only</option>
<option value="inactive" :selected="false === filters.active" label="Inactive accounts">Inactive accounts only
<option value="active" :selected="true === filters.active" label="{{ __('firefly.active_accounts_only') }}">{{ __('firefly.active_accounts_only') }}</option>
<option value="inactive" :selected="false === filters.active" label="{{ __('firefly.inactive_accounts_only') }}">{{ __('firefly.inactive_accounts_only') }}
</option>
<option value="both" :selected="null === filters.active" label="Both">All accounts</option>
<option value="both" :selected="null === filters.active" label="{{ __('firefly.show_all_accounts') }}">{{ __('firefly.show_all_accounts') }}</option>
</select>
<div id="emailHelp" class="form-text">TODO Bla bla bla.</div>
</div>
</div>
<!--
<div class="row mb-3">
<label for="inputEmail3" class="col-sm-4 col-form-label">Group accounts</label>
<label class="col-sm-4 col-form-label">Group accounts</label>
<div class="col-sm-8">
<div class="form-check form-switch">
<label>
@@ -345,6 +365,8 @@
</div>
</div>
</div>
-->
<!--
<div class="row mb-3">
<label for="inputEmail3" class="col-sm-4 col-form-label">Show info boxes</label>
<div class="col-sm-8">
@@ -365,9 +387,10 @@
</div>
</div>
</div>
-->
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">{{ __('firefly.close') }}</button>
</div>
</div>
</div>
@@ -375,6 +398,32 @@
</div>
</div>
<div class="modal fade" id="filterModal" tabindex="-1" aria-labelledby="filterModalLabel" aria-hidden="true">
<div class="modal-dialog modal-sm">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="filterModalLabel">TODO Filter field</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="mb-3">
<label for="filterInput" class="form-label">Search in column: <span x-text="lastClickedFilter"></span></label>
<input @keyup.enter="applyFilter()" type="text" class="form-control" id="filterInput" placeholder="" x-model="lastFilterInput">
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal"><em
class="fa-solid fa-right-from-bracket"></em> Cancel
</button>
<button @click="applyFilter()" type="button" class="btn btn-primary" data-bs-dismiss="modal"><em
class="fa-solid fa-magnifying-glass"></em> Search
</button>
</div>
</div>
</div>
</div>
<div class="modal fade" id="wizardModal" tabindex="-1" aria-labelledby="wizardModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
@@ -383,6 +432,7 @@
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
Quick intro about this page<br><br>
Need to learn what's on this page?<br>
Take me to the help pages (opens in a new window or tab)
</div>