automatically save transaction draft
This commit is contained in:
+10
-3
@@ -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', {
|
||||
|
||||
@@ -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');
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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": "基本信息",
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user