support scheduled transaction (#2)

This commit is contained in:
MaysWind
2024-08-26 01:52:52 +08:00
parent 17d4fec256
commit d2eaf5c6da
42 changed files with 1437 additions and 112 deletions
+1
View File
@@ -8,6 +8,7 @@
<f7-list-item :title="$t('Transaction Categories')" link="/category/all"></f7-list-item>
<f7-list-item :title="$t('Transaction Tags')" link="/tag/list"></f7-list-item>
<f7-list-item :title="$t('Transaction Templates')" link="/template/list"></f7-list-item>
<f7-list-item :title="$t('Scheduled Transactions')" link="/schedule/list"></f7-list-item>
<f7-list-item :title="$t('Data Management')" link="/user/data/management"></f7-list-item>
<f7-list-item :title="$t('Two-Factor Authentication')" link="/user/2fa"></f7-list-item>
<f7-list-item :title="$t('Device & Sessions')" link="/user/sessions"></f7-list-item>
+17 -4
View File
@@ -2,7 +2,7 @@
<f7-page :ptr="!sortable" @ptr:refresh="reload" @page:afterin="onPageAfterIn">
<f7-navbar>
<f7-nav-left :back-link="$t('Back')"></f7-nav-left>
<f7-nav-title :title="$t('Transaction Templates')"></f7-nav-title>
<f7-nav-title :title="templateType === allTemplateTypes.Schedule ? $t('Scheduled Transactions') : $t('Transaction Templates')"></f7-nav-title>
<f7-nav-right class="navbar-compact-icons">
<f7-link icon-f7="ellipsis" :class="{ 'disabled': !templates.length }" v-if="!sortable" @click="showMoreActionSheet = true"></f7-link>
<f7-link :href="'/template/add?templateType=' + templateType" icon-f7="plus" v-if="!sortable"></f7-link>
@@ -21,7 +21,10 @@
<f7-list strong inset dividers class="margin-top" v-if="!loading && noAvailableTemplate">
<f7-list-item :title="$t('No available template')"
:footer="$t('Once you add templates, you can long press the Add button on the home page to quickly add a new transaction')"></f7-list-item>
:footer="$t('Once you add templates, you can long press the Add button on the home page to quickly add a new transaction')"
v-if="templateType === allTemplateTypes.Normal"></f7-list-item>
<f7-list-item :title="$t('No available scheduled transactions')" v-if="templateType === allTemplateTypes.Schedule"></f7-list-item>
<f7-list-item :title="$t('No available template')" v-else></f7-list-item>
</f7-list>
<f7-list strong inset dividers sortable class="margin-top template-list"
@@ -37,7 +40,7 @@
v-show="showHidden || !template.hidden"
@taphold="setSortable()">
<template #media>
<f7-icon f7="doc_plaintext">
<f7-icon :f7="templateType === allTemplateTypes.Schedule ? 'clock' : 'doc_plaintext'">
<f7-badge color="gray" class="right-bottom-icon" v-if="template.hidden">
<f7-icon f7="eye_slash_fill"></f7-icon>
</f7-badge>
@@ -91,6 +94,7 @@ import { onSwipeoutDeleted } from '@/lib/ui.mobile.js';
export default {
props: [
'f7route',
'f7router'
],
data() {
@@ -138,11 +142,20 @@ export default {
}
return true;
},
allTemplateTypes() {
return templateConstants.allTemplateTypes;
}
},
created() {
const self = this;
if (self.f7route.path === '/template/list') {
self.templateType = templateConstants.allTemplateTypes.Normal;
} else if (self.f7route.path === '/schedule/list') {
self.templateType = templateConstants.allTemplateTypes.Schedule;
}
self.loading = true;
self.transactionTemplatesStore.loadAllTemplates({
@@ -263,7 +276,7 @@ export default {
});
},
edit(template) {
this.f7router.navigate('/template/edit?id=' + template.id);
this.f7router.navigate(`/template/edit?id=${template.id}&templateType=${template.templateType}`);
},
hide(template, hidden) {
const self = this;
+78 -3
View File
@@ -37,7 +37,8 @@
<f7-list-item class="list-item-with-header-and-title list-item-title-hide-overflow" header="Category" title="Category Names"></f7-list-item>
<f7-list-item class="list-item-with-header-and-title" header="Account" title="Account Name"></f7-list-item>
<f7-list-item class="list-item-with-header-and-title" header="Transaction Time" title="YYYY/MM/DD HH:mm:ss" v-if="type === 'transaction'"></f7-list-item>
<f7-list-item class="list-item-with-header-and-title list-item-title-hide-overflow list-item-no-item-after" header="Transaction Timezone" title="(UTC XX:XX) System Default" link="#" :no-chevron="mode === 'view'" v-if="type === 'transaction'"></f7-list-item>
<f7-list-item class="list-item-with-header-and-title" header="Scheduled Transaction Frequency" title="Every XXXXX" v-if="type === 'template' && transaction.templateType === allTemplateTypes.Schedule"></f7-list-item>
<f7-list-item class="list-item-with-header-and-title list-item-title-hide-overflow list-item-no-item-after" header="Transaction Timezone" title="(UTC XX:XX) System Default" link="#" :no-chevron="mode === 'view'" v-if="type === 'transaction' || (type === 'template' && transaction.templateType === allTemplateTypes.Schedule)"></f7-list-item>
<f7-list-item class="list-item-with-header-and-title list-item-title-hide-overflow" header="Geographic Location" title="No Location" v-if="type === 'transaction'"></f7-list-item>
<f7-list-item header="Tags">
<template #footer>
@@ -242,13 +243,28 @@
</date-time-selection-sheet>
</f7-list-item>
<f7-list-item
class="list-item-with-header-and-title"
link="#" no-chevron
:class="{ 'readonly': mode === 'view' }"
:header="$t('Scheduled Transaction Frequency')"
:title="transactionDisplayScheduledFrequency"
@click="showTransactionScheduledFrequencySheet = true"
v-if="type === 'template' && transaction.templateType === allTemplateTypes.Schedule"
>
<schedule-frequency-sheet v-model:show="showTransactionScheduledFrequencySheet"
v-model:type="transaction.scheduledFrequencyType"
v-model="transaction.scheduledFrequency">
</schedule-frequency-sheet>
</f7-list-item>
<f7-list-item
:no-chevron="mode === 'view'"
class="list-item-with-header-and-title list-item-title-hide-overflow list-item-no-item-after"
:class="{ 'readonly': mode === 'view' }"
:header="$t('Transaction Timezone')"
smart-select :smart-select-params="{ openIn: 'popup', popupPush: true, closeOnSelect: true, scrollToSelectedItem: true, searchbar: true, searchbarPlaceholder: $t('Timezone'), searchbarDisableText: $t('Cancel'), appendSearchbarNotFound: $t('No results'), pageTitle: $t('Transaction Timezone'), popupCloseLinkText: $t('Done') }"
v-if="type === 'transaction'"
v-if="type === 'transaction' || (type === 'template' && transaction.templateType === allTemplateTypes.Schedule)"
>
<select v-model="transaction.timeZone">
<option :value="timezone.name" :key="timezone.name"
@@ -424,6 +440,7 @@ export default {
showSourceAccountSheet: false,
showDestinationAccountSheet: false,
showTransactionDateTimeSheet: false,
showTransactionScheduledFrequencySheet: false,
showGeoLocationMapSheet: false,
showTransactionTagSheet: false
};
@@ -439,12 +456,18 @@ export default {
} else {
return 'Transaction Detail';
}
} else if (this.type === 'template') {
} else if (this.type === 'template' && this.transaction.templateType === templateConstants.allTemplateTypes.Normal) {
if (this.mode === 'add') {
return 'Add Transaction Template';
} else if (this.mode === 'edit') {
return 'Edit Transaction Template';
}
} else if (this.type === 'template' && this.transaction.templateType === templateConstants.allTemplateTypes.Schedule) {
if (this.mode === 'add') {
return 'Add Scheduled Transaction';
} else if (this.mode === 'edit') {
return 'Edit Scheduled Transaction';
}
}
return '';
@@ -509,6 +532,9 @@ export default {
allCategoryTypes() {
return categoryConstants.allCategoryTypes;
},
allTemplateTypes() {
return templateConstants.allTemplateTypes;
},
allTimezones() {
return this.$locale.getAllTimezones(true);
},
@@ -581,6 +607,44 @@ export default {
return `${this.$locale.formatUnixTimeToLongDateTime(this.userStore, getActualUnixTimeForStore(this.transaction.time, this.transaction.utcOffset, getBrowserTimezoneOffsetMinutes()))} (UTC${getTimezoneOffset(this.settingsStore.appSettings.timeZone)})`;
},
transactionDisplayScheduledFrequency() {
if (this.type !== 'template') {
return '';
}
if (this.transaction.scheduledFrequencyType === templateConstants.allTemplateScheduledFrequencyTypes.Disabled.type) {
return this.$t('Disabled');
}
const items = this.transaction.scheduledFrequency.split(',');
const scheduledFrequencyValues = [];
for (let i = 0; i < items.length; i++) {
if (items[i]) {
scheduledFrequencyValues.push(parseInt(items[i]));
}
}
if (this.transaction.scheduledFrequencyType === templateConstants.allTemplateScheduledFrequencyTypes.Weekly.type) {
if (scheduledFrequencyValues.length) {
return this.$t('format.misc.everyMultiDaysOfWeek', {
days: this.$locale.getMultiWeekdayLongNames(scheduledFrequencyValues)
});
} else {
return this.$t('Weekly');
}
} else if (this.transaction.scheduledFrequencyType === templateConstants.allTemplateScheduledFrequencyTypes.Monthly.type) {
if (scheduledFrequencyValues.length) {
return this.$t('format.misc.everyMultiDaysOfMonth', {
days: this.$locale.getMultiMonthdayShortNames(scheduledFrequencyValues)
});
} else {
return this.$t('Monthly');
}
} else {
return '';
}
},
transactionDisplayTimezone() {
return `UTC${getUtcOffsetByUtcOffsetMinutes(this.transaction.utcOffset)}`;
},
@@ -750,6 +814,11 @@ export default {
self.transaction.templateType = parseInt(query.templateType);
}
if (self.transaction.templateType === templateConstants.allTemplateTypes.Schedule) {
self.transaction.scheduledFrequencyType = templateConstants.allTemplateScheduledFrequencyTypes.Disabled.type;
self.transaction.scheduledFrequency = '';
}
if (query.id) {
if (self.mode === 'edit') {
self.editId = query.id;
@@ -820,6 +889,12 @@ export default {
self.transaction.id = template.id;
self.transaction.templateType = template.templateType;
self.transaction.name = template.name;
if (self.transaction.templateType === templateConstants.allTemplateTypes.Schedule) {
self.transaction.scheduledFrequencyType = template.scheduledFrequencyType;
self.transaction.scheduledFrequency = template.scheduledFrequency;
self.transaction.utcOffset = template.utcOffset;
}
}
self.loading = false;
@@ -8,6 +8,7 @@
<f7-list-item title="Transaction Categories" after="Count"></f7-list-item>
<f7-list-item title="Transaction Tags" after="Count"></f7-list-item>
<f7-list-item title="Transaction Templates" after="Count"></f7-list-item>
<f7-list-item title="Scheduled Transactions" after="Count"></f7-list-item>
</f7-list>
<f7-list strong inset dividers class="margin-vertical" v-else-if="!loading">
@@ -16,6 +17,7 @@
<f7-list-item :title="$t('Transaction Categories')" :after="displayDataStatistics.totalTransactionCategoryCount"></f7-list-item>
<f7-list-item :title="$t('Transaction Tags')" :after="displayDataStatistics.totalTransactionTagCount"></f7-list-item>
<f7-list-item :title="$t('Transaction Templates')" :after="displayDataStatistics.totalTransactionTemplateCount"></f7-list-item>
<f7-list-item :title="$t('Scheduled Transactions')" :after="displayDataStatistics.totalScheduledTransactionCount"></f7-list-item>
</f7-list>
<f7-list strong inset dividers class="margin-vertical" :class="{ 'disabled': loading }">
@@ -109,7 +111,8 @@ export default {
totalAccountCount: self.$locale.appendDigitGroupingSymbol(self.userStore, self.dataStatistics.totalAccountCount),
totalTransactionCategoryCount: self.$locale.appendDigitGroupingSymbol(self.userStore, self.dataStatistics.totalTransactionCategoryCount),
totalTransactionTagCount: self.$locale.appendDigitGroupingSymbol(self.userStore, self.dataStatistics.totalTransactionTagCount),
totalTransactionTemplateCount: self.$locale.appendDigitGroupingSymbol(self.userStore, self.dataStatistics.totalTransactionTemplateCount)
totalTransactionTemplateCount: self.$locale.appendDigitGroupingSymbol(self.userStore, self.dataStatistics.totalTransactionTemplateCount),
totalScheduledTransactionCount: self.$locale.appendDigitGroupingSymbol(self.userStore, self.dataStatistics.totalScheduledTransactionCount)
};
},
isDataExportingEnabled() {