Frontend updates

This commit is contained in:
James Cole
2022-05-02 18:54:43 +02:00
parent 8c64c1d5e4
commit 0babe84a33
11 changed files with 834 additions and 452 deletions

View File

@@ -11,12 +11,13 @@
}, },
"dependencies": { "dependencies": {
"@popperjs/core": "^2.11.2", "@popperjs/core": "^2.11.2",
"@quasar/extras": "^1.13.5", "@quasar/extras": "^1.13.6",
"apexcharts": "^3.32.1", "apexcharts": "^3.32.1",
"axios": "^0.21.1", "axios": "^0.21.1",
"axios-cache-adapter": "^2.7.3", "axios-cache-adapter": "^2.7.3",
"core-js": "^3.6.5", "core-js": "^3.6.5",
"date-fns": "^2.28.0", "date-fns": "^2.28.0",
"pinia": "^2.0.13",
"quasar": "^2.6.6", "quasar": "^2.6.6",
"vue": "3", "vue": "3",
"vue-i18n": "^9.0.0", "vue-i18n": "^9.0.0",

View File

@@ -25,47 +25,49 @@
import {defineComponent} from 'vue'; import {defineComponent} from 'vue';
import Preferences from "./api/preferences"; import Preferences from "./api/preferences";
import Currencies from "./api/currencies"; import Currencies from "./api/currencies";
import {setDatesFromViewRange} from "./store/fireflyiii/actions"; import {useFireflyIIIStore} from 'stores/fireflyiii'
export default defineComponent( export default defineComponent(
{ {
name: 'App', name: 'App',
preFetch({store}) { preFetch({store}) {
const ffStore = useFireflyIIIStore(store);
store.dispatch('fireflyiii/refreshCacheKey'); ffStore.refreshCacheKey();
const getViewRange = function() { const getViewRange = function () {
let pref = new Preferences(); let pref = new Preferences();
return pref.getByName('viewRange').then(data => { return pref.getByName('viewRange').then(data => {
const viewRange = data.data.data.attributes.data; const viewRange = data.data.data.attributes.data;
store.commit('fireflyiii/updateViewRange', viewRange); ffStore.updateViewRange(viewRange);
store.dispatch('fireflyiii/setDatesFromViewRange'); ffStore.setDatesFromViewRange();
}).catch((err) => { }).catch((err) => {
console.error('Could not load view range.') console.error('Could not load view range.')
console.log(err); console.log(err);
}); });
}; };
const getListPageSize = function() { const getListPageSize = function () {
let pref = new Preferences(); let pref = new Preferences();
return pref.getByName('listPageSize').then(data => { return pref.getByName('listPageSize').then(data => {
const listPageSize = data.data.data.attributes.data; const listPageSize = data.data.data.attributes.data;
store.commit('fireflyiii/updateListPageSize', listPageSize); ffStore.updateListPageSize(listPageSize);
}).catch((err) => { }).catch((err) => {
console.error('Could not load listPageSize.') console.error('Could not load listPageSize.')
console.log(err); console.log(err);
}); });
}; };
const getDefaultCurrency = function() { const getDefaultCurrency = function () {
let curr = new Currencies(); let curr = new Currencies();
return curr.default().then(data => { return curr.default().then(data => {
let currencyId = parseInt(data.data.data.id); let currencyId = parseInt(data.data.data.id);
let currencyCode = data.data.data.attributes.code; let currencyCode = data.data.data.attributes.code;
store.commit('fireflyiii/setCurrencyId', currencyId); ffStore.setCurrencyId(currencyId);
store.commit('fireflyiii/setCurrencyCode', currencyCode); ffStore.setCurrencyCode(currencyCode);
}).catch((err) => { }).catch((err) => {
console.error('Could not load preferences.'); console.error('Could not load preferences.');
console.log(err); console.log(err);

View File

@@ -22,7 +22,7 @@
<q-page> <q-page>
<div class="q-ma-md" v-if="0 === assetCount"> <div class="q-ma-md" v-if="0 === assetCount">
<NewUser <NewUser
v-on:created-accounts="refreshThenCount" v-on:created-accounts="refreshThenCount"
></NewUser> ></NewUser>
</div> </div>
<div class="q-ma-md" v-if="assetCount > 0"> <div class="q-ma-md" v-if="assetCount > 0">
@@ -114,7 +114,8 @@
<script> <script>
import {defineAsyncComponent, defineComponent} from "vue"; import {defineAsyncComponent, defineComponent} from "vue";
import List from "../api/accounts/list"; import List from "../api/accounts/list";
import {mapGetters} from "vuex"; //import {mapGetters} from "vuex";
import {useFireflyIIIStore} from '../stores/fireflyiii'
export default defineComponent( export default defineComponent(
{ {
@@ -130,19 +131,21 @@ export default defineComponent(
} }
}, },
computed: { computed: {
...mapGetters('fireflyiii', ['getCacheKey']), //...mapGetters('fireflyiii', ['getCacheKey']),
}, },
mounted() { mounted() {
this.countAssetAccounts(); this.countAssetAccounts();
}, },
methods: { methods: {
refreshThenCount: function() { refreshThenCount: function () {
this.$store.dispatch('fireflyiii/refreshCacheKey'); const store = useFireflyIIIStore();
store.refreshCacheKey();
//this.$store.dispatch('fireflyiii/refreshCacheKey');
this.countAssetAccounts(); this.countAssetAccounts();
}, },
countAssetAccounts: function () { countAssetAccounts: function () {
let list = new List; let list = new List;
list.list('asset',1, this.getCacheKey).then((response) => { list.list('asset', 1, this.getCacheKey).then((response) => {
this.assetCount = parseInt(response.data.meta.pagination.total); this.assetCount = parseInt(response.data.meta.pagination.total);
}); });
} }

View File

@@ -82,12 +82,13 @@
<script> <script>
import Basic from "src/api/summary/basic"; import Basic from "src/api/summary/basic";
import {mapGetters, useStore} from "vuex"; //import {mapGetters, useStore} from "vuex";
import {useFireflyIIIStore} from '../../stores/fireflyiii'
export default { export default {
name: 'Boxes', name: 'Boxes',
computed: { computed: {
...mapGetters('fireflyiii', ['getCurrencyCode', 'getCurrencyId', 'getRange','getCacheKey']), //...mapGetters('fireflyiii', ['getCurrencyCode', 'getCurrencyId', 'getRange','getCacheKey']),
prefBillsUnpaid: function () { prefBillsUnpaid: function () {
return this.filterOnCurrency(this.billsUnpaid); return this.filterOnCurrency(this.billsUnpaid);
}, },
@@ -119,36 +120,43 @@ export default {
range: { range: {
start: null, start: null,
end: null, end: null,
} },
store: null
} }
}, },
mounted() { mounted() {
this.store = useFireflyIIIStore();
if (null === this.range.start || null === this.range.end) { if (null === this.range.start || null === this.range.end) {
// subscribe, then update: // subscribe, then update:
const $store = useStore();
$store.subscribe((mutation) => { this.store.$onAction(
if ('fireflyiii/setRange' === mutation.type) { ({name, $store, args, after, onError,}) => {
this.range = mutation.payload; after((result) => {
this.triggerUpdate(); if (name === 'setRange') {
this.range = result;
this.triggerUpdate();
}
})
} }
}); )
} }
if (null !== this.getRange.start && null !== this.getRange.end) {
this.start = this.getRange.start; if (null !== this.store.getRange.start && null !== this.store.getRange.end) {
this.end = this.getRange.end; this.start = this.store.getRange.start;
this.end = this.store.getRange.end;
this.triggerUpdate(); this.triggerUpdate();
} }
}, },
methods: { methods: {
triggerForcedUpgrade: function() { triggerForcedUpgrade: function () {
this.$store.dispatch('fireflyiii/refreshCacheKey'); this.store.refreshCacheKey();
this.triggerUpdate(); this.triggerUpdate();
}, },
triggerUpdate: function () { triggerUpdate: function () {
if (null !== this.getRange.start && null !== this.getRange.end) { if (null !== this.store.getRange.start && null !== this.store.getRange.end) {
const basic = new Basic; const basic = new Basic;
basic.list({start: this.getRange.start, end: this.getRange.end}, this.getCacheKey).then(data => { basic.list({start: this.store.getRange.start, end: this.store.getRange.end}, this.store.getCacheKey).then(data => {
this.netWorth = this.getKeyedEntries(data.data, 'net-worth-in-'); this.netWorth = this.getKeyedEntries(data.data, 'net-worth-in-');
this.leftToSpend = this.getKeyedEntries(data.data, 'left-to-spend-in-'); this.leftToSpend = this.getKeyedEntries(data.data, 'left-to-spend-in-');
this.billsPaid = this.getKeyedEntries(data.data, 'bills-paid-in-'); this.billsPaid = this.getKeyedEntries(data.data, 'bills-paid-in-');
@@ -171,7 +179,7 @@ export default {
let ret = []; let ret = [];
for (const key in array) { for (const key in array) {
if (array.hasOwnProperty(key)) { if (array.hasOwnProperty(key)) {
if (array[key].currency_id === this.getCurrencyId) { if (array[key].currency_id === this.store.getCurrencyId) {
ret.push(array[key]); ret.push(array[key]);
} }
} }
@@ -186,7 +194,7 @@ export default {
let ret = []; let ret = [];
for (const key in array) { for (const key in array) {
if (array.hasOwnProperty(key)) { if (array.hasOwnProperty(key)) {
if (array[key].currency_id !== this.getCurrencyId) { if (array[key].currency_id !== this.store.getCurrencyId) {
ret.push(array[key]); ret.push(array[key]);
} }
} }
@@ -196,7 +204,3 @@ export default {
} }
} }
</script> </script>
<style scoped>
</style>

View File

@@ -28,14 +28,15 @@
import {defineAsyncComponent} from "vue"; import {defineAsyncComponent} from "vue";
import Overview from '../../api/chart/account/overview'; import Overview from '../../api/chart/account/overview';
import {mapGetters, useStore} from "vuex"; //import {mapGetters, useStore} from "vuex";
import format from "date-fns/format"; import format from "date-fns/format";
import {useQuasar} from "quasar"; import {useQuasar} from "quasar";
import {useFireflyIIIStore} from "../../stores/fireflyiii";
export default { export default {
name: "HomeChart", name: "HomeChart",
computed: { computed: {
...mapGetters('fireflyiii', ['getRange', 'getCacheKey']), //...mapGetters('fireflyiii', ['getRange', 'getCacheKey']),
}, },
data() { data() {
return { return {
@@ -79,6 +80,7 @@ export default {
series: [], series: [],
locale: 'en-US', locale: 'en-US',
dateFormat: 'MMMM d, y', dateFormat: 'MMMM d, y',
store: null,
} }
}, },
created() { created() {
@@ -89,17 +91,22 @@ export default {
mounted() { mounted() {
const $q = useQuasar(); const $q = useQuasar();
this.options.theme.mode = $q.dark.isActive ? 'dark' : 'light'; this.options.theme.mode = $q.dark.isActive ? 'dark' : 'light';
this.store = useFireflyIIIStore();
if (null === this.range.start || null === this.range.end) { if (null === this.range.start || null === this.range.end) {
// subscribe, then update: // subscribe, then update:
const $store = useStore();
$store.subscribe((mutation, state) => { this.store.$onAction(
if ('fireflyiii/setRange' === mutation.type) { ({name, $store, args, after, onError,}) => {
this.range = mutation.payload; after((result) => {
this.buildChart(); if (name === 'setRange') {
this.range = result;
this.buildChart();
}
})
} }
}); )
} }
if (null !== this.getRange.start && null !== this.getRange.end) { if (null !== this.store.getRange.start && null !== this.store.getRange.end) {
this.buildChart(); this.buildChart();
} }
}, },
@@ -109,9 +116,9 @@ export default {
return Intl.NumberFormat(this.locale, {style: 'currency', currency: currencyCode}).format(value); return Intl.NumberFormat(this.locale, {style: 'currency', currency: currencyCode}).format(value);
}, },
buildChart: function () { buildChart: function () {
if (null !== this.getRange.start && null !== this.getRange.end) { if (null !== this.store.getRange.start && null !== this.store.getRange.end) {
let start = this.getRange.start; let start = this.store.getRange.start;
let end = this.getRange.end; let end = this.store.getRange.end;
if (false === this.loading) { if (false === this.loading) {
this.loading = true; this.loading = true;
const overview = new Overview(); const overview = new Overview();

View File

@@ -33,7 +33,7 @@ import fireflyiii from './fireflyiii'
*/ */
export default store(function (/* { ssrContext } */) { export default store(function (/* { ssrContext } */) {
const Store = createStore({ return createStore({
modules: { modules: {
// example // example
fireflyiii fireflyiii
@@ -43,6 +43,4 @@ export default store(function (/* { ssrContext } */) {
// for dev mode and --debug builds only // for dev mode and --debug builds only
strict: process.env.DEBUGGING strict: process.env.DEBUGGING
}) })
return Store
}) })

189
frontend/src/stores/fireflyiii.js vendored Normal file
View File

@@ -0,0 +1,189 @@
import {defineStore} from 'pinia';
import {
endOfDay,
endOfMonth,
endOfQuarter,
endOfWeek,
startOfDay,
startOfMonth,
startOfQuarter,
startOfWeek,
startOfYear,
subDays
} from "date-fns";
export const useFireflyIIIStore = defineStore('counter', {
state: () => ({
drawerState: true, viewRange: '1M', listPageSize: 10, range: {
start: null, end: null
}, defaultRange: {
start: null, end: null
}, currencyCode: 'AAA', currencyId: '0', cacheKey: 'initial'
}),
getters: {
getViewRange(state) {
return state.viewRange;
},
getListPageSize(state) {
return state.listPageSize;
},
getCurrencyCode(state) {
return state.currencyCode;
}, getCurrencyId(state) {
return state.currencyId;
},
getRange(state) {
return state.range;
}, getDefaultRange(state) {
return state.defaultRange;
},
getCacheKey(state) {
return state.cacheKey;
}
},
actions: {
// actions
refreshCacheKey() {
let cacheKey = Math.random().toString(36).replace(/[^a-z]+/g, '').slice(0, 8);
this.setCacheKey(cacheKey);
},
resetRange() {
let defaultRange = this.defaultRange;
this.setRange(defaultRange);
},
setDatesFromViewRange() {
let start;
let end;
let viewRange = this.viewRange;
let today = new Date;
switch (viewRange) {
case 'last365':
start = startOfDay(subDays(today, 365));
end = endOfDay(today);
break;
case 'last90':
start = startOfDay(subDays(today, 90));
end = endOfDay(today);
break;
case 'last30':
start = startOfDay(subDays(today, 30));
end = endOfDay(today);
break;
case 'last7':
start = startOfDay(subDays(today, 7));
end = endOfDay(today);
break;
case 'YTD':
start = startOfYear(today);
end = endOfDay(today);
break;
case 'QTD':
start = startOfQuarter(today);
end = endOfDay(today);
break;
case 'MTD':
start = startOfMonth(today);
end = endOfDay(today);
break;
case '1D':
// today:
start = startOfDay(today);
end = endOfDay(today);
break;
case '1W':
// this week:
start = startOfDay(startOfWeek(today, {weekStartsOn: 1}));
end = endOfDay(endOfWeek(today, {weekStartsOn: 1}));
break;
case '1M':
// this month:
start = startOfDay(startOfMonth(today));
end = endOfDay(endOfMonth(today));
break;
case '3M':
// this quarter
start = startOfDay(startOfQuarter(today));
end = endOfDay(endOfQuarter(today));
break;
case '6M':
// this half-year
if (today.getMonth() <= 5) {
start = new Date(today);
start.setMonth(0);
start.setDate(1);
start = startOfDay(start);
end = new Date(today);
end.setMonth(5);
end.setDate(30);
end = endOfDay(start);
}
if (today.getMonth() > 5) {
start = new Date(today);
start.setMonth(6);
start.setDate(1);
start = startOfDay(start);
end = new Date(today);
end.setMonth(11);
end.setDate(31);
end = endOfDay(start);
}
break;
case '1Y':
// this year
start = new Date(today);
start.setMonth(0);
start.setDate(1);
start = startOfDay(start);
end = new Date(today);
end.setMonth(11);
end.setDate(31);
end = endOfDay(end);
break;
}
this.setRange({start: start, end: end});
this.setDefaultRange({start: start, end: end});
},
// mutators
increment() {
this.counter++
},
updateViewRange(viewRange) {
this.viewRange = viewRange;
},
updateListPageSize(value) {
this.listPageSize = value;
},
setRange(value) {
this.range = value;
return value;
},
setDefaultRange(value) {
this.defaultRange = value;
},
setCurrencyCode(value) {
this.currencyCode = value;
}, setCurrencyId(value) {
this.currencyId = value;
},
setCacheKey(value) {
this.cacheKey = value;
}
}
})

20
frontend/src/stores/index.js vendored Normal file
View File

@@ -0,0 +1,20 @@
import { store } from 'quasar/wrappers'
import { createPinia } from 'pinia'
/*
* If not building with SSR mode, you can
* directly export the Store instantiation;
*
* The function below can be async too; either use
* async/await or return a Promise which resolves
* with the Store instance.
*/
export default store((/* { ssrContext } */) => {
const pinia = createPinia()
// You can add Pinia plugins here
// pinia.use(SomePiniaPlugin)
return pinia
})

10
frontend/src/stores/store-flag.d.ts vendored Normal file
View File

@@ -0,0 +1,10 @@
/* eslint-disable */
// THIS FEATURE-FLAG FILE IS AUTOGENERATED,
// REMOVAL OR CHANGES WILL CAUSE RELATED TYPES TO STOP WORKING
import "quasar/dist/types/feature-flag";
declare module "quasar/dist/types/feature-flag" {
interface QuasarFeatureFlags {
store: true;
}
}

19
frontend/src/stores/teststore.js vendored Normal file
View File

@@ -0,0 +1,19 @@
import { defineStore } from 'pinia';
export const useCounterStore = defineStore('counter', {
state: () => ({
counter: 0
}),
getters: {
doubleCount (state) {
return state.counter * 2
}
},
actions: {
increment () {
this.counter++
}
}
})

File diff suppressed because it is too large Load Diff