migrate importing transaction dialog to composition API and typescript
This commit is contained in:
+7
-16
@@ -1,21 +1,12 @@
|
||||
import type { ImportFileType } from '@/core/file.ts';
|
||||
|
||||
export const SUPPORTED_IMAGE_EXTENSIONS: string = '.jpg,.jpeg,.png,.gif,.webp';
|
||||
|
||||
export interface ImportFileType {
|
||||
readonly type: string;
|
||||
readonly name: string;
|
||||
readonly extensions: string;
|
||||
readonly subTypes?: ImportFileTypeSubType[];
|
||||
readonly document?: {
|
||||
readonly supportMultiLanguages: boolean | string;
|
||||
readonly anchor: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface ImportFileTypeSubType {
|
||||
readonly type: string;
|
||||
readonly name: string;
|
||||
readonly extensions?: string;
|
||||
}
|
||||
export const DEFAULT_DOCUMENT_LANGUAGE_FOR_IMPORT_FILE: string = 'en';
|
||||
export const SUPPORTED_DOCUMENT_LANGUAGES_FOR_IMPORT_FILE: Record<string, boolean> = {
|
||||
DEFAULT_DOCUMENT_LANGUAGE_FOR_IMPORT_FILE: true,
|
||||
'zh-Hans': true
|
||||
};
|
||||
|
||||
export const SUPPORTED_IMPORT_FILE_TYPES: ImportFileType[] = [
|
||||
{
|
||||
|
||||
@@ -3,6 +3,11 @@ export type PartialRecord<K extends keyof any, T> = {
|
||||
[P in K]?: T;
|
||||
}
|
||||
|
||||
export interface NameValue {
|
||||
name: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
export interface TypeAndName {
|
||||
readonly type: number;
|
||||
readonly name: string;
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
export interface ImportFileTypeAndExtensions {
|
||||
readonly type: string;
|
||||
readonly extensions?: string;
|
||||
}
|
||||
|
||||
export interface ImportFileType extends ImportFileTypeAndExtensions {
|
||||
readonly type: string;
|
||||
readonly name: string;
|
||||
readonly extensions: string;
|
||||
readonly subTypes?: ImportFileTypeSubType[];
|
||||
readonly document?: {
|
||||
readonly supportMultiLanguages: boolean | string;
|
||||
readonly anchor: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface ImportFileTypeSubType extends ImportFileTypeAndExtensions {
|
||||
readonly type: string;
|
||||
readonly name: string;
|
||||
readonly extensions?: string;
|
||||
}
|
||||
|
||||
export interface LocalizedImportFileType extends ImportFileTypeAndExtensions {
|
||||
readonly type: string;
|
||||
readonly displayName: string;
|
||||
readonly extensions: string;
|
||||
readonly subTypes?: LocalizedImportFileTypeSubType[];
|
||||
readonly document?: LocalizedImportFileDocument;
|
||||
}
|
||||
|
||||
export interface LocalizedImportFileTypeSubType extends ImportFileTypeAndExtensions {
|
||||
readonly type: string;
|
||||
readonly displayName: string;
|
||||
readonly extensions?: string;
|
||||
}
|
||||
|
||||
export interface LocalizedImportFileDocument {
|
||||
readonly language: string;
|
||||
readonly displayLanguageName: string;
|
||||
readonly anchor: string;
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
import type { ImportFileTypeAndExtensions } from '@/core/file.ts';
|
||||
|
||||
import { isString } from './common.ts';
|
||||
|
||||
export function getFileExtension(filename: string): string {
|
||||
@@ -9,6 +11,20 @@ export function getFileExtension(filename: string): string {
|
||||
return parts[parts.length - 1];
|
||||
}
|
||||
|
||||
export function findExtensionByType(items: ImportFileTypeAndExtensions[] | undefined, type: string): string | undefined {
|
||||
if (!items || items.length < 1) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
for (const item of items) {
|
||||
if (item.type === type) {
|
||||
return item.extensions;
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function isFileExtensionSupported(filename: string, supportedExtensions: string): boolean {
|
||||
if (!supportedExtensions) {
|
||||
return false;
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import { DEFAULT_LANGUAGE, ALL_LANGUAGES } from '@/locales/index.ts';
|
||||
|
||||
import { WeekDay, LongDateFormat, ShortDateFormat, LongTimeFormat, ShortTimeFormat, DateRange } from '@/core/datetime.ts';
|
||||
import { DecimalSeparator, DigitGroupingSymbol, DigitGroupingType } from '@/core/numeral.ts';
|
||||
import { CurrencyDisplayType } from '@/core/currency.ts'
|
||||
@@ -8,7 +6,6 @@ import { TransactionTagFilterType } from '@/core/transaction.ts';
|
||||
|
||||
import { UTC_TIMEZONE, ALL_TIMEZONES } from '@/consts/timezone.ts';
|
||||
import { ALL_CURRENCIES } from '@/consts/currency.ts';
|
||||
import { SUPPORTED_IMPORT_FILE_TYPES } from '@/consts/file.ts';
|
||||
import { KnownErrorCode, SPECIFIED_API_NOT_FOUND_ERRORS, PARAMETERIZED_ERRORS } from '@/consts/api.ts';
|
||||
|
||||
import {
|
||||
@@ -48,14 +45,6 @@ import {
|
||||
getAllFilteredAccountsBalance
|
||||
} from '@/lib/account.ts';
|
||||
|
||||
function getLanguageDisplayName(translateFn, languageName) {
|
||||
return translateFn(`language.${languageName}`);
|
||||
}
|
||||
|
||||
function getCurrentLanguageTag(i18nGlobal) {
|
||||
return i18nGlobal.locale;
|
||||
}
|
||||
|
||||
function getLocalizedDisplayNameAndType(typeAndNames, translateFn) {
|
||||
const ret = [];
|
||||
|
||||
@@ -550,72 +539,6 @@ function getAllTransactionTagFilterTypes(translateFn) {
|
||||
return getLocalizedDisplayNameAndType(TransactionTagFilterType.values(), translateFn);
|
||||
}
|
||||
|
||||
function getAllSupportedImportFileTypes(i18nGlobal, translateFn) {
|
||||
const allSupportedImportFileTypes = [];
|
||||
|
||||
for (let i = 0; i < SUPPORTED_IMPORT_FILE_TYPES.length; i++) {
|
||||
const fileType = SUPPORTED_IMPORT_FILE_TYPES[i];
|
||||
let document = {
|
||||
language: '',
|
||||
displayLanguageName: '',
|
||||
anchor: ''
|
||||
};
|
||||
|
||||
if (fileType.document) {
|
||||
if (fileType.document.supportMultiLanguages === true) {
|
||||
document.language = getCurrentLanguageTag(i18nGlobal);
|
||||
document.anchor = translateFn(`document.anchor.export_and_import.${fileType.document.anchor}`);
|
||||
} else if (isString(fileType.document.supportMultiLanguages) && ALL_LANGUAGES[fileType.document.supportMultiLanguages]) {
|
||||
document.language = fileType.document.supportMultiLanguages;
|
||||
|
||||
if (document.language !== getCurrentLanguageTag(i18nGlobal)) {
|
||||
document.displayLanguageName = getLanguageDisplayName(translateFn, ALL_LANGUAGES[fileType.document.supportMultiLanguages].name);
|
||||
}
|
||||
|
||||
document.anchor = fileType.document.anchor;
|
||||
}
|
||||
|
||||
if (document.language) {
|
||||
document.language = document.language.replace(/-/g, '_');
|
||||
}
|
||||
|
||||
if (document.anchor) {
|
||||
document.anchor = document.anchor.toLowerCase().replace(/ /g, '-');
|
||||
}
|
||||
|
||||
if (document.language === DEFAULT_LANGUAGE) {
|
||||
document.language = '';
|
||||
}
|
||||
} else {
|
||||
document = null;
|
||||
}
|
||||
|
||||
const subTypes = [];
|
||||
|
||||
if (fileType.subTypes) {
|
||||
for (let i = 0; i < fileType.subTypes.length; i++) {
|
||||
const subType = fileType.subTypes[i];
|
||||
|
||||
subTypes.push({
|
||||
type: subType.type,
|
||||
displayName: translateFn(subType.name),
|
||||
extensions: subType.extensions
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
allSupportedImportFileTypes.push({
|
||||
type: fileType.type,
|
||||
displayName: translateFn(fileType.name),
|
||||
extensions: fileType.extensions,
|
||||
subTypes: subTypes.length ? subTypes : undefined,
|
||||
document: document
|
||||
});
|
||||
}
|
||||
|
||||
return allSupportedImportFileTypes;
|
||||
}
|
||||
|
||||
function getCategorizedAccountsWithDisplayBalance(allVisibleAccounts, showAccountBalance, defaultCurrency, userStore, settingsStore, exchangeRatesStore, translateFn) {
|
||||
const ret = [];
|
||||
const allCategories = AccountCategory.values();
|
||||
@@ -785,7 +708,6 @@ export function i18nFunctions(i18nGlobal) {
|
||||
formatAmountWithCurrency: (settingsStore, userStore, value, currencyCode) => getFormattedAmountWithCurrency(value, currencyCode, i18nGlobal.t, userStore, settingsStore),
|
||||
getAdaptiveAmountRate: (userStore, amount1, amount2, fromExchangeRate, toExchangeRate) => getAdaptiveAmountRate(amount1, amount2, fromExchangeRate, toExchangeRate, i18nGlobal.t, userStore),
|
||||
getAllTransactionTagFilterTypes: () => getAllTransactionTagFilterTypes(i18nGlobal.t),
|
||||
getAllSupportedImportFileTypes: () => getAllSupportedImportFileTypes(i18nGlobal, i18nGlobal.t),
|
||||
getCategorizedAccountsWithDisplayBalance: (allVisibleAccounts, showAccountBalance, defaultCurrency, settingsStore, userStore, exchangeRatesStore) => getCategorizedAccountsWithDisplayBalance(allVisibleAccounts, showAccountBalance, defaultCurrency, userStore, settingsStore, exchangeRatesStore, i18nGlobal.t)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -82,6 +82,12 @@ import {
|
||||
ChartDateAggregationType
|
||||
} from '@/core/statistics.ts';
|
||||
|
||||
import {
|
||||
type LocalizedImportFileType,
|
||||
type LocalizedImportFileTypeSubType,
|
||||
type LocalizedImportFileDocument,
|
||||
} from '@/core/file.ts';
|
||||
|
||||
import type { LocaleDefaultSettings } from '@/core/setting.ts';
|
||||
import type { ErrorResponse } from '@/core/api.ts';
|
||||
|
||||
@@ -89,6 +95,7 @@ import { UTC_TIMEZONE, ALL_TIMEZONES } from '@/consts/timezone.ts';
|
||||
import { ALL_CURRENCIES } from '@/consts/currency.ts';
|
||||
import { DEFAULT_EXPENSE_CATEGORIES, DEFAULT_INCOME_CATEGORIES, DEFAULT_TRANSFER_CATEGORIES } from '@/consts/category.ts';
|
||||
import { KnownErrorCode, SPECIFIED_API_NOT_FOUND_ERRORS, PARAMETERIZED_ERRORS } from '@/consts/api.ts';
|
||||
import { DEFAULT_DOCUMENT_LANGUAGE_FOR_IMPORT_FILE, SUPPORTED_DOCUMENT_LANGUAGES_FOR_IMPORT_FILE, SUPPORTED_IMPORT_FILE_TYPES } from '@/consts/file.ts';
|
||||
|
||||
import {
|
||||
type CategorizedAccount,
|
||||
@@ -1066,6 +1073,85 @@ export function useI18n() {
|
||||
return availableExchangeRates;
|
||||
}
|
||||
|
||||
function getAllSupportedImportFileTypes(): LocalizedImportFileType[] {
|
||||
const allSupportedImportFileTypes: LocalizedImportFileType[] = [];
|
||||
|
||||
for (let i = 0; i < SUPPORTED_IMPORT_FILE_TYPES.length; i++) {
|
||||
const fileType = SUPPORTED_IMPORT_FILE_TYPES[i];
|
||||
let document: LocalizedImportFileDocument | undefined;
|
||||
|
||||
if (fileType.document) {
|
||||
let documentLanguage = '';
|
||||
let documentDisplayLanguageName = '';
|
||||
let documentAnchor = '';
|
||||
|
||||
if (fileType.document.supportMultiLanguages === true) {
|
||||
documentLanguage = getCurrentLanguageTag();
|
||||
|
||||
if (SUPPORTED_DOCUMENT_LANGUAGES_FOR_IMPORT_FILE[documentLanguage]) {
|
||||
documentAnchor = t(`document.anchor.export_and_import.${fileType.document.anchor}`);
|
||||
} else {
|
||||
documentLanguage = DEFAULT_DOCUMENT_LANGUAGE_FOR_IMPORT_FILE;
|
||||
documentAnchor = t(`document.anchor.export_and_import.${fileType.document.anchor}`, {}, { locale: documentLanguage });
|
||||
}
|
||||
} else if (isString(fileType.document.supportMultiLanguages) && ALL_LANGUAGES[fileType.document.supportMultiLanguages]) {
|
||||
documentLanguage = fileType.document.supportMultiLanguages;
|
||||
documentAnchor = fileType.document.anchor;
|
||||
}
|
||||
|
||||
if (documentLanguage && documentLanguage !== getCurrentLanguageTag()) {
|
||||
documentDisplayLanguageName = getLanguageDisplayName(ALL_LANGUAGES[documentLanguage].name);
|
||||
}
|
||||
|
||||
if (documentLanguage) {
|
||||
documentLanguage = documentLanguage.replace(/-/g, '_');
|
||||
}
|
||||
|
||||
if (documentAnchor) {
|
||||
documentAnchor = documentAnchor.toLowerCase().replace(/ /g, '-');
|
||||
}
|
||||
|
||||
if (documentLanguage === DEFAULT_LANGUAGE) {
|
||||
documentLanguage = '';
|
||||
}
|
||||
|
||||
document = {
|
||||
language: documentLanguage,
|
||||
displayLanguageName: documentDisplayLanguageName,
|
||||
anchor: documentAnchor
|
||||
};
|
||||
} else {
|
||||
document = undefined;
|
||||
}
|
||||
|
||||
const subTypes: LocalizedImportFileTypeSubType[] = [];
|
||||
|
||||
if (fileType.subTypes) {
|
||||
for (let i = 0; i < fileType.subTypes.length; i++) {
|
||||
const subType = fileType.subTypes[i];
|
||||
const localizedSubType: LocalizedImportFileTypeSubType = {
|
||||
type: subType.type,
|
||||
displayName: t(subType.name),
|
||||
extensions: subType.extensions
|
||||
};
|
||||
|
||||
subTypes.push(localizedSubType);
|
||||
}
|
||||
}
|
||||
|
||||
const localizedFileType: LocalizedImportFileType = {
|
||||
type: fileType.type,
|
||||
displayName: t(fileType.name),
|
||||
extensions: fileType.extensions,
|
||||
subTypes: subTypes.length ? subTypes : undefined,
|
||||
document: document
|
||||
};
|
||||
allSupportedImportFileTypes.push(localizedFileType);
|
||||
}
|
||||
|
||||
return allSupportedImportFileTypes;
|
||||
}
|
||||
|
||||
function getLanguageInfo(languageKey: string): LanguageInfo | undefined {
|
||||
return ALL_LANGUAGES[languageKey];
|
||||
}
|
||||
@@ -1593,6 +1679,7 @@ export function useI18n() {
|
||||
getAllTransactionScheduledFrequencyTypes: () => getLocalizedDisplayNameAndType(ScheduledTemplateFrequencyType.values()),
|
||||
getAllTransactionDefaultCategories,
|
||||
getAllDisplayExchangeRates,
|
||||
getAllSupportedImportFileTypes,
|
||||
// get localized info
|
||||
getLanguageInfo,
|
||||
getMonthShortName,
|
||||
|
||||
@@ -180,8 +180,9 @@ import { useAccountsStore } from '@/stores/account.ts';
|
||||
import { useTransactionCategoriesStore } from '@/stores/transactionCategory.ts';
|
||||
import { useTransactionTagsStore } from '@/stores/transactionTag.ts';
|
||||
|
||||
import type { NameValue } from '@/core/base.ts';
|
||||
import { CategoryType } from '@/core/category.ts';
|
||||
import { type CategorizedAccountWithDisplayBalance, Account } from '@/models/account.ts';
|
||||
import { Account, type CategorizedAccountWithDisplayBalance } from '@/models/account.ts';
|
||||
import type { TransactionCategory } from '@/models/transaction_category.ts';
|
||||
import type { TransactionTag } from '@/models/transaction_tag.ts';
|
||||
|
||||
@@ -195,11 +196,6 @@ import {
|
||||
mdiPound
|
||||
} from '@mdi/js';
|
||||
|
||||
interface BatchReplaceDialogInvalidItem {
|
||||
name: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
interface BatchReplaceDialogResponse {
|
||||
sourceItem?: string;
|
||||
targetItem?: string;
|
||||
@@ -223,7 +219,7 @@ const icons = {
|
||||
const showState = ref<boolean>(false);
|
||||
const mode = ref<string>('');
|
||||
const type = ref<string>('');
|
||||
const invalidItems = ref<BatchReplaceDialogInvalidItem[] | undefined>([]);
|
||||
const invalidItems = ref<NameValue[] | undefined>([]);
|
||||
const sourceItem = ref<string | undefined>(undefined);
|
||||
const targetItem = ref<string | undefined>(undefined);
|
||||
|
||||
@@ -272,7 +268,7 @@ function getAccountDisplayName(accountId?: string): string {
|
||||
}
|
||||
}
|
||||
|
||||
function open(options: { mode: string; type: string; invalidItems?: BatchReplaceDialogInvalidItem[] }): Promise<BatchReplaceDialogResponse> {
|
||||
function open(options: { mode: string; type: string; invalidItems?: NameValue[] }): Promise<BatchReplaceDialogResponse> {
|
||||
mode.value = options.mode;
|
||||
type.value = options.type;
|
||||
sourceItem.value = undefined;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user