Add index options

This commit is contained in:
James Cole 2024-04-21 17:09:15 +02:00
parent 1a1e06e6e8
commit cdc0b8dd2c
No known key found for this signature in database
GPG Key ID: B49A324B7EAD6D80
4 changed files with 158 additions and 44 deletions
resources
assets/v2
views/v2/accounts

View File

@ -32,6 +32,8 @@ import Put from "../../api/v2/model/account/put.js";
import AccountRenderer from "../../support/renderers/AccountRenderer.js"; import AccountRenderer from "../../support/renderers/AccountRenderer.js";
import {showInternalsButton} from "../../support/page-settings/show-internals-button.js"; import {showInternalsButton} from "../../support/page-settings/show-internals-button.js";
import {showWizardButton} from "../../support/page-settings/show-wizard-button.js"; import {showWizardButton} from "../../support/page-settings/show-wizard-button.js";
import {getVariable} from "../../store/get-variable.js";
import {setVariable} from "../../store/set-variable.js";
// set type from URL // set type from URL
@ -50,7 +52,6 @@ sortingColumn = params.column ?? '';
sortDirection = params.direction ?? ''; sortDirection = params.direction ?? '';
showInternalsButton(); showInternalsButton();
showWizardButton(); showWizardButton();
@ -66,10 +67,64 @@ let index = function () {
show: false, text: '', show: false, text: '',
} }
}, totalPages: 1, page: 1, // available columns: },
totalPages: 1,
page: 1,
// available columns:
// visible is hard coded, enabled is user-configurable.
tableColumns: { tableColumns: {
drag_and_drop: {
visible: true,
enabled: true,
},
active: {
visible: true,
enabled: true,
},
name: { name: {
enabled: true visible: true,
enabled: true,
},
type: {
visible: true,
enabled: true,
},
liability_type: {
visible: type === 'liabilities',
enabled: true,
},
liability_direction: {
visible: type === 'liabilities',
enabled: true,
},
liability_interest: {
visible: type === 'liabilities',
enabled: true,
},
number: {
visible: true,
enabled: true,
},
current_balance: {
visible: type !== 'liabilities',
enabled: true,
},
amount_due: {
visible: type === 'liabilities',
enabled: true,
},
last_activity: {
visible: true,
enabled: true,
},
balance_difference: {
visible: true,
enabled: true,
},
menu: {
visible: true,
enabled: true,
}, },
}, },
editors: {}, editors: {},
@ -99,11 +154,34 @@ let index = function () {
format(date) { format(date) {
return format(date, i18next.t('config.date_time_fns')); return format(date, i18next.t('config.date_time_fns'));
}, },
saveColumnSettings() {
let newSettings = {};
for (let key in this.tableColumns) {
if (this.tableColumns.hasOwnProperty(key)) {
newSettings[key] = this.tableColumns[key].enabled;
}
}
console.log('New settings', newSettings);
setVariable('accts_columns_' + type, newSettings);
},
init() { init() {
this.notifications.wait.show = true; this.notifications.wait.show = true;
this.notifications.wait.text = i18next.t('firefly.wait_loading_data') this.notifications.wait.text = i18next.t('firefly.wait_loading_data')
this.loadAccounts();
const key = 'accts_columns_' + type;
const defaultValue = {"drag_and_drop": false};
getVariable(key, defaultValue).then((response) => {
for (let k in response) {
if (response.hasOwnProperty(k) && this.tableColumns.hasOwnProperty(k)) {
this.tableColumns[k].enabled = response[k] ?? true;
}
}
}).then(() => {
this.loadAccounts();
});
}, },
renderObjectValue(field, account) { renderObjectValue(field, account) {
let renderer = new AccountRenderer(); let renderer = new AccountRenderer();
@ -148,18 +226,32 @@ let index = function () {
}, },
loadAccounts() { loadAccounts() {
// sort instructions
const sorting = [{column: this.sortingColumn, direction: this.sortDirection}];
// get start and end from the store: // get start and end from the store:
const start = new Date(window.store.get('start')); const start = new Date(window.store.get('start'));
const end = new Date(window.store.get('end')); const end = new Date(window.store.get('end'));
let params = {
sorting: sorting,
type: type,
page: this.page,
start: start,
end: end
};
if(!this.tableColumns.balance_difference.enabled){
delete params.start;
delete params.end;
}
this.notifications.wait.show = true; this.notifications.wait.show = true;
this.notifications.wait.text = i18next.t('firefly.wait_loading_data') this.notifications.wait.text = i18next.t('firefly.wait_loading_data')
this.accounts = []; this.accounts = [];
// sort instructions
// &sorting[0][column]=description&sorting[0][direction]=asc
const sorting = [{column: this.sortingColumn, direction: this.sortDirection}];
// one page only.o // one page only.o
(new Get()).index({sorting: sorting, type: type, page: this.page, start: start, end: end}).then(response => { (new Get()).index(params).then(response => {
for (let i = 0; i < response.data.data.length; i++) { for (let i = 0; i < response.data.data.length; i++) {
if (response.data.data.hasOwnProperty(i)) { if (response.data.data.hasOwnProperty(i)) {
let current = response.data.data[i]; let current = response.data.data[i];

View File

@ -22,31 +22,27 @@ import Get from "../api/v1/preferences/index.js";
import Post from "../api/v1/preferences/post.js"; import Post from "../api/v1/preferences/post.js";
export function getVariable(name, defaultValue = null) { export function getVariable(name, defaultValue = null) {
const validCache = window.store.get('cacheValid'); const validCache = window.store.get('cacheValid');
// currently unused, window.X can be used by the blade template // currently unused, window.X can be used by the blade template
// to make things available quicker than if the store has to grab it through the API. // to make things available quicker than if the store has to grab it through the API.
// then again, it's not that slow. // then again, it's not that slow.
if (validCache && window.hasOwnProperty(name)) { if (validCache && window.hasOwnProperty(name)) {
// console.log('Get from window');
return Promise.resolve(window[name]); return Promise.resolve(window[name]);
} }
// load from store2, if it's present. // load from store2, if it's present.
const fromStore = window.store.get(name); const fromStore = window.store.get(name);
if (validCache && typeof fromStore !== 'undefined') { if (validCache && typeof fromStore !== 'undefined') {
// console.log('Get "' + name + '" from store');
return Promise.resolve(fromStore); return Promise.resolve(fromStore);
} }
let getter = (new Get); let getter = (new Get);
return getter.getByName(name).then((response) => { return getter.getByName(name).then((response) => {
// console.log('Get "' + name + '" from API');
return Promise.resolve(parseResponse(name, response)); return Promise.resolve(parseResponse(name, response));
}).catch(() => { }).catch((error) => {
// preference does not exist (yet). // preference does not exist (yet).
// POST it and then return it anyway. // POST it and then return it anyway.
let poster = (new Post); let poster = (new Post);
poster.post(name, defaultValue).then((response) => { return poster.post(name, defaultValue).then((response) => {
return Promise.resolve(parseResponse(name, response)); return Promise.resolve(parseResponse(name, response));
}); });
}); });
@ -55,7 +51,6 @@ export function getVariable(name, defaultValue = null) {
export function parseResponse(name, response) { export function parseResponse(name, response) {
let value = response.data.data.attributes.data; let value = response.data.data.attributes.data;
window.store.set(name, value); window.store.set(name, value);
// console.log('Store "' + name + '" in localStorage');
return value; return value;
} }

View File

@ -73,6 +73,9 @@ export default defineConfig({
server: { server: {
usePolling: true, usePolling: true,
watch: {
usePolling: true,
},
host: '10.0.0.15', host: '10.0.0.15',
// hmr: { // hmr: {
// protocol: 'wss', // protocol: 'wss',

View File

@ -56,58 +56,56 @@
<table class="table"> <table class="table">
<thead> <thead>
<tr> <tr>
<td>&nbsp;</td> <td x-show="tableColumns.drag_and_drop.visible && tableColumns.drag_and_drop.enabled">&nbsp;</td>
<td> <td x-show="tableColumns.active.visible">
<a href="#" x-on:click.prevent="sort('active')">Active?</a> <a href="#" x-on:click.prevent="sort('active')">Active?</a>
<em x-show="sortingColumn === 'active' && sortDirection === 'asc'" class="fa-solid fa-arrow-down-wide-short"></em> <em x-show="sortingColumn === 'active' && sortDirection === 'asc'" class="fa-solid fa-arrow-down-wide-short"></em>
<em x-show="sortingColumn === 'active' && sortDirection === 'desc'" class="fa-solid fa-arrow-up-wide-short"></em> <em x-show="sortingColumn === 'active' && sortDirection === 'desc'" class="fa-solid fa-arrow-up-wide-short"></em>
</td> </td>
<td> <td 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')">Name</a>
<em x-show="sortingColumn === 'name' && sortDirection === 'asc'" class="fa-solid fa-arrow-down-z-a"></em> <em x-show="sortingColumn === 'name' && sortDirection === 'asc'" class="fa-solid fa-arrow-down-z-a"></em>
<em x-show="sortingColumn === 'name' && sortDirection === 'desc'" class="fa-solid fa-arrow-up-z-a"></em> <em x-show="sortingColumn === 'name' && sortDirection === 'desc'" class="fa-solid fa-arrow-up-z-a"></em>
</td> </td>
<td>Type</td> <td x-show="tableColumns.type.visible && tableColumns.type.enabled">Type</td>
<td> <td x-show="tableColumns.liability_type.visible && tableColumns.liability_type.enabled">Liability type</td>
<td x-show="tableColumns.liability_direction.visible && tableColumns.liability_direction.enabled">Liability direction</td>
<td x-show="tableColumns.liability_interest.visible && tableColumns.liability_interest.enabled">Liability interest</td>
<td 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')">Account number</a>
<em x-show="sortingColumn === 'iban' && sortDirection === 'asc'" class="fa-solid fa-arrow-down-z-a"></em> <em x-show="sortingColumn === 'iban' && sortDirection === 'asc'" class="fa-solid fa-arrow-down-z-a"></em>
<em x-show="sortingColumn === 'iban' && sortDirection === 'desc'" class="fa-solid fa-arrow-up-z-a"></em> <em x-show="sortingColumn === 'iban' && sortDirection === 'desc'" class="fa-solid fa-arrow-up-z-a"></em>
</td> </td>
<td> <td 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')">Current balance</a>
<em x-show="sortingColumn === 'balance' && sortDirection === 'asc'" class="fa-solid fa-arrow-down-wide-short"></em> <em x-show="sortingColumn === 'balance' && sortDirection === 'asc'" class="fa-solid fa-arrow-down-wide-short"></em>
<em x-show="sortingColumn === 'balance' && sortDirection === 'desc'" class="fa-solid fa-arrow-up-wide-short"></em> <em x-show="sortingColumn === 'balance' && sortDirection === 'desc'" class="fa-solid fa-arrow-up-wide-short"></em>
</td> </td>
<td> <td x-show="tableColumns.amount_due.visible && tableColumns.amount_due.enabled">
<a href="#" x-on:click.prevent="sort('amount_due')">Current balance</a>
<em x-show="sortingColumn === 'amount_due' && sortDirection === 'asc'" class="fa-solid fa-arrow-down-wide-short"></em>
<em x-show="sortingColumn === 'amount_due' && sortDirection === 'desc'" class="fa-solid fa-arrow-up-wide-short"></em>
</td>
<td 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')">Last activity</a>
<em x-show="sortingColumn === 'last_activity' && sortDirection === 'asc'" class="fa-solid fa-arrow-down-wide-short"></em> <em x-show="sortingColumn === 'last_activity' && sortDirection === 'asc'" class="fa-solid fa-arrow-down-wide-short"></em>
<em x-show="sortingColumn === 'last_activity' && sortDirection === 'desc'" class="fa-solid fa-arrow-up-wide-short"></em> <em x-show="sortingColumn === 'last_activity' && sortDirection === 'desc'" class="fa-solid fa-arrow-up-wide-short"></em>
</td> </td>
<td> <td 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')">Balance difference</a>
<em x-show="sortingColumn === 'balance_difference' && sortDirection === 'asc'" class="fa-solid fa-arrow-down-wide-short"></em> <em x-show="sortingColumn === 'balance_difference' && sortDirection === 'asc'" class="fa-solid fa-arrow-down-wide-short"></em>
<em x-show="sortingColumn === 'balance_difference' && sortDirection === 'desc'" class="fa-solid fa-arrow-up-wide-short"></em> <em x-show="sortingColumn === 'balance_difference' && sortDirection === 'desc'" class="fa-solid fa-arrow-up-wide-short"></em>
</td> </td>
<td x-show="tableColumns.menu.visible && tableColumns.menu.enabled">&nbsp;</td>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<template x-for="(account, index) in accounts" :key="index"> <template x-for="(account, index) in accounts" :key="index">
<tr> <tr>
<td> <td x-show="tableColumns.drag_and_drop.visible && tableColumns.drag_and_drop.enabled">
<!-- Example split danger button --> <em class="fa-solid fa-bars"></em>
<div class="btn-group btn-group-sm">
<a :href="'./accounts/edit/' + account.id" class="btn btn-sm btn-light"><em class="fa-solid fa-pencil"></em></a>
<button type="button" class="btn btn-light dropdown-toggle dropdown-toggle-split" data-bs-toggle="dropdown" aria-expanded="false">
<span class="visually-hidden">{{ __('firefly.toggle_dropdown') }}</span>
</button>
<ul class="dropdown-menu">
<li><a class="dropdown-item" :href="'./accounts/show/' + account.id"><em class="fa-solid fa-eye"></em> {{ __('firefly.show') }}</a></li>
<li><a class="dropdown-item" :href="'./accounts/reconcile/' + account.id"><em class="fa-solid fa-calculator"></em> {{ __('firefly.reconcile_selected') }}</a></li>
<li><a class="dropdown-item" :href="'./accounts/delete/' + account.id"><em class="fa-solid fa-trash"></em> {{ __('firefly.delete') }}</a></li>
</ul>
</div>
</td> </td>
<td> <td x-show="tableColumns.active.visible && tableColumns.active.enabled">
<template x-if="account.active"> <template x-if="account.active">
<em class="text-success fa-solid fa-check"></em> <em class="text-success fa-solid fa-check"></em>
&nbsp;</template> &nbsp;</template>
@ -115,7 +113,7 @@
<em class="text-danger fa-solid fa-xmark"></em> <em class="text-danger fa-solid fa-xmark"></em>
&nbsp;</template> &nbsp;</template>
</td> </td>
<td> <td x-show="tableColumns.name.visible && tableColumns.name.enabled">
<!-- render content using a function --> <!-- render content using a function -->
<span x-html="renderObjectValue('name', account)" x-show="!account.nameEditorVisible"></span> <span x-html="renderObjectValue('name', account)" x-show="!account.nameEditorVisible"></span>
@ -135,7 +133,7 @@
</div> </div>
</div> </div>
</td> </td>
<td> <td x-show="tableColumns.type.visible && tableColumns.type.enabled">
<template x-if="null === account.role || '' === account.role"> <template x-if="null === account.role || '' === account.role">
<span><em>{{ __('firefly.no_account_role') }}</em></span> <span><em>{{ __('firefly.no_account_role') }}</em></span>
</template> </template>
@ -143,7 +141,10 @@
<span x-text="accountRole(account.role)"></span>" <span x-text="accountRole(account.role)"></span>"
</template> </template>
</td> </td>
<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.number.visible && tableColumns.number.enabled">
<!-- IBAN and no account nr --> <!-- IBAN and no account nr -->
<template x-if="'' === account.account_number && '' !== account.iban"> <template x-if="'' === account.account_number && '' !== account.iban">
<span x-text="account.iban"></span> <span x-text="account.iban"></span>
@ -160,17 +161,33 @@
</span> </span>
</template> </template>
</td> </td>
<td> <td x-show="tableColumns.current_balance.visible && tableColumns.current_balance.enabled">
<span x-text="formatMoney(account.current_balance, account.currency_code)"></span> <span x-text="formatMoney(account.current_balance, account.currency_code)"></span>
</td> </td>
<td> <td x-show="tableColumns.amount_due.visible && tableColumns.amount_due.enabled">
TODO
</td>
<td x-show="tableColumns.last_activity.visible && tableColumns.last_activity.enabled">
<span x-text="account.last_activity"></span> <span x-text="account.last_activity"></span>
</td> </td>
<td> <td x-show="tableColumns.balance_difference.visible && tableColumns.balance_difference.enabled">
<template x-if="null !== account.balance_difference"> <template x-if="null !== account.balance_difference">
<span x-text="formatMoney(account.balance_difference, account.currency_code)"></span> <span x-text="formatMoney(account.balance_difference, account.currency_code)"></span>
</template> </template>
</td> </td>
<td x-show="tableColumns.menu.visible && tableColumns.menu.enabled">
<div class="btn-group btn-group-sm">
<a :href="'./accounts/edit/' + account.id" class="btn btn-sm btn-light"><em class="fa-solid fa-pencil"></em></a>
<button type="button" class="btn btn-light dropdown-toggle dropdown-toggle-split" data-bs-toggle="dropdown" aria-expanded="false">
<span class="visually-hidden">{{ __('firefly.toggle_dropdown') }}</span>
</button>
<ul class="dropdown-menu">
<li><a class="dropdown-item" :href="'./accounts/show/' + account.id"><em class="fa-solid fa-eye"></em> {{ __('firefly.show') }}</a></li>
<li><a class="dropdown-item" :href="'./accounts/reconcile/' + account.id"><em class="fa-solid fa-calculator"></em> {{ __('firefly.reconcile_selected') }}</a></li>
<li><a class="dropdown-item" :href="'./accounts/delete/' + account.id"><em class="fa-solid fa-trash"></em> {{ __('firefly.delete') }}</a></li>
</ul>
</div>
</td>
</tr> </tr>
</template> </template>
</tbody> </tbody>
@ -196,6 +213,13 @@
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<h2>Visible columns</h2>
<template x-for="(column, key) in tableColumns" :key="key">
<div class="form-check" x-show="column.visible">
<input class="form-check-input" type="checkbox" x-model="column.enabled" @change="saveColumnSettings"> <span x-text="key"></span>
</div>
</template>
- Group accounts <br> - Group accounts <br>
- Columns to show<br> - Columns to show<br>
- Show / hide inactive accounts (dropdown: both, active inactive only)<br> - Show / hide inactive accounts (dropdown: both, active inactive only)<br>