diff --git a/src/consts/file.js b/src/consts/file.js index 435091af..fbd1c82d 100644 --- a/src/consts/file.js +++ b/src/consts/file.js @@ -2,18 +2,21 @@ const supportedImageExtensions = '.jpg,.jpeg,.png,.gif,.webp'; const supportedImportFileTypes = [ { - type: 'ezbookkeeping_csv', - name: 'ezbookkeeping Data Export File (CSV)', - extensions: '.csv', - document: { - supportMultiLanguages: true, - anchor: 'export-transactions' - } - }, - { - type: 'ezbookkeeping_tsv', - name: 'ezbookkeeping Data Export File (TSV)', - extensions: '.tsv', + type: 'ezbookkeeping', + name: 'ezbookkeeping Data Export File', + extensions: '.csv,.tsv', + subTypes: [ + { + type: 'ezbookkeeping_csv', + name: 'CSV (Comma-separated values) File', + extensions: '.csv', + }, + { + type: 'ezbookkeeping_tsv', + name: 'TSV (Tab-separated values) File', + extensions: '.tsv', + } + ], document: { supportMultiLanguages: true, anchor: 'export-transactions' diff --git a/src/lib/file.js b/src/lib/file.js new file mode 100644 index 00000000..135adbe0 --- /dev/null +++ b/src/lib/file.js @@ -0,0 +1,29 @@ +import { isString } from './common.js'; + +export function getFileExtension(filename) { + if (!filename || !isString(filename)) { + return ''; + } + + const parts = filename.split('.'); + return parts[parts.length - 1]; +} + +export function isFileExtensionSupported(filename, supportedExtensions) { + if (!supportedExtensions) { + return false; + } + + const supportedExtensionsArray = supportedExtensions.split(','); + const fileExtension = getFileExtension(filename).toLowerCase(); + + for (let i = 0; i < supportedExtensionsArray.length; i++) { + const supportedExtension = getFileExtension(supportedExtensionsArray[i]).toLowerCase(); + + if (supportedExtension === fileExtension) { + return true; + } + } + + return false; +} diff --git a/src/lib/i18n.js b/src/lib/i18n.js index b6ad5bdc..f948b20c 100644 --- a/src/lib/i18n.js +++ b/src/lib/i18n.js @@ -1308,6 +1308,7 @@ function getAllSupportedImportFileTypes(i18nGlobal, translateFn) { subTypes.push({ type: subType.type, displayName: translateFn(subType.name), + extensions: subType.extensions }); } } diff --git a/src/locales/en.json b/src/locales/en.json index d3e2efdd..b98960b3 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -1244,6 +1244,7 @@ "Time": "Time", "Color": "Color", "Type": "Type", + "Format": "Format", "All Types": "All Types", "More": "More", "All": "All", @@ -1523,8 +1524,7 @@ "Data Import Completed": "Data Import Completed", "File Type": "File Type", "How to export this file?": "How to export this file?", - "ezbookkeeping Data Export File (CSV)": "ezbookkeeping Data Export File (CSV)", - "ezbookkeeping Data Export File (TSV)": "ezbookkeeping Data Export File (TSV)", + "ezbookkeeping Data Export File": "ezbookkeeping Data Export File", "Quicken Interchange Format (QIF) File": "Quicken Interchange Format (QIF) File", "Year-month-day format": "Year-month-day format", "Month-day-year format": "Month-day-year format", diff --git a/src/locales/zh_Hans.json b/src/locales/zh_Hans.json index 2c0446eb..ea714ea0 100644 --- a/src/locales/zh_Hans.json +++ b/src/locales/zh_Hans.json @@ -1244,6 +1244,7 @@ "Time": "时间", "Color": "颜色", "Type": "类型", + "Format": "格式", "All Types": "全部类型", "More": "更多", "All": "全部", @@ -1523,8 +1524,7 @@ "Data Import Completed": "数据导入完成", "File Type": "文件类型", "How to export this file?": "如何导出该文件?", - "ezbookkeeping Data Export File (CSV)": "ezbookkeeping 数据导出文件 (CSV)", - "ezbookkeeping Data Export File (TSV)": "ezbookkeeping 数据导出文件 (TSV)", + "ezbookkeeping Data Export File": "ezbookkeeping 数据导出文件", "Quicken Interchange Format (QIF) File": "Quicken Interchange Format (QIF) 文件", "Year-month-day format": "年-月-日 格式", "Month-day-year format": "月-日-年 格式", diff --git a/src/views/desktop/transactions/list/dialogs/ImportDialog.vue b/src/views/desktop/transactions/list/dialogs/ImportDialog.vue index cdf6591a..8e2a789b 100644 --- a/src/views/desktop/transactions/list/dialogs/ImportDialog.vue +++ b/src/views/desktop/transactions/list/dialogs/ImportDialog.vue @@ -83,8 +83,8 @@ item-title="displayName" item-value="type" :disabled="submitting" - :label="$t('Type')" - :placeholder="$t('Type')" + :label="$t('Format')" + :placeholder="$t('Format')" :items="allFileSubTypes" v-model="fileSubType" /> @@ -490,6 +490,7 @@ import { useExchangeRatesStore } from '@/stores/exchangeRates.js'; import categoryConstants from '@/consts/category.js'; import transactionConstants from '@/consts/transaction.js'; import { getNameByKeyValue } from '@/lib/common.js'; +import { isFileExtensionSupported } from '@/lib/file.js'; import { generateRandomUUID } from '@/lib/misc.js'; import logger from '@/lib/logger.js'; import { @@ -534,8 +535,8 @@ export default { showState: false, clientSessionId: '', currentStep: 'uploadFile', - fileType: 'ezbookkeeping_csv', - fileSubType: '', + fileType: 'ezbookkeeping', + fileSubType: 'ezbookkeeping_csv', importFile: null, importTransactions: null, editingTransaction: null, @@ -656,6 +657,14 @@ export default { return getTimezoneOffsetMinutes(this.settingsStore.appSettings.timeZone); }, supportedImportFileExtensions() { + if (this.allFileSubTypes && this.allFileSubTypes.length) { + const subTypeExtensions = getNameByKeyValue(this.allFileSubTypes, this.fileSubType, 'type', 'extensions'); + + if (subTypeExtensions) { + return subTypeExtensions; + } + } + return getNameByKeyValue(this.allSupportedImportFileTypes, this.fileType, 'type', 'extensions'); }, exportFileGuideDocumentUrl() { @@ -852,12 +861,24 @@ export default { this.editingTags = []; this.currentPage = 1; this.countPerPage = 10; + }, + fileSubType: function (newValue) { + let supportedExtensions = getNameByKeyValue(this.allFileSubTypes, newValue, 'type', 'extensions'); + + if (!supportedExtensions) { + supportedExtensions = getNameByKeyValue(this.allSupportedImportFileTypes, this.fileType, 'type', 'extensions'); + } + + if (this.importFile && this.importFile.name && !isFileExtensionSupported(this.importFile.name, supportedExtensions)) { + this.importFile = null; + } } }, methods: { open() { const self = this; - self.fileType = 'ezbookkeeping_csv'; + self.fileType = 'ezbookkeeping'; + self.fileSubType = 'ezbookkeeping_csv'; self.currentStep = 'uploadFile'; self.importFile = null; self.importTransactions = null;