automatically save transaction draft

This commit is contained in:
MaysWind
2024-09-22 14:41:35 +08:00
parent 49df497f35
commit 4c13b7ad02
16 changed files with 384 additions and 26 deletions
+10 -3
View File
@@ -2,7 +2,10 @@ import axios from 'axios';
import apiConstants from '@/consts/api.js';
import userState from './userstate.js';
import { isBoolean } from './common.js';
import {
isDefined,
isBoolean
} from './common.js';
import {
getGoogleMapAPIKey,
getBaiduMapAK,
@@ -395,8 +398,12 @@ export default {
return axios.get(`v1/transactions/amounts.json?use_transaction_timezone=${useTransactionTimezone}` + (queryParams.length ? '&query=' + queryParams.join('|') : ''));
},
getTransaction: ({ id }) => {
return axios.get(`v1/transactions/get.json?id=${id}&with_pictures=true&trim_account=true&trim_category=true&trim_tag=true`);
getTransaction: ({ id, withPictures }) => {
if (!isDefined(withPictures)) {
withPictures = true;
}
return axios.get(`v1/transactions/get.json?id=${id}&with_pictures=${withPictures}&trim_account=true&trim_category=true&trim_tag=true`);
},
addTransaction: ({ type, categoryId, time, sourceAccountId, destinationAccountId, sourceAmount, destinationAmount, hideAmount, tagIds, pictureIds, comment, geoLocation, utcOffset, clientSessionId }) => {
return axios.post('v1/transactions/add.json', {
+9
View File
@@ -11,6 +11,7 @@ const defaultSettings = {
applicationLock: false,
applicationLockWebAuthn: false,
autoUpdateExchangeRatesData: true,
autoSaveTransactionDraft: 'disabled',
autoGetCurrentGeoLocation: false,
showAmountInHomePage: true,
timezoneUsedForStatisticsInHomePage: timezoneConstants.defaultTimezoneTypesUsedForStatistics,
@@ -157,6 +158,14 @@ export function setAutoUpdateExchangeRatesData(value) {
setOption('autoUpdateExchangeRatesData', value);
}
export function getAutoSaveTransactionDraft() {
return getOption('autoSaveTransactionDraft');
}
export function setAutoSaveTransactionDraft(value) {
setOption('autoSaveTransactionDraft', value);
}
export function isAutoGetCurrentGeoLocation() {
return getOption('autoGetCurrentGeoLocation');
}
+1 -4
View File
@@ -165,10 +165,7 @@ export function setTransactionModelByTransaction(transaction, transaction2, allC
transaction.hideAmount = transaction2.hideAmount;
transaction.tagIds = transaction2.tagIds || [];
if (setContextData) {
transaction.pictures = transaction2.pictures || [];
}
transaction.pictures = transaction2.pictures || [];
transaction.comment = transaction2.comment;
+39
View File
@@ -9,6 +9,7 @@ const appLockSecretBaseStringPrefix = 'EBK_LOCK_SECRET_';
const tokenLocalStorageKey = 'ebk_user_token';
const webauthnConfigLocalStorageKey = 'ebk_user_webauthn_config';
const userInfoLocalStorageKey = 'ebk_user_info';
const transactionDraftLocalStorageKey = 'ebk_user_draft_transaction';
const tokenSessionStorageKey = 'ebk_user_session_token';
const encryptedTokenSessionStorageKey = 'ebk_user_session_encrypted_token';
@@ -59,6 +60,21 @@ function getUserInfo() {
return JSON.parse(data);
}
function getUserTransactionDraft() {
let data = localStorage.getItem(transactionDraftLocalStorageKey);
if (!data) {
return null;
}
if (isEnableApplicationLock()) {
const appLockState = getUserAppLockState();
data = getDecryptedToken(data, appLockState);
}
return JSON.parse(data);
}
function getUserAppLockState() {
const data = sessionStorage.getItem(appLockStateSessionStorageKey);
return JSON.parse(data);
@@ -183,10 +199,29 @@ function updateUserInfo(user) {
}
}
function updateUserTransactionDraft(transaction) {
if (!isObject(transaction)) {
return;
}
let data = JSON.stringify(transaction);
if (isEnableApplicationLock()) {
const appLockState = getUserAppLockState();
data = getEncryptedToken(data, appLockState);
}
localStorage.setItem(transactionDraftLocalStorageKey, data);
}
function clearUserInfo() {
localStorage.removeItem(userInfoLocalStorageKey);
}
function clearUserTransactionDraft() {
localStorage.removeItem(transactionDraftLocalStorageKey);
}
function clearSessionToken() {
sessionStorage.removeItem(tokenSessionStorageKey);
sessionStorage.removeItem(encryptedTokenSessionStorageKey);
@@ -201,12 +236,14 @@ function clearTokenAndUserInfo(clearAppLockState) {
sessionStorage.removeItem(tokenSessionStorageKey);
sessionStorage.removeItem(encryptedTokenSessionStorageKey);
localStorage.removeItem(tokenLocalStorageKey);
clearUserTransactionDraft();
clearUserInfo();
}
export default {
getToken,
getUserInfo,
getUserTransactionDraft,
getUserAppLockState,
isUserLogined,
isUserUnlocked,
@@ -219,8 +256,10 @@ export default {
decryptToken,
isCorrectPinCode,
updateToken,
updateUserTransactionDraft,
updateUserInfo,
clearUserInfo,
clearUserTransactionDraft,
clearSessionToken,
clearTokenAndUserInfo
};
+3
View File
@@ -1521,6 +1521,7 @@
"Unable to save transaction": "Unable to save transaction",
"You have added a new transaction": "You have added a new transaction",
"You have saved this transaction": "You have saved this transaction",
"Do you want to save this transaction draft?": "Do you want to save this transaction draft?",
"Add Picture": "Add Picture",
"Remove Picture": "Remove Picture",
"Are you sure you want to remove this transaction picture?": "Are you sure you want to remove this transaction picture?",
@@ -1608,6 +1609,8 @@
"Show Monthly Total Amount": "Show Monthly Total Amount",
"Show Transaction Tag": "Show Transaction Tag",
"Transaction Edit Page": "Transaction Edit Page",
"Automatically Save Draft": "Automatically Save Draft",
"Show Confirmation Every Time": "Show Confirmation Every Time",
"Automatically Add Geolocation": "Automatically Add Geolocation",
"Enable Animation": "Enable Animation",
"Basic Information": "Basic Information",
+3
View File
@@ -1521,6 +1521,7 @@
"Unable to save transaction": "无法保存交易",
"You have added a new transaction": "您已经添加新交易",
"You have saved this transaction": "您已经保存该交易",
"Do you want to save this transaction draft?": "您是否要保存这个交易草稿?",
"Add Picture": "添加图片",
"Remove Picture": "删除图片",
"Are you sure you want to remove this transaction picture?": "您确定要删除这张交易图片?",
@@ -1608,6 +1609,8 @@
"Show Monthly Total Amount": "显示月度总金额",
"Show Transaction Tag": "显示交易标签",
"Transaction Edit Page": "交易编辑页面",
"Automatically Save Draft": "自动保存草稿",
"Show Confirmation Every Time": "每次提示确认",
"Automatically Add Geolocation": "自动添加地理位置",
"Enable Animation": "启用动画",
"Basic Information": "基本信息",
+5
View File
@@ -13,6 +13,7 @@ export const useSettingsStore = defineStore('settings', {
applicationLock: settings.isEnableApplicationLock(),
applicationLockWebAuthn: settings.isEnableApplicationLockWebAuthn(),
autoUpdateExchangeRatesData: settings.isAutoUpdateExchangeRatesData(),
autoSaveTransactionDraft: settings.getAutoSaveTransactionDraft(),
autoGetCurrentGeoLocation: settings.isAutoGetCurrentGeoLocation(),
showAmountInHomePage: settings.isShowAmountInHomePage(),
timezoneUsedForStatisticsInHomePage: settings.getTimezoneUsedForStatisticsInHomePage(),
@@ -63,6 +64,10 @@ export const useSettingsStore = defineStore('settings', {
settings.setAutoUpdateExchangeRatesData(value);
this.appSettings.autoUpdateExchangeRatesData = value;
},
setAutoSaveTransactionDraft(value) {
settings.setAutoSaveTransactionDraft(value);
this.appSettings.autoSaveTransactionDraft = value;
},
setAutoGetCurrentGeoLocation(value) {
settings.setAutoGetCurrentGeoLocation(value);
this.appSettings.autoGetCurrentGeoLocation = value;
+153 -3
View File
@@ -1,6 +1,7 @@
import { defineStore } from 'pinia';
import { useSettingsStore } from './setting.js';
import { useUserStore } from './user.js';
import { useAccountsStore } from './account.js';
import { useTransactionCategoriesStore } from './transactionCategory.js';
import { useOverviewStore } from './overview.js';
@@ -8,10 +9,16 @@ import { useStatisticsStore } from './statistics.js';
import { useExchangeRatesStore } from './exchangeRates.js';
import datetimeConstants from '@/consts/datetime.js';
import categoryConstants from '@/consts/category.js';
import transactionConstants from '@/consts/transaction.js';
import userState from '@/lib/userstate.js';
import services from '@/lib/services.js';
import logger from '@/lib/logger.js';
import { isNumber, isString } from '@/lib/common.js';
import {
isDefined,
isNumber,
isString
} from '@/lib/common.js';
import {
getCurrentUnixTime,
getTimezoneOffsetMinutes,
@@ -25,6 +32,7 @@ import {
getDay,
getDayOfWeekName
} from '@/lib/datetime.js';
import { getFirstAvailableCategoryId } from '@/lib/category.js';
const emptyTransactionResult = {
items: [],
@@ -315,8 +323,47 @@ function buildBasicSubmitTransaction(transaction, dummyTime) {
return submitTransaction;
}
function buildTransactionDraft(transaction) {
if (!transaction) {
return null;
}
let categoryId = '';
if (transaction.type === transactionConstants.allTransactionTypes.Expense) {
categoryId = transaction.expenseCategory;
} else if (transaction.type === transactionConstants.allTransactionTypes.Income) {
categoryId = transaction.incomeCategory;
} else if (transaction.type === transactionConstants.allTransactionTypes.Transfer) {
categoryId = transaction.transferCategory;
} else {
return null;
}
const transactionDraft = {
type: transaction.type,
categoryId: categoryId,
sourceAccountId: transaction.sourceAccountId,
sourceAmount: transaction.sourceAmount,
destinationAccountId: '0',
destinationAmount: 0,
hideAmount: transaction.hideAmount,
tagIds: transaction.tagIds,
pictures: transaction.pictures,
comment: transaction.comment,
};
if (transaction.type === transactionConstants.allTransactionTypes.Transfer) {
transactionDraft.destinationAccountId = transaction.destinationAccountId;
transactionDraft.destinationAmount = transaction.destinationAmount;
}
return transactionDraft;
}
export const useTransactionsStore = defineStore('transactions', {
state: () => ({
transactionDraft: userState.getUserTransactionDraft(),
transactionsFilter: {
dateType: datetimeConstants.allDateRanges.All.type,
maxTime: 0,
@@ -447,6 +494,104 @@ export const useTransactionsStore = defineStore('transactions', {
}
},
actions: {
initTransactionDraft() {
const settingsStore = useSettingsStore();
if (settingsStore.appSettings.autoSaveTransactionDraft === 'enabled' || settingsStore.appSettings.autoSaveTransactionDraft === 'confirmation') {
this.transactionDraft = userState.getUserTransactionDraft();
} else {
this.transactionDraft = null;
}
},
isTransactionDraftModified(transaction) {
if (!transaction) {
return false;
}
const userStore = useUserStore();
const transactionCategoriesStore = useTransactionCategoriesStore();
if (transaction.sourceAmount !== 0) {
return true;
}
if (transaction.type === transactionConstants.allTransactionTypes.Transfer && transaction.destinationAmount !== 0) {
return true;
}
if (transaction.sourceAccountId && transaction.sourceAccountId !== '0' && transaction.sourceAccountId !== userStore.currentUserDefaultAccountId) {
return true;
}
if (transaction.type === transactionConstants.allTransactionTypes.Transfer && transaction.destinationAccountId && transaction.destinationAccountId !== '0' && transaction.destinationAccountId !== userStore.currentUserDefaultAccountId) {
return true;
}
const allCategories = transactionCategoriesStore.allTransactionCategories;
if (allCategories) {
if (transaction.type === transactionConstants.allTransactionTypes.Expense) {
const defaultCategoryId = getFirstAvailableCategoryId(allCategories[categoryConstants.allCategoryTypes.Expense]);
if (transaction.expenseCategory && transaction.expenseCategory !== '0' && transaction.expenseCategory !== defaultCategoryId) {
return true;
}
} else if (transaction.type === transactionConstants.allTransactionTypes.Income) {
const defaultCategoryId = getFirstAvailableCategoryId(allCategories[categoryConstants.allCategoryTypes.Income]);
if (transaction.incomeCategory && transaction.incomeCategory !== '0' && transaction.incomeCategory !== defaultCategoryId) {
return true;
}
} else if (transaction.type === transactionConstants.allTransactionTypes.Transfer) {
const defaultCategoryId = getFirstAvailableCategoryId(allCategories[categoryConstants.allCategoryTypes.Transfer]);
if (transaction.transferCategory && transaction.transferCategory !== '0' && transaction.transferCategory !== defaultCategoryId) {
return true;
}
}
}
if (transaction.hideAmount) {
return true;
}
if (transaction.tagIds && transaction.tagIds.length > 0) {
return true;
}
if (transaction.pictures && transaction.pictures.length > 0) {
return true;
}
if (transaction.comment && transaction.comment.trim()) {
return true;
}
return false;
},
saveTransactionDraft(transaction) {
const settingsStore = useSettingsStore();
if (settingsStore.appSettings.autoSaveTransactionDraft !== 'enabled' && settingsStore.appSettings.autoSaveTransactionDraft !== 'confirmation') {
this.clearTransactionDraft();
return;
}
if (transaction) {
if (!this.isTransactionDraftModified(transaction)) {
this.clearTransactionDraft();
return;
}
this.transactionDraft = buildTransactionDraft(transaction);
}
userState.updateUserTransactionDraft(this.transactionDraft);
},
clearTransactionDraft() {
this.transactionDraft = null;
userState.clearUserTransactionDraft();
},
generateNewTransactionModel(type) {
const settingsStore = useSettingsStore();
const now = getCurrentUnixTime();
@@ -827,10 +972,15 @@ export const useTransactionsStore = defineStore('transactions', {
});
});
},
getTransaction({ transactionId }) {
getTransaction({ transactionId, withPictures }) {
return new Promise((resolve, reject) => {
if (!isDefined(withPictures)) {
withPictures = true;
}
services.getTransaction({
id: transactionId
id: transactionId,
withPictures: withPictures
}).then(response => {
const data = response.data;
+4 -1
View File
@@ -114,6 +114,7 @@ import { useRootStore } from '@/stores/index.js';
import { useSettingsStore } from '@/stores/setting.js';
import { useUserStore } from '@/stores/user.js';
import { useTokensStore } from '@/stores/token.js';
import { useTransactionsStore } from '@/stores/transaction.js';
import { useExchangeRatesStore } from '@/stores/exchangeRates.js';
import assetConstants from '@/consts/asset.js';
@@ -129,7 +130,7 @@ export default {
};
},
computed: {
...mapStores(useRootStore, useSettingsStore, useUserStore, useTokensStore, useExchangeRatesStore),
...mapStores(useRootStore, useSettingsStore, useUserStore, useTokensStore, useTransactionsStore, useExchangeRatesStore),
ezBookkeepingLogoPath() {
return assetConstants.ezBookkeepingLogoPath;
},
@@ -181,6 +182,7 @@ export default {
self.verifyingByWebAuthn = false;
self.$user.unlockTokenByWebAuthn(id, userName, userSecret);
self.transactionsStore.initTransactionDraft();
self.tokensStore.refreshTokenAndRevokeOldToken().then(response => {
if (response.user) {
const localeDefaultSettings = self.$locale.setLanguage(response.user.language);
@@ -230,6 +232,7 @@ export default {
try {
self.$user.unlockTokenByPinCode(user.username, pinCode);
self.transactionsStore.initTransactionDraft();
self.tokensStore.refreshTokenAndRevokeOldToken().then(response => {
if (response.user) {
const localeDefaultSettings = self.$locale.setLanguage(response.user.language);
@@ -145,6 +145,22 @@
<v-form>
<v-card-text>
<v-row>
<v-col cols="12" md="6">
<v-select
item-title="displayName"
item-value="value"
persistent-placeholder
:label="$t('Automatically Save Draft')"
:placeholder="$t('Automatically Save Draft')"
:items="[
{ value: 'disabled', displayName: $t('Disabled') },
{ value: 'enabled', displayName: $t('Enabled') },
{ value: 'confirmation', displayName: $t('Show Confirmation Every Time') }
]"
v-model="autoSaveTransactionDraft"
/>
</v-col>
<v-col cols="12" md="6">
<v-select
item-title="displayName"
@@ -275,6 +291,18 @@ export default {
this.settingsStore.setItemsCountInTransactionListPage(value);
}
},
autoSaveTransactionDraft: {
get: function () {
return this.settingsStore.appSettings.autoSaveTransactionDraft;
},
set: function (value) {
this.settingsStore.setAutoSaveTransactionDraft(value);
if (value === 'disabled') {
this.transactionsStore.clearTransactionDraft();
}
}
},
isAutoGetCurrentGeoLocation: {
get: function () {
return this.settingsStore.appSettings.autoGetCurrentGeoLocation;
@@ -64,6 +64,7 @@
import { mapStores } from 'pinia';
import { useSettingsStore } from '@/stores/setting.js';
import { useUserStore } from '@/stores/user.js';
import { useTransactionsStore } from '@/stores/transaction.js';
import logger from '@/lib/logger.js';
import webauthn from '@/lib/webauthn.js';
@@ -77,7 +78,7 @@ export default {
};
},
computed: {
...mapStores(useSettingsStore, useUserStore),
...mapStores(useSettingsStore, useUserStore, useTransactionsStore),
isEnableApplicationLock: {
get: function () {
return this.settingsStore.appSettings.applicationLock;
@@ -168,6 +169,7 @@ export default {
this.$user.encryptToken(user.username, this.pinCode);
this.settingsStore.setEnableApplicationLock(true);
this.transactionsStore.saveTransactionDraft();
this.settingsStore.setEnableApplicationLockWebAuthn(false);
this.$user.clearWebAuthnConfig();
@@ -190,6 +192,7 @@ export default {
this.$user.decryptToken();
this.settingsStore.setEnableApplicationLock(false);
this.transactionsStore.saveTransactionDraft();
this.settingsStore.setEnableApplicationLockWebAuthn(false);
this.$user.clearWebAuthnConfig();
@@ -447,6 +447,8 @@ export default {
showState: false,
mode: 'add',
activeTab: 'basicInfo',
addByTemplateId: null,
duplicateFromId: null,
editId: null,
originalTransactionEditable: false,
clientSessionId: '',
@@ -758,6 +760,8 @@ export default {
methods: {
open(options) {
const self = this;
self.addByTemplateId = null;
self.duplicateFromId = null;
self.showState = true;
self.activeTab = 'basicInfo';
self.loading = true;
@@ -790,6 +794,9 @@ export default {
if (options.template) {
self.setTransaction(options.template, options, false, false);
self.addByTemplateId = options.template.id;
} else if ((self.settingsStore.appSettings.autoSaveTransactionDraft === 'enabled' || self.settingsStore.appSettings.autoSaveTransactionDraft === 'confirmation') && self.transactionsStore.transactionDraft) {
self.setTransaction(self.transactionsStore.transactionDraft, options, false, false);
}
if (self.settingsStore.appSettings.autoGetCurrentGeoLocation
@@ -931,6 +938,10 @@ export default {
}
}
if (self.mode === 'add' && !self.addByTemplateId && !self.duplicateFromId) {
self.transactionsStore.clearTransactionDraft();
}
self.showState = false;
}).catch(error => {
self.submitting = false;
@@ -1004,6 +1015,7 @@ export default {
}
this.editId = null;
this.duplicateFromId = this.transaction.id;
this.transaction.id = null;
this.transaction.time = getCurrentUnixTime();
this.transaction.timeZone = this.settingsStore.appSettings.timeZone;
@@ -1049,11 +1061,40 @@ export default {
});
},
cancel() {
if (this.reject) {
this.reject();
const self = this;
const doClose = function () {
if (self.reject) {
self.reject();
}
self.showState = false;
};
if (self.type !== 'transaction' || self.mode !== 'add' || self.addByTemplateId || self.duplicateFromId) {
doClose();
return;
}
this.showState = false;
if (self.settingsStore.appSettings.autoSaveTransactionDraft === 'confirmation') {
if (self.transactionsStore.isTransactionDraftModified(self.transaction)) {
self.$refs.confirmDialog.open('Do you want to save this transaction draft?').then(() => {
self.transactionsStore.saveTransactionDraft(self.transaction);
doClose();
}).catch(() => {
self.transactionsStore.clearTransactionDraft();
doClose();
});
} else {
self.transactionsStore.clearTransactionDraft();
doClose();
}
} else if (self.settingsStore.appSettings.autoSaveTransactionDraft === 'enabled') {
self.transactionsStore.saveTransactionDraft(self.transaction);
doClose();
} else {
doClose();
}
},
showDateTimeError(error) {
this.$refs.snackbar.showError(error);
+4 -1
View File
@@ -39,6 +39,7 @@
import { mapStores } from 'pinia';
import { useSettingsStore } from '@/stores/setting.js';
import { useUserStore } from '@/stores/user.js';
import { useTransactionsStore } from '@/stores/transaction.js';
import logger from '@/lib/logger.js';
import webauthn from '@/lib/webauthn.js';
@@ -54,7 +55,7 @@ export default {
};
},
computed: {
...mapStores(useSettingsStore, useUserStore),
...mapStores(useSettingsStore, useUserStore, useTransactionsStore),
isEnableApplicationLock: {
get: function () {
return this.settingsStore.appSettings.applicationLock;
@@ -145,6 +146,7 @@ export default {
this.$user.encryptToken(user.username, pinCode);
this.settingsStore.setEnableApplicationLock(true);
this.transactionsStore.saveTransactionDraft();
this.settingsStore.setEnableApplicationLockWebAuthn(false);
this.$user.clearWebAuthnConfig();
@@ -169,6 +171,7 @@ export default {
this.$user.decryptToken();
this.settingsStore.setEnableApplicationLock(false);
this.transactionsStore.saveTransactionDraft();
this.settingsStore.setEnableApplicationLockWebAuthn(false);
this.$user.clearWebAuthnConfig();
+4 -1
View File
@@ -70,6 +70,7 @@ import { useRootStore } from '@/stores/index.js';
import { useSettingsStore } from '@/stores/setting.js';
import { useUserStore } from '@/stores/user.js';
import { useTokensStore } from '@/stores/token.js';
import { useTransactionsStore } from '@/stores/transaction.js';
import { useExchangeRatesStore } from '@/stores/exchangeRates.js';
import assetConstants from '@/consts/asset.js';
@@ -88,7 +89,7 @@ export default {
}
},
computed: {
...mapStores(useRootStore, useSettingsStore, useUserStore, useTokensStore, useExchangeRatesStore),
...mapStores(useRootStore, useSettingsStore, useUserStore, useTokensStore, useTransactionsStore, useExchangeRatesStore),
ezBookkeepingLogoPath() {
return assetConstants.ezBookkeepingLogoPath;
},
@@ -134,6 +135,7 @@ export default {
self.$hideLoading();
self.$user.unlockTokenByWebAuthn(id, userName, userSecret);
self.transactionsStore.initTransactionDraft();
self.tokensStore.refreshTokenAndRevokeOldToken().then(response => {
if (response.user) {
const localeDefaultSettings = self.$locale.setLanguage(response.user.language);
@@ -188,6 +190,7 @@ export default {
try {
self.$user.unlockTokenByPinCode(user.username, pinCode);
self.transactionsStore.initTransactionDraft();
self.tokensStore.refreshTokenAndRevokeOldToken().then(response => {
if (response.user) {
const localeDefaultSettings = self.$locale.setLanguage(response.user.language);
+23 -1
View File
@@ -34,6 +34,15 @@
<f7-block-title>{{ $t('Transaction Edit Page') }}</f7-block-title>
<f7-list strong inset dividers>
<f7-list-item
:title="$t('Automatically Save Draft')"
smart-select :smart-select-params="{ openIn: 'popup', popupPush: true, closeOnSelect: true, scrollToSelectedItem: true, searchbar: true, searchbarPlaceholder: $t('Automatically Save Draft'), searchbarDisableText: $t('Cancel'), appendSearchbarNotFound: $t('No results'), popupCloseLinkText: $t('Done') }">
<select v-model="autoSaveTransactionDraft">
<option value="disabled">{{ $t('Disabled') }}</option>
<option value="enabled">{{ $t('Enabled') }}</option>
<option value="confirmation">{{ $t('Show Confirmation Every Time') }}</option>
</select>
</f7-list-item>
<f7-list-item>
<span>{{ $t('Automatically Add Geolocation') }}</span>
<f7-toggle :checked="isAutoGetCurrentGeoLocation" @toggle:change="isAutoGetCurrentGeoLocation = $event"></f7-toggle>
@@ -45,11 +54,12 @@
<script>
import { mapStores } from 'pinia';
import { useSettingsStore } from '@/stores/setting.js';
import { useTransactionsStore } from '@/stores/transaction.js';
import { useOverviewStore } from '@/stores/overview.js';
export default {
computed: {
...mapStores(useSettingsStore, useOverviewStore),
...mapStores(useSettingsStore, useTransactionsStore, useOverviewStore),
allTimezoneTypesUsedForStatistics() {
return this.$locale.getAllTimezoneTypesUsedForStatistics();
},
@@ -86,6 +96,18 @@ export default {
this.settingsStore.setShowTagInTransactionListPage(value);
}
},
autoSaveTransactionDraft: {
get: function () {
return this.settingsStore.appSettings.autoSaveTransactionDraft;
},
set: function (value) {
this.settingsStore.setAutoSaveTransactionDraft(value);
if (value === 'disabled') {
this.transactionsStore.clearTransactionDraft();
}
}
},
isAutoGetCurrentGeoLocation: {
get: function () {
return this.settingsStore.appSettings.autoGetCurrentGeoLocation;
+50 -8
View File
@@ -1,5 +1,5 @@
<template>
<f7-page with-subnavbar @page:afterin="onPageAfterIn">
<f7-page with-subnavbar @page:afterin="onPageAfterIn" @page:beforeout="onPageBeforeOut">
<f7-navbar>
<f7-nav-left :back-link="$t('Back')"></f7-nav-left>
<f7-nav-title :title="$t(title)"></f7-nav-title>
@@ -473,6 +473,8 @@ export default {
return {
type: 'transaction',
mode: 'add',
addByTemplateId: null,
duplicateFromId: null,
editId: null,
transaction: newTransaction,
clientSessionId: '',
@@ -480,6 +482,7 @@ export default {
loadingError: null,
geoLocationStatus: null,
submitting: false,
submitted: false,
uploadingPicture: false,
removingPictureId: null,
isSupportGeoLocation: !!navigator.geolocation,
@@ -903,9 +906,11 @@ export default {
if (query.id) {
if (self.mode === 'edit') {
self.editId = query.id;
} else if (self.mode === 'add') {
self.duplicateFromId = query.id;
}
promises.push(self.transactionsStore.getTransaction({ transactionId: query.id }));
promises.push(self.transactionsStore.getTransaction({ transactionId: query.id, withPictures: self.mode !== 'add' }));
}
} else if (self.type === 'template') {
self.transaction.name = '';
@@ -953,12 +958,22 @@ export default {
let fromTransaction = null;
if (self.type === 'transaction' && query.id) {
fromTransaction = responses[4];
} else if (self.type === 'transaction' && self.transactionTemplatesStore.allTransactionTemplatesMap && self.transactionTemplatesStore.allTransactionTemplatesMap[templateConstants.allTemplateTypes.Normal]) {
fromTransaction = self.transactionTemplatesStore.allTransactionTemplatesMap[templateConstants.allTemplateTypes.Normal][query.templateId];
} else if (self.type === 'template' && query.id) {
fromTransaction = responses[4];
if (self.type === 'transaction') {
if (query.id) {
fromTransaction = responses[4];
} else if (query.templateId && self.transactionTemplatesStore.allTransactionTemplatesMap && self.transactionTemplatesStore.allTransactionTemplatesMap[templateConstants.allTemplateTypes.Normal]) {
fromTransaction = self.transactionTemplatesStore.allTransactionTemplatesMap[templateConstants.allTemplateTypes.Normal][query.templateId];
if (fromTransaction) {
self.addByTemplateId = fromTransaction.id;
}
} else if ((self.settingsStore.appSettings.autoSaveTransactionDraft === 'enabled' || self.settingsStore.appSettings.autoSaveTransactionDraft === 'confirmation') && self.transactionsStore.transactionDraft) {
fromTransaction = self.transactionsStore.transactionDraft;
}
} else if (self.type === 'template') {
if (query.id) {
fromTransaction = responses[4];
}
}
setTransactionModelByTransaction(
@@ -1019,6 +1034,27 @@ export default {
this.updateGeoLocation(false);
}
},
onPageBeforeOut() {
const self = this;
if (self.submitted || self.type !== 'transaction' || self.mode !== 'add' || self.addByTemplateId || self.duplicateFromId) {
return;
}
if (self.settingsStore.appSettings.autoSaveTransactionDraft === 'confirmation') {
if (self.transactionsStore.isTransactionDraftModified(self.transaction)) {
self.$confirm('Do you want to save this transaction draft?', () => {
self.transactionsStore.saveTransactionDraft(self.transaction);
}, () => {
self.transactionsStore.clearTransactionDraft();
});
} else {
self.transactionsStore.clearTransactionDraft();
}
} else if (self.settingsStore.appSettings.autoSaveTransactionDraft === 'enabled') {
self.transactionsStore.saveTransactionDraft(self.transaction);
}
},
save() {
const self = this;
const router = self.f7router;
@@ -1054,6 +1090,11 @@ export default {
self.$toast('You have saved this transaction');
}
if (self.mode === 'add' && !self.addByTemplateId && !self.duplicateFromId) {
self.transactionsStore.clearTransactionDraft();
}
self.submitted = true;
router.back();
}).catch(error => {
self.submitting = false;
@@ -1111,6 +1152,7 @@ export default {
self.$toast('You have saved this template');
}
self.submitted = true;
router.back();
}).catch(error => {
self.submitting = false;