add refresh accounts, categories and tags button on import dialog

This commit is contained in:
MaysWind
2026-01-24 23:21:02 +08:00
parent a8b6f72ee6
commit bee7772bfd
21 changed files with 102 additions and 1 deletions
@@ -5,7 +5,18 @@
<div class="d-flex align-center justify-center">
<div class="d-flex w-100 align-center">
<h4 class="text-h4">{{ tt('Import Transactions') }}</h4>
<v-progress-circular indeterminate size="22" class="ms-2" v-if="loading"></v-progress-circular>
<v-progress-circular indeterminate size="22" class="ms-2" v-if="currentStep !== 'checkData' && loading"></v-progress-circular>
<v-btn density="compact" color="default" variant="text" size="24"
class="ms-2" :icon="true" :disabled="loading"
:loading="loading"
v-if="currentStep === 'checkData'"
@click="reloadBasisData">
<template #loader>
<v-progress-circular indeterminate size="20"/>
</template>
<v-icon :icon="mdiRefresh" size="24" />
<v-tooltip activator="parent">{{ tt('Refresh Accounts, Categories and Tags') }}</v-tooltip>
</v-btn>
</div>
<v-btn density="comfortable" color="default" variant="text" class="ms-2"
:icon="true" :disabled="loading || submitting"
@@ -307,6 +318,7 @@ import { generateRandomUUID } from '@/lib/misc.ts';
import logger from '@/lib/logger.ts';
import {
mdiRefresh,
mdiFilterOutline,
mdiCheck,
mdiDotsVertical,
@@ -674,6 +686,46 @@ function setImportFile(event: Event): void {
}
}
function reloadBasisData(): void {
loading.value = true;
Promise.allSettled([
accountsStore.loadAllAccounts({ force: true }),
transactionCategoriesStore.loadAllCategories({ force: true }),
transactionTagsStore.loadAllTags({ force: true })
]).then(results => {
loading.value = false;
const isAllUpToDate = results.length === 3
&& results[0].status === 'rejected' && results[0].reason?.isUpToDate
&& results[1].status === 'rejected' && results[1].reason?.isUpToDate
&& results[2].status === 'rejected' && results[2].reason?.isUpToDate;
// show info if all up to date
if (isAllUpToDate) {
snackbar.value?.showMessage('Data is up to date');
return;
}
// show error if any
for (const result of results) {
if (result.status === 'rejected' && !result.reason?.isUpToDate) {
snackbar.value?.showError(result.reason);
return;
}
}
// show info if one of them updated
for (const result of results) {
if (result.status === 'fulfilled') {
snackbar.value?.showMessage('Data has been updated');
importTransactionCheckDataTab.value?.updateAllTransactionsIsValid();
return;
}
}
});
}
function parseData(): void {
let uploadFile: File;
let type: string = fileType.value;
@@ -1634,14 +1634,43 @@ function updateTransactionData(transaction: ImportTransaction): void {
if (transaction.categoryId && allCategoriesMap.value[transaction.categoryId]) {
transaction.actualCategoryName = allCategoriesMap.value[transaction.categoryId]!.name;
} else {
if (transaction.type !== TransactionType.ModifyBalance) {
transaction.valid = false;
}
}
if (transaction.sourceAccountId && allAccountsMap.value[transaction.sourceAccountId]) {
transaction.actualSourceAccountName = allAccountsMap.value[transaction.sourceAccountId]!.name;
} else {
transaction.valid = false;
}
if (transaction.destinationAccountId && allAccountsMap.value[transaction.destinationAccountId]) {
transaction.actualDestinationAccountName = allAccountsMap.value[transaction.destinationAccountId]!.name;
} else {
if (transaction.type === TransactionType.Transfer) {
transaction.valid = false;
}
}
if (transaction.tagIds && transaction.tagIds.length) {
for (const tagId of transaction.tagIds) {
if (!tagId || !allTagsMap.value[tagId]) {
transaction.valid = false;
break;
}
}
}
}
function updateAllTransactionsIsValid(): void {
if (!props.importTransactions || props.importTransactions.length < 1) {
return;
}
for (const importTransaction of props.importTransactions) {
updateTransactionData(importTransaction);
}
}
@@ -2227,6 +2256,7 @@ defineExpose({
toolMenus,
isEditing,
canImport,
updateAllTransactionsIsValid,
reset,
setCountPerPage
});