migrate to typescript

This commit is contained in:
MaysWind
2024-12-29 14:24:37 +08:00
parent b638a73e4d
commit 2560a70e5e
171 changed files with 3402 additions and 2557 deletions
+35 -32
View File
@@ -1,36 +1,39 @@
import globals from 'globals'; import pluginVue from 'eslint-plugin-vue';
import vueTsEslintConfig from '@vue/eslint-config-typescript';
import path from 'node:path'; export default [
import { fileURLToPath } from 'node:url'; ...pluginVue.configs['flat/essential'],
...vueTsEslintConfig(),
import js from '@eslint/js'; {
import { FlatCompat } from '@eslint/eslintrc'; languageOptions: {
import { includeIgnoreFile } from '@eslint/compat'; parserOptions: {
projectService: true,
const __filename = fileURLToPath(import.meta.url); tsconfigRootDir: import.meta.dirname,
const __dirname = path.dirname(__filename); }
const gitignorePath = path.resolve(__dirname, '.gitignore');
const compat = new FlatCompat({
baseDirectory: __dirname,
recommendedConfig: js.configs.recommended,
allConfig: js.configs.all
});
export default [...compat.extends('eslint:recommended', 'plugin:vue/vue3-essential'),
includeIgnoreFile(gitignorePath), {
languageOptions: {
globals: {
...globals.node,
}, },
}, },
files: [ {
"**/*.{vue,js,jsx,cjs,mjs}" ignores: [
], 'dist/**',
rules: { '**/*.{js,jsx,cjs,mjs}'
'vue/no-use-v-if-with-v-for': 'off', ]
'vue/valid-v-slot': ['error', {
allowModifiers: true,
}],
}, },
}]; {
files: [
'**/*.{vue,ts,tsx,mts,js,jsx,cjs,mjs}'
],
rules: {
'@typescript-eslint/no-this-alias': ['error', {
allowedNames: ['self']
}],
'vue/valid-v-slot': ['error', {
allowModifiers: true
}],
'vue/block-lang': ['error', {
script: {
lang: ['ts', 'js']
}
}],
}
},
];
+875 -235
View File
File diff suppressed because it is too large Load Diff
+11 -6
View File
@@ -15,7 +15,7 @@
"serve": "cross-env NODE_ENV=development vite", "serve": "cross-env NODE_ENV=development vite",
"build": "cross-env NODE_ENV=production vite build", "build": "cross-env NODE_ENV=production vite build",
"serve:dist": "vite preview", "serve:dist": "vite preview",
"lint": "eslint . --fix" "lint": "tsc --noEmit && eslint . --fix"
}, },
"dependencies": { "dependencies": {
"@mdi/js": "^7.4.47", "@mdi/js": "^7.4.47",
@@ -47,20 +47,25 @@
"vuetify": "^3.7.6" "vuetify": "^3.7.6"
}, },
"devDependencies": { "devDependencies": {
"@eslint/compat": "^1.2.4", "@tsconfig/node22": "^22.0.0",
"@eslint/eslintrc": "^3.2.0", "@types/crypto-js": "^4.2.2",
"@eslint/js": "^9.17.0", "@types/git-rev-sync": "^2.0.2",
"@types/node": "^22.10.2",
"@types/ua-parser-js": "^0.7.39",
"@vitejs/plugin-vue": "^5.2.1", "@vitejs/plugin-vue": "^5.2.1",
"@vue/eslint-config-typescript": "^14.1.3",
"@vue/tsconfig": "^0.7.0",
"cross-env": "^7.0.3", "cross-env": "^7.0.3",
"eslint": "^9.17.0", "eslint": "^9.17.0",
"eslint-plugin-vue": "^9.32.0", "eslint-plugin-vue": "^9.32.0",
"git-rev-sync": "^3.0.2", "git-rev-sync": "^3.0.2",
"globals": "^15.14.0",
"postcss-preset-env": "^10.1.2", "postcss-preset-env": "^10.1.2",
"sass": "^1.83.0", "sass": "^1.83.0",
"typescript": "^5.7.2",
"vite": "^6.0.5", "vite": "^6.0.5",
"vite-plugin-pwa": "^0.21.1", "vite-plugin-pwa": "^0.21.1",
"vite-plugin-vuetify": "^2.0.4" "vite-plugin-vuetify": "^2.0.4",
"vue-tsc": "^2.1.10"
}, },
"browserslist": [ "browserslist": [
"> 1%", "> 1%",
+11 -10
View File
@@ -26,10 +26,11 @@ import { useUserStore } from '@/stores/user.js';
import { useTokensStore } from '@/stores/token.js'; import { useTokensStore } from '@/stores/token.js';
import { useExchangeRatesStore } from '@/stores/exchangeRates.js'; import { useExchangeRatesStore } from '@/stores/exchangeRates.js';
import assetConstants from '@/consts/asset.js'; import { APPLICATION_LOGO_PATH } from '@/consts/asset.ts';
import { isProduction } from '@/lib/version.js'; import { ThemeType } from '@/core/theme.ts';
import { isProduction } from '@/lib/version.ts';
import { loadMapAssets } from '@/lib/map/index.js'; import { loadMapAssets } from '@/lib/map/index.js';
import { getSystemTheme, setExpenseAndIncomeAmountColor } from '@/lib/ui.js'; import { getSystemTheme, setExpenseAndIncomeAmountColor } from '@/lib/ui/common.ts';
export default { export default {
data() { data() {
@@ -40,7 +41,7 @@ export default {
computed: { computed: {
...mapStores(useRootStore, useSettingsStore, useUserStore, useTokensStore, useExchangeRatesStore), ...mapStores(useRootStore, useSettingsStore, useUserStore, useTokensStore, useExchangeRatesStore),
ezBookkeepingLogoPath() { ezBookkeepingLogoPath() {
return assetConstants.ezBookkeepingLogoPath; return APPLICATION_LOGO_PATH;
}, },
currentNotificationContent() { currentNotificationContent() {
return this.rootStore.currentNotification; return this.rootStore.currentNotification;
@@ -55,10 +56,10 @@ export default {
const self = this; const self = this;
const theme = useTheme(); const theme = useTheme();
if (self.settingsStore.appSettings.theme === 'light') { if (self.settingsStore.appSettings.theme === ThemeType.Light) {
theme.global.name.value = 'light'; theme.global.name.value = ThemeType.Light;
} else if (self.settingsStore.appSettings.theme === 'dark') { } else if (self.settingsStore.appSettings.theme === ThemeType.Dark) {
theme.global.name.value = 'dark'; theme.global.name.value = ThemeType.Dark;
} else { } else {
theme.global.name.value = getSystemTheme(); theme.global.name.value = getSystemTheme();
} }
@@ -66,9 +67,9 @@ export default {
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', function (e) { window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', function (e) {
if (self.settingsStore.appSettings.theme === 'auto') { if (self.settingsStore.appSettings.theme === 'auto') {
if (e.matches) { if (e.matches) {
theme.global.name.value = 'dark'; theme.global.name.value = ThemeType.Dark;
} else { } else {
theme.global.name.value = 'light'; theme.global.name.value = ThemeType.Light;
} }
} }
}); });
+8 -7
View File
@@ -15,21 +15,22 @@ import { useUserStore } from '@/stores/user.js';
import { useTokensStore } from '@/stores/token.js'; import { useTokensStore } from '@/stores/token.js';
import { useExchangeRatesStore } from '@/stores/exchangeRates.js'; import { useExchangeRatesStore } from '@/stores/exchangeRates.js';
import assetConstants from '@/consts/asset.js'; import { APPLICATION_LOGO_PATH } from '@/consts/asset.ts';
import { isProduction } from '@/lib/version.js'; import { ThemeType } from '@/core/theme.ts';
import { isProduction } from '@/lib/version.ts';
import { getTheme, isEnableAnimate } from '@/lib/settings.js'; import { getTheme, isEnableAnimate } from '@/lib/settings.js';
import { loadMapAssets } from '@/lib/map/index.js'; import { loadMapAssets } from '@/lib/map/index.js';
import { setExpenseAndIncomeAmountColor } from '@/lib/ui.js'; import { setExpenseAndIncomeAmountColor } from '@/lib/ui/common.ts';
import { isModalShowing, setAppFontSize } from '@/lib/ui.mobile.js'; import { isModalShowing, setAppFontSize } from '@/lib/ui/mobile.js';
export default { export default {
data() { data() {
const self = this; const self = this;
let darkMode = 'auto'; let darkMode = 'auto';
if (getTheme() === 'light') { if (getTheme() === ThemeType.Light) {
darkMode = false; darkMode = false;
} else if (getTheme() === 'dark') { } else if (getTheme() === ThemeType.Dark) {
darkMode = true; darkMode = true;
} }
@@ -112,7 +113,7 @@ export default {
if (newValue) { if (newValue) {
f7ready((f7) => { f7ready((f7) => {
self.notification = f7.notification.create({ self.notification = f7.notification.create({
icon: `<img alt="logo" src="${assetConstants.ezBookkeepingLogoPath}" />`, icon: `<img alt="logo" src="${APPLICATION_LOGO_PATH}" />`,
title: self.$t('global.app.title'), title: self.$t('global.app.title'),
text: newValue, text: newValue,
closeOnClick: true, closeOnClick: true,
+1 -1
View File
@@ -11,7 +11,7 @@
<script> <script>
import { import {
copyObjectTo copyObjectTo
} from '@/lib/common.js'; } from '@/lib/common.ts';
import { import {
createMapHolder, createMapHolder,
initMapInstance, initMapInstance,
+10 -10
View File
@@ -34,8 +34,8 @@ import { mapStores } from 'pinia';
import { useSettingsStore } from '@/stores/setting.js'; import { useSettingsStore } from '@/stores/setting.js';
import { useUserStore } from '@/stores/user.js'; import { useUserStore } from '@/stores/user.js';
import transactionConstants from '@/consts/transaction.js'; import { TRANSACTION_MIN_AMOUNT, TRANSACTION_MAX_AMOUNT } from '@/consts/transaction.ts';
import { removeAll } from '@/lib/common.js'; import { removeAll } from '@/lib/common.ts';
import logger from '@/lib/logger.js'; import logger from '@/lib/logger.js';
export default { export default {
@@ -76,7 +76,7 @@ export default {
return self.$t('Amount value is not number'); return self.$t('Amount value is not number');
} }
return (val >= transactionConstants.minAmountNumber && val <= transactionConstants.maxAmountNumber) || self.$t('Amount value exceeds limitation'); return (val >= TRANSACTION_MIN_AMOUNT && val <= TRANSACTION_MAX_AMOUNT) || self.$t('Amount value exceeds limitation');
} catch (ex) { } catch (ex) {
logger.warn('cannot parse amount in amount input, original value is ' + v, ex); logger.warn('cannot parse amount in amount input, original value is ' + v, ex);
return self.$t('Amount value is not number'); return self.$t('Amount value is not number');
@@ -222,7 +222,7 @@ export default {
} }
let decimalLength = 0; let decimalLength = 0;
let decimalIndex = str.indexOf(decimalSeparator); const decimalIndex = str.indexOf(decimalSeparator);
if (decimalIndex >= 0) { if (decimalIndex >= 0) {
decimalLength = str.length - str.indexOf(decimalSeparator) - 1; decimalLength = str.length - str.indexOf(decimalSeparator) - 1;
@@ -285,16 +285,16 @@ export default {
e.preventDefault(); e.preventDefault();
}, },
getValidFormattedValue(value, textualValue, hasDecimalSeparator) { getValidFormattedValue(value, textualValue, hasDecimalSeparator) {
let maxLength = transactionConstants.maxAmountNumber.toString().length; let maxLength = TRANSACTION_MAX_AMOUNT.toString().length;
if (value < 0) { if (value < 0) {
maxLength = transactionConstants.minAmountNumber.toString().length; maxLength = TRANSACTION_MIN_AMOUNT.toString().length;
} }
if (value < transactionConstants.minAmountNumber) { if (value < TRANSACTION_MIN_AMOUNT) {
return this.getFormattedValue(this.userStore, transactionConstants.minAmountNumber); return this.getFormattedValue(this.userStore, TRANSACTION_MIN_AMOUNT);
} else if (value > transactionConstants.maxAmountNumber) { } else if (value > TRANSACTION_MAX_AMOUNT) {
return this.getFormattedValue(this.userStore, transactionConstants.maxAmountNumber); return this.getFormattedValue(this.userStore, TRANSACTION_MAX_AMOUNT);
} }
if (!hasDecimalSeparator && textualValue.length > maxLength) { if (!hasDecimalSeparator && textualValue.length > maxLength) {
+5 -5
View File
@@ -39,10 +39,10 @@
</template> </template>
<script> <script>
import colorConstants from '@/consts/color.js'; import { DEFAULT_ICON_COLOR } from '@/consts/color.ts';
import { arrayContainsFieldValue } from '@/lib/common.js'; import { arrayContainsFieldValue } from '@/lib/common.ts';
import { getColorsInRows } from '@/lib/color.js'; import { getColorsInRows } from '@/lib/color.ts';
import { scrollToSelectedItem } from '@/lib/ui.desktop.js'; import { scrollToSelectedItem } from '@/lib/ui/desktop.js';
import { import {
mdiSquareRounded, mdiSquareRounded,
@@ -89,7 +89,7 @@ export default {
return arrayContainsFieldValue(row, 'id', this.modelValue); return arrayContainsFieldValue(row, 'id', this.modelValue);
}, },
getFinalColor(color) { getFinalColor(color) {
if (color && color !== colorConstants.defaultAccountColor) { if (color && color !== DEFAULT_ICON_COLOR) {
return '#' + color; return '#' + color;
} else { } else {
return 'var(--default-icon-color)'; return 'var(--default-icon-color)';
+1 -1
View File
@@ -15,7 +15,7 @@
</template> </template>
<script> <script>
import { isString } from '@/lib/common.js'; import { isString } from '@/lib/common.ts';
export default { export default {
props: [ props: [
@@ -60,7 +60,8 @@ import { mapStores } from 'pinia';
import { useUserStore } from '@/stores/user.js'; import { useUserStore } from '@/stores/user.js';
import datetimeConstants from '@/consts/datetime.js'; import datetimeConstants from '@/consts/datetime.js';
import { arrangeArrayWithNewStartIndex } from '@/lib/common.js'; import { ThemeType } from '@/core/theme.ts';
import { arrangeArrayWithNewStartIndex } from '@/lib/common.ts';
import { import {
getCurrentUnixTime, getCurrentUnixTime,
getCurrentYear, getCurrentYear,
@@ -122,7 +123,7 @@ export default {
} }
}, },
isDarkMode() { isDarkMode() {
return this.globalTheme.global.name.value === 'dark'; return this.globalTheme.global.name.value === ThemeType.Dark;
}, },
firstDayOfWeek() { firstDayOfWeek() {
return this.userStore.currentUserFirstDayOfWeek; return this.userStore.currentUserFirstDayOfWeek;
+3 -2
View File
@@ -43,7 +43,8 @@ import { useTheme } from 'vuetify';
import { mapStores } from 'pinia'; import { mapStores } from 'pinia';
import { useUserStore } from '@/stores/user.js'; import { useUserStore } from '@/stores/user.js';
import { arrangeArrayWithNewStartIndex } from '@/lib/common.js'; import { ThemeType } from '@/core/theme.ts';
import { arrangeArrayWithNewStartIndex } from '@/lib/common.ts';
import { import {
getCurrentYear, getCurrentYear,
getTimezoneOffsetMinutes, getTimezoneOffsetMinutes,
@@ -90,7 +91,7 @@ export default {
} }
}, },
isDarkMode() { isDarkMode() {
return this.globalTheme.global.name.value === 'dark'; return this.globalTheme.global.name.value === ThemeType.Dark;
}, },
firstDayOfWeek() { firstDayOfWeek() {
return this.userStore.currentUserFirstDayOfWeek; return this.userStore.currentUserFirstDayOfWeek;
+3 -3
View File
@@ -37,9 +37,9 @@
</template> </template>
<script> <script>
import { arrayContainsFieldValue } from '@/lib/common.js'; import { arrayContainsFieldValue } from '@/lib/common.ts';
import { getIconsInRows } from '@/lib/icon.js'; import { getIconsInRows } from '@/lib/icon.ts';
import { scrollToSelectedItem } from '@/lib/ui.desktop.js'; import { scrollToSelectedItem } from '@/lib/ui/desktop.js';
import { import {
mdiCheck mdiCheck
+12 -12
View File
@@ -12,9 +12,9 @@
</template> </template>
<script> <script>
import iconConstants from '@/consts/icon.js'; import { ALL_ACCOUNT_ICONS, DEFAULT_ACCOUNT_ICON, ALL_CATEGORY_ICONS, DEFAULT_CATEGORY_ICON } from '@/consts/icon.ts';
import colorConstants from '@/consts/color.js'; import { DEFAULT_ICON_COLOR, DEFAULT_ACCOUNT_COLOR, DEFAULT_CATEGORY_COLOR } from '@/consts/color.ts';
import { isNumber } from '@/lib/common.js'; import { isNumber } from '@/lib/common.ts';
import { import {
mdiEyeOffOutline mdiEyeOffOutline
@@ -74,25 +74,25 @@ export default {
iconId = iconId.toString(); iconId = iconId.toString();
} }
if (!iconConstants.allAccountIcons[iconId]) { if (!ALL_ACCOUNT_ICONS[iconId]) {
return iconConstants.defaultAccountIcon.icon; return DEFAULT_ACCOUNT_ICON.icon;
} }
return iconConstants.allAccountIcons[iconId].icon; return ALL_ACCOUNT_ICONS[iconId].icon;
}, },
getCategoryIcon(iconId) { getCategoryIcon(iconId) {
if (isNumber(iconId)) { if (isNumber(iconId)) {
iconId = iconId.toString(); iconId = iconId.toString();
} }
if (!iconConstants.allCategoryIcons[iconId]) { if (!ALL_CATEGORY_ICONS[iconId]) {
return iconConstants.defaultCategoryIcon.icon; return DEFAULT_CATEGORY_ICON.icon;
} }
return iconConstants.allCategoryIcons[iconId].icon; return ALL_CATEGORY_ICONS[iconId].icon;
}, },
getAccountIconStyle(color, defaultColor, additionalColorAttr) { getAccountIconStyle(color, defaultColor, additionalColorAttr) {
if (color && color !== colorConstants.defaultAccountColor) { if (color && color !== DEFAULT_ACCOUNT_COLOR) {
color = '#' + color; color = '#' + color;
} else { } else {
color = defaultColor; color = defaultColor;
@@ -113,7 +113,7 @@ export default {
return ret; return ret;
}, },
getCategoryIconStyle(color, defaultColor, additionalColorAttr) { getCategoryIconStyle(color, defaultColor, additionalColorAttr) {
if (color && color !== colorConstants.defaultCategoryColor) { if (color && color !== DEFAULT_CATEGORY_COLOR) {
color = '#' + color; color = '#' + color;
} else { } else {
color = defaultColor; color = defaultColor;
@@ -134,7 +134,7 @@ export default {
return ret; return ret;
}, },
getDefaultIconStyle(color, defaultColor, additionalColorAttr) { getDefaultIconStyle(color, defaultColor, additionalColorAttr) {
if (color && color !== colorConstants.defaultColor) { if (color && color !== DEFAULT_ICON_COLOR) {
color = '#' + color; color = '#' + color;
} else { } else {
color = defaultColor; color = defaultColor;
@@ -69,6 +69,7 @@ import { useTheme } from 'vuetify';
import { mapStores } from 'pinia'; import { mapStores } from 'pinia';
import { useUserStore } from '@/stores/user.js'; import { useUserStore } from '@/stores/user.js';
import { ThemeType } from '@/core/theme.ts';
import { import {
getYearMonthObjectFromString, getYearMonthObjectFromString,
getYearMonthStringFromObject, getYearMonthStringFromObject,
@@ -125,7 +126,7 @@ export default {
} }
}, },
isDarkMode() { isDarkMode() {
return this.globalTheme.global.name.value === 'dark'; return this.globalTheme.global.name.value === ThemeType.Dark;
}, },
isYearFirst() { isYearFirst() {
return this.$locale.isLongDateMonthAfterYear(this.userStore); return this.$locale.isLongDateMonthAfterYear(this.userStore);
+5 -4
View File
@@ -10,7 +10,8 @@ import { mapStores } from 'pinia';
import { useSettingsStore } from '@/stores/setting.js'; import { useSettingsStore } from '@/stores/setting.js';
import { useUserStore } from '@/stores/user.js'; import { useUserStore } from '@/stores/user.js';
import colorConstants from '@/consts/color.js'; import { DEFAULT_ICON_COLOR, DEFAULT_CHART_COLORS } from '@/consts/color.ts';
import { ThemeType } from '@/core/theme.ts';
import { formatPercent } from '@/lib/numeral.js'; import { formatPercent } from '@/lib/numeral.js';
export default { export default {
@@ -40,7 +41,7 @@ export default {
computed: { computed: {
...mapStores(useSettingsStore, useUserStore), ...mapStores(useSettingsStore, useUserStore),
isDarkMode() { isDarkMode() {
return this.globalTheme.global.name.value === 'dark'; return this.globalTheme.global.name.value === ThemeType.Dark;
}, },
itemsMap: function () { itemsMap: function () {
const map = {}; const map = {};
@@ -87,7 +88,7 @@ export default {
percent: (item[this.percentField] > 0 || item[this.percentField] === 0 || item[this.percentField] === '0') ? item[this.percentField] : (item[this.valueField] / totalValidValue * 100), percent: (item[this.percentField] > 0 || item[this.percentField] === 0 || item[this.percentField] === '0') ? item[this.percentField] : (item[this.valueField] / totalValidValue * 100),
actualPercent: item[this.valueField] / totalValidValue, actualPercent: item[this.valueField] / totalValidValue,
itemStyle: { itemStyle: {
color: this.getColor(item[this.colorField] ? item[this.colorField] : colorConstants.defaultChartColors[validItems.length % colorConstants.defaultChartColors.length]), color: this.getColor(item[this.colorField] ? item[this.colorField] : DEFAULT_CHART_COLORS[validItems.length % DEFAULT_CHART_COLORS.length]),
}, },
selected: true, selected: true,
sourceItem: item sourceItem: item
@@ -283,7 +284,7 @@ export default {
} }
}, },
getColor: function (color) { getColor: function (color) {
if (color && color !== colorConstants.defaultColor) { if (color && color !== DEFAULT_ICON_COLOR) {
color = '#' + color; color = '#' + color;
} }
@@ -58,9 +58,9 @@
import { mapStores } from 'pinia'; import { mapStores } from 'pinia';
import { useUserStore } from '@/stores/user.js'; import { useUserStore } from '@/stores/user.js';
import templateConstants from '@/consts/template.js'; import { ScheduledTemplateFrequencyType } from '@/core/template.ts';
import { sortNumbersArray } from '@/lib/common.js'; import { sortNumbersArray } from '@/lib/common.ts';
import { scrollToSelectedItem } from '@/lib/ui.desktop.js'; import { scrollToSelectedItem } from '@/lib/ui/desktop.js';
export default { export default {
props: [ props: [
@@ -85,7 +85,7 @@ export default {
return this.$locale.getAllTransactionScheduledFrequencyTypes(); return this.$locale.getAllTransactionScheduledFrequencyTypes();
}, },
allTemplateScheduledFrequencyTypes() { allTemplateScheduledFrequencyTypes() {
return templateConstants.allTemplateScheduledFrequencyTypes; return ScheduledTemplateFrequencyType.all();
}, },
allWeekDays() { allWeekDays() {
return this.$locale.getAllWeekDays(this.firstDayOfWeek); return this.$locale.getAllWeekDays(this.firstDayOfWeek);
@@ -113,9 +113,9 @@ export default {
if (this.type !== value) { if (this.type !== value) {
this.$emit('update:type', value); this.$emit('update:type', value);
if (value === templateConstants.allTemplateScheduledFrequencyTypes.Weekly.type) { if (value === ScheduledTemplateFrequencyType.Weekly.type) {
this.frequencyValue = [this.firstDayOfWeek]; this.frequencyValue = [this.firstDayOfWeek];
} else if (value === templateConstants.allTemplateScheduledFrequencyTypes.Monthly.type) { } else if (value === ScheduledTemplateFrequencyType.Monthly.type) {
this.frequencyValue = [1]; this.frequencyValue = [1];
} else { } else {
this.frequencyValue = []; this.frequencyValue = [];
@@ -141,9 +141,9 @@ export default {
} }
}, },
displayFrequency() { displayFrequency() {
if (this.type === templateConstants.allTemplateScheduledFrequencyTypes.Disabled.type) { if (this.type === ScheduledTemplateFrequencyType.Disabled.type) {
return this.$t('Disabled'); return this.$t('Disabled');
} else if (this.type === templateConstants.allTemplateScheduledFrequencyTypes.Weekly.type) { } else if (this.type === ScheduledTemplateFrequencyType.Weekly.type) {
if (this.frequencyValue.length) { if (this.frequencyValue.length) {
return this.$t('format.misc.everyMultiDaysOfWeek', { return this.$t('format.misc.everyMultiDaysOfWeek', {
days: this.$locale.getMultiWeekdayLongNames(this.frequencyValue, this.firstDayOfWeek) days: this.$locale.getMultiWeekdayLongNames(this.frequencyValue, this.firstDayOfWeek)
@@ -151,7 +151,7 @@ export default {
} else { } else {
return this.$t('Weekly'); return this.$t('Weekly');
} }
} else if (this.type === templateConstants.allTemplateScheduledFrequencyTypes.Monthly.type) { } else if (this.type === ScheduledTemplateFrequencyType.Monthly.type) {
if (this.frequencyValue.length) { if (this.frequencyValue.length) {
return this.$t('format.misc.everyMultiDaysOfMonth', { return this.$t('format.misc.everyMultiDaysOfMonth', {
days: this.$locale.getMultiMonthdayShortNames(this.frequencyValue) days: this.$locale.getMultiMonthdayShortNames(this.frequencyValue)
@@ -30,7 +30,7 @@
<script> <script>
import { getMobileUrlQrCodePath } from '@/lib/qrcode.js'; import { getMobileUrlQrCodePath } from '@/lib/qrcode.js';
import { getMobileVersionPath } from '@/lib/version.js'; import { getMobileVersionPath } from '@/lib/version.ts';
export default { export default {
props: [ props: [
+7 -6
View File
@@ -10,13 +10,14 @@ import { mapStores } from 'pinia';
import { useSettingsStore } from '@/stores/setting.js'; import { useSettingsStore } from '@/stores/setting.js';
import { useUserStore } from '@/stores/user.js'; import { useUserStore } from '@/stores/user.js';
import colorConstants from '@/consts/color.js'; import { DEFAULT_ICON_COLOR, DEFAULT_CHART_COLORS } from '@/consts/color.ts';
import datetimeConstants from '@/consts/datetime.js'; import datetimeConstants from '@/consts/datetime.js';
import statisticsConstants from '@/consts/statistics.js'; import statisticsConstants from '@/consts/statistics.js';
import { ThemeType } from '@/core/theme.ts';
import { import {
isArray, isArray,
isNumber isNumber
} from '@/lib/common.js'; } from '@/lib/common.ts';
import { import {
getYearMonthFirstUnixTime, getYearMonthFirstUnixTime,
getYearMonthLastUnixTime, getYearMonthLastUnixTime,
@@ -59,7 +60,7 @@ export default {
computed: { computed: {
...mapStores(useSettingsStore, useUserStore), ...mapStores(useSettingsStore, useUserStore),
isDarkMode() { isDarkMode() {
return this.globalTheme.global.name.value === 'dark'; return this.globalTheme.global.name.value === ThemeType.Dark;
}, },
itemsMap: function () { itemsMap: function () {
const map = {}; const map = {};
@@ -167,7 +168,7 @@ export default {
id: (this.idField && item[this.idField]) ? item[this.idField] : this.getItemName(item[this.nameField]), id: (this.idField && item[this.idField]) ? item[this.idField] : this.getItemName(item[this.nameField]),
name: (this.idField && item[this.idField]) ? item[this.idField] : this.getItemName(item[this.nameField]), name: (this.idField && item[this.idField]) ? item[this.idField] : this.getItemName(item[this.nameField]),
itemStyle: { itemStyle: {
color: this.getColor(item[this.colorField] ? item[this.colorField] : colorConstants.defaultChartColors[i % colorConstants.defaultChartColors.length]), color: this.getColor(item[this.colorField] ? item[this.colorField] : DEFAULT_CHART_COLORS[i % DEFAULT_CHART_COLORS.length]),
}, },
selected: true, selected: true,
type: 'line', type: 'line',
@@ -212,7 +213,7 @@ export default {
const maxValueText = this.getDisplayCurrency(maxValue, this.defaultCurrency); const maxValueText = this.getDisplayCurrency(maxValue, this.defaultCurrency);
const minValueText = this.getDisplayCurrency(minValue, this.defaultCurrency); const minValueText = this.getDisplayCurrency(minValue, this.defaultCurrency);
let maxLengthText = maxValueText.length > minValueText.length ? maxValueText : minValueText; const maxLengthText = maxValueText.length > minValueText.length ? maxValueText : minValueText;
const canvas = document.createElement('canvas'); const canvas = document.createElement('canvas');
const context = canvas.getContext('2d'); const context = canvas.getContext('2d');
@@ -387,7 +388,7 @@ export default {
}); });
}, },
getColor: function (color) { getColor: function (color) {
if (color && color !== colorConstants.defaultColor) { if (color && color !== DEFAULT_ICON_COLOR) {
color = '#' + color; color = '#' + color;
} }
+2 -2
View File
@@ -79,8 +79,8 @@ import {
getItemByKeyValue, getItemByKeyValue,
getNameByKeyValue, getNameByKeyValue,
getPrimaryValueBySecondaryValue getPrimaryValueBySecondaryValue
} from '@/lib/common.js'; } from '@/lib/common.ts';
import { scrollToSelectedItem } from '@/lib/ui.desktop.js'; import { scrollToSelectedItem } from '@/lib/ui/desktop.js';
import { import {
mdiChevronRight mdiChevronRight
@@ -29,9 +29,9 @@
</template> </template>
<script> <script>
import { arrayContainsFieldValue } from '@/lib/common.js'; import { arrayContainsFieldValue } from '@/lib/common.ts';
import { getColorsInRows } from '@/lib/color.js'; import { getColorsInRows } from '@/lib/color.ts';
import { scrollToSelectedItem } from '@/lib/ui.mobile.js'; import { scrollToSelectedItem } from '@/lib/ui/mobile.js';
export default { export default {
props: [ props: [
@@ -57,7 +57,7 @@ import { mapStores } from 'pinia';
import { useUserStore } from '@/stores/user.js'; import { useUserStore } from '@/stores/user.js';
import datetimeConstants from '@/consts/datetime.js'; import datetimeConstants from '@/consts/datetime.js';
import { arrangeArrayWithNewStartIndex } from '@/lib/common.js'; import { arrangeArrayWithNewStartIndex } from '@/lib/common.ts';
import { import {
getCurrentUnixTime, getCurrentUnixTime,
getCurrentYear, getCurrentYear,
@@ -53,7 +53,7 @@ import { mapStores } from 'pinia';
import { useUserStore } from '@/stores/user.js'; import { useUserStore } from '@/stores/user.js';
import datetimeConstants from '@/consts/datetime.js'; import datetimeConstants from '@/consts/datetime.js';
import { arrangeArrayWithNewStartIndex } from '@/lib/common.js'; import { arrangeArrayWithNewStartIndex } from '@/lib/common.ts';
import { import {
getCurrentUnixTime, getCurrentUnixTime,
getCurrentYear, getCurrentYear,
@@ -65,7 +65,7 @@ import {
getTimeValues, getTimeValues,
getCombinedDateAndTimeValues getCombinedDateAndTimeValues
} from '@/lib/datetime.js'; } from '@/lib/datetime.js';
import { createInlinePicker } from '@/lib/ui.mobile.js'; import { createInlinePicker } from '@/lib/ui/mobile.js';
export default { export default {
props: [ props: [
+3 -3
View File
@@ -29,9 +29,9 @@
</template> </template>
<script> <script>
import { arrayContainsFieldValue } from '@/lib/common.js'; import { arrayContainsFieldValue } from '@/lib/common.ts';
import { getIconsInRows } from '@/lib/icon.js'; import { getIconsInRows } from '@/lib/icon.ts';
import { scrollToSelectedItem } from '@/lib/ui.mobile.js'; import { scrollToSelectedItem } from '@/lib/ui/mobile.js';
export default { export default {
props: [ props: [
+3 -3
View File
@@ -25,7 +25,7 @@
</template> </template>
<script> <script>
import { makeButtonCopyToClipboard, changeClipboardObjectText } from '@/lib/misc.js'; import { ClipboardHolder } from '@/lib/clipboard.ts';
export default { export default {
props: [ props: [
@@ -54,7 +54,7 @@ export default {
watch: { watch: {
'information': function (newValue) { 'information': function (newValue) {
if (this.clipboardHolder) { if (this.clipboardHolder) {
changeClipboardObjectText(this.clipboardHolder, newValue); this.clipboardHolder.setClipboardText(newValue);
} }
} }
}, },
@@ -73,7 +73,7 @@ export default {
} }
if (self.$refs.copyToClipboardIcon) { if (self.$refs.copyToClipboardIcon) {
self.clipboardHolder = makeButtonCopyToClipboard({ self.clipboardHolder = ClipboardHolder.create({
el: '#copy-to-clipboard-icon', el: '#copy-to-clipboard-icon',
text: self.information, text: self.information,
successCallback: function () { successCallback: function () {
+12 -12
View File
@@ -5,9 +5,9 @@
</template> </template>
<script> <script>
import iconConstants from '@/consts/icon.js'; import { ALL_ACCOUNT_ICONS, DEFAULT_ACCOUNT_ICON, ALL_CATEGORY_ICONS, DEFAULT_CATEGORY_ICON } from '@/consts/icon.ts';
import colorConstants from '@/consts/color.js'; import { DEFAULT_ICON_COLOR, DEFAULT_ACCOUNT_COLOR, DEFAULT_CATEGORY_COLOR } from '@/consts/color.ts';
import { isNumber } from '@/lib/common.js'; import { isNumber } from '@/lib/common.ts';
export default { export default {
props: [ props: [
@@ -58,25 +58,25 @@ export default {
iconId = iconId.toString(); iconId = iconId.toString();
} }
if (!iconConstants.allAccountIcons[iconId]) { if (!ALL_ACCOUNT_ICONS[iconId]) {
return iconConstants.defaultAccountIcon.icon; return DEFAULT_ACCOUNT_ICON.icon;
} }
return iconConstants.allAccountIcons[iconId].icon; return ALL_ACCOUNT_ICONS[iconId].icon;
}, },
getCategoryIcon(iconId) { getCategoryIcon(iconId) {
if (isNumber(iconId)) { if (isNumber(iconId)) {
iconId = iconId.toString(); iconId = iconId.toString();
} }
if (!iconConstants.allCategoryIcons[iconId]) { if (!ALL_CATEGORY_ICONS[iconId]) {
return iconConstants.defaultCategoryIcon.icon; return DEFAULT_CATEGORY_ICON.icon;
} }
return iconConstants.allCategoryIcons[iconId].icon; return ALL_CATEGORY_ICONS[iconId].icon;
}, },
getAccountIconStyle(color, defaultColor, additionalColorAttr) { getAccountIconStyle(color, defaultColor, additionalColorAttr) {
if (color && color !== colorConstants.defaultAccountColor) { if (color && color !== DEFAULT_ACCOUNT_COLOR) {
color = '#' + color; color = '#' + color;
} else { } else {
color = defaultColor; color = defaultColor;
@@ -93,7 +93,7 @@ export default {
return ret; return ret;
}, },
getCategoryIconStyle(color, defaultColor, additionalColorAttr) { getCategoryIconStyle(color, defaultColor, additionalColorAttr) {
if (color && color !== colorConstants.defaultCategoryColor) { if (color && color !== DEFAULT_CATEGORY_COLOR) {
color = '#' + color; color = '#' + color;
} else { } else {
color = defaultColor; color = defaultColor;
@@ -110,7 +110,7 @@ export default {
return ret; return ret;
}, },
getDefaultIconStyle(color, defaultColor, additionalColorAttr) { getDefaultIconStyle(color, defaultColor, additionalColorAttr) {
if (color && color !== colorConstants.defaultColor) { if (color && color !== DEFAULT_ICON_COLOR) {
color = '#' + color; color = '#' + color;
} else { } else {
color = defaultColor; color = defaultColor;
@@ -32,7 +32,7 @@
</template> </template>
<script> <script>
import { scrollToSelectedItem } from '@/lib/ui.mobile.js'; import { scrollToSelectedItem } from '@/lib/ui/mobile.js';
export default { export default {
props: [ props: [
+6 -6
View File
@@ -69,8 +69,8 @@
import { mapStores } from 'pinia'; import { mapStores } from 'pinia';
import { useUserStore } from '@/stores/user.js'; import { useUserStore } from '@/stores/user.js';
import currencyConstants from '@/consts/currency.js'; import { ALL_CURRENCIES } from '@/consts/currency.ts';
import { isString, isNumber, removeAll } from '@/lib/common.js'; import { isString, isNumber, removeAll } from '@/lib/common.ts';
export default { export default {
props: [ props: [
@@ -100,11 +100,11 @@ export default {
return this.$locale.getCurrentDecimalSeparator(this.userStore); return this.$locale.getCurrentDecimalSeparator(this.userStore);
}, },
supportDecimalSeparator() { supportDecimalSeparator() {
if (!this.currency || !currencyConstants.all[this.currency] || !isNumber(currencyConstants.all[this.currency].fraction)) { if (!this.currency || !ALL_CURRENCIES[this.currency] || !isNumber(ALL_CURRENCIES[this.currency].fraction)) {
return true; return true;
} }
return currencyConstants.all[this.currency].fraction > 0; return ALL_CURRENCIES[this.currency].fraction > 0;
}, },
currentDisplay() { currentDisplay() {
const previousValue = this.$locale.appendDigitGroupingSymbol(this.userStore, this.previousValue); const previousValue = this.$locale.appendDigitGroupingSymbol(this.userStore, this.previousValue);
@@ -160,8 +160,8 @@ export default {
return str; return str;
} }
let integer = str.substring(0, decimalSeparatorPos); const integer = str.substring(0, decimalSeparatorPos);
let decimals = str.substring(decimalSeparatorPos + 1, str.length); const decimals = str.substring(decimalSeparatorPos + 1, str.length);
let newDecimals = ''; let newDecimals = '';
for (let i = decimals.length - 1; i >= 0; i--) { for (let i = decimals.length - 1; i >= 0; i--) {
+3 -3
View File
@@ -81,7 +81,7 @@ import { mapStores } from 'pinia';
import { useSettingsStore } from '@/stores/setting.js'; import { useSettingsStore } from '@/stores/setting.js';
import { useUserStore } from '@/stores/user.js'; import { useUserStore } from '@/stores/user.js';
import colorConstants from '@/consts/color.js'; import { DEFAULT_ICON_COLOR, DEFAULT_CHART_COLORS } from '@/consts/color.ts';
import { formatPercent } from '@/lib/numeral.js'; import { formatPercent } from '@/lib/numeral.js';
export default { export default {
@@ -139,7 +139,7 @@ export default {
value: item[this.valueField], value: item[this.valueField],
percent: (item[this.percentField] > 0 || item[this.percentField] === 0 || item[this.percentField] === '0') ? item[this.percentField] : (item[this.valueField] / totalValidValue * 100), percent: (item[this.percentField] > 0 || item[this.percentField] === 0 || item[this.percentField] === '0') ? item[this.percentField] : (item[this.valueField] / totalValidValue * 100),
actualPercent: item[this.valueField] / totalValidValue, actualPercent: item[this.valueField] / totalValidValue,
color: item[this.colorField] ? item[this.colorField] : colorConstants.defaultChartColors[validItems.length % colorConstants.defaultChartColors.length], color: item[this.colorField] ? item[this.colorField] : DEFAULT_CHART_COLORS[validItems.length % DEFAULT_CHART_COLORS.length],
sourceItem: item sourceItem: item
}; };
@@ -223,7 +223,7 @@ export default {
} }
}, },
getColor: function (color) { getColor: function (color) {
if (color && color !== colorConstants.defaultColor) { if (color && color !== DEFAULT_ICON_COLOR) {
color = '#' + color; color = '#' + color;
} else { } else {
color = 'var(--default-icon-color)'; color = 'var(--default-icon-color)';
@@ -68,9 +68,9 @@
import { mapStores } from 'pinia'; import { mapStores } from 'pinia';
import { useUserStore } from '@/stores/user.js'; import { useUserStore } from '@/stores/user.js';
import templateConstants from '@/consts/template.js'; import { ScheduledTemplateFrequencyType } from '@/core/template.ts';
import { sortNumbersArray } from '@/lib/common.js'; import { sortNumbersArray } from '@/lib/common.ts';
import { scrollToSelectedItem } from '@/lib/ui.mobile.js'; import { scrollToSelectedItem } from '@/lib/ui/mobile.js';
export default { export default {
props: [ props: [
@@ -100,7 +100,7 @@ export default {
return this.$locale.getAllTransactionScheduledFrequencyTypes(); return this.$locale.getAllTransactionScheduledFrequencyTypes();
}, },
allTemplateScheduledFrequencyTypes() { allTemplateScheduledFrequencyTypes() {
return templateConstants.allTemplateScheduledFrequencyTypes; return ScheduledTemplateFrequencyType.all();
}, },
allWeekDays() { allWeekDays() {
return this.$locale.getAllWeekDays(this.firstDayOfWeek); return this.$locale.getAllWeekDays(this.firstDayOfWeek);
@@ -134,9 +134,9 @@ export default {
if (this.currentFrequencyType !== value) { if (this.currentFrequencyType !== value) {
this.currentFrequencyType = value; this.currentFrequencyType = value;
if (value === templateConstants.allTemplateScheduledFrequencyTypes.Weekly.type) { if (value === ScheduledTemplateFrequencyType.Weekly.type) {
this.currentFrequencyValue = [this.firstDayOfWeek]; this.currentFrequencyValue = [this.firstDayOfWeek];
} else if (value === templateConstants.allTemplateScheduledFrequencyTypes.Monthly.type) { } else if (value === ScheduledTemplateFrequencyType.Monthly.type) {
this.currentFrequencyValue = [1]; this.currentFrequencyValue = [1];
} else { } else {
this.currentFrequencyValue = []; this.currentFrequencyValue = [];
@@ -79,8 +79,8 @@
import { mapStores } from 'pinia'; import { mapStores } from 'pinia';
import { useTransactionTagsStore } from '@/stores/transactionTag.js'; import { useTransactionTagsStore } from '@/stores/transactionTag.js';
import { copyArrayTo } from '@/lib/common.js'; import { copyArrayTo } from '@/lib/common.ts';
import { scrollToSelectedItem } from '@/lib/ui.mobile.js'; import { scrollToSelectedItem } from '@/lib/ui/mobile.js';
export default { export default {
props: [ props: [
@@ -41,8 +41,8 @@
</template> </template>
<script> <script>
import { isArray } from '@/lib/common.js'; import { isArray } from '@/lib/common.ts';
import { scrollToSelectedItem } from '@/lib/ui.mobile.js'; import { scrollToSelectedItem } from '@/lib/ui/mobile.js';
export default { export default {
props: [ props: [
@@ -85,7 +85,7 @@ export default {
if (isArray(this.items)) { if (isArray(this.items)) {
count = this.items.length; count = this.items.length;
} else { } else {
for (let field in this.items) { for (const field in this.items) {
if (!Object.prototype.hasOwnProperty.call(this.items, field)) { if (!Object.prototype.hasOwnProperty.call(this.items, field)) {
continue; continue;
} }
+4 -4
View File
@@ -93,10 +93,10 @@ import { mapStores } from 'pinia';
import { useSettingsStore } from '@/stores/setting.js'; import { useSettingsStore } from '@/stores/setting.js';
import { useUserStore } from '@/stores/user.js'; import { useUserStore } from '@/stores/user.js';
import colorConstants from '@/consts/color.js'; import { DEFAULT_ICON_COLOR, DEFAULT_CHART_COLORS } from '@/consts/color.ts';
import datetimeConstants from '@/consts/datetime.js'; import datetimeConstants from '@/consts/datetime.js';
import statisticsConstants from '@/consts/statistics.js'; import statisticsConstants from '@/consts/statistics.js';
import { isNumber } from '@/lib/common.js'; import { isNumber } from '@/lib/common.ts';
import { import {
getYearMonthFirstUnixTime, getYearMonthFirstUnixTime,
getYearMonthLastUnixTime, getYearMonthLastUnixTime,
@@ -154,7 +154,7 @@ export default {
const legend = { const legend = {
id: id, id: id,
name: (this.nameField && item[this.nameField]) ? this.getItemName(item[this.nameField]) : id, name: (this.nameField && item[this.nameField]) ? this.getItemName(item[this.nameField]) : id,
color: this.getColor(item[this.colorField] ? item[this.colorField] : colorConstants.defaultChartColors[i % colorConstants.defaultChartColors.length]), color: this.getColor(item[this.colorField] ? item[this.colorField] : DEFAULT_CHART_COLORS[i % DEFAULT_CHART_COLORS.length]),
displayOrders: (this.displayOrdersField && item[this.displayOrdersField]) ? item[this.displayOrdersField] : [0] displayOrders: (this.displayOrdersField && item[this.displayOrdersField]) ? item[this.displayOrdersField] : [0]
}; };
@@ -322,7 +322,7 @@ export default {
} }
}, },
getColor: function (color) { getColor: function (color) {
if (color && color !== colorConstants.defaultColor) { if (color && color !== DEFAULT_ICON_COLOR) {
color = '#' + color; color = '#' + color;
} }
@@ -65,8 +65,8 @@
import { import {
getItemByKeyValue, getItemByKeyValue,
getPrimaryValueBySecondaryValue getPrimaryValueBySecondaryValue
} from '@/lib/common.js'; } from '@/lib/common.ts';
import { scrollToSelectedItem } from '@/lib/ui.mobile.js'; import { scrollToSelectedItem } from '@/lib/ui/mobile.js';
export default { export default {
props: [ props: [
-80
View File
@@ -1,80 +0,0 @@
const allAccountCategories = {
Cash: {
id: 1,
name: 'Cash',
defaultAccountIconId: '1'
},
CheckingAccount: {
id: 2,
name: 'Checking Account',
defaultAccountIconId: '100'
},
SavingsAccount: {
id: 8,
name: 'Savings Account',
defaultAccountIconId: '100'
},
CreditCard: {
id: 3,
name: 'Credit Card',
defaultAccountIconId: '100'
},
VirtualAccount: {
id: 4,
name: 'Virtual Account',
defaultAccountIconId: '500'
},
DebtAccount: {
id: 5,
name: 'Debt Account',
defaultAccountIconId: '600'
},
Receivables: {
id: 6,
name: 'Receivables',
defaultAccountIconId: '700'
},
CertificatePfDeposit: {
id: 9,
name: 'Certificate of Deposit',
defaultAccountIconId: '110'
},
InvestmentAccount: {
id: 7,
name: 'Investment Account',
defaultAccountIconId: '800'
}
};
const allAccountCategoriesArray = [
allAccountCategories.Cash,
allAccountCategories.CheckingAccount,
allAccountCategories.SavingsAccount,
allAccountCategories.CreditCard,
allAccountCategories.VirtualAccount,
allAccountCategories.DebtAccount,
allAccountCategories.Receivables,
allAccountCategories.CertificatePfDeposit,
allAccountCategories.InvestmentAccount
];
const allAccountTypes = {
SingleAccount: 1,
MultiSubAccounts: 2
};
const allAccountTypesArray = [
{
id: allAccountTypes.SingleAccount,
name: 'Single Account'
}, {
id: allAccountTypes.MultiSubAccounts,
name: 'Multiple Sub-accounts'
}
];
export default {
cashCategoryType: allAccountCategories.Cash.id,
creditCardCategoryType: allAccountCategories.CreditCard.id,
allCategories: allAccountCategoriesArray,
allAccountTypes: allAccountTypes,
allAccountTypesArray: allAccountTypesArray,
};
+36 -39
View File
@@ -1,27 +1,45 @@
const defaultTimeout = 10000; // 10s export const BASE_API_URL_PATH: string = '/api';
const uploadTimeout = 30000; // 30s export const BASE_QRCODE_PATH: string = '/qrcode';
const importTimeout = 1800000; // 1800s export const BASE_PROXY_URL_PATH: string = '/proxy';
const baseApiUrlPath = '/api'; export const BASE_AMAP_API_PROXY_URL_PATH: string = '/_AMapService';
const baseQrcodePath = '/qrcode';
const baseProxyUrlPath = '/proxy';
const baseAmapApiProxyUrlPath = '/_AMapService';
const apiNotFoundErrorCode = 100001;
const validatorErrorCode = 200000;
const userEmailNotVerifiedErrorCode = 201020;
const transactionCannotCreateInThisTimeErrorCode = 205017;
const transactionCannotModifyInThisTimeErrorCode = 205018;
const transactionPictureNotFoundErrorCode = 211001;
const googleMapJavascriptUrl = 'https://maps.googleapis.com/maps/api/js';
const baiduMapJavascriptUrl = 'https://api.map.baidu.com/api?v=3.0';
const amapJavascriptUrl = 'https://webapi.amap.com/maps?v=2.0';
const specifiedApiNotFoundErrors = { export const DEFAULT_API_TIMEOUT: number = 10000; // 10s
export const DEFAULT_UPLOAD_API_TIMEOUT: number = 30000; // 30s
export const DEFAULT_IMPORT_API_TIMEOUT: number = 1800000; // 1800s
export const GOOGLE_MAP_JAVASCRIPT_URL: string = 'https://maps.googleapis.com/maps/api/js';
export const BAIDU_MAP_JAVASCRIPT_URL: string = 'https://api.map.baidu.com/api?v=3.0';
export const AMAP_JAVASCRIPT_URL: string = 'https://webapi.amap.com/maps?v=2.0';
export enum KnownErrorCode {
ApiNotFound = 100001,
ValidatorError = 200000,
UserEmailNotVerified = 201020,
TransactionCannotCreateInThisTime = 205017,
TransactionCannotModifyInThisTime = 205018,
TransactionPictureNotFound = 211001
}
export interface SpecifiedApiError {
readonly message: string;
}
export const SPECIFIED_API_NOT_FOUND_ERRORS: Record<string, SpecifiedApiError> = {
'/api/register.json': { '/api/register.json': {
message: 'User registration is disabled' message: 'User registration is disabled'
} }
}; };
const parameterizedErrors = [ export interface ParameterizedError {
readonly localeKey: string;
readonly regex: RegExp;
readonly parameters: {
readonly field: string;
readonly localized: boolean;
}[];
}
export const PARAMETERIZED_ERRORS: ParameterizedError[] = [
{ {
localeKey: 'parameter invalid', localeKey: 'parameter invalid',
regex: /^parameter "(\w+)" is invalid$/, regex: /^parameter "(\w+)" is invalid$/,
@@ -142,24 +160,3 @@ const parameterizedErrors = [
}] }]
} }
]; ];
export default {
defaultTimeout: defaultTimeout,
uploadTimeout: uploadTimeout,
importTimeout: importTimeout,
baseApiUrlPath: baseApiUrlPath,
baseQrcodePath: baseQrcodePath,
baseProxyUrlPath: baseProxyUrlPath,
baseAmapApiProxyUrlPath: baseAmapApiProxyUrlPath,
apiNotFoundErrorCode: apiNotFoundErrorCode,
validatorErrorCode: validatorErrorCode,
userEmailNotVerifiedErrorCode: userEmailNotVerifiedErrorCode,
transactionCannotCreateInThisTimeErrorCode: transactionCannotCreateInThisTimeErrorCode,
transactionCannotModifyInThisTimeErrorCode: transactionCannotModifyInThisTimeErrorCode,
transactionPictureNotFoundErrorCode: transactionPictureNotFoundErrorCode,
specifiedApiNotFoundErrors: specifiedApiNotFoundErrors,
parameterizedErrors: parameterizedErrors,
googleMapJavascriptUrl: googleMapJavascriptUrl,
baiduMapJavascriptUrl: baiduMapJavascriptUrl,
amapJavascriptUrl: amapJavascriptUrl
}
-6
View File
@@ -1,6 +0,0 @@
const baseImagePath = 'img';
const ezBookkeepingLogoPath = baseImagePath + '/ezbookkeeping-192.png';
export default {
ezBookkeepingLogoPath: ezBookkeepingLogoPath
}
+2
View File
@@ -0,0 +1,2 @@
const baseImagePath: string = 'img';
export const APPLICATION_LOGO_PATH: string = baseImagePath + '/ezbookkeeping-192.png';
@@ -1,10 +1,19 @@
const allCategoryTypes = { import type { ColorValue } from '@/core/color.ts';
Income: 1,
Expense: 2,
Transfer: 3
};
const defaultExpenseCategories = [ export interface PresetCategory {
name: string;
categoryIconId: string;
color: ColorValue;
subCategories: PresetSubCategory[];
}
export interface PresetSubCategory {
name: string;
categoryIconId: string;
color: ColorValue;
}
export const DEFAULT_EXPENSE_CATEGORIES: PresetCategory[] = [
{ {
name: 'Food & Drink', name: 'Food & Drink',
categoryIconId: '1', categoryIconId: '1',
@@ -294,7 +303,7 @@ const defaultExpenseCategories = [
} }
]; ];
const defaultIncomeCategories = [ export const DEFAULT_INCOME_CATEGORIES: PresetCategory[] = [
{ {
name: 'Occupational Earnings', name: 'Occupational Earnings',
categoryIconId: '2000', categoryIconId: '2000',
@@ -373,7 +382,7 @@ const defaultIncomeCategories = [
} }
]; ];
const defaultTransferCategories = [ export const DEFAULT_TRANSFER_CATEGORIES: PresetCategory[] = [
{ {
name: 'General Transfer', name: 'General Transfer',
categoryIconId: '4000', categoryIconId: '4000',
@@ -447,10 +456,3 @@ const defaultTransferCategories = [
] ]
} }
]; ];
export default {
allCategoryTypes: allCategoryTypes,
defaultExpenseCategories: defaultExpenseCategories,
defaultIncomeCategories: defaultIncomeCategories,
defaultTransferCategories: defaultTransferCategories,
};
-98
View File
@@ -1,98 +0,0 @@
const defaultColor = '000000';
const allAvailableColors = [
'000000', // black
'8e8e93', // gray
'ff3b30', // red
'ff2d55', // pink
'ff6b22', // deep orange
'ff9500', // orange
'ffcc00', // yellow
'cddc39', // lime
'009688', // teal
'4cd964', // green
'5ac8fa', // light blue
'2196f3', // blue
'673ab7', // deep purple
'9c27b0', // purple
];
const defaultChartColors = [
'cc4a66',
'e3564a',
'fc892c',
'ffc349',
'4dd291',
'24ceb3',
'2ab4d0',
'065786',
'713670',
'8e1d51'
];
const allAmountColors = {
Green: {
type: 1,
name: 'Green',
lightThemeColor: '#009688',
darkThemeColor: '#009688',
expenseClassName: 'expense-amount-color-green',
incomeClassName: 'income-amount-color-green'
},
Red: {
type: 2,
name: 'Red',
lightThemeColor: '#d43f3f',
darkThemeColor: '#d43f3f',
expenseClassName: 'expense-amount-color-red',
incomeClassName: 'income-amount-color-red'
},
Yellow: {
type: 3,
name: 'Yellow',
lightThemeColor: '#e2b60a',
darkThemeColor: '#e2b60a',
expenseClassName: 'expense-amount-color-yellow',
incomeClassName: 'income-amount-color-yellow'
},
BlackOrWhite: {
type: 4,
name: 'Black or White',
lightThemeColor: '#413935',
darkThemeColor: '#fcf0e3',
expenseClassName: 'expense-amount-color-blackorwhite',
incomeClassName: 'income-amount-color-blackorwhite'
}
}
const allAmountColorsArray = [
allAmountColors.Green,
allAmountColors.Red,
allAmountColors.Yellow,
allAmountColors.BlackOrWhite
];
const allAmountColorTypesMap = {
[allAmountColors.Green.type]: allAmountColors.Green,
[allAmountColors.Red.type]: allAmountColors.Red,
[allAmountColors.Yellow.type]: allAmountColors.Yellow,
[allAmountColors.BlackOrWhite.type]: allAmountColors.BlackOrWhite
};
const defaultExpenseIncomeAmountValue = 0;
const defaultExpenseAmountColor = allAmountColors.Green;
const defaultIncomeAmountColor = allAmountColors.Red;
export default {
defaultColor: defaultColor,
allAccountColors: allAvailableColors,
defaultAccountColor: defaultColor,
allCategoryColors: allAvailableColors,
defaultCategoryColor: defaultColor,
defaultChartColors: defaultChartColors,
allAmountColors: allAmountColors,
allAmountColorsArray: allAmountColorsArray,
allAmountColorTypesMap: allAmountColorTypesMap,
defaultExpenseIncomeAmountValue: defaultExpenseIncomeAmountValue,
defaultExpenseAmountColor: defaultExpenseAmountColor,
defaultIncomeAmountColor: defaultIncomeAmountColor,
};
+40
View File
@@ -0,0 +1,40 @@
import type { ColorValue } from '@/core/color.ts';
const defaultColor: ColorValue = '000000';
export const DEFAULT_ICON_COLOR: ColorValue = defaultColor;
export const DEFAULT_ACCOUNT_COLOR: ColorValue = defaultColor;
export const DEFAULT_CATEGORY_COLOR: ColorValue = defaultColor;
const allAvailableColors: ColorValue[] = [
'000000', // black
'8e8e93', // gray
'ff3b30', // red
'ff2d55', // pink
'ff6b22', // deep orange
'ff9500', // orange
'ffcc00', // yellow
'cddc39', // lime
'009688', // teal
'4cd964', // green
'5ac8fa', // light blue
'2196f3', // blue
'673ab7', // deep purple
'9c27b0', // purple
];
export const ALL_ACCOUNT_COLORS: ColorValue[] = allAvailableColors;
export const ALL_CATEGORY_COLORS: ColorValue[] = allAvailableColors;
export const DEFAULT_CHART_COLORS: ColorValue[] = [
'cc4a66',
'e3564a',
'fc892c',
'ffc349',
'4dd291',
'24ceb3',
'2ab4d0',
'065786',
'713670',
'8e1d51'
];
+13 -177
View File
@@ -1,9 +1,16 @@
const parentAccountCurrencyPlaceholder = '---'; export interface CurrencyInfo {
const defaultCurrencySymbol = '¤'; readonly code: string,
readonly fraction?: number,
readonly symbol?: {
readonly normal: string,
readonly plural?: string
},
readonly unit: string
}
// ISO 4217 // ISO 4217
// Reference: https://www.six-group.com/dam/download/financial-information/data-center/iso-currrency/lists/list-one.xml // Reference: https://www.six-group.com/dam/download/financial-information/data-center/iso-currrency/lists/list-one.xml
const allCurrencies = { export const ALL_CURRENCIES: Record<string, CurrencyInfo> = {
'AED': { // UAE Dirham 'AED': { // UAE Dirham
code: 'AED', code: 'AED',
fraction: 2, fraction: 2,
@@ -1284,177 +1291,6 @@ const allCurrencies = {
} }
}; };
const allCurrencyDisplaySymbol = { export const DEFAULT_CURRENCY_SYMBOL: string = '¤';
None: 0, export const DEFAULT_CURRENCY_CODE: string = ALL_CURRENCIES.USD.code;
Symbol: 1, export const PARENT_ACCOUNT_CURRENCY_PLACEHOLDER: string = '---';
Code: 2,
Unit: 3,
Name: 4
};
const allCurrencyDisplayLocation = {
BeforeAmount: 0,
AfterAmount: 1
};
const allCurrencyDisplayType = {
None: {
type: 1,
name: 'None',
fraction: 2,
symbol: allCurrencyDisplaySymbol.None,
separator: ''
},
SymbolBeforeAmount: {
type: 2,
name: 'Currency Symbol',
fraction: 2,
symbol: allCurrencyDisplaySymbol.Symbol,
location: allCurrencyDisplayLocation.BeforeAmount,
separator: ' '
},
SymbolAfterAmount: {
type: 3,
name: 'Currency Symbol',
fraction: 2,
symbol: allCurrencyDisplaySymbol.Symbol,
location: allCurrencyDisplayLocation.AfterAmount,
separator: ' '
},
SymbolBeforeAmountWithoutSpace: {
type: 4,
name: 'Currency Symbol',
fraction: 2,
symbol: allCurrencyDisplaySymbol.Symbol,
location: allCurrencyDisplayLocation.BeforeAmount,
separator: ''
},
SymbolAfterAmountWithoutSpace: {
type: 5,
name: 'Currency Symbol',
fraction: 2,
symbol: allCurrencyDisplaySymbol.Symbol,
location: allCurrencyDisplayLocation.AfterAmount,
separator: ''
},
CodeBeforeAmount: {
type: 6,
name: 'Currency Code',
fraction: 2,
symbol: allCurrencyDisplaySymbol.Code,
location: allCurrencyDisplayLocation.BeforeAmount,
separator: ' '
},
CodeAfterAmount: {
type: 7,
name: 'Currency Code',
fraction: 2,
symbol: allCurrencyDisplaySymbol.Code,
location: allCurrencyDisplayLocation.AfterAmount,
separator: ' '
},
UnitBeforeAmount: {
type: 8,
name: 'Currency Unit',
fraction: 2,
symbol: allCurrencyDisplaySymbol.Unit,
location: allCurrencyDisplayLocation.BeforeAmount,
separator: ' '
},
UnitAfterAmount: {
type: 9,
name: 'Currency Unit',
fraction: 2,
symbol: allCurrencyDisplaySymbol.Unit,
location: allCurrencyDisplayLocation.AfterAmount,
separator: ' '
},
NameBeforeAmount: {
type: 10,
name: 'Currency Name',
fraction: 2,
symbol: allCurrencyDisplaySymbol.Name,
location: allCurrencyDisplayLocation.BeforeAmount,
separator: ' '
},
NameAfterAmount: {
type: 11,
name: 'Currency Name',
fraction: 2,
symbol: allCurrencyDisplaySymbol.Name,
location: allCurrencyDisplayLocation.AfterAmount,
separator: ' '
}
};
const allCurrencyDisplayTypeArray = [
allCurrencyDisplayType.None,
allCurrencyDisplayType.SymbolBeforeAmount,
allCurrencyDisplayType.SymbolAfterAmount,
allCurrencyDisplayType.SymbolBeforeAmountWithoutSpace,
allCurrencyDisplayType.SymbolAfterAmountWithoutSpace,
allCurrencyDisplayType.CodeBeforeAmount,
allCurrencyDisplayType.CodeAfterAmount,
allCurrencyDisplayType.UnitBeforeAmount,
allCurrencyDisplayType.UnitAfterAmount,
allCurrencyDisplayType.NameBeforeAmount,
allCurrencyDisplayType.NameAfterAmount
];
const allCurrencyDisplayTypeMap = {
[allCurrencyDisplayType.None.type]: allCurrencyDisplayType.None,
[allCurrencyDisplayType.SymbolBeforeAmount.type]: allCurrencyDisplayType.SymbolBeforeAmount,
[allCurrencyDisplayType.SymbolAfterAmount.type]: allCurrencyDisplayType.SymbolAfterAmount,
[allCurrencyDisplayType.SymbolBeforeAmountWithoutSpace.type]: allCurrencyDisplayType.SymbolBeforeAmountWithoutSpace,
[allCurrencyDisplayType.SymbolAfterAmountWithoutSpace.type]: allCurrencyDisplayType.SymbolAfterAmountWithoutSpace,
[allCurrencyDisplayType.CodeBeforeAmount.type]: allCurrencyDisplayType.CodeBeforeAmount,
[allCurrencyDisplayType.CodeAfterAmount.type]: allCurrencyDisplayType.CodeAfterAmount,
[allCurrencyDisplayType.UnitBeforeAmount.type]: allCurrencyDisplayType.UnitBeforeAmount,
[allCurrencyDisplayType.UnitAfterAmount.type]: allCurrencyDisplayType.UnitAfterAmount,
[allCurrencyDisplayType.NameBeforeAmount.type]: allCurrencyDisplayType.NameBeforeAmount,
[allCurrencyDisplayType.NameAfterAmount.type]: allCurrencyDisplayType.NameAfterAmount
};
const defaultCurrency = allCurrencies.USD.code;
const defaultCurrencyDisplayType = allCurrencyDisplayType.SymbolBeforeAmount;
const defaultCurrencyDisplayTypeValue = 0;
const allCurrencySortingTypes = {
Name: {
type: 0,
name: 'Currency Name'
},
CurrencyCode: {
type: 1,
name: 'Currency Code'
},
ExchangeRate: {
type: 2,
name: 'Exchange Rate'
}
};
const allCurrencySortingTypesArray = [
allCurrencySortingTypes.Name,
allCurrencySortingTypes.CurrencyCode,
allCurrencySortingTypes.ExchangeRate
]
const defaultCurrencySortingType = allCurrencySortingTypes.Name.type;
export default {
parentAccountCurrencyPlaceholder: parentAccountCurrencyPlaceholder,
defaultCurrencySymbol: defaultCurrencySymbol,
all: allCurrencies,
defaultCurrency: defaultCurrency,
allCurrencyDisplaySymbol: allCurrencyDisplaySymbol,
allCurrencyDisplayLocation: allCurrencyDisplayLocation,
allCurrencyDisplayType: allCurrencyDisplayType,
allCurrencyDisplayTypeArray: allCurrencyDisplayTypeArray,
allCurrencyDisplayTypeMap: allCurrencyDisplayTypeMap,
defaultCurrencyDisplayType: defaultCurrencyDisplayType,
defaultCurrencyDisplayTypeValue: defaultCurrencyDisplayTypeValue,
allCurrencySortingTypes: allCurrencySortingTypes,
allCurrencySortingTypesArray: allCurrencySortingTypesArray,
defaultCurrencySortingType: defaultCurrencySortingType
};
+19 -7
View File
@@ -1,6 +1,23 @@
const supportedImageExtensions = '.jpg,.jpeg,.png,.gif,.webp'; export const SUPPORTED_IMAGE_EXTENSIONS: string = '.jpg,.jpeg,.png,.gif,.webp';
const supportedImportFileTypes = [ 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 SUPPORTED_IMPORT_FILE_TYPES: ImportFileType[] = [
{ {
type: 'ezbookkeeping', type: 'ezbookkeeping',
name: 'ezbookkeeping Data Export File', name: 'ezbookkeeping Data Export File',
@@ -120,8 +137,3 @@ const supportedImportFileTypes = [
} }
} }
]; ];
export default {
supportedImageExtensions: supportedImageExtensions,
supportedImportFileTypes: supportedImportFileTypes
}
-50
View File
@@ -1,50 +0,0 @@
const allFontSize = {
Small: {
type: 0,
className: 'font-size-small'
},
Default: {
type: 1,
className: 'font-size-default'
},
Large: {
type: 2,
className: 'font-size-large'
},
XLarge: {
type: 3,
className: 'font-size-x-large'
},
XXLarge: {
type: 4,
className: 'font-size-xx-large'
},
XXXLarge: {
type: 5,
className: 'font-size-xxx-large'
},
XXXXLarge: {
type: 6,
className: 'font-size-xxxx-large'
}
}
const allFontSizeArray = [
allFontSize.Small,
allFontSize.Default,
allFontSize.Large,
allFontSize.XLarge,
allFontSize.XXLarge,
allFontSize.XXXLarge,
allFontSize.XXXXLarge
];
const defaultFontSize = allFontSize.Default;
const fontSizePreviewClassNamePrefix = 'preview-';
export default {
allFontSize: allFontSize,
allFontSizeArray: allFontSizeArray,
defaultFontSize: defaultFontSize,
fontSizePreviewClassNamePrefix: fontSizePreviewClassNamePrefix
};
+11 -12
View File
@@ -1,5 +1,8 @@
const defaultAccountIconId = '1'; import type { IconInfo } from '@/core/icon.ts';
const allAccountIcons = {
export const DEFAULT_ACCOUNT_ICON_ID = '1';
export const ALL_ACCOUNT_ICONS: Record<string, IconInfo> = {
// 1 - 99 : Cash Symbols // 1 - 99 : Cash Symbols
'1': { '1': {
icon: 'las la-wallet' icon: 'las la-wallet'
@@ -158,8 +161,11 @@ const allAccountIcons = {
} }
}; };
const defaultCategoryIconId = '1'; export const DEFAULT_ACCOUNT_ICON = ALL_ACCOUNT_ICONS[DEFAULT_ACCOUNT_ICON_ID];
const allCategoryIcons = {
export const DEFAULT_CATEGORY_ICON_ID = '1';
export const ALL_CATEGORY_ICONS = {
// 1 - 99 : Expense - Food & Drink // 1 - 99 : Expense - Food & Drink
'1': { '1': {
icon: 'las la-utensils' icon: 'las la-utensils'
@@ -830,11 +836,4 @@ const allCategoryIcons = {
} }
}; };
export default { export const DEFAULT_CATEGORY_ICON = ALL_CATEGORY_ICONS[DEFAULT_CATEGORY_ICON_ID];
allAccountIcons: allAccountIcons,
defaultAccountIconId: defaultAccountIconId,
defaultAccountIcon: allAccountIcons[defaultAccountIconId],
allCategoryIcons: allCategoryIcons,
defaultCategoryIconId: defaultCategoryIconId,
defaultCategoryIcon: allCategoryIcons[defaultCategoryIconId]
};
+20 -5
View File
@@ -1,4 +1,23 @@
const leafletTileSources = { export interface PresetLeafletTileSource {
readonly tileUrlFormat: string;
readonly tileUrlSubDomains: string;
readonly tileUrlExtraParams?: PresetLeafletTileSourceExtraParam[];
readonly annotationUrlFormat?: string;
readonly annotationUrlSubDomains?: string;
readonly annotationUrlExtraParams?: PresetLeafletTileSourceExtraParam[];
readonly minZoom: number;
readonly maxZoom: number;
readonly defaultZoomLevel: number;
readonly website: string;
readonly attribution: string;
}
export interface PresetLeafletTileSourceExtraParam {
readonly paramName: string;
readonly paramValueType: string;
}
export const LEAFLET_TILE_SOURCES: Record<string, PresetLeafletTileSource> = {
'openstreetmap': { 'openstreetmap': {
tileUrlFormat: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', tileUrlFormat: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
tileUrlSubDomains: 'abc', tileUrlSubDomains: 'abc',
@@ -96,7 +115,3 @@ const leafletTileSources = {
attribution : '<a href="https://www.tianditu.gov.cn" class="external" target="_blank">天地图</a>' attribution : '<a href="https://www.tianditu.gov.cn" class="external" target="_blank">天地图</a>'
} }
} }
export default {
leafletTileSources: leafletTileSources
}
-24
View File
@@ -1,24 +0,0 @@
const allTemplateTypes = {
Normal: 1,
Schedule: 2,
};
const allTemplateScheduledFrequencyTypes = {
Disabled: {
type: 0,
name: 'Disabled'
},
Weekly: {
type: 1,
name: 'Weekly'
},
Monthly: {
type: 2,
name: 'Monthly'
}
};
export default {
allTemplateTypes: allTemplateTypes,
allTemplateScheduledFrequencyTypes: allTemplateScheduledFrequencyTypes,
}
@@ -1,5 +1,15 @@
export interface TimezoneInfo {
readonly displayName: string;
readonly timezoneName: string;
}
export const UTC_TIMEZONE: TimezoneInfo = {
displayName: 'Coordinated Universal Time',
timezoneName: 'Etc/GMT'
};
// Reference: https://github.com/nodatime/nodatime/blob/main/data/cldr/windowsZones-45.xml // Reference: https://github.com/nodatime/nodatime/blob/main/data/cldr/windowsZones-45.xml
const allAvailableTimezones = [ export const ALL_TIMEZONES: TimezoneInfo[] = [
// UTC-12:00 // UTC-12:00
{ {
displayName: 'International Date Line West', displayName: 'International Date Line West',
@@ -591,17 +601,3 @@ const allAvailableTimezones = [
timezoneName: 'Pacific/Kiritimati' timezoneName: 'Pacific/Kiritimati'
} }
]; ];
const allTimezoneTypesUsedForStatistics = {
ApplicationTimezone: 0,
TransactionTimezone: 1
};
const defaultTimezoneTypesUsedForStatistics = allTimezoneTypesUsedForStatistics.ApplicationTimezone;
export default {
all: allAvailableTimezones,
utcTimezoneName: 'Etc/GMT',
allTimezoneTypesUsedForStatistics: allTimezoneTypesUsedForStatistics,
defaultTimezoneTypesUsedForStatistics: defaultTimezoneTypesUsedForStatistics
};
-72
View File
@@ -1,72 +0,0 @@
const allTransactionTypes = {
ModifyBalance: 1,
Income: 2,
Expense: 3,
Transfer: 4
};
const allTransactionEditScopeTypes = {
None: {
type: 0,
name: 'None'
},
All: {
type: 1,
name: 'All'
},
TodayOrLater: {
type: 2,
name: 'Today or later'
},
Recent24HoursOrLater: {
type: 3,
name: 'Recent 24 hours or later'
},
ThisWeekOrLater: {
type: 4,
name: 'This week or later'
},
ThisMonthOrLater: {
type: 5,
name: 'This month or later'
},
ThisYearOrLater: {
type: 6,
name: 'This year or later'
}
};
const allTransactionTagFilterTypes = {
HasAny: {
type: 0,
name: 'With Any Selected Tags'
},
HasAll: {
type: 1,
name: 'With All Selected Tags'
},
NotHasAny: {
type: 2,
name: 'Without Any Selected Tags'
},
NotHasAll: {
type: 3,
name: 'Without All Selected Tags'
}
};
const defaultTransactionTagFilterType = allTransactionTagFilterTypes.HasAny;
const minAmountNumber = -99999999999; // -999999999.99
const maxAmountNumber = 99999999999; // 999999999.99
const maxPictureCount = 10;
export default {
allTransactionTypes: allTransactionTypes,
allTransactionEditScopeTypes: allTransactionEditScopeTypes,
allTransactionTagFilterTypes: allTransactionTagFilterTypes,
defaultTransactionTagFilterType: defaultTransactionTagFilterType,
minAmountNumber: minAmountNumber,
maxAmountNumber: maxAmountNumber,
maxPictureCount: maxPictureCount,
};
+3
View File
@@ -0,0 +1,3 @@
export const TRANSACTION_MIN_AMOUNT: number = -99999999999; // -999999999.99
export const TRANSACTION_MAX_AMOUNT: number = 99999999999; // 999999999.99
export const TRANSACTION_MAX_PICTURE_COUNT: number = 10;
+80
View File
@@ -0,0 +1,80 @@
import type { TypeAndName } from './base.ts';
type AccountTypeName = 'SingleAccount' | 'MultiSubAccounts';
export class AccountType implements TypeAndName {
private static readonly allInstances: AccountType[] = [];
private static readonly allInstancesByTypeName: Record<string, AccountType> = {};
public static readonly SingleAccount = new AccountType(1, 'SingleAccount', 'Single Account');
public static readonly MultiSubAccounts = new AccountType(2, 'MultiSubAccounts', 'Multiple Sub-accounts');
public readonly type: number;
public readonly typeName: AccountTypeName;
public readonly name: string;
private constructor(type: number, typeName: AccountTypeName, name: string) {
this.type = type;
this.typeName = typeName;
this.name = name;
AccountType.allInstances.push(this);
AccountType.allInstancesByTypeName[typeName] = this;
}
public static values(): AccountType[] {
return AccountType.allInstances;
}
public static all(): Record<AccountTypeName, AccountType> {
return AccountType.allInstancesByTypeName;
}
}
type AccountCategoryTypeName = 'Cash' | 'CheckingAccount' | 'SavingsAccount' | 'CreditCard' | 'VirtualAccount' | 'DebtAccount' | 'Receivables' | 'CertificateOfDeposit' | 'InvestmentAccount';
export class AccountCategory implements TypeAndName {
private static readonly allInstances: AccountCategory[] = [];
private static readonly allInstancesByType: Record<number, AccountCategory> = {};
private static readonly allInstancesByTypeName: Record<string, AccountCategory> = {};
public static readonly Cash = new AccountCategory(1, 'Cash', 'Cash', '1');
public static readonly CheckingAccount = new AccountCategory(2, 'CheckingAccount', 'Checking Account', '100');
public static readonly SavingsAccount = new AccountCategory(8, 'SavingsAccount', 'Savings Account', '100');
public static readonly CreditCard = new AccountCategory(3, 'CreditCard', 'Credit Card', '100');
public static readonly VirtualAccount = new AccountCategory(4, 'VirtualAccount', 'Virtual Account', '500');
public static readonly DebtAccount = new AccountCategory(5, 'DebtAccount', 'Debt Account', '600');
public static readonly Receivables = new AccountCategory(6, 'Receivables', 'Receivables', '700');
public static readonly CertificateOfDeposit = new AccountCategory(9, 'CertificateOfDeposit', 'Certificate of Deposit', '110');
public static readonly InvestmentAccount = new AccountCategory(7, 'InvestmentAccount', 'Investment Account', '800');
public static readonly Default = AccountCategory.Cash;
public readonly type: number;
public readonly typeName: AccountCategoryTypeName;
public readonly name: string;
public readonly defaultAccountIconId: string;
private constructor(type: number, typeName: AccountCategoryTypeName, name: string, defaultAccountIconId: string) {
this.type = type;
this.typeName = typeName;
this.name = name;
this.defaultAccountIconId = defaultAccountIconId;
AccountCategory.allInstances.push(this);
AccountCategory.allInstancesByType[type] = this;
AccountCategory.allInstancesByTypeName[typeName] = this;
}
public static values(): AccountCategory[] {
return AccountCategory.allInstances;
}
public static all(): Record<AccountCategoryTypeName, AccountCategory> {
return AccountCategory.allInstancesByTypeName;
}
public static valueOf(type: number): AccountCategory {
return AccountCategory.allInstancesByType[type];
}
}
+9
View File
@@ -0,0 +1,9 @@
export interface TypeAndName {
readonly type: number;
readonly name: string;
}
export interface TypeAndDisplayName {
readonly type: number;
readonly displayName: string;
}
+5
View File
@@ -0,0 +1,5 @@
export enum CategoryType {
Income = 1,
Expense = 2,
Transfer = 3
}
+53
View File
@@ -0,0 +1,53 @@
import type { TypeAndName } from './base.ts';
export type ColorValue = string;
export interface ColorInfo {
readonly color: ColorValue;
}
export interface AmountColor {
readonly expenseAmountColor: ColorValue;
readonly incomeAmountColor: ColorValue;
}
export class PresetAmountColor implements TypeAndName {
private static readonly allInstances: PresetAmountColor[] = [];
private static readonly allInstancesByType: Record<number, PresetAmountColor> = {};
public static readonly SystemDefaultType: number = 0;
public static readonly Green = new PresetAmountColor(1, 'Green', '#009688', '#009688', 'expense-amount-color-green', 'income-amount-color-green');
public static readonly Red = new PresetAmountColor(2, 'Red', '#d43f3f', '#d43f3f', 'expense-amount-color-red', 'income-amount-color-red');
public static readonly Yellow = new PresetAmountColor(3, 'Yellow', '#e2b60a', '#e2b60a', 'expense-amount-color-yellow', 'income-amount-color-yellow');
public static readonly BlackOrWhite = new PresetAmountColor(4, 'Black or White', '#413935', '#fcf0e3', 'expense-amount-color-blackorwhite', 'income-amount-color-blackorwhite');
public static readonly DefaultExpenseColor = PresetAmountColor.Green;
public static readonly DefaultIncomeColor = PresetAmountColor.Red;
public readonly type: number;
public readonly name: string;
public readonly lightThemeColor: string;
public readonly darkThemeColor: string;
public readonly expenseClassName: string;
public readonly incomeClassName: string;
private constructor(type: number, name: string, lightThemeColor: string, darkThemeColor: string, expenseClassName: string, incomeClassName: string) {
this.type = type;
this.name = name;
this.lightThemeColor = lightThemeColor;
this.darkThemeColor = darkThemeColor;
this.expenseClassName = expenseClassName;
this.incomeClassName = incomeClassName;
PresetAmountColor.allInstances.push(this);
PresetAmountColor.allInstancesByType[type] = this;
}
public static values(): PresetAmountColor[] {
return PresetAmountColor.allInstances;
}
public static valueOf(type: number): PresetAmountColor {
return PresetAmountColor.allInstancesByType[type];
}
}
+98
View File
@@ -0,0 +1,98 @@
import type { TypeAndName } from './base.ts';
export enum CurrencyDisplaySymbol {
None = 0,
Symbol = 1,
Code = 2,
Unit = 3,
Name = 4
}
export enum CurrencyDisplayLocation {
BeforeAmount = 0,
AfterAmount = 1
}
export interface CurrencyPrependAndAppendText {
prependText?: string;
appendText?: string;
}
export class CurrencyDisplayType implements TypeAndName {
private static readonly allInstances: CurrencyDisplayType[] = [];
private static readonly allInstancesByType: Record<number, CurrencyDisplayType> = {};
private static readonly allInstancesByTypeName: Record<string, CurrencyDisplayType> = {};
public static readonly LanguageDefaultType = 0;
public static readonly None = new CurrencyDisplayType(1, 'None', 'None', 2, CurrencyDisplaySymbol.None, undefined, '');
public static readonly SymbolBeforeAmount = new CurrencyDisplayType(2, 'SymbolBeforeAmount', 'Currency Symbol', 2, CurrencyDisplaySymbol.Symbol, CurrencyDisplayLocation.BeforeAmount, ' ');
public static readonly SymbolAfterAmount = new CurrencyDisplayType(3, 'SymbolAfterAmount', 'Currency Symbol', 2, CurrencyDisplaySymbol.Symbol, CurrencyDisplayLocation.AfterAmount, ' ');
public static readonly SymbolBeforeAmountWithoutSpace = new CurrencyDisplayType(4, 'SymbolBeforeAmountWithoutSpace', 'Currency Symbol', 2, CurrencyDisplaySymbol.Symbol, CurrencyDisplayLocation.BeforeAmount, '');
public static readonly SymbolAfterAmountWithoutSpace = new CurrencyDisplayType(5, 'SymbolAfterAmountWithoutSpace', 'Currency Symbol', 2, CurrencyDisplaySymbol.Symbol, CurrencyDisplayLocation.AfterAmount, '');
public static readonly CodeBeforeAmount = new CurrencyDisplayType(6, 'CodeBeforeAmount', 'Currency Code', 2, CurrencyDisplaySymbol.Code, CurrencyDisplayLocation.BeforeAmount, ' ');
public static readonly CodeAfterAmount = new CurrencyDisplayType(7, 'CodeAfterAmount', 'Currency Code', 2, CurrencyDisplaySymbol.Code, CurrencyDisplayLocation.AfterAmount, ' ');
public static readonly UnitBeforeAmount = new CurrencyDisplayType(8, 'UnitBeforeAmount', 'Currency Unit', 2, CurrencyDisplaySymbol.Unit, CurrencyDisplayLocation.BeforeAmount, ' ');
public static readonly UnitAfterAmount = new CurrencyDisplayType(9, 'UnitAfterAmount', 'Currency Unit', 2, CurrencyDisplaySymbol.Unit, CurrencyDisplayLocation.AfterAmount, ' ');
public static readonly NameBeforeAmount = new CurrencyDisplayType(10, 'NameBeforeAmount', 'Currency Name', 2, CurrencyDisplaySymbol.Name, CurrencyDisplayLocation.BeforeAmount, ' ');
public static readonly NameAfterAmount = new CurrencyDisplayType(11, 'NameAfterAmount', 'Currency Name', 2, CurrencyDisplaySymbol.Name, CurrencyDisplayLocation.AfterAmount, ' ');
public static readonly Default = CurrencyDisplayType.SymbolBeforeAmount;
public readonly type: number;
public readonly typeName: string;
public readonly name: string;
public readonly fraction: number;
public readonly symbol: CurrencyDisplaySymbol;
public readonly location: CurrencyDisplayLocation | undefined;
public readonly separator: string;
private constructor(type: number, typeName: string, name: string, fraction: number, symbol: CurrencyDisplaySymbol, location: CurrencyDisplayLocation | undefined, separator: string) {
this.type = type;
this.typeName = typeName;
this.name = name;
this.fraction = fraction;
this.symbol = symbol;
this.location = location;
this.separator = separator;
CurrencyDisplayType.allInstances.push(this);
CurrencyDisplayType.allInstancesByType[type] = this;
CurrencyDisplayType.allInstancesByTypeName[typeName] = this;
}
public static values(): CurrencyDisplayType[] {
return CurrencyDisplayType.allInstances;
}
public static valueOf(type: number): CurrencyDisplayType {
return CurrencyDisplayType.allInstancesByType[type];
}
public static parse(typeName: string): CurrencyDisplayType {
return CurrencyDisplayType.allInstancesByTypeName[typeName];
}
}
export class CurrencySortingType implements TypeAndName {
private static readonly allInstances: CurrencySortingType[] = [];
public static readonly Name = new CurrencySortingType(0, 'Currency Name');
public static readonly CurrencyCode = new CurrencySortingType(1, 'Currency Code');
public static readonly ExchangeRate = new CurrencySortingType(2, 'Exchange Rate');
public static readonly Default = CurrencySortingType.Name;
public readonly type: number;
public readonly name: string;
private constructor(type: number, name: string) {
this.type = type;
this.name = name;
CurrencySortingType.allInstances.push(this);
}
public static values(): CurrencySortingType[] {
return CurrencySortingType.allInstances;
}
}
+20
View File
@@ -0,0 +1,20 @@
export class MeridiemIndicator {
private static readonly allInstances: MeridiemIndicator[] = [];
public static readonly AM = new MeridiemIndicator(0, 'AM');
public static readonly PM = new MeridiemIndicator(1, 'PM');
public readonly type: number;
public readonly value: string;
private constructor(type: number, value: string) {
this.type = type;
this.value = value;
MeridiemIndicator.allInstances.push(this);
}
public static values(): MeridiemIndicator[] {
return MeridiemIndicator.allInstances;
}
}
+30
View File
@@ -0,0 +1,30 @@
export class FontSize {
private static readonly allInstances: FontSize[] = [];
public static readonly Small = new FontSize(0, 'font-size-small');
public static readonly Default = new FontSize(1, 'font-size-default');
public static readonly Large = new FontSize(2, 'font-size-large');
public static readonly XLarge = new FontSize(3, 'font-size-x-large');
public static readonly XXLarge = new FontSize(4, 'font-size-xx-large');
public static readonly XXXLarge = new FontSize(5, 'font-size-xxx-large');
public static readonly XXXXLarge = new FontSize(6, 'font-size-xxxx-large');
public static readonly MinimumFontSize = FontSize.Small;
public static readonly MaximumFontSize = FontSize.XXXXLarge;
public readonly type: number;
public readonly className: string;
private constructor(type: number, className: string) {
this.type = type;
this.className = className;
FontSize.allInstances.push(this);
}
public static values(): FontSize[] {
return FontSize.allInstances;
}
}
export const FONT_SIZE_PREVIEW_CLASSNAME_PREFIX: string = 'preview-';
+10
View File
@@ -0,0 +1,10 @@
export type LineAwesomeIconClassName = string;
export interface IconInfo {
readonly icon: LineAwesomeIconClassName;
}
export interface IconInfoWithId {
readonly id: string;
readonly icon: LineAwesomeIconClassName;
}
+72
View File
@@ -0,0 +1,72 @@
import type { TypeAndName } from './base.ts';
type TemplateTypeName = 'Normal' | 'Schedule';
export class TemplateType implements TypeAndName {
private static readonly allInstances: TemplateType[] = [];
private static readonly allInstancesByType: Record<number, TemplateType> = {};
private static readonly allInstancesByTypeName: Record<string, TemplateType> = {};
public static readonly Normal = new TemplateType(1, 'Normal');
public static readonly Schedule = new TemplateType(2, 'Schedule');
public readonly type: number;
public readonly name: TemplateTypeName;
private constructor(type: number, name: TemplateTypeName) {
this.type = type;
this.name = name;
TemplateType.allInstances.push(this);
TemplateType.allInstancesByType[type] = this;
TemplateType.allInstancesByTypeName[name] = this;
}
public static values(): TemplateType[] {
return TemplateType.allInstances;
}
public static all(): Record<TemplateTypeName, TemplateType> {
return TemplateType.allInstancesByTypeName;
}
public static valueOf(type: number): TemplateType {
return TemplateType.allInstancesByType[type];
}
}
type ScheduledTemplateFrequencyTypeName = 'Disabled' | 'Weekly' | 'Monthly';
export class ScheduledTemplateFrequencyType implements TypeAndName {
private static readonly allInstances: ScheduledTemplateFrequencyType[] = [];
private static readonly allInstancesByType: Record<number, ScheduledTemplateFrequencyType> = {};
private static readonly allInstancesByTypeName: Record<string, ScheduledTemplateFrequencyType> = {};
public static readonly Disabled = new ScheduledTemplateFrequencyType(0, 'Disabled');
public static readonly Weekly = new ScheduledTemplateFrequencyType(1, 'Weekly');
public static readonly Monthly = new ScheduledTemplateFrequencyType(2, 'Monthly');
public readonly type: number;
public readonly name: ScheduledTemplateFrequencyTypeName;
private constructor(type: number, name: ScheduledTemplateFrequencyTypeName) {
this.type = type;
this.name = name;
ScheduledTemplateFrequencyType.allInstances.push(this);
ScheduledTemplateFrequencyType.allInstancesByType[type] = this;
ScheduledTemplateFrequencyType.allInstancesByTypeName[name] = this;
}
public static values(): ScheduledTemplateFrequencyType[] {
return ScheduledTemplateFrequencyType.allInstances;
}
public static all(): Record<ScheduledTemplateFrequencyTypeName, ScheduledTemplateFrequencyType> {
return ScheduledTemplateFrequencyType.allInstancesByTypeName;
}
public static valueOf(type: number): ScheduledTemplateFrequencyType {
return ScheduledTemplateFrequencyType.allInstancesByType[type];
}
}
+4
View File
@@ -0,0 +1,4 @@
export enum ThemeType {
Light = 'light',
Dark = 'dark'
}
+16
View File
@@ -0,0 +1,16 @@
import type { TypeAndName } from './base.ts';
export class TimezoneTypeForStatistics implements TypeAndName {
public static readonly ApplicationTimezone = new TimezoneTypeForStatistics(0, 'Application Timezone');
public static readonly TransactionTimezone = new TimezoneTypeForStatistics(1, 'Transaction Timezone');
public static readonly Default = TimezoneTypeForStatistics.ApplicationTimezone;
public readonly type: number;
public readonly name: string;
private constructor(type: number, name: string) {
this.type = type;
this.name = name;
}
}
+59
View File
@@ -0,0 +1,59 @@
import type { TypeAndName } from './base.ts';
export enum TransactionType {
ModifyBalance = 1,
Income = 2,
Expense = 3,
Transfer = 4
}
export class TransactionEditScopeType implements TypeAndName {
private static readonly allInstances: TransactionEditScopeType[] = [];
public static readonly None = new TransactionEditScopeType(0, 'None');
public static readonly All = new TransactionEditScopeType(1, 'All');
public static readonly TodayOrLater = new TransactionEditScopeType(2, 'Today or later');
public static readonly Recent24HoursOrLater = new TransactionEditScopeType(3, 'Recent 24 hours or later');
public static readonly ThisWeekOrLater = new TransactionEditScopeType(4, 'This week or later');
public static readonly ThisMonthOrLater = new TransactionEditScopeType(5, 'This month or later');
public static readonly ThisYearOrLater = new TransactionEditScopeType(6, 'This year or later');
public readonly type: number;
public readonly name: string;
private constructor(type: number, name: string) {
this.type = type;
this.name = name;
TransactionEditScopeType.allInstances.push(this);
}
public static values(): TransactionEditScopeType[] {
return TransactionEditScopeType.allInstances;
}
}
export class TransactionTagFilterType implements TypeAndName {
private static readonly allInstances: TransactionTagFilterType[] = [];
public static readonly HasAny = new TransactionTagFilterType(0, 'With Any Selected Tags');
public static readonly HasAll = new TransactionTagFilterType(1, 'With All Selected Tags');
public static readonly NotHasAny = new TransactionTagFilterType(2, 'Without Any Selected Tags');
public static readonly NotHasAll = new TransactionTagFilterType(3, 'Without All Selected Tags');
public static readonly Default = TransactionTagFilterType.HasAny;
public readonly type: number;
public readonly name: string;
private constructor(type: number, name: string) {
this.type = type;
this.name = name;
TransactionTagFilterType.allInstances.push(this);
}
public static values(): TransactionTagFilterType[] {
return TransactionTagFilterType.allInstances;
}
}
+1 -1
View File
@@ -70,7 +70,7 @@ import draggable from 'vuedraggable';
import router from '@/router/desktop.js'; import router from '@/router/desktop.js';
import { getVersion, getBuildTime } from '@/lib/version.js'; import { getVersion, getBuildTime } from '@/lib/version.ts';
import userstate from '@/lib/userstate.js'; import userstate from '@/lib/userstate.js';
import { import {
getI18nOptions, getI18nOptions,
+1 -1
View File
@@ -1,4 +1,4 @@
import { autoChangeTextareaSize } from '@/lib/ui.mobile.js'; import { autoChangeTextareaSize } from '@/lib/ui/mobile.js';
export default { export default {
mounted(el) { mounted(el) {
+12
View File
@@ -0,0 +1,12 @@
declare const __EZBOOKKEEPING_IS_PRODUCTION__: boolean;
declare const __EZBOOKKEEPING_VERSION__: string;
declare const __EZBOOKKEEPING_BUILD_UNIX_TIME__: string;
declare const __EZBOOKKEEPING_BUILD_COMMIT_HASH__: string;
declare const __EZBOOKKEEPING_LICENSE__: string;
declare const __EZBOOKKEEPING_THIRD_PARTY_LICENSES__: string[];
interface Window {
EZBOOKKEEPING_SERVER_SETTINGS?: {
[key: string]: string | number | boolean | undefined | null;
};
}
+41 -47
View File
@@ -1,5 +1,5 @@
import currencyConstants from '@/consts/currency.js'; import { AccountType, AccountCategory } from '@/core/account.ts';
import accountConstants from '@/consts/account.js'; import { PARENT_ACCOUNT_CURRENCY_PLACEHOLDER } from '@/consts/currency.ts';
export function setAccountModelByAnotherAccount(account, account2) { export function setAccountModelByAnotherAccount(account, account2) {
account.id = account2.id; account.id = account2.id;
@@ -16,22 +16,12 @@ export function setAccountModelByAnotherAccount(account, account2) {
account.visible = !account2.hidden; account.visible = !account2.hidden;
} }
export function getAccountCategoryInfo(categoryId) {
for (let i = 0; i < accountConstants.allCategories.length; i++) {
if (accountConstants.allCategories[i].id === categoryId) {
return accountConstants.allCategories[i];
}
}
return null;
}
export function getAccountOrSubAccountId(account, subAccountId) { export function getAccountOrSubAccountId(account, subAccountId) {
if (account.type === accountConstants.allAccountTypes.SingleAccount) { if (account.type === AccountType.SingleAccount.type) {
return account.id; return account.id;
} else if (account.type === accountConstants.allAccountTypes.MultiSubAccounts && !subAccountId) { } else if (account.type === AccountType.MultiSubAccounts.type && !subAccountId) {
return account.id; return account.id;
} else if (account.type === accountConstants.allAccountTypes.MultiSubAccounts && subAccountId) { } else if (account.type === AccountType.MultiSubAccounts.type && subAccountId) {
if (!account.subAccounts || !account.subAccounts.length) { if (!account.subAccounts || !account.subAccounts.length) {
return null; return null;
} }
@@ -51,11 +41,11 @@ export function getAccountOrSubAccountId(account, subAccountId) {
} }
export function getAccountOrSubAccountComment(account, subAccountId) { export function getAccountOrSubAccountComment(account, subAccountId) {
if (account.type === accountConstants.allAccountTypes.SingleAccount) { if (account.type === AccountType.SingleAccount.type) {
return account.comment; return account.comment;
} else if (account.type === accountConstants.allAccountTypes.MultiSubAccounts && !subAccountId) { } else if (account.type === AccountType.MultiSubAccounts.type && !subAccountId) {
return account.comment; return account.comment;
} else if (account.type === accountConstants.allAccountTypes.MultiSubAccounts && subAccountId) { } else if (account.type === AccountType.MultiSubAccounts.type && subAccountId) {
if (!account.subAccounts || !account.subAccounts.length) { if (!account.subAccounts || !account.subAccounts.length) {
return null; return null;
} }
@@ -109,7 +99,7 @@ export function getCategorizedAccountsMap(allAccounts) {
const account = allAccounts[i]; const account = allAccounts[i];
if (!ret[account.category]) { if (!ret[account.category]) {
const categoryInfo = getAccountCategoryInfo(account.category); const categoryInfo = AccountCategory.valueOf(account.category);
if (categoryInfo) { if (categoryInfo) {
ret[account.category] = { ret[account.category] = {
@@ -132,16 +122,17 @@ export function getCategorizedAccountsMap(allAccounts) {
export function getCategorizedAccounts(allAccounts) { export function getCategorizedAccounts(allAccounts) {
const ret = []; const ret = [];
const allCategories = AccountCategory.values();
const categorizedAccounts = getCategorizedAccountsMap(allAccounts); const categorizedAccounts = getCategorizedAccountsMap(allAccounts);
for (let i = 0; i < accountConstants.allCategories.length; i++) { for (let i = 0; i < allCategories.length; i++) {
const category = accountConstants.allCategories[i]; const category = allCategories[i];
if (!categorizedAccounts[category.id]) { if (!categorizedAccounts[category.type]) {
continue; continue;
} }
const accountCategory = categorizedAccounts[category.id]; const accountCategory = categorizedAccounts[category.type];
ret.push(accountCategory); ret.push(accountCategory);
} }
@@ -150,15 +141,16 @@ export function getCategorizedAccounts(allAccounts) {
export function getCategorizedAccountsWithVisibleCount(categorizedAccountsMap) { export function getCategorizedAccountsWithVisibleCount(categorizedAccountsMap) {
const ret = []; const ret = [];
const allCategories = AccountCategory.values();
for (let i = 0; i < accountConstants.allCategories.length; i++) { for (let i = 0; i < allCategories.length; i++) {
const accountCategory = accountConstants.allCategories[i]; const accountCategory = allCategories[i];
if (!categorizedAccountsMap[accountCategory.id] || !categorizedAccountsMap[accountCategory.id].accounts) { if (!categorizedAccountsMap[accountCategory.type] || !categorizedAccountsMap[accountCategory.type].accounts) {
continue; continue;
} }
const allAccounts = categorizedAccountsMap[accountCategory.id].accounts; const allAccounts = categorizedAccountsMap[accountCategory.type].accounts;
const allSubAccounts = {}; const allSubAccounts = {};
const allVisibleSubAccountCounts = {}; const allVisibleSubAccountCounts = {};
const allFirstVisibleSubAccountIndexes = {}; const allFirstVisibleSubAccountIndexes = {};
@@ -176,7 +168,7 @@ export function getCategorizedAccountsWithVisibleCount(categorizedAccountsMap) {
} }
} }
if (account.type === accountConstants.allAccountTypes.MultiSubAccounts && account.subAccounts) { if (account.type === AccountType.MultiSubAccounts.type && account.subAccounts) {
let visibleSubAccountCount = 0; let visibleSubAccountCount = 0;
let firstVisibleSubAccountIndex = -1; let firstVisibleSubAccountIndex = -1;
@@ -202,7 +194,7 @@ export function getCategorizedAccountsWithVisibleCount(categorizedAccountsMap) {
if (allAccounts.length > 0) { if (allAccounts.length > 0) {
ret.push({ ret.push({
category: accountCategory.id, category: accountCategory.type,
name: accountCategory.name, name: accountCategory.name,
icon: accountCategory.defaultAccountIconId, icon: accountCategory.defaultAccountIconId,
allAccounts: allAccounts, allAccounts: allAccounts,
@@ -219,31 +211,31 @@ export function getCategorizedAccountsWithVisibleCount(categorizedAccountsMap) {
} }
export function getAllFilteredAccountsBalance(categorizedAccounts, accountFilter) { export function getAllFilteredAccountsBalance(categorizedAccounts, accountFilter) {
const allAccountCategories = accountConstants.allCategories; const allAccountCategories = AccountCategory.values();
const ret = []; const ret = [];
for (let categoryIdx = 0; categoryIdx < allAccountCategories.length; categoryIdx++) { for (let categoryIdx = 0; categoryIdx < allAccountCategories.length; categoryIdx++) {
const accountCategory = allAccountCategories[categoryIdx]; const accountCategory = allAccountCategories[categoryIdx];
if (!categorizedAccounts[accountCategory.id] || !categorizedAccounts[accountCategory.id].accounts) { if (!categorizedAccounts[accountCategory.type] || !categorizedAccounts[accountCategory.type].accounts) {
continue; continue;
} }
for (let accountIdx = 0; accountIdx < categorizedAccounts[accountCategory.id].accounts.length; accountIdx++) { for (let accountIdx = 0; accountIdx < categorizedAccounts[accountCategory.type].accounts.length; accountIdx++) {
const account = categorizedAccounts[accountCategory.id].accounts[accountIdx]; const account = categorizedAccounts[accountCategory.type].accounts[accountIdx];
if (account.hidden || !accountFilter(account)) { if (account.hidden || !accountFilter(account)) {
continue; continue;
} }
if (account.type === accountConstants.allAccountTypes.SingleAccount) { if (account.type === AccountType.SingleAccount.type) {
ret.push({ ret.push({
balance: account.balance, balance: account.balance,
isAsset: account.isAsset, isAsset: account.isAsset,
isLiability: account.isLiability, isLiability: account.isLiability,
currency: account.currency currency: account.currency
}); });
} else if (account.type === accountConstants.allAccountTypes.MultiSubAccounts && account.subAccounts) { } else if (account.type === AccountType.MultiSubAccounts.type && account.subAccounts) {
for (let subAccountIdx = 0; subAccountIdx < account.subAccounts.length; subAccountIdx++) { for (let subAccountIdx = 0; subAccountIdx < account.subAccounts.length; subAccountIdx++) {
const subAccount = account.subAccounts[subAccountIdx]; const subAccount = account.subAccounts[subAccountIdx];
@@ -307,7 +299,7 @@ export function getUnifiedSelectedAccountsCurrencyOrDefaultCurrency(allAccounts,
const account = allAccounts[accountId]; const account = allAccounts[accountId];
if (account.currency === currencyConstants.parentAccountCurrencyPlaceholder) { if (account.currency === PARENT_ACCOUNT_CURRENCY_PLACEHOLDER) {
continue; continue;
} }
@@ -326,9 +318,9 @@ export function getUnifiedSelectedAccountsCurrencyOrDefaultCurrency(allAccounts,
} }
export function selectAccountOrSubAccounts(filterAccountIds, account, value) { export function selectAccountOrSubAccounts(filterAccountIds, account, value) {
if (account.type === accountConstants.allAccountTypes.SingleAccount) { if (account.type === AccountType.SingleAccount.type) {
filterAccountIds[account.id] = value; filterAccountIds[account.id] = value;
} else if (account.type === accountConstants.allAccountTypes.MultiSubAccounts) { } else if (account.type === AccountType.MultiSubAccounts.type) {
if (!account.subAccounts || !account.subAccounts.length) { if (!account.subAccounts || !account.subAccounts.length) {
return; return;
} }
@@ -348,7 +340,7 @@ export function selectAll(filterAccountIds, allAccountsMap) {
const account = allAccountsMap[accountId]; const account = allAccountsMap[accountId];
if (account && account.type === accountConstants.allAccountTypes.SingleAccount) { if (account && account.type === AccountType.SingleAccount.type) {
filterAccountIds[account.id] = false; filterAccountIds[account.id] = false;
} }
} }
@@ -362,7 +354,7 @@ export function selectNone(filterAccountIds, allAccountsMap) {
const account = allAccountsMap[accountId]; const account = allAccountsMap[accountId];
if (account && account.type === accountConstants.allAccountTypes.SingleAccount) { if (account && account.type === AccountType.SingleAccount.type) {
filterAccountIds[account.id] = true; filterAccountIds[account.id] = true;
} }
} }
@@ -376,7 +368,7 @@ export function selectInvert(filterAccountIds, allAccountsMap) {
const account = allAccountsMap[accountId]; const account = allAccountsMap[accountId];
if (account && account.type === accountConstants.allAccountTypes.SingleAccount) { if (account && account.type === AccountType.SingleAccount.type) {
filterAccountIds[account.id] = !filterAccountIds[account.id]; filterAccountIds[account.id] = !filterAccountIds[account.id];
} }
} }
@@ -415,9 +407,11 @@ export function isAccountOrSubAccountsHasButNotAllChecked(account, filterAccount
} }
export function setAccountSuitableIcon(account, oldCategory, newCategory) { export function setAccountSuitableIcon(account, oldCategory, newCategory) {
for (let i = 0; i < accountConstants.allCategories.length; i++) { const allCategories = AccountCategory.values();
if (accountConstants.allCategories[i].id === oldCategory) {
if (account.icon !== accountConstants.allCategories[i].defaultAccountIconId) { for (let i = 0; i < allCategories.length; i++) {
if (allCategories[i].type === oldCategory) {
if (account.icon !== allCategories[i].defaultAccountIconId) {
return; return;
} else { } else {
break; break;
@@ -425,9 +419,9 @@ export function setAccountSuitableIcon(account, oldCategory, newCategory) {
} }
} }
for (let i = 0; i < accountConstants.allCategories.length; i++) { for (let i = 0; i < allCategories.length; i++) {
if (accountConstants.allCategories[i].id === newCategory) { if (allCategories[i].type === newCategory) {
account.icon = accountConstants.allCategories[i].defaultAccountIconId; account.icon = allCategories[i].defaultAccountIconId;
} }
} }
} }
+20 -20
View File
@@ -1,5 +1,5 @@
import categoryConstants from '@/consts/category.js'; import { CategoryType } from '@/core/category.ts';
import transactionConstants from '@/consts/transaction.js'; import { TransactionType } from '@/core/transaction.ts';
export function setCategoryModelByAnotherCategory(category, category2) { export function setCategoryModelByAnotherCategory(category, category2) {
category.id = category2.id; category.id = category2.id;
@@ -13,24 +13,24 @@ export function setCategoryModelByAnotherCategory(category, category2) {
} }
export function transactionTypeToCategoryType(transactionType) { export function transactionTypeToCategoryType(transactionType) {
if (transactionType === transactionConstants.allTransactionTypes.Income) { if (transactionType === TransactionType.Income) {
return categoryConstants.allCategoryTypes.Income; return CategoryType.Income;
} else if (transactionType === transactionConstants.allTransactionTypes.Expense) { } else if (transactionType === TransactionType.Expense) {
return categoryConstants.allCategoryTypes.Expense; return CategoryType.Expense;
} else if (transactionType === transactionConstants.allTransactionTypes.Transfer) { } else if (transactionType === TransactionType.Transfer) {
return categoryConstants.allCategoryTypes.Transfer; return CategoryType.Transfer;
} else { } else {
return null; return null;
} }
} }
export function categoryTypeToTransactionType(categoryType) { export function categoryTypeToTransactionType(categoryType) {
if (categoryType === categoryConstants.allCategoryTypes.Income) { if (categoryType === CategoryType.Income) {
return transactionConstants.allTransactionTypes.Income; return TransactionType.Income;
} else if (categoryType === categoryConstants.allCategoryTypes.Expense) { } else if (categoryType === CategoryType.Expense) {
return transactionConstants.allTransactionTypes.Expense; return TransactionType.Expense;
} else if (categoryType === categoryConstants.allCategoryTypes.Transfer) { } else if (categoryType === CategoryType.Transfer) {
return transactionConstants.allTransactionTypes.Transfer; return TransactionType.Transfer;
} else { } else {
return null; return null;
} }
@@ -73,16 +73,16 @@ export function getTransactionSecondaryCategoryName(categoryId, allCategories) {
export function allTransactionCategoriesWithVisibleCount(allTransactionCategories, allowCategoryTypes) { export function allTransactionCategoriesWithVisibleCount(allTransactionCategories, allowCategoryTypes) {
const ret = {}; const ret = {};
const hasAllowCategoryTypes = allowCategoryTypes const hasAllowCategoryTypes = allowCategoryTypes
&& (allowCategoryTypes[categoryConstants.allCategoryTypes.Income.toString()] && (allowCategoryTypes[CategoryType.Income.toString()]
|| allowCategoryTypes[categoryConstants.allCategoryTypes.Expense.toString()] || allowCategoryTypes[CategoryType.Expense.toString()]
|| allowCategoryTypes[categoryConstants.allCategoryTypes.Transfer.toString()]); || allowCategoryTypes[CategoryType.Transfer.toString()]);
for (let key in categoryConstants.allCategoryTypes) { for (let key in CategoryType) {
if (!Object.prototype.hasOwnProperty.call(categoryConstants.allCategoryTypes, key)) { if (!Object.prototype.hasOwnProperty.call(CategoryType, key)) {
continue; continue;
} }
const categoryType = categoryConstants.allCategoryTypes[key]; const categoryType = CategoryType[key];
if (!allTransactionCategories[categoryType]) { if (!allTransactionCategories[categoryType]) {
continue; continue;
+76
View File
@@ -0,0 +1,76 @@
import Clipboard from 'clipboard';
export interface ClipboardCreateContext {
readonly el: string | Element;
readonly text: string;
readonly successCallback?: (e: ClipboardEvent) => void;
readonly errorCallback?: (e: ClipboardEvent) => void;
}
export interface ClipboardEvent {
readonly text: string;
readonly action: string;
}
export class ClipboardTextHolder {
private text: string;
constructor(text: string) {
this.text = text;
}
public getText(): string {
return this.text;
}
public setText(text: string): void {
this.text = text;
}
}
export class ClipboardHolder {
private readonly textHolder: ClipboardTextHolder;
private readonly clipboard: Clipboard;
private constructor(textHolder: ClipboardTextHolder, clipboard: Clipboard) {
this.textHolder = textHolder;
this.clipboard = clipboard;
}
public setClipboardText(text: string): void {
this.textHolder.setText(text);
}
public destroy(): void {
this.clipboard.destroy();
}
public static create({ el, text, successCallback, errorCallback }: ClipboardCreateContext): ClipboardHolder {
const textHolder = new ClipboardTextHolder(text);
const clipboard = new Clipboard(el, {
text: function () {
return textHolder.getText();
}
});
clipboard.on('success', (e) => {
if (successCallback) {
successCallback({
text: e.text,
action: e.action
});
}
});
clipboard.on('error', (e) => {
if (errorCallback) {
errorCallback({
text: e.text,
action: e.action
});
}
});
return new ClipboardHolder(textHolder, clipboard);
}
}
-16
View File
@@ -1,16 +0,0 @@
export function getColorsInRows(allColorInfos, itemPerRow) {
const ret = [];
let rowCount = -1;
for (let i = 0; i < allColorInfos.length; i++) {
if (i % itemPerRow === 0) {
ret[++rowCount] = [];
}
ret[rowCount].push({
color: allColorInfos[i]
});
}
return ret;
}
+18
View File
@@ -0,0 +1,18 @@
import type { ColorValue, ColorInfo } from '@/core/color.ts';
export function getColorsInRows(allColorValues: ColorValue[], itemPerRow: number): ColorInfo[][] {
const ret: ColorInfo[][] = [];
let rowCount = -1;
for (let i = 0; i < allColorValues.length; i++) {
if (i % itemPerRow === 0) {
ret[++rowCount] = [];
}
ret[rowCount].push({
color: allColorValues[i]
});
}
return ret;
}
+119 -96
View File
@@ -1,16 +1,16 @@
export function isFunction(val) { export function isFunction(val: unknown): boolean {
return typeof(val) === 'function'; return typeof(val) === 'function';
} }
export function isDefined(val) { export function isDefined(val: unknown): boolean {
return typeof val !== 'undefined'; return typeof val !== 'undefined';
} }
export function isObject(val) { export function isObject(val: unknown): boolean {
return val != null && typeof(val) === 'object' && !isArray(val); return val != null && typeof(val) === 'object' && !isArray(val);
} }
export function isArray(val) { export function isArray(val: unknown): boolean {
if (isFunction(Array.isArray)) { if (isFunction(Array.isArray)) {
return Array.isArray(val); return Array.isArray(val);
} }
@@ -18,23 +18,23 @@ export function isArray(val) {
return Object.prototype.toString.call(val) === '[object Array]'; return Object.prototype.toString.call(val) === '[object Array]';
} }
export function isString(val) { export function isString(val: unknown): boolean {
return typeof(val) === 'string'; return typeof(val) === 'string';
} }
export function isNumber(val) { export function isNumber(val: unknown): boolean {
return typeof(val) === 'number'; return typeof(val) === 'number';
} }
export function isInteger(val) { export function isInteger(val: unknown): boolean {
return Number.isInteger(val); return Number.isInteger(val);
} }
export function isBoolean(val) { export function isBoolean(val: unknown): boolean {
return typeof(val) === 'boolean'; return typeof(val) === 'boolean';
} }
export function isYearMonth(val) { export function isYearMonth(val: unknown): boolean {
if (typeof(val) !== 'string') { if (typeof(val) !== 'string') {
return false; return false;
} }
@@ -45,50 +45,53 @@ export function isYearMonth(val) {
return false; return false;
} }
return parseInt(items[0]) && parseInt(items[1]); return !!parseInt(items[0]) && !!parseInt(items[1]);
} }
export function isEquals(obj1, obj2) { export function isEquals(obj1: unknown, obj2: unknown): boolean {
if (obj1 === obj2) { if (obj1 === obj2) {
return true; return true;
} }
if (isArray(obj1) && isArray(obj2)) { if (isArray(obj1) && isArray(obj2)) {
if (obj1.length !== obj2.length) { const arr1 = obj1 as unknown[];
const arr2 = obj2 as unknown[];
if (arr1.length !== arr2.length) {
return false; return false;
} }
for (let i = 0; i < obj1.length; i++) { for (let i = 0; i < arr1.length; i++) {
if (!isEquals(obj1[i], obj2[i])) { if (!isEquals(arr1[i], arr2[i])) {
return false; return false;
} }
} }
return true; return true;
} else if (isObject(obj1) && isObject(obj2)) { } else if (isObject(obj1) && isObject(obj2)) {
const keys1 = Object.keys(obj1); const keys1 = Object.keys(obj1 as Record<string, unknown>);
const keys2 = Object.keys(obj2); const keys2 = Object.keys(obj2 as Record<string, unknown>);
if (keys1.length !== keys2.length) { if (keys1.length !== keys2.length) {
return false; return false;
} }
const keyExistsMap2 = {}; const keyExistsMap2 = new Map<string, boolean>();
for (let i = 0; i < keys2.length; i++) { for (let i = 0; i < keys2.length; i++) {
const key = keys2[i]; const key = keys2[i];
keyExistsMap2[key] = true; keyExistsMap2.set(key, true);
} }
for (let i = 0; i < keys1.length; i++) { for (let i = 0; i < keys1.length; i++) {
const key = keys1[i]; const key = keys1[i];
if (!keyExistsMap2[key]) { if (!keyExistsMap2.get(key)) {
return false; return false;
} }
if (!isEquals(obj1[key], obj2[key])) { if (!isEquals((obj1 as Record<string, unknown>)[key], (obj2 as Record<string, unknown>)[key])) {
return false; return false;
} }
} }
@@ -99,7 +102,7 @@ export function isEquals(obj1, obj2) {
} }
} }
export function isYearMonthEquals(val1, val2) { export function isYearMonthEquals(val1: unknown, val2: unknown): boolean {
if (typeof(val1) !== 'string' || typeof(val2) !== 'string') { if (typeof(val1) !== 'string' || typeof(val2) !== 'string') {
return false; return false;
} }
@@ -111,15 +114,15 @@ export function isYearMonthEquals(val1, val2) {
return false; return false;
} }
return (parseInt(items1[0]) && parseInt(items1[1])) && (parseInt(items1[0]) === parseInt(items2[0])) && (parseInt(items1[1]) === parseInt(items2[1])); return (!!parseInt(items1[0]) && !!parseInt(items1[1])) && (parseInt(items1[0]) === parseInt(items2[0])) && (parseInt(items1[1]) === parseInt(items2[1]));
} }
export function isObjectEmpty(obj) { export function isObjectEmpty(obj: object): boolean {
if (!obj) { if (!obj) {
return true; return true;
} }
for (let field in obj) { for (const field in obj) {
if (!Object.prototype.hasOwnProperty.call(obj, field)) { if (!Object.prototype.hasOwnProperty.call(obj, field)) {
continue; continue;
} }
@@ -130,20 +133,20 @@ export function isObjectEmpty(obj) {
return true; return true;
} }
export function sortNumbersArray(array) { export function sortNumbersArray(array: number[]): number[] {
return array.sort(function (num1, num2) { return array.sort(function (num1, num2) {
return num1 - num2; return num1 - num2;
}); });
} }
export function getObjectOwnFieldCount(object) { export function getObjectOwnFieldCount(object: object): number {
let count = 0; let count = 0;
if (!object || !isObject(object)) { if (!object || !isObject(object)) {
return count; return count;
} }
for (let field in object) { for (const field in object) {
if (!Object.prototype.hasOwnProperty.call(object, field)) { if (!Object.prototype.hasOwnProperty.call(object, field)) {
continue; continue;
} }
@@ -154,7 +157,7 @@ export function getObjectOwnFieldCount(object) {
return count; return count;
} }
export function replaceAll(value, originalValue, targetValue) { export function replaceAll(value: string, originalValue: string, targetValue: string): string {
// Escape special characters in originalValue to safely use it in a regex pattern. // Escape special characters in originalValue to safely use it in a regex pattern.
// This ensures that characters like . (dot), * (asterisk), +, ?, etc. are treated literally, // This ensures that characters like . (dot), * (asterisk), +, ?, etc. are treated literally,
// rather than as special regex symbols. // rather than as special regex symbols.
@@ -163,11 +166,11 @@ export function replaceAll(value, originalValue, targetValue) {
return value.replaceAll(new RegExp(escapedOriginalValue, 'g'), targetValue); return value.replaceAll(new RegExp(escapedOriginalValue, 'g'), targetValue);
} }
export function removeAll(value, originalValue) { export function removeAll(value: string, originalValue: string): string {
return replaceAll(value, originalValue, ''); return replaceAll(value, originalValue, '');
} }
export function limitText(value, maxLength) { export function limitText(value: string, maxLength: number): string {
let length = 0; let length = 0;
for (let i = 0; i < value.length; i++) { for (let i = 0; i < value.length; i++) {
@@ -187,7 +190,7 @@ export function limitText(value, maxLength) {
return value.substring(0, maxLength - 3) + '...'; return value.substring(0, maxLength - 3) + '...';
} }
export function getTextBefore(fullText, text) { export function getTextBefore(fullText: string, text: string): string {
if (!text) { if (!text) {
return fullText; return fullText;
} }
@@ -201,7 +204,7 @@ export function getTextBefore(fullText, text) {
return ''; return '';
} }
export function getTextAfter(fullText, text) { export function getTextAfter(fullText: string, text: string): string {
if (!text) { if (!text) {
return fullText; return fullText;
} }
@@ -216,15 +219,15 @@ export function getTextAfter(fullText, text) {
return ''; return '';
} }
export function base64encode(arrayBuffer) { export function base64encode(arrayBuffer: ArrayBuffer): string | null {
if (!arrayBuffer || arrayBuffer.length === 0) { if (!arrayBuffer) {
return null; return null;
} }
return btoa(String.fromCharCode.apply(null, new Uint8Array(arrayBuffer))); return btoa(String.fromCharCode.apply(null, Array.from(new Uint8Array(arrayBuffer))));
} }
export function base64decode(str) { export function base64decode(str: string): string | null {
if (!str) { if (!str) {
return ''; return '';
} }
@@ -232,56 +235,64 @@ export function base64decode(str) {
return atob(str); return atob(str);
} }
export function arrayBufferToString(arrayBuffer) { export function arrayBufferToString(arrayBuffer: ArrayBuffer): string {
return String.fromCharCode.apply(null, new Uint8Array(arrayBuffer)); return String.fromCharCode.apply(null, Array.from(new Uint8Array(arrayBuffer)));
} }
export function stringToArrayBuffer(str){ export function stringToArrayBuffer(str: string): ArrayBuffer {
return Uint8Array.from(str, c => c.charCodeAt(0)).buffer; return Uint8Array.from(str, c => c.charCodeAt(0)).buffer;
} }
export function getFirstVisibleItem(items, hiddenField) { export function getFirstVisibleItem(items: Record<string, unknown>[] | Record<string, Record<string, unknown>>, hiddenField: string): unknown {
if (isArray(items) && items.length > 0) { if (isArray(items) && (items as Record<string, unknown>[]).length > 0) {
for (let i = 0; i < items.length; i++) { const arr = items as Record<string, unknown>[];
if (hiddenField && items[i][hiddenField]) {
for (let i = 0; i < arr.length; i++) {
if (hiddenField && arr[i][hiddenField]) {
continue; continue;
} }
return items[i]; return arr[i];
} }
} else if (isObject(items)) { } else if (isObject(items)) {
for (let field in items) { const obj = items as Record<string, Record<string, unknown>>;
if (!Object.prototype.hasOwnProperty.call(items, field)) {
for (const field in obj) {
if (!Object.prototype.hasOwnProperty.call(obj, field)) {
continue; continue;
} }
if (hiddenField && items[field][hiddenField]) { if (hiddenField && obj[field][hiddenField]) {
continue; continue;
} }
return items[field]; return obj[field];
} }
} }
return null; return null;
} }
export function getItemByKeyValue(src, value, keyField) { export function getItemByKeyValue(src: Record<string, unknown>[] | Record<string, Record<string, unknown>>, value: unknown, keyField: string) {
if (isArray(src)) { if (isArray(src)) {
for (let i = 0; i < src.length; i++) { const arr = src as Record<string, unknown>[];
const item = src[i];
for (let i = 0; i < arr.length; i++) {
const item = arr[i];
if (item[keyField] === value) { if (item[keyField] === value) {
return item; return item;
} }
} }
} else if (isObject(src)) { } else if (isObject(src)) {
for (let field in src) { const obj = src as Record<string, Record<string, unknown>>;
for (const field in obj) {
if (!Object.prototype.hasOwnProperty.call(src, field)) { if (!Object.prototype.hasOwnProperty.call(src, field)) {
continue; continue;
} }
const item = src[field]; const item = obj[field];
if (item[keyField] === value) { if (item[keyField] === value) {
return item; return item;
@@ -292,39 +303,47 @@ export function getItemByKeyValue(src, value, keyField) {
return null; return null;
} }
export function getNameByKeyValue(src, value, keyField, nameField, defaultName) { export function getNameByKeyValue(src: Record<string, unknown>[] | Record<string, Record<string, unknown>>, value: unknown, keyField: string, nameField: string, defaultName: string): unknown {
if (isArray(src)) { if (isArray(src)) {
const arr = src as Record<string, unknown>[];
if (keyField) { if (keyField) {
for (let i = 0; i < src.length; i++) { for (let i = 0; i < arr.length; i++) {
const option = src[i]; const option = arr[i];
if (option[keyField] === value) { if (option[keyField] === value) {
return option[nameField]; return option[nameField];
} }
} }
} else { } else if (isNumber(value)) {
if (src[value]) { const index = value as number;
const option = src[value];
if (arr[index]) {
const option = arr[index];
return option[nameField]; return option[nameField];
} }
} }
} else if (isObject(src)) { } else if (isObject(src)) {
const obj = src as Record<string, Record<string, unknown>>;
if (keyField) { if (keyField) {
for (let key in src) { for (const key in obj) {
if (!Object.prototype.hasOwnProperty.call(src, key)) { if (!Object.prototype.hasOwnProperty.call(src, key)) {
continue; continue;
} }
const option = src[key]; const option = obj[key];
if (option[keyField] === value) { if (option[keyField] === value) {
return option[nameField]; return option[nameField];
} }
} }
} else { } else if (isNumber(value)) {
if (src[value]) { const index = value as number;
const option = src[value];
if (obj[index]) {
const option = obj[index];
return option[nameField]; return option[nameField];
} }
@@ -334,7 +353,7 @@ export function getNameByKeyValue(src, value, keyField, nameField, defaultName)
return defaultName; return defaultName;
} }
export function copyObjectTo(fromObject, toObject) { export function copyObjectTo(fromObject: Record<string, unknown>, toObject: Record<string, unknown>): object {
if (!isObject(fromObject)) { if (!isObject(fromObject)) {
return toObject; return toObject;
} }
@@ -343,7 +362,7 @@ export function copyObjectTo(fromObject, toObject) {
toObject = {}; toObject = {};
} }
for (let key in fromObject) { for (const key in fromObject) {
if (!Object.prototype.hasOwnProperty.call(fromObject, key)) { if (!Object.prototype.hasOwnProperty.call(fromObject, key)) {
continue; continue;
} }
@@ -352,9 +371,9 @@ export function copyObjectTo(fromObject, toObject) {
const toValue = toObject[key]; const toValue = toObject[key];
if (isArray(fromValue)) { if (isArray(fromValue)) {
toObject[key] = copyArrayTo(fromValue, toValue); toObject[key] = copyArrayTo(fromValue as unknown[], toValue as unknown[]);
} else if (isObject(fromValue)) { } else if (isObject(fromValue)) {
toObject[key] = copyObjectTo(fromValue, toValue); toObject[key] = copyObjectTo(fromValue as Record<string, unknown>, toValue as Record<string, unknown>);
} else { } else {
if (fromValue !== toValue) { if (fromValue !== toValue) {
toObject[key] = fromValue; toObject[key] = fromValue;
@@ -365,7 +384,7 @@ export function copyObjectTo(fromObject, toObject) {
return toObject; return toObject;
} }
export function copyArrayTo(fromArray, toArray) { export function copyArrayTo(fromArray: unknown[], toArray: unknown[]) {
if (!isArray(fromArray)) { if (!isArray(fromArray)) {
return toArray; return toArray;
} }
@@ -381,9 +400,9 @@ export function copyArrayTo(fromArray, toArray) {
const toValue = toArray[i]; const toValue = toArray[i];
if (isArray(fromValue)) { if (isArray(fromValue)) {
toArray[i] = copyArrayTo(fromValue, toValue); toArray[i] = copyArrayTo(fromValue as unknown[], toValue as unknown[]);
} else if (isObject(fromValue)) { } else if (isObject(fromValue)) {
toArray[i] = copyObjectTo(fromValue, toValue); toArray[i] = copyObjectTo(fromValue as Record<string, unknown>, toValue as Record<string, unknown>);
} else { } else {
if (fromValue !== toValue) { if (fromValue !== toValue) {
toArray[i] = fromValue; toArray[i] = fromValue;
@@ -391,9 +410,9 @@ export function copyArrayTo(fromArray, toArray) {
} }
} else { } else {
if (isArray(fromValue)) { if (isArray(fromValue)) {
toArray.push(copyArrayTo(fromValue, [])); toArray.push(copyArrayTo(fromValue as unknown[], []));
} else if (isObject(fromValue)) { } else if (isObject(fromValue)) {
toArray.push(copyObjectTo(fromValue, {})); toArray.push(copyObjectTo(fromValue as Record<string, unknown>, {}));
} else { } else {
toArray.push(fromValue); toArray.push(fromValue);
} }
@@ -403,7 +422,7 @@ export function copyArrayTo(fromArray, toArray) {
return toArray; return toArray;
} }
export function arrayContainsFieldValue(array, fieldName, value) { export function arrayContainsFieldValue(array: Record<string, unknown>[], fieldName: string, value: unknown): boolean {
if (!value || !array || !array.length) { if (!value || !array || !array.length) {
return false; return false;
} }
@@ -417,10 +436,10 @@ export function arrayContainsFieldValue(array, fieldName, value) {
return false; return false;
} }
export function objectFieldToArrayItem(object) { export function objectFieldToArrayItem(object: object): string[] {
const ret = []; const ret: string[] = [];
for (let field in object) { for (const field in object) {
if (!Object.prototype.hasOwnProperty.call(object, field)) { if (!Object.prototype.hasOwnProperty.call(object, field)) {
continue; continue;
} }
@@ -431,8 +450,8 @@ export function objectFieldToArrayItem(object) {
return ret; return ret;
} }
export function arrayItemToObjectField(array, value) { export function arrayItemToObjectField(array: string[], value: unknown): Record<string, unknown> {
const ret = {}; const ret: Record<string, unknown> = {};
for (let i = 0; i < array.length; i++) { for (let i = 0; i < array.length; i++) {
ret[array[i]] = value; ret[array[i]] = value;
@@ -441,10 +460,10 @@ export function arrayItemToObjectField(array, value) {
return ret; return ret;
} }
export function categorizedArrayToPlainArray(object) { export function categorizedArrayToPlainArray(object: Record<string, unknown[]>): unknown[] {
const ret = []; const ret: unknown[] = [];
for (let field in object) { for (const field in object) {
if (!Object.prototype.hasOwnProperty.call(object, field)) { if (!Object.prototype.hasOwnProperty.call(object, field)) {
continue; continue;
} }
@@ -459,8 +478,8 @@ export function categorizedArrayToPlainArray(object) {
return ret; return ret;
} }
export function selectAll(filterItemIds, allItemsMap) { export function selectAll(filterItemIds: Record<string, boolean>, allItemsMap: { [key: string]: { id: string } }): void {
for (let itemId in filterItemIds) { for (const itemId in filterItemIds) {
if (!Object.prototype.hasOwnProperty.call(filterItemIds, itemId)) { if (!Object.prototype.hasOwnProperty.call(filterItemIds, itemId)) {
continue; continue;
} }
@@ -473,8 +492,8 @@ export function selectAll(filterItemIds, allItemsMap) {
} }
} }
export function selectNone(filterItemIds, allItemsMap) { export function selectNone(filterItemIds: Record<string, boolean>, allItemsMap: { [key: string]: { id: string } }): void {
for (let itemId in filterItemIds) { for (const itemId in filterItemIds) {
if (!Object.prototype.hasOwnProperty.call(filterItemIds, itemId)) { if (!Object.prototype.hasOwnProperty.call(filterItemIds, itemId)) {
continue; continue;
} }
@@ -487,8 +506,8 @@ export function selectNone(filterItemIds, allItemsMap) {
} }
} }
export function selectInvert(filterItemIds, allItemsMap) { export function selectInvert(filterItemIds: Record<string, boolean>, allItemsMap: { [key: string]: { id: string } }): void {
for (let itemId in filterItemIds) { for (const itemId in filterItemIds) {
if (!Object.prototype.hasOwnProperty.call(filterItemIds, itemId)) { if (!Object.prototype.hasOwnProperty.call(filterItemIds, itemId)) {
continue; continue;
} }
@@ -501,7 +520,7 @@ export function selectInvert(filterItemIds, allItemsMap) {
} }
} }
export function isPrimaryItemHasSecondaryValue(primaryItem, primarySubItemsField, secondaryValueField, secondaryHiddenField, secondaryValue) { export function isPrimaryItemHasSecondaryValue(primaryItem: Record<string, Record<string, unknown>[]>, primarySubItemsField: string, secondaryValueField: string, secondaryHiddenField: string, secondaryValue: unknown): boolean {
for (let i = 0; i < primaryItem[primarySubItemsField].length; i++) { for (let i = 0; i < primaryItem[primarySubItemsField].length; i++) {
const secondaryItem = primaryItem[primarySubItemsField][i]; const secondaryItem = primaryItem[primarySubItemsField][i];
@@ -519,11 +538,13 @@ export function isPrimaryItemHasSecondaryValue(primaryItem, primarySubItemsField
return false; return false;
} }
export function getPrimaryValueBySecondaryValue(items, primarySubItemsField, primaryValueField, primaryHiddenField, secondaryValueField, secondaryHiddenField, secondaryValue) { export function getPrimaryValueBySecondaryValue(items: Record<string, Record<string, unknown>[]>[] | Record<string, Record<string, Record<string, unknown>[]>>, primarySubItemsField: string, primaryValueField: string, primaryHiddenField: string, secondaryValueField: string, secondaryHiddenField: string, secondaryValue: unknown): unknown {
if (primarySubItemsField) { if (primarySubItemsField) {
if (isArray(items)) { if (isArray(items)) {
for (let i = 0; i < items.length; i++) { const arr = items as Record<string, Record<string, unknown>[]>[];
const primaryItem = items[i];
for (let i = 0; i < arr.length; i++) {
const primaryItem = arr[i];
if (primaryHiddenField && primaryItem[primaryHiddenField]) { if (primaryHiddenField && primaryItem[primaryHiddenField]) {
continue; continue;
@@ -538,12 +559,14 @@ export function getPrimaryValueBySecondaryValue(items, primarySubItemsField, pri
} }
} }
} else { } else {
for (let field in items) { const obj = items as Record<string, Record<string, Record<string, unknown>[]>>;
if (!Object.prototype.hasOwnProperty.call(items, field)) {
for (const field in obj) {
if (!Object.prototype.hasOwnProperty.call(obj, field)) {
continue; continue;
} }
const primaryItem = items[field]; const primaryItem = obj[field];
if (primaryHiddenField && primaryItem[primaryHiddenField]) { if (primaryHiddenField && primaryItem[primaryHiddenField]) {
continue; continue;
@@ -563,7 +586,7 @@ export function getPrimaryValueBySecondaryValue(items, primarySubItemsField, pri
return null; return null;
} }
export function arrangeArrayWithNewStartIndex(array, startIndex) { export function arrangeArrayWithNewStartIndex(array: unknown[], startIndex: number): unknown[] {
if (startIndex <= 0 || startIndex >= array.length) { if (startIndex <= 0 || startIndex >= array.length) {
return array; return array;
} }
-83
View File
@@ -1,83 +0,0 @@
import currencyConstants from '@/consts/currency.js';
import { isString, isNumber } from './common.js';
export function getCurrencyFraction(currencyCode) {
const currencyInfo = currencyConstants.all[currencyCode];
if (currencyInfo) {
return currencyInfo.fraction;
}
return null;
}
export function appendCurrencySymbol(value, currencyDisplayType, currencyCode, currencyUnit, currencyName, isPlural) {
if (isNumber(value)) {
value = value.toString();
}
if (!isString(value)) {
return value;
}
const symbol = getAmountPrependAndAppendCurrencySymbol(currencyDisplayType, currencyCode, currencyUnit, currencyName, isPlural);
if (!symbol) {
return value;
}
const separator = currencyDisplayType.separator || '';
if (symbol.prependText) {
value = symbol.prependText + separator + value;
}
if (symbol.appendText) {
value = value + separator + symbol.appendText;
}
return value;
}
export function getAmountPrependAndAppendCurrencySymbol(currencyDisplayType, currencyCode, currencyUnit, currencyName, isPlural) {
if (!currencyDisplayType) {
return null;
}
let symbol = '';
if (currencyDisplayType.symbol === currencyConstants.allCurrencyDisplaySymbol.Symbol) {
const currencyInfo = currencyConstants.all[currencyCode];
if (currencyInfo && currencyInfo.symbol && currencyInfo.symbol.normal) {
symbol = currencyInfo.symbol.normal;
if (isPlural && currencyInfo.symbol.plural) {
symbol = currencyInfo.symbol.plural;
}
}
if (!symbol) {
symbol = currencyConstants.defaultCurrencySymbol;
}
} else if (currencyDisplayType.symbol === currencyConstants.allCurrencyDisplaySymbol.Code) {
symbol = currencyCode;
} else if (currencyDisplayType.symbol === currencyConstants.allCurrencyDisplaySymbol.Unit) {
symbol = currencyUnit;
} else if (currencyDisplayType.symbol === currencyConstants.allCurrencyDisplaySymbol.Name) {
symbol = currencyName;
}
if (currencyDisplayType.location === currencyConstants.allCurrencyDisplayLocation.BeforeAmount) {
return {
prependText: symbol
};
} else if (currencyDisplayType.location === currencyConstants.allCurrencyDisplayLocation.AfterAmount) {
return {
appendText: symbol
};
} else {
return null;
}
}
+80
View File
@@ -0,0 +1,80 @@
import { CurrencyDisplaySymbol, CurrencyDisplayLocation, type CurrencyPrependAndAppendText, CurrencyDisplayType } from '@/core/currency.ts';
import { ALL_CURRENCIES, DEFAULT_CURRENCY_SYMBOL } from '@/consts/currency.ts';
import { isString, isNumber } from './common.ts';
export function getCurrencyFraction(currencyCode: string): number | undefined {
const currencyInfo = ALL_CURRENCIES[currencyCode];
return currencyInfo?.fraction;
}
export function appendCurrencySymbol(value: unknown, currencyDisplayType: CurrencyDisplayType, currencyCode: string, currencyUnit: string, currencyName: string, isPlural: boolean): string | null {
if (isNumber(value)) {
value = (value as number).toString();
}
if (!isString(value)) {
return null;
}
const symbol = getAmountPrependAndAppendCurrencySymbol(currencyDisplayType, currencyCode, currencyUnit, currencyName, isPlural);
if (!symbol) {
return value as string;
}
const separator = currencyDisplayType.separator || '';
let ret = value as string;
if (symbol.prependText) {
ret = symbol.prependText + separator + ret;
}
if (symbol.appendText) {
ret = ret + separator + symbol.appendText;
}
return ret;
}
export function getAmountPrependAndAppendCurrencySymbol(currencyDisplayType: CurrencyDisplayType, currencyCode: string, currencyUnit: string, currencyName: string, isPlural: boolean): CurrencyPrependAndAppendText | null {
if (!currencyDisplayType) {
return null;
}
let symbol = '';
if (currencyDisplayType.symbol === CurrencyDisplaySymbol.Symbol) {
const currencyInfo = ALL_CURRENCIES[currencyCode];
if (currencyInfo && currencyInfo.symbol && currencyInfo.symbol.normal) {
symbol = currencyInfo.symbol.normal;
if (isPlural && currencyInfo.symbol.plural) {
symbol = currencyInfo.symbol.plural;
}
}
if (!symbol) {
symbol = DEFAULT_CURRENCY_SYMBOL;
}
} else if (currencyDisplayType.symbol === CurrencyDisplaySymbol.Code) {
symbol = currencyCode;
} else if (currencyDisplayType.symbol === CurrencyDisplaySymbol.Unit) {
symbol = currencyUnit;
} else if (currencyDisplayType.symbol === CurrencyDisplaySymbol.Name) {
symbol = currencyName;
}
if (currencyDisplayType.location === CurrencyDisplayLocation.BeforeAmount) {
return {
prependText: symbol
};
} else if (currencyDisplayType.location === CurrencyDisplayLocation.AfterAmount) {
return {
appendText: symbol
};
} else {
return null;
}
}
+1 -1
View File
@@ -1,7 +1,7 @@
import moment from 'moment'; import moment from 'moment';
import dateTimeConstants from '@/consts/datetime.js'; import dateTimeConstants from '@/consts/datetime.js';
import { isObject, isString, isNumber } from './common.js'; import { isObject, isString, isNumber } from './common.ts';
export function isYearMonthValid(year, month) { export function isYearMonthValid(year, month) {
if (!isNumber(year) || !isNumber(month)) { if (!isNumber(year) || !isNumber(month)) {
+3 -3
View File
@@ -1,6 +1,6 @@
import { isString } from './common.js'; import { isString } from './common.ts';
export function getFileExtension(filename) { export function getFileExtension(filename: string): string {
if (!filename || !isString(filename)) { if (!filename || !isString(filename)) {
return ''; return '';
} }
@@ -9,7 +9,7 @@ export function getFileExtension(filename) {
return parts[parts.length - 1]; return parts[parts.length - 1];
} }
export function isFileExtensionSupported(filename, supportedExtensions) { export function isFileExtensionSupported(filename: string, supportedExtensions: string): boolean {
if (!supportedExtensions) { if (!supportedExtensions) {
return false; return false;
} }
+99 -146
View File
@@ -1,18 +1,23 @@
import moment from 'moment-timezone'; import moment from 'moment-timezone';
import { defaultLanguage, allLanguages } from '@/locales/index.js'; import { defaultLanguage, allLanguages } from '@/locales/index.ts';
import { TimezoneTypeForStatistics } from '@/core/timezone.ts';
import { CurrencyDisplayType, CurrencySortingType } from '@/core/currency.ts';
import { PresetAmountColor } from '@/core/color.ts';
import { AccountType, AccountCategory } from '@/core/account.ts';
import { CategoryType } from '@/core/category.ts';
import { TransactionEditScopeType, TransactionTagFilterType } from '@/core/transaction.ts';
import { ScheduledTemplateFrequencyType } from '@/core/template.ts';
import numeralConstants from '@/consts/numeral.js'; import numeralConstants from '@/consts/numeral.js';
import datetimeConstants from '@/consts/datetime.js'; import datetimeConstants from '@/consts/datetime.js';
import timezoneConstants from '@/consts/timezone.js'; import { UTC_TIMEZONE, ALL_TIMEZONES } from '@/consts/timezone.ts';
import currencyConstants from '@/consts/currency.js'; import { ALL_CURRENCIES } from '@/consts/currency.ts';
import colorConstants from '@/consts/color.js'; import { SUPPORTED_IMPORT_FILE_TYPES } from '@/consts/file.ts';
import accountConstants from '@/consts/account.js'; import { DEFAULT_EXPENSE_CATEGORIES, DEFAULT_INCOME_CATEGORIES, DEFAULT_TRANSFER_CATEGORIES } from '@/consts/category.ts';
import fileConstants from '@/consts/file.js';
import categoryConstants from '@/consts/category.js';
import transactionConstants from '@/consts/transaction.js';
import templateConstants from '@/consts/template.js';
import statisticsConstants from '@/consts/statistics.js'; import statisticsConstants from '@/consts/statistics.js';
import apiConstants from '@/consts/api.js'; import { KnownErrorCode, SPECIFIED_API_NOT_FOUND_ERRORS, PARAMETERIZED_ERRORS } from '@/consts/api.ts';
import { import {
isDefined, isDefined,
@@ -22,7 +27,7 @@ import {
getNameByKeyValue, getNameByKeyValue,
copyObjectTo, copyObjectTo,
copyArrayTo copyArrayTo
} from './common.js'; } from './common.ts';
import { import {
isPM, isPM,
@@ -53,7 +58,7 @@ import {
getCurrencyFraction, getCurrencyFraction,
appendCurrencySymbol, appendCurrencySymbol,
getAmountPrependAndAppendCurrencySymbol getAmountPrependAndAppendCurrencySymbol
} from './currency.js'; } from './currency.ts';
import { import {
getCategorizedAccountsMap, getCategorizedAccountsMap,
@@ -201,6 +206,21 @@ function getCurrentLanguageDisplayName(i18nGlobal) {
return currentLanguageInfo.displayName; return currentLanguageInfo.displayName;
} }
function getLocalizedDisplayNameAndType(nameAndTypes, translateFn) {
const ret = [];
for (let i = 0; i < nameAndTypes.length; i++) {
const nameAndType = nameAndTypes[i];
ret.push({
type: nameAndType.type,
displayName: translateFn(nameAndType.name)
});
}
return ret;
}
function getDefaultCurrency(translateFn) { function getDefaultCurrency(translateFn) {
return translateFn('default.currency'); return translateFn('default.currency');
} }
@@ -214,7 +234,7 @@ function getCurrencyName(currencyCode, translateFn) {
} }
function getCurrencyUnitName(currencyCode, isPlural, translateFn) { function getCurrencyUnitName(currencyCode, isPlural, translateFn) {
const currencyInfo = currencyConstants.all[currencyCode]; const currencyInfo = ALL_CURRENCIES[currencyCode];
if (currencyInfo && currencyInfo.unit) { if (currencyInfo && currencyInfo.unit) {
if (isPlural) { if (isPlural) {
@@ -521,17 +541,16 @@ function getDateTimeFormat(translateFn, allFormatMap, allFormatArray, localeForm
function getAllTimezones(includeSystemDefault, translateFn) { function getAllTimezones(includeSystemDefault, translateFn) {
const defaultTimezoneOffset = getBrowserTimezoneOffset(); const defaultTimezoneOffset = getBrowserTimezoneOffset();
const defaultTimezoneOffsetMinutes = getBrowserTimezoneOffsetMinutes(); const defaultTimezoneOffsetMinutes = getBrowserTimezoneOffsetMinutes();
const allTimezones = timezoneConstants.all;
const allTimezoneInfos = []; const allTimezoneInfos = [];
for (let i = 0; i < allTimezones.length; i++) { for (let i = 0; i < ALL_TIMEZONES.length; i++) {
const utcOffset = (allTimezones[i].timezoneName !== timezoneConstants.utcTimezoneName ? getTimezoneOffset(allTimezones[i].timezoneName) : ''); const utcOffset = (ALL_TIMEZONES[i].timezoneName !== UTC_TIMEZONE.timezoneName ? getTimezoneOffset(ALL_TIMEZONES[i].timezoneName) : '');
const displayName = translateFn(`timezone.${allTimezones[i].displayName}`); const displayName = translateFn(`timezone.${ALL_TIMEZONES[i].displayName}`);
allTimezoneInfos.push({ allTimezoneInfos.push({
name: allTimezones[i].timezoneName, name: ALL_TIMEZONES[i].timezoneName,
utcOffset: utcOffset, utcOffset: utcOffset,
utcOffsetMinutes: getTimezoneOffsetMinutes(allTimezones[i].timezoneName), utcOffsetMinutes: getTimezoneOffsetMinutes(ALL_TIMEZONES[i].timezoneName),
displayName: displayName, displayName: displayName,
displayNameWithUtcOffset: `(UTC${utcOffset}) ${displayName}` displayNameWithUtcOffset: `(UTC${utcOffset}) ${displayName}`
}); });
@@ -595,11 +614,10 @@ function getTimezoneDifferenceDisplayText(utcOffset, translateFn) {
} }
function getAllCurrencies(translateFn) { function getAllCurrencies(translateFn) {
const allCurrencyCodes = currencyConstants.all;
const allCurrencies = []; const allCurrencies = [];
for (let currencyCode in allCurrencyCodes) { for (let currencyCode in ALL_CURRENCIES) {
if (!Object.prototype.hasOwnProperty.call(allCurrencyCodes, currencyCode)) { if (!Object.prototype.hasOwnProperty.call(ALL_CURRENCIES, currencyCode)) {
continue; continue;
} }
@@ -772,12 +790,12 @@ function getAllTimezoneTypesUsedForStatistics(currentTimezone, translateFn) {
return [ return [
{ {
displayName: translateFn('Application Timezone') + ` (UTC${currentTimezoneOffset})`, displayName: translateFn(TimezoneTypeForStatistics.ApplicationTimezone.name) + ` (UTC${currentTimezoneOffset})`,
type: timezoneConstants.allTimezoneTypesUsedForStatistics.ApplicationTimezone type: TimezoneTypeForStatistics.ApplicationTimezone.type
}, },
{ {
displayName: translateFn('Transaction Timezone'), displayName: translateFn(TimezoneTypeForStatistics.TransactionTimezone.name),
type: timezoneConstants.allTimezoneTypesUsedForStatistics.TransactionTimezone type: TimezoneTypeForStatistics.TransactionTimezone.type
} }
]; ];
} }
@@ -851,10 +869,10 @@ function getAllDigitGroupingTypes(translateFn) {
function getAllCurrencyDisplayTypes(userStore, settingsStore, translateFn) { function getAllCurrencyDisplayTypes(userStore, settingsStore, translateFn) {
const defaultCurrencyDisplayTypeName = translateFn('default.currencyDisplayType'); const defaultCurrencyDisplayTypeName = translateFn('default.currencyDisplayType');
let defaultCurrencyDisplayType = currencyConstants.allCurrencyDisplayType[defaultCurrencyDisplayTypeName]; let defaultCurrencyDisplayType = CurrencyDisplayType.parse(defaultCurrencyDisplayTypeName);
if (!defaultCurrencyDisplayType) { if (!defaultCurrencyDisplayType) {
defaultCurrencyDisplayType = currencyConstants.defaultCurrencyDisplayType; defaultCurrencyDisplayType = CurrencyDisplayType.Default;
} }
const defaultCurrency = userStore.currentUserDefaultCurrency; const defaultCurrency = userStore.currentUserDefaultCurrency;
@@ -863,12 +881,14 @@ function getAllCurrencyDisplayTypes(userStore, settingsStore, translateFn) {
const defaultSampleValue = getFormattedAmountWithCurrency(12345, defaultCurrency, translateFn, userStore, settingsStore, false, defaultCurrencyDisplayType); const defaultSampleValue = getFormattedAmountWithCurrency(12345, defaultCurrency, translateFn, userStore, settingsStore, false, defaultCurrencyDisplayType);
ret.push({ ret.push({
type: currencyConstants.defaultCurrencyDisplayTypeValue, type: CurrencyDisplayType.LanguageDefaultType,
displayName: `${translateFn('Language Default')} (${defaultSampleValue})` displayName: `${translateFn('Language Default')} (${defaultSampleValue})`
}); });
for (let i = 0; i < currencyConstants.allCurrencyDisplayTypeArray.length; i++) { const allCurrencyDisplayTypes = CurrencyDisplayType.values();
const type = currencyConstants.allCurrencyDisplayTypeArray[i];
for (let i = 0; i < allCurrencyDisplayTypes.length; i++) {
const type = allCurrencyDisplayTypes[i];
const sampleValue = getFormattedAmountWithCurrency(12345, defaultCurrency, translateFn, userStore, settingsStore, false, type); const sampleValue = getFormattedAmountWithCurrency(12345, defaultCurrency, translateFn, userStore, settingsStore, false, type);
const displayName = `${translateFn(type.name)} (${sampleValue})` const displayName = `${translateFn(type.name)} (${sampleValue})`
@@ -882,22 +902,7 @@ function getAllCurrencyDisplayTypes(userStore, settingsStore, translateFn) {
} }
function getAllCurrencySortingTypes(translateFn) { function getAllCurrencySortingTypes(translateFn) {
const allCurrencySortingTypes = []; return getLocalizedDisplayNameAndType(CurrencySortingType.values(), translateFn);
for (const sortingTypeField in currencyConstants.allCurrencySortingTypes) {
if (!Object.prototype.hasOwnProperty.call(currencyConstants.allCurrencySortingTypes, sortingTypeField)) {
continue;
}
const sortingType = currencyConstants.allCurrencySortingTypes[sortingTypeField];
allCurrencySortingTypes.push({
type: sortingType.type,
displayName: translateFn(sortingType.name)
});
}
return allCurrencySortingTypes;
} }
function getCurrentDecimalSeparator(translateFn, decimalSeparator) { function getCurrentDecimalSeparator(translateFn, decimalSeparator) {
@@ -970,15 +975,15 @@ function getFormattedAmount(value, translateFn, userStore, currencyCode) {
} }
function getCurrentCurrencyDisplayType(translateFn, userStore) { function getCurrentCurrencyDisplayType(translateFn, userStore) {
let currencyDisplayType = currencyConstants.allCurrencyDisplayTypeMap[userStore.currentUserCurrencyDisplayType]; let currencyDisplayType = CurrencyDisplayType.valueOf(userStore.currentUserCurrencyDisplayType);
if (!currencyDisplayType) { if (!currencyDisplayType) {
const defaultCurrencyDisplayTypeName = translateFn('default.currencyDisplayType'); const defaultCurrencyDisplayTypeName = translateFn('default.currencyDisplayType');
currencyDisplayType = currencyConstants.allCurrencyDisplayType[defaultCurrencyDisplayTypeName]; currencyDisplayType = CurrencyDisplayType.parse(defaultCurrencyDisplayTypeName);
} }
if (!currencyDisplayType) { if (!currencyDisplayType) {
currencyDisplayType = currencyConstants.defaultCurrencyDisplayType; currencyDisplayType = CurrencyDisplayType.Default;
} }
return currencyDisplayType; return currencyDisplayType;
@@ -1047,65 +1052,57 @@ function getAmountPrependAndAppendText(currencyCode, userStore, settingsStore, i
} }
function getAllExpenseIncomeAmountColors(translateFn, expenseOrIncome) { function getAllExpenseIncomeAmountColors(translateFn, expenseOrIncome) {
const allAmountColors = []; const ret = [];
let defaultAmountName = ''; let defaultAmountName = '';
if (expenseOrIncome === 1) { // expense if (expenseOrIncome === 1) { // expense
defaultAmountName = colorConstants.defaultExpenseAmountColor.name; defaultAmountName = PresetAmountColor.DefaultExpenseColor.name;
} else if (expenseOrIncome === 2) { // income } else if (expenseOrIncome === 2) { // income
defaultAmountName = colorConstants.defaultIncomeAmountColor.name; defaultAmountName = PresetAmountColor.DefaultIncomeColor.name;
} }
if (defaultAmountName) { if (defaultAmountName) {
defaultAmountName = translateFn('color.amount.' + defaultAmountName); defaultAmountName = translateFn('color.amount.' + defaultAmountName);
} }
allAmountColors.push({ ret.push({
type: colorConstants.defaultExpenseIncomeAmountValue, type: PresetAmountColor.SystemDefaultType,
displayName: translateFn('System Default') + (defaultAmountName ? ` (${defaultAmountName})` : '') displayName: translateFn('System Default') + (defaultAmountName ? ` (${defaultAmountName})` : '')
}); });
for (let i = 0; i < colorConstants.allAmountColorsArray.length; i++) { const allPresetAmountColors = PresetAmountColor.values();
const amountColor = colorConstants.allAmountColorsArray[i];
allAmountColors.push({ for (let i = 0; i < allPresetAmountColors.length; i++) {
const amountColor = allPresetAmountColors[i];
ret.push({
type: amountColor.type, type: amountColor.type,
displayName: translateFn('color.amount.' + amountColor.name) displayName: translateFn('color.amount.' + amountColor.name)
}); });
} }
return allAmountColors; return ret;
} }
function getAllAccountCategories(translateFn) { function getAllAccountCategories(translateFn) {
const allAccountCategories = []; const ret = [];
const allCategories = AccountCategory.values();
for (let i = 0; i < accountConstants.allCategories.length; i++) { for (let i = 0; i < allCategories.length; i++) {
const accountCategory = accountConstants.allCategories[i]; const accountCategory = allCategories[i];
allAccountCategories.push({ ret.push({
id: accountCategory.id, type: accountCategory.type,
displayName: translateFn(accountCategory.name), displayName: translateFn(accountCategory.name),
defaultAccountIconId: accountCategory.defaultAccountIconId defaultAccountIconId: accountCategory.defaultAccountIconId
}); });
} }
return allAccountCategories; return ret;
} }
function getAllAccountTypes(translateFn) { function getAllAccountTypes(translateFn) {
const allAccountTypes = []; return getLocalizedDisplayNameAndType(AccountType.values(), translateFn);
for (let i = 0; i < accountConstants.allAccountTypesArray.length; i++) {
const accountType = accountConstants.allAccountTypesArray[i];
allAccountTypes.push({
id: accountType.id,
displayName: translateFn(accountType.name)
});
}
return allAccountTypes;
} }
function getAllCategoricalChartTypes(translateFn) { function getAllCategoricalChartTypes(translateFn) {
@@ -1202,60 +1199,15 @@ function getAllStatisticsDateAggregationTypes(translateFn) {
} }
function getAllTransactionEditScopeTypes(translateFn) { function getAllTransactionEditScopeTypes(translateFn) {
const allEditScopeTypes = []; return getLocalizedDisplayNameAndType(TransactionEditScopeType.values(), translateFn);
for (const typeName in transactionConstants.allTransactionEditScopeTypes) {
if (!Object.prototype.hasOwnProperty.call(transactionConstants.allTransactionEditScopeTypes, typeName)) {
continue;
}
const editScopeType = transactionConstants.allTransactionEditScopeTypes[typeName];
allEditScopeTypes.push({
type: editScopeType.type,
displayName: translateFn(editScopeType.name)
});
}
return allEditScopeTypes;
} }
function getAllTransactionTagFilterTypes(translateFn) { function getAllTransactionTagFilterTypes(translateFn) {
const allTagFilterTypes = []; return getLocalizedDisplayNameAndType(TransactionTagFilterType.values(), translateFn);
for (const typeName in transactionConstants.allTransactionTagFilterTypes) {
if (!Object.prototype.hasOwnProperty.call(transactionConstants.allTransactionTagFilterTypes, typeName)) {
continue;
}
const tagFilterType = transactionConstants.allTransactionTagFilterTypes[typeName];
allTagFilterTypes.push({
type: tagFilterType.type,
displayName: translateFn(tagFilterType.name)
});
}
return allTagFilterTypes;
} }
function getAllTransactionScheduledFrequencyTypes(translateFn) { function getAllTransactionScheduledFrequencyTypes(translateFn) {
const allScheduledFrequencyTypes = []; return getLocalizedDisplayNameAndType(ScheduledTemplateFrequencyType.values(), translateFn);
for (const typeName in templateConstants.allTemplateScheduledFrequencyTypes) {
if (!Object.prototype.hasOwnProperty.call(templateConstants.allTemplateScheduledFrequencyTypes, typeName)) {
continue;
}
const frequencyType = templateConstants.allTemplateScheduledFrequencyTypes[typeName];
allScheduledFrequencyTypes.push({
type: frequencyType.type,
displayName: translateFn(frequencyType.name)
});
}
return allScheduledFrequencyTypes;
} }
function getAllTransactionDefaultCategories(categoryType, locale, translateFn) { function getAllTransactionDefaultCategories(categoryType, locale, translateFn) {
@@ -1263,7 +1215,7 @@ function getAllTransactionDefaultCategories(categoryType, locale, translateFn) {
const categoryTypes = []; const categoryTypes = [];
if (categoryType === 0) { if (categoryType === 0) {
for (let i = categoryConstants.allCategoryTypes.Income; i <= categoryConstants.allCategoryTypes.Transfer; i++) { for (let i = CategoryType.Income; i <= CategoryType.Transfer; i++) {
categoryTypes.push(i); categoryTypes.push(i);
} }
} else { } else {
@@ -1275,12 +1227,12 @@ function getAllTransactionDefaultCategories(categoryType, locale, translateFn) {
const categoryType = categoryTypes[i]; const categoryType = categoryTypes[i];
let defaultCategories = []; let defaultCategories = [];
if (categoryType === categoryConstants.allCategoryTypes.Income) { if (categoryType === CategoryType.Income) {
defaultCategories = copyArrayTo(categoryConstants.defaultIncomeCategories, []); defaultCategories = copyArrayTo(DEFAULT_INCOME_CATEGORIES, []);
} else if (categoryType === categoryConstants.allCategoryTypes.Expense) { } else if (categoryType === CategoryType.Expense) {
defaultCategories = copyArrayTo(categoryConstants.defaultExpenseCategories, []); defaultCategories = copyArrayTo(DEFAULT_EXPENSE_CATEGORIES, []);
} else if (categoryType === categoryConstants.allCategoryTypes.Transfer) { } else if (categoryType === CategoryType.Transfer) {
defaultCategories = copyArrayTo(categoryConstants.defaultTransferCategories, []); defaultCategories = copyArrayTo(DEFAULT_TRANSFER_CATEGORIES, []);
} }
for (let j = 0; j < defaultCategories.length; j++) { for (let j = 0; j < defaultCategories.length; j++) {
@@ -1330,15 +1282,15 @@ function getAllDisplayExchangeRates(settingsStore, exchangeRatesData, translateF
}); });
} }
if (settingsStore.appSettings.currencySortByInExchangeRatesPage === currencyConstants.allCurrencySortingTypes.Name.type) { if (settingsStore.appSettings.currencySortByInExchangeRatesPage === CurrencySortingType.Name.type) {
availableExchangeRates.sort(function(c1, c2) { availableExchangeRates.sort(function(c1, c2) {
return c1.currencyDisplayName.localeCompare(c2.currencyDisplayName); return c1.currencyDisplayName.localeCompare(c2.currencyDisplayName);
}); });
} else if (settingsStore.appSettings.currencySortByInExchangeRatesPage === currencyConstants.allCurrencySortingTypes.CurrencyCode.type) { } else if (settingsStore.appSettings.currencySortByInExchangeRatesPage === CurrencySortingType.CurrencyCode.type) {
availableExchangeRates.sort(function(c1, c2) { availableExchangeRates.sort(function(c1, c2) {
return c1.currencyCode.localeCompare(c2.currencyCode); return c1.currencyCode.localeCompare(c2.currencyCode);
}); });
} else if (settingsStore.appSettings.currencySortByInExchangeRatesPage === currencyConstants.allCurrencySortingTypes.ExchangeRate.type) { } else if (settingsStore.appSettings.currencySortByInExchangeRatesPage === CurrencySortingType.ExchangeRate.type) {
availableExchangeRates.sort(function(c1, c2) { availableExchangeRates.sort(function(c1, c2) {
const rate1 = parseFloat(c1.rate); const rate1 = parseFloat(c1.rate);
const rate2 = parseFloat(c2.rate); const rate2 = parseFloat(c2.rate);
@@ -1359,8 +1311,8 @@ function getAllDisplayExchangeRates(settingsStore, exchangeRatesData, translateF
function getAllSupportedImportFileTypes(i18nGlobal, translateFn) { function getAllSupportedImportFileTypes(i18nGlobal, translateFn) {
const allSupportedImportFileTypes = []; const allSupportedImportFileTypes = [];
for (let i = 0; i < fileConstants.supportedImportFileTypes.length; i++) { for (let i = 0; i < SUPPORTED_IMPORT_FILE_TYPES.length; i++) {
const fileType = fileConstants.supportedImportFileTypes[i]; const fileType = SUPPORTED_IMPORT_FILE_TYPES[i];
let document = { let document = {
language: '', language: '',
displayLanguageName: '', displayLanguageName: '',
@@ -1434,16 +1386,17 @@ function getEnableDisableOptions(translateFn) {
function getCategorizedAccountsWithDisplayBalance(allVisibleAccounts, showAccountBalance, defaultCurrency, userStore, settingsStore, exchangeRatesStore, translateFn) { function getCategorizedAccountsWithDisplayBalance(allVisibleAccounts, showAccountBalance, defaultCurrency, userStore, settingsStore, exchangeRatesStore, translateFn) {
const ret = []; const ret = [];
const allCategories = AccountCategory.values();
const categorizedAccounts = copyObjectTo(getCategorizedAccountsMap(allVisibleAccounts), {}); const categorizedAccounts = copyObjectTo(getCategorizedAccountsMap(allVisibleAccounts), {});
for (let i = 0; i < accountConstants.allCategories.length; i++) { for (let i = 0; i < allCategories.length; i++) {
const category = accountConstants.allCategories[i]; const category = allCategories[i];
if (!categorizedAccounts[category.id]) { if (!categorizedAccounts[category.type]) {
continue; continue;
} }
const accountCategory = categorizedAccounts[category.id]; const accountCategory = categorizedAccounts[category.type];
if (accountCategory.accounts) { if (accountCategory.accounts) {
for (let i = 0; i < accountCategory.accounts.length; i++) { for (let i = 0; i < accountCategory.accounts.length; i++) {
@@ -1527,20 +1480,20 @@ function joinMultiText(textArray, translateFn) {
} }
function getLocalizedError(error) { function getLocalizedError(error) {
if (error.errorCode === apiConstants.apiNotFoundErrorCode && apiConstants.specifiedApiNotFoundErrors[error.path]) { if (error.errorCode === KnownErrorCode.ApiNotFound && SPECIFIED_API_NOT_FOUND_ERRORS[error.path]) {
return { return {
message: `${apiConstants.specifiedApiNotFoundErrors[error.path].message}` message: `${SPECIFIED_API_NOT_FOUND_ERRORS[error.path].message}`
}; };
} }
if (error.errorCode !== apiConstants.validatorErrorCode) { if (error.errorCode !== KnownErrorCode.ValidatorError) {
return { return {
message: `error.${error.errorMessage}` message: `error.${error.errorMessage}`
}; };
} }
for (let i = 0; i < apiConstants.parameterizedErrors.length; i++) { for (let i = 0; i < PARAMETERIZED_ERRORS.length; i++) {
const errorInfo = apiConstants.parameterizedErrors[i]; const errorInfo = PARAMETERIZED_ERRORS[i];
const matches = error.errorMessage.match(errorInfo.regex); const matches = error.errorMessage.match(errorInfo.regex);
if (matches && matches.length === errorInfo.parameters.length + 1) { if (matches && matches.length === errorInfo.parameters.length + 1) {
+5 -3
View File
@@ -1,8 +1,10 @@
export function getIconsInRows(allIconInfos, itemPerRow) { import type { IconInfo, IconInfoWithId } from '@/core/icon.ts';
const ret = [];
export function getIconsInRows(allIconInfos: IconInfo[], itemPerRow: number): IconInfoWithId[][] {
const ret: IconInfoWithId[][] = [];
let rowCount = 0; let rowCount = 0;
for (let iconInfoId in allIconInfos) { for (const iconInfoId in allIconInfos) {
if (!Object.prototype.hasOwnProperty.call(allIconInfos, iconInfoId)) { if (!Object.prototype.hasOwnProperty.call(allIconInfos, iconInfoId)) {
continue; continue;
} }
-8
View File
@@ -1,8 +0,0 @@
export default {
getLicense: () => {
return __EZBOOKKEEPING_LICENSE__; // eslint-disable-line
},
getThirdPartyLicenses: () => {
return __EZBOOKKEEPING_THIRD_PARTY_LICENSES__ || []; // eslint-disable-line
}
};
+7
View File
@@ -0,0 +1,7 @@
export function getLicense(): string {
return __EZBOOKKEEPING_LICENSE__;
}
export function getThirdPartyLicenses(): string[] {
return __EZBOOKKEEPING_THIRD_PARTY_LICENSES__ || [];
}
+2 -2
View File
@@ -1,10 +1,10 @@
import { asyncLoadAssets } from '@/lib/misc.js'; import { asyncLoadAssets } from '@/lib/misc.ts';
import services from '@/lib/services.js'; import services from '@/lib/services.js';
import { import {
getAmapSecurityVerificationMethod, getAmapSecurityVerificationMethod,
getAmapApiExternalProxyUrl, getAmapApiExternalProxyUrl,
getAmapApplicationSecret getAmapApplicationSecret
} from '@/lib/server_settings.js'; } from '@/lib/server_settings.ts';
import logger from '@/lib/logger.js'; import logger from '@/lib/logger.js';
const amapHolder = { const amapHolder = {
+1 -1
View File
@@ -1,4 +1,4 @@
import { asyncLoadAssets } from '@/lib/misc.js'; import { asyncLoadAssets } from '@/lib/misc.ts';
import services from '@/lib/services.js'; import services from '@/lib/services.js';
import logger from '@/lib/logger.js'; import logger from '@/lib/logger.js';
+1 -1
View File
@@ -1,4 +1,4 @@
import { asyncLoadAssets } from '@/lib/misc.js'; import { asyncLoadAssets } from '@/lib/misc.ts';
import services from '@/lib/services.js'; import services from '@/lib/services.js';
const googleMapHolder = { const googleMapHolder = {
+10 -10
View File
@@ -1,7 +1,7 @@
import mapConstants from '@/consts/map.js'; import { LEAFLET_TILE_SOURCES } from '@/consts/map.ts';
import { import {
getMapProvider getMapProvider
} from '@/lib/server_settings.js'; } from '@/lib/server_settings.ts';
import { import {
loadLeafletMapAssets, loadLeafletMapAssets,
@@ -45,8 +45,8 @@ import {
export function getMapWebsite() { export function getMapWebsite() {
if (getMapProvider() === 'custom') { if (getMapProvider() === 'custom') {
return ''; return '';
} else if (mapConstants.leafletTileSources[getMapProvider()]) { } else if (LEAFLET_TILE_SOURCES[getMapProvider()]) {
return mapConstants.leafletTileSources[getMapProvider()].website; return LEAFLET_TILE_SOURCES[getMapProvider()].website;
} else if (getMapProvider() === 'googlemap') { } else if (getMapProvider() === 'googlemap') {
return getGoogleMapWebsite(); return getGoogleMapWebsite();
} else if (getMapProvider() === 'baidumap') { } else if (getMapProvider() === 'baidumap') {
@@ -57,7 +57,7 @@ export function getMapWebsite() {
} }
export function loadMapAssets(language) { export function loadMapAssets(language) {
if (mapConstants.leafletTileSources[getMapProvider()] || getMapProvider() === 'custom') { if (LEAFLET_TILE_SOURCES[getMapProvider()] || getMapProvider() === 'custom') {
return loadLeafletMapAssets(language); return loadLeafletMapAssets(language);
} else if (getMapProvider() === 'googlemap') { } else if (getMapProvider() === 'googlemap') {
return loadGoogleMapAssets(language); return loadGoogleMapAssets(language);
@@ -69,7 +69,7 @@ export function loadMapAssets(language) {
} }
export function createMapHolder() { export function createMapHolder() {
if (mapConstants.leafletTileSources[getMapProvider()] || getMapProvider() === 'custom') { if (LEAFLET_TILE_SOURCES[getMapProvider()] || getMapProvider() === 'custom') {
return createLeafletMapHolder(getMapProvider()); return createLeafletMapHolder(getMapProvider());
} else if (getMapProvider() === 'googlemap') { } else if (getMapProvider() === 'googlemap') {
return createGoogleMapHolder(getMapProvider()); return createGoogleMapHolder(getMapProvider());
@@ -87,7 +87,7 @@ export function initMapInstance(mapHolder, mapContainer, options) {
return; return;
} }
if (mapConstants.leafletTileSources[getMapProvider()] || getMapProvider() === 'custom') { if (LEAFLET_TILE_SOURCES[getMapProvider()] || getMapProvider() === 'custom') {
createLeafletMapInstance(mapHolder, mapContainer, options); createLeafletMapInstance(mapHolder, mapContainer, options);
} else if (mapHolder.mapProvider === 'googlemap') { } else if (mapHolder.mapProvider === 'googlemap') {
createGoogleMapInstance(mapHolder, mapContainer, options); createGoogleMapInstance(mapHolder, mapContainer, options);
@@ -103,7 +103,7 @@ export function setMapCenterTo(mapHolder, center, zoomLevel) {
return; return;
} }
if (mapConstants.leafletTileSources[getMapProvider()] || getMapProvider() === 'custom') { if (LEAFLET_TILE_SOURCES[getMapProvider()] || getMapProvider() === 'custom') {
setLeafletMapCenterTo(mapHolder, center, zoomLevel); setLeafletMapCenterTo(mapHolder, center, zoomLevel);
} else if (mapHolder.mapProvider === 'googlemap') { } else if (mapHolder.mapProvider === 'googlemap') {
setGoogleMapCenterTo(mapHolder, center, zoomLevel); setGoogleMapCenterTo(mapHolder, center, zoomLevel);
@@ -119,7 +119,7 @@ export function setMapCenterMarker(mapHolder, position) {
return; return;
} }
if (mapConstants.leafletTileSources[getMapProvider()] || getMapProvider() === 'custom') { if (LEAFLET_TILE_SOURCES[getMapProvider()] || getMapProvider() === 'custom') {
setLeafletMapCenterMaker(mapHolder, position); setLeafletMapCenterMaker(mapHolder, position);
} else if (mapHolder.mapProvider === 'googlemap') { } else if (mapHolder.mapProvider === 'googlemap') {
setGoogleMapCenterMaker(mapHolder, position); setGoogleMapCenterMaker(mapHolder, position);
@@ -135,7 +135,7 @@ export function removeMapCenterMarker(mapHolder) {
return; return;
} }
if (mapConstants.leafletTileSources[getMapProvider()] || getMapProvider() === 'custom') { if (LEAFLET_TILE_SOURCES[getMapProvider()] || getMapProvider() === 'custom') {
removeLeafletMapCenterMaker(mapHolder); removeLeafletMapCenterMaker(mapHolder);
} else if (mapHolder.mapProvider === 'googlemap') { } else if (mapHolder.mapProvider === 'googlemap') {
removeGoogleMapCenterMaker(mapHolder); removeGoogleMapCenterMaker(mapHolder);
+4 -4
View File
@@ -1,4 +1,4 @@
import mapConstants from '@/consts/map.js'; import { LEAFLET_TILE_SOURCES } from '@/consts/map.ts';
import { import {
isMapDataFetchProxyEnabled, isMapDataFetchProxyEnabled,
getCustomMapTileLayerUrl, getCustomMapTileLayerUrl,
@@ -9,7 +9,7 @@ import {
getCustomMapDefaultZoomLevel, getCustomMapDefaultZoomLevel,
getTomTomMapAPIKey, getTomTomMapAPIKey,
getTianDiTuMapAPIKey getTianDiTuMapAPIKey
} from '@/lib/server_settings.js'; } from '@/lib/server_settings.ts';
import services from '@/lib/services.js'; import services from '@/lib/services.js';
const leafletHolder = { const leafletHolder = {
@@ -24,7 +24,7 @@ export function loadLeafletMapAssets() {
} }
export function createLeafletMapHolder(mapProvider) { export function createLeafletMapHolder(mapProvider) {
const mapTileSource = mapConstants.leafletTileSources[mapProvider]; const mapTileSource = LEAFLET_TILE_SOURCES[mapProvider];
if (mapProvider !== 'custom' && !mapTileSource) { if (mapProvider !== 'custom' && !mapTileSource) {
return null; return null;
@@ -60,7 +60,7 @@ export function createLeafletMapInstance(mapHolder, mapContainer, options) {
let mapTileSource = null; let mapTileSource = null;
if (mapHolder.mapProvider !== 'custom') { if (mapHolder.mapProvider !== 'custom') {
mapTileSource = Object.assign({}, mapConstants.leafletTileSources[mapHolder.mapProvider]); mapTileSource = Object.assign({}, LEAFLET_TILE_SOURCES[mapHolder.mapProvider]);
} else { } else {
mapTileSource = createCustomMapSource(); mapTileSource = createCustomMapSource();
} }
-229
View File
@@ -1,229 +0,0 @@
import Clipboard from 'clipboard';
import CryptoJS from 'crypto-js';
import uaParser from 'ua-parser-js';
import { base64encode } from './common.js';
export function asyncLoadAssets(type, assetUrl) {
return new Promise(function (resolve, reject) {
let addElement = false;
let el = null;
if (type === 'js') {
el = document.querySelector('script[src="' + assetUrl + '"]');
} else if (type === 'css') {
el = document.querySelector('link[href="' + assetUrl + '"]');
} else {
reject({
type: type,
assetUrl: assetUrl,
error: 'notsupport'
});
return;
}
if (!el) {
if (type === 'js') {
el = document.createElement('script');
el.setAttribute('type', 'text/javascript');
el.setAttribute('async', 'true');
el.setAttribute('src', assetUrl);
} else if (type === 'css') {
el = document.createElement('link');
el.setAttribute('rel', 'stylesheet');
el.setAttribute('type', 'text/css');
el.setAttribute('href', assetUrl);
}
addElement = true;
} else if (el.hasAttribute('data-loaded')) {
resolve({
type: type,
assetUrl: assetUrl
});
return;
}
el.addEventListener('load', () => {
el.setAttribute('data-loaded', true);
resolve({
type: type,
assetUrl: assetUrl
});
});
el.addEventListener('error', () => {
reject({
type: type,
assetUrl: assetUrl,
error: 'error'
});
});
el.addEventListener('abort', () => {
reject({
type: type,
assetUrl: assetUrl,
error: 'abort'
});
});
if (addElement) {
document.head.appendChild(el);
}
});
}
export function generateRandomString() {
let baseString = 'ebk_' + new Date().getTime();
if (crypto && crypto.getRandomValues) {
const randoms = new Uint8Array(256);
crypto.getRandomValues(randoms);
baseString += '_' + base64encode(randoms);
} else {
baseString += '_' + Math.random();
}
return CryptoJS.SHA256(baseString).toString();
}
export function generateRandomUUID() {
const randomString = generateRandomString();
// convert hash string to UUID Version 8
const uuid = randomString.substring(0, 8) + '-'
+ randomString.substring(8, 12) + '-'
+ '8' + randomString.substring(13, 16) + '-'
+ (0x8 | (parseInt(randomString.charAt(16), 16) & 0x3)).toString(16) + randomString.substring(17, 20) + '-'
+ randomString.substring(20, 32);
return uuid;
}
export function isSessionUserAgentCreatedByCli(ua) {
return ua === 'ezbookkeeping Cli';
}
export function parseUserAgent(ua) {
const uaParseRet = uaParser(ua);
return {
device: {
vendor: uaParseRet.device.vendor,
model: uaParseRet.device.model,
type: uaParseRet.device.type
},
os: {
name: uaParseRet.os.name,
version: uaParseRet.os.version
},
browser: {
name: uaParseRet.browser.name,
version: uaParseRet.browser.version
}
};
}
export function parseDeviceInfo(uaInfo) {
if (!uaInfo) {
return '';
}
let result = '';
if (uaInfo.device && uaInfo.device.model) {
result = uaInfo.device.model;
} else if (uaInfo.os && uaInfo.os.name) {
result = uaInfo.os.name;
if (uaInfo.os.version) {
result += ' ' + uaInfo.os.version;
}
}
if (uaInfo.browser && uaInfo.browser.name) {
let browserInfo = uaInfo.browser.name;
if (uaInfo.browser.version) {
browserInfo += ' ' + uaInfo.browser.version;
}
if (result) {
result += ' (' + browserInfo + ')';
} else {
result = browserInfo;
}
}
if (!result) {
return 'Unknown Device';
}
return result;
}
export function parseSessionInfo(token) {
const isCreatedByCli = isSessionUserAgentCreatedByCli(token.userAgent);
const uaInfo = parseUserAgent(token.userAgent);
let deviceType = '';
if (isCreatedByCli) {
deviceType = 'cli';
} else {
if (uaInfo && uaInfo.device) {
if (uaInfo.device.type === 'mobile') {
deviceType = 'phone';
} else if (uaInfo.device.type === 'wearable') {
deviceType = 'wearable';
} else if (uaInfo.device.type === 'tablet') {
deviceType = 'tablet';
} else if (uaInfo.device.type === 'smarttv') {
deviceType = 'tv';
} else {
deviceType = 'default';
}
} else {
deviceType = 'default';
}
}
return {
tokenId: token.tokenId,
isCurrent: token.isCurrent,
deviceType: deviceType,
deviceInfo: isCreatedByCli ? token.userAgent : parseDeviceInfo(uaInfo),
createdByCli: isCreatedByCli,
lastSeen: token.lastSeen
}
}
export function makeButtonCopyToClipboard({ text, el, successCallback, errorCallback }) {
const clipboard = new Clipboard(el, {
text: function () {
return text;
}
});
clipboard.on('success', (e) => {
if (successCallback) {
successCallback(e);
}
});
clipboard.on('error', (e) => {
if (errorCallback) {
errorCallback(e);
}
});
return clipboard;
}
export function changeClipboardObjectText(clipboard, text) {
if (!clipboard) {
return;
}
clipboard.text = function () {
return text;
};
}
+112
View File
@@ -0,0 +1,112 @@
import CryptoJS from 'crypto-js';
import { base64encode } from './common.ts';
export interface AsyncLoadAssetsResult {
readonly type: string;
readonly assetUrl: string;
}
export function asyncLoadAssets(type: string, assetUrl: string): Promise<AsyncLoadAssetsResult> {
return new Promise(function (resolve, reject) {
let addElement = false;
let el = null;
if (type === 'js') {
el = document.querySelector('script[src="' + assetUrl + '"]');
} else if (type === 'css') {
el = document.querySelector('link[href="' + assetUrl + '"]');
} else {
reject({
type: type,
assetUrl: assetUrl,
error: 'notsupport'
});
return;
}
if (!el) {
if (type === 'js') {
el = document.createElement('script');
el.setAttribute('type', 'text/javascript');
el.setAttribute('async', 'true');
el.setAttribute('src', assetUrl);
} else if (type === 'css') {
el = document.createElement('link');
el.setAttribute('rel', 'stylesheet');
el.setAttribute('type', 'text/css');
el.setAttribute('href', assetUrl);
}
addElement = true;
} else if (el.hasAttribute('data-loaded')) {
resolve({
type: type,
assetUrl: assetUrl
});
return;
}
if (!el) {
reject({
type: type,
assetUrl: assetUrl,
error: 'unexpected'
});
return;
}
el.addEventListener('load', () => {
el.setAttribute('data-loaded', 'true');
resolve({
type: type,
assetUrl: assetUrl
});
});
el.addEventListener('error', () => {
reject({
type: type,
assetUrl: assetUrl,
error: 'error'
});
});
el.addEventListener('abort', () => {
reject({
type: type,
assetUrl: assetUrl,
error: 'abort'
});
});
if (addElement) {
document.head.appendChild(el);
}
});
}
export function generateRandomString(): string {
let baseString = 'ebk_' + new Date().getTime();
if (crypto && crypto.getRandomValues) {
const randoms = new Uint8Array(256);
crypto.getRandomValues(randoms);
baseString += '_' + base64encode(randoms.buffer);
} else {
baseString += '_' + Math.random();
}
return CryptoJS.SHA256(baseString).toString();
}
export function generateRandomUUID(): string {
const randomString = generateRandomString();
// convert hash string to UUID Version 8
const uuid = randomString.substring(0, 8) + '-'
+ randomString.substring(8, 12) + '-'
+ '8' + randomString.substring(13, 16) + '-'
+ (0x8 | (parseInt(randomString.charAt(16), 16) & 0x3)).toString(16) + randomString.substring(17, 20) + '-'
+ randomString.substring(20, 32);
return uuid;
}
+1 -1
View File
@@ -1,6 +1,6 @@
import numeralConstants from '@/consts/numeral.js'; import numeralConstants from '@/consts/numeral.js';
import { isString, isNumber, removeAll } from './common.js'; import { isString, isNumber, removeAll } from './common.ts';
export function appendDigitGroupingSymbol(value, options) { export function appendDigitGroupingSymbol(value, options) {
if (isNumber(value)) { if (isNumber(value)) {
-109
View File
@@ -1,109 +0,0 @@
const serverSettingsGlobalVariableName = 'EZBOOKKEEPING_SERVER_SETTINGS';
function getServerSetting(key) {
const settings = window[serverSettingsGlobalVariableName] || {};
return settings[key];
}
export function isUserRegistrationEnabled() {
return getServerSetting('r') === 1;
}
export function isUserForgetPasswordEnabled() {
return getServerSetting('f') === 1;
}
export function isUserVerifyEmailEnabled() {
return getServerSetting('v') === 1;
}
export function isTransactionPicturesEnabled() {
return getServerSetting('p') === 1;
}
export function isUserScheduledTransactionEnabled() {
return getServerSetting('s') === 1;
}
export function isDataExportingEnabled() {
return getServerSetting('e') === 1;
}
export function isDataImportingEnabled() {
return getServerSetting('i') === 1;
}
export function getLoginPageTips() {
return getServerSetting('lpt');
}
export function getMapProvider() {
return getServerSetting('m');
}
export function isMapDataFetchProxyEnabled() {
return getServerSetting('mp') === 1;
}
export function getCustomMapTileLayerUrl() {
return getServerSetting('cmsu');
}
export function getCustomMapAnnotationLayerUrl() {
return getServerSetting('cmau');
}
export function isCustomMapAnnotationLayerDataFetchProxyEnabled() {
return getServerSetting('cmap') === 1;
}
export function getCustomMapMinZoomLevel() {
const zoomLevelSettings = (getServerSetting('cmzl') || '').split('-');
return (zoomLevelSettings && zoomLevelSettings[0]) ? parseInt(zoomLevelSettings[0]) : 1;
}
export function getCustomMapMaxZoomLevel() {
const zoomLevelSettings = (getServerSetting('cmzl') || '').split('-');
return (zoomLevelSettings && zoomLevelSettings[1]) ? parseInt(zoomLevelSettings[1]) : 18;
}
export function getCustomMapDefaultZoomLevel() {
const zoomLevelSettings = (getServerSetting('cmzl') || '').split('-');
return (zoomLevelSettings && zoomLevelSettings[2]) ? parseInt(zoomLevelSettings[2]) : 14;
}
export function getTomTomMapAPIKey() {
return getServerSetting('tmak');
}
export function getTianDiTuMapAPIKey() {
return getServerSetting('tdak');
}
export function getGoogleMapAPIKey() {
return getServerSetting('gmak');
}
export function getBaiduMapAK() {
return getServerSetting('bmak');
}
export function getAmapApplicationKey() {
return getServerSetting('amak');
}
export function getAmapSecurityVerificationMethod() {
return getServerSetting('amsv');
}
export function getAmapApiExternalProxyUrl() {
return getServerSetting('amep');
}
export function getAmapApplicationSecret() {
return getServerSetting('amas');
}
export function getExchangeRatesRequestTimeout() {
return getServerSetting('errt');
}
+107
View File
@@ -0,0 +1,107 @@
function getServerSetting(key: string): string | number | boolean | undefined | null {
const settings = window.EZBOOKKEEPING_SERVER_SETTINGS || {};
return settings[key];
}
export function isUserRegistrationEnabled(): boolean {
return getServerSetting('r') === 1;
}
export function isUserForgetPasswordEnabled(): boolean {
return getServerSetting('f') === 1;
}
export function isUserVerifyEmailEnabled(): boolean {
return getServerSetting('v') === 1;
}
export function isTransactionPicturesEnabled(): boolean {
return getServerSetting('p') === 1;
}
export function isUserScheduledTransactionEnabled(): boolean {
return getServerSetting('s') === 1;
}
export function isDataExportingEnabled(): boolean {
return getServerSetting('e') === 1;
}
export function isDataImportingEnabled(): boolean {
return getServerSetting('i') === 1;
}
export function getLoginPageTips(): string {
return getServerSetting('lpt') as string;
}
export function getMapProvider(): string {
return getServerSetting('m') as string;
}
export function isMapDataFetchProxyEnabled(): boolean {
return getServerSetting('mp') === 1;
}
export function getCustomMapTileLayerUrl(): string {
return getServerSetting('cmsu') as string;
}
export function getCustomMapAnnotationLayerUrl(): string {
return getServerSetting('cmau') as string;
}
export function isCustomMapAnnotationLayerDataFetchProxyEnabled(): boolean {
return getServerSetting('cmap') === 1;
}
export function getCustomMapMinZoomLevel(): number {
const zoomLevelSettings = (getServerSetting('cmzl') as string || '').split('-');
return (zoomLevelSettings && zoomLevelSettings[0]) ? parseInt(zoomLevelSettings[0]) : 1;
}
export function getCustomMapMaxZoomLevel(): number {
const zoomLevelSettings = (getServerSetting('cmzl') as string || '').split('-');
return (zoomLevelSettings && zoomLevelSettings[1]) ? parseInt(zoomLevelSettings[1]) : 18;
}
export function getCustomMapDefaultZoomLevel(): number {
const zoomLevelSettings = (getServerSetting('cmzl') as string || '').split('-');
return (zoomLevelSettings && zoomLevelSettings[2]) ? parseInt(zoomLevelSettings[2]) : 14;
}
export function getTomTomMapAPIKey(): string {
return getServerSetting('tmak') as string;
}
export function getTianDiTuMapAPIKey(): string {
return getServerSetting('tdak') as string;
}
export function getGoogleMapAPIKey(): string {
return getServerSetting('gmak') as string;
}
export function getBaiduMapAK(): string {
return getServerSetting('bmak') as string;
}
export function getAmapApplicationKey(): string {
return getServerSetting('amak') as string;
}
export function getAmapSecurityVerificationMethod(): string {
return getServerSetting('amsv') as string;
}
export function getAmapApiExternalProxyUrl(): string {
return getServerSetting('amep') as string;
}
export function getAmapApplicationSecret(): string {
return getServerSetting('amas') as string;
}
export function getExchangeRatesRequestTimeout(): number {
return getServerSetting('errt') as number;
}
+29 -18
View File
@@ -1,25 +1,36 @@
import axios from 'axios'; import axios from 'axios';
import apiConstants from '@/consts/api.js'; import {
BASE_API_URL_PATH,
BASE_QRCODE_PATH,
BASE_PROXY_URL_PATH,
BASE_AMAP_API_PROXY_URL_PATH,
DEFAULT_API_TIMEOUT,
DEFAULT_UPLOAD_API_TIMEOUT,
DEFAULT_IMPORT_API_TIMEOUT,
GOOGLE_MAP_JAVASCRIPT_URL,
BAIDU_MAP_JAVASCRIPT_URL,
AMAP_JAVASCRIPT_URL
} from '@/consts/api.ts';
import userState from './userstate.js'; import userState from './userstate.js';
import { import {
isDefined, isDefined,
isBoolean isBoolean
} from './common.js'; } from './common.ts';
import { import {
getGoogleMapAPIKey, getGoogleMapAPIKey,
getBaiduMapAK, getBaiduMapAK,
getAmapApplicationKey, getAmapApplicationKey,
getExchangeRatesRequestTimeout getExchangeRatesRequestTimeout
} from './server_settings.js'; } from './server_settings.ts';
import { getTimezoneOffsetMinutes } from './datetime.js'; import { getTimezoneOffsetMinutes } from './datetime.js';
import { generateRandomUUID } from './misc.js'; import { generateRandomUUID } from './misc.ts';
let needBlockRequest = false; let needBlockRequest = false;
let blockedRequests = []; let blockedRequests = [];
axios.defaults.baseURL = apiConstants.baseApiUrlPath; axios.defaults.baseURL = BASE_API_URL_PATH;
axios.defaults.timeout = apiConstants.defaultTimeout; axios.defaults.timeout = DEFAULT_API_TIMEOUT;
axios.interceptors.request.use(config => { axios.interceptors.request.use(config => {
const token = userState.getToken(); const token = userState.getToken();
@@ -202,7 +213,7 @@ export default {
return axios.postForm('v1/users/avatar/update.json', { return axios.postForm('v1/users/avatar/update.json', {
avatar: avatarFile avatar: avatarFile
}, { }, {
timeout: apiConstants.uploadTimeout timeout: DEFAULT_UPLOAD_API_TIMEOUT
}); });
}, },
removeAvatar: () => { removeAvatar: () => {
@@ -471,7 +482,7 @@ export default {
fileType: fileType, fileType: fileType,
file: importFile file: importFile
}, { }, {
timeout: apiConstants.uploadTimeout timeout: DEFAULT_UPLOAD_API_TIMEOUT
}); });
}, },
importTransactions: ({ transactions, clientSessionId }) => { importTransactions: ({ transactions, clientSessionId }) => {
@@ -479,7 +490,7 @@ export default {
transactions: transactions, transactions: transactions,
clientSessionId: clientSessionId clientSessionId: clientSessionId
}, { }, {
timeout: apiConstants.importTimeout timeout: DEFAULT_IMPORT_API_TIMEOUT
}); });
}, },
uploadTransactionPicture: ({ pictureFile, clientSessionId }) => { uploadTransactionPicture: ({ pictureFile, clientSessionId }) => {
@@ -487,7 +498,7 @@ export default {
picture: pictureFile, picture: pictureFile,
clientSessionId: clientSessionId clientSessionId: clientSessionId
}, { }, {
timeout: apiConstants.uploadTimeout timeout: DEFAULT_UPLOAD_API_TIMEOUT
}); });
}, },
removeUnusedTransactionPicture: ({ id }) => { removeUnusedTransactionPicture: ({ id }) => {
@@ -639,15 +650,15 @@ export default {
getLatestExchangeRates: ({ ignoreError }) => { getLatestExchangeRates: ({ ignoreError }) => {
return axios.get('v1/exchange_rates/latest.json', { return axios.get('v1/exchange_rates/latest.json', {
ignoreError: !!ignoreError, ignoreError: !!ignoreError,
timeout: getExchangeRatesRequestTimeout() || apiConstants.defaultTimeout timeout: getExchangeRatesRequestTimeout() || DEFAULT_API_TIMEOUT
}); });
}, },
generateQrCodeUrl: (qrCodeName) => { generateQrCodeUrl: (qrCodeName) => {
return `${apiConstants.baseQrcodePath}/${qrCodeName}.png`; return `${BASE_QRCODE_PATH}/${qrCodeName}.png`;
}, },
generateMapProxyTileImageUrl: (mapProvider, language) => { generateMapProxyTileImageUrl: (mapProvider, language) => {
const token = userState.getToken(); const token = userState.getToken();
let url = `${apiConstants.baseProxyUrlPath}/map/tile/{z}/{x}/{y}.png?provider=${mapProvider}&token=${token}`; let url = `${BASE_PROXY_URL_PATH}/map/tile/{z}/{x}/{y}.png?provider=${mapProvider}&token=${token}`;
if (language) { if (language) {
url = url + `&language=${language}`; url = url + `&language=${language}`;
@@ -657,7 +668,7 @@ export default {
}, },
generateMapProxyAnnotationImageUrl: (mapProvider, language) => { generateMapProxyAnnotationImageUrl: (mapProvider, language) => {
const token = userState.getToken(); const token = userState.getToken();
let url = `${apiConstants.baseProxyUrlPath}/map/annotation/{z}/{x}/{y}.png?provider=${mapProvider}&token=${token}`; let url = `${BASE_PROXY_URL_PATH}/map/annotation/{z}/{x}/{y}.png?provider=${mapProvider}&token=${token}`;
if (language) { if (language) {
url = url + `&language=${language}`; url = url + `&language=${language}`;
@@ -666,7 +677,7 @@ export default {
return url; return url;
}, },
generateGoogleMapJavascriptUrl: (language, callbackFnName) => { generateGoogleMapJavascriptUrl: (language, callbackFnName) => {
let url = `${apiConstants.googleMapJavascriptUrl}?key=${getGoogleMapAPIKey()}&libraries=core,marker&callback=${callbackFnName}`; let url = `${GOOGLE_MAP_JAVASCRIPT_URL}?key=${getGoogleMapAPIKey()}&libraries=core,marker&callback=${callbackFnName}`;
if (language) { if (language) {
url = url + `&language=${language}`; url = url + `&language=${language}`;
@@ -675,13 +686,13 @@ export default {
return url; return url;
}, },
generateBaiduMapJavascriptUrl: (callbackFnName) => { generateBaiduMapJavascriptUrl: (callbackFnName) => {
return `${apiConstants.baiduMapJavascriptUrl}&ak=${getBaiduMapAK()}&callback=${callbackFnName}`; return `${BAIDU_MAP_JAVASCRIPT_URL}&ak=${getBaiduMapAK()}&callback=${callbackFnName}`;
}, },
generateAmapJavascriptUrl: (callbackFnName) => { generateAmapJavascriptUrl: (callbackFnName) => {
return `${apiConstants.amapJavascriptUrl}&key=${getAmapApplicationKey()}&plugin=AMap.ToolBar&callback=${callbackFnName}`; return `${AMAP_JAVASCRIPT_URL}&key=${getAmapApplicationKey()}&plugin=AMap.ToolBar&callback=${callbackFnName}`;
}, },
generateAmapApiInternalProxyUrl: () => { generateAmapApiInternalProxyUrl: () => {
return `${window.location.origin}${apiConstants.baseAmapApiProxyUrlPath}`; return `${window.location.origin}${BASE_AMAP_API_PROXY_URL_PATH}`;
}, },
getInternalAvatarUrlWithToken(avatarUrl, disableBrowserCache) { getInternalAvatarUrlWithToken(avatarUrl, disableBrowserCache) {
if (!avatarUrl) { if (!avatarUrl) {
+116
View File
@@ -0,0 +1,116 @@
import uaParser from 'ua-parser-js';
import { CliUserAgent, type TokenInfoResponse, SessionInfo } from '@/models/token.ts';
interface UserAgentInfo {
device: {
vendor?: string;
model?: string;
type?: string;
};
os: {
name?: string;
version?: string;
};
browser: {
name?: string;
version?: string;
};
}
function parseUserAgent(ua: string): UserAgentInfo {
const uaParseRet = uaParser(ua);
return {
device: {
vendor: uaParseRet.device.vendor,
model: uaParseRet.device.model,
type: uaParseRet.device.type
},
os: {
name: uaParseRet.os.name,
version: uaParseRet.os.version
},
browser: {
name: uaParseRet.browser.name,
version: uaParseRet.browser.version
}
};
}
function isSessionUserAgentCreatedByCli(ua: string): boolean {
return ua === CliUserAgent;
}
function parseDeviceInfo(uaInfo: UserAgentInfo): string {
if (!uaInfo) {
return '';
}
let result = '';
if (uaInfo.device && uaInfo.device.model) {
result = uaInfo.device.model;
} else if (uaInfo.os && uaInfo.os.name) {
result = uaInfo.os.name;
if (uaInfo.os.version) {
result += ' ' + uaInfo.os.version;
}
}
if (uaInfo.browser && uaInfo.browser.name) {
let browserInfo = uaInfo.browser.name;
if (uaInfo.browser.version) {
browserInfo += ' ' + uaInfo.browser.version;
}
if (result) {
result += ' (' + browserInfo + ')';
} else {
result = browserInfo;
}
}
if (!result) {
return 'Unknown Device';
}
return result;
}
export function parseSessionInfo(token: TokenInfoResponse): SessionInfo {
const isCreatedByCli = isSessionUserAgentCreatedByCli(token.userAgent);
const uaInfo = parseUserAgent(token.userAgent);
let deviceType = '';
if (isCreatedByCli) {
deviceType = 'cli';
} else {
if (uaInfo && uaInfo.device) {
if (uaInfo.device.type === 'mobile') {
deviceType = 'phone';
} else if (uaInfo.device.type === 'wearable') {
deviceType = 'wearable';
} else if (uaInfo.device.type === 'tablet') {
deviceType = 'tablet';
} else if (uaInfo.device.type === 'smarttv') {
deviceType = 'tv';
} else {
deviceType = 'default';
}
} else {
deviceType = 'default';
}
}
return SessionInfo.of(
token.tokenId,
token.isCurrent,
deviceType,
isCreatedByCli ? token.userAgent : parseDeviceInfo(uaInfo),
isCreatedByCli,
token.lastSeen
);
}
+5 -5
View File
@@ -1,5 +1,5 @@
import timezoneConstants from '@/consts/timezone.js'; import { TimezoneTypeForStatistics } from '@/core/timezone.ts';
import currencyConstants from '@/consts/currency.js'; import { CurrencySortingType } from '@/core/currency.ts';
import statisticsConstants from '@/consts/statistics.js'; import statisticsConstants from '@/consts/statistics.js';
const settingsLocalStorageKey = 'ebk_app_settings'; const settingsLocalStorageKey = 'ebk_app_settings';
@@ -15,15 +15,15 @@ const defaultSettings = {
autoSaveTransactionDraft: 'disabled', autoSaveTransactionDraft: 'disabled',
autoGetCurrentGeoLocation: false, autoGetCurrentGeoLocation: false,
showAmountInHomePage: true, showAmountInHomePage: true,
timezoneUsedForStatisticsInHomePage: timezoneConstants.defaultTimezoneTypesUsedForStatistics, timezoneUsedForStatisticsInHomePage: TimezoneTypeForStatistics.Default.type,
itemsCountInTransactionListPage: 15, itemsCountInTransactionListPage: 15,
showTotalAmountInTransactionListPage: true, showTotalAmountInTransactionListPage: true,
showTagInTransactionListPage: true, showTagInTransactionListPage: true,
showAccountBalance: true, showAccountBalance: true,
currencySortByInExchangeRatesPage: currencyConstants.defaultCurrencySortingType, currencySortByInExchangeRatesPage: CurrencySortingType.Default.type,
statistics: { statistics: {
defaultChartDataType: statisticsConstants.defaultChartDataType, defaultChartDataType: statisticsConstants.defaultChartDataType,
defaultTimezoneType: timezoneConstants.defaultTimezoneTypesUsedForStatistics, defaultTimezoneType: TimezoneTypeForStatistics.Default.type,
defaultAccountFilter: {}, defaultAccountFilter: {},
defaultTransactionCategoryFilter: {}, defaultTransactionCategoryFilter: {},
defaultSortingType: statisticsConstants.defaultSortingType, defaultSortingType: statisticsConstants.defaultSortingType,
+21 -21
View File
@@ -1,8 +1,8 @@
import categoryConstants from '@/consts/category.js'; import { CategoryType } from '@/core/category.ts';
import transactionConstants from '@/consts/transaction.js'; import { TransactionType } from '@/core/transaction.ts';
import { import {
isNumber isNumber
} from './common.js'; } from './common.ts';
import { import {
getBrowserTimezoneOffsetMinutes, getBrowserTimezoneOffsetMinutes,
getDummyUnixTimeForLocalUsage getDummyUnixTimeForLocalUsage
@@ -32,48 +32,48 @@ export function setTransactionModelByTransaction(transaction, transaction2, allC
} }
} }
if (allCategories[categoryConstants.allCategoryTypes.Expense] && if (allCategories[CategoryType.Expense] &&
allCategories[categoryConstants.allCategoryTypes.Expense].length) { allCategories[CategoryType.Expense].length) {
if (options.categoryId && options.categoryId !== '0') { if (options.categoryId && options.categoryId !== '0') {
if (isSubCategoryIdAvailable(allCategories[categoryConstants.allCategoryTypes.Expense], options.categoryId)) { if (isSubCategoryIdAvailable(allCategories[CategoryType.Expense], options.categoryId)) {
transaction.expenseCategory = options.categoryId; transaction.expenseCategory = options.categoryId;
} else { } else {
transaction.expenseCategory = getFirstAvailableSubCategoryId(allCategories[categoryConstants.allCategoryTypes.Expense], options.categoryId); transaction.expenseCategory = getFirstAvailableSubCategoryId(allCategories[CategoryType.Expense], options.categoryId);
} }
} }
if (!transaction.expenseCategory) { if (!transaction.expenseCategory) {
transaction.expenseCategory = getFirstAvailableCategoryId(allCategories[categoryConstants.allCategoryTypes.Expense]); transaction.expenseCategory = getFirstAvailableCategoryId(allCategories[CategoryType.Expense]);
} }
} }
if (allCategories[categoryConstants.allCategoryTypes.Income] && if (allCategories[CategoryType.Income] &&
allCategories[categoryConstants.allCategoryTypes.Income].length) { allCategories[CategoryType.Income].length) {
if (options.categoryId && options.categoryId !== '0') { if (options.categoryId && options.categoryId !== '0') {
if (isSubCategoryIdAvailable(allCategories[categoryConstants.allCategoryTypes.Income], options.categoryId)) { if (isSubCategoryIdAvailable(allCategories[CategoryType.Income], options.categoryId)) {
transaction.incomeCategory = options.categoryId; transaction.incomeCategory = options.categoryId;
} else { } else {
transaction.incomeCategory = getFirstAvailableSubCategoryId(allCategories[categoryConstants.allCategoryTypes.Income], options.categoryId); transaction.incomeCategory = getFirstAvailableSubCategoryId(allCategories[CategoryType.Income], options.categoryId);
} }
} }
if (!transaction.incomeCategory) { if (!transaction.incomeCategory) {
transaction.incomeCategory = getFirstAvailableCategoryId(allCategories[categoryConstants.allCategoryTypes.Income]); transaction.incomeCategory = getFirstAvailableCategoryId(allCategories[CategoryType.Income]);
} }
} }
if (allCategories[categoryConstants.allCategoryTypes.Transfer] && if (allCategories[CategoryType.Transfer] &&
allCategories[categoryConstants.allCategoryTypes.Transfer].length) { allCategories[CategoryType.Transfer].length) {
if (options.categoryId && options.categoryId !== '0') { if (options.categoryId && options.categoryId !== '0') {
if (isSubCategoryIdAvailable(allCategories[categoryConstants.allCategoryTypes.Transfer], options.categoryId)) { if (isSubCategoryIdAvailable(allCategories[CategoryType.Transfer], options.categoryId)) {
transaction.transferCategory = options.categoryId; transaction.transferCategory = options.categoryId;
} else { } else {
transaction.transferCategory = getFirstAvailableSubCategoryId(allCategories[categoryConstants.allCategoryTypes.Transfer], options.categoryId); transaction.transferCategory = getFirstAvailableSubCategoryId(allCategories[CategoryType.Transfer], options.categoryId);
} }
} }
if (!transaction.transferCategory) { if (!transaction.transferCategory) {
transaction.transferCategory = getFirstAvailableCategoryId(allCategories[categoryConstants.allCategoryTypes.Transfer]); transaction.transferCategory = getFirstAvailableCategoryId(allCategories[CategoryType.Transfer]);
} }
} }
@@ -128,11 +128,11 @@ export function setTransactionModelByTransaction(transaction, transaction2, allC
transaction.type = transaction2.type; transaction.type = transaction2.type;
if (transaction.type === transactionConstants.allTransactionTypes.Expense) { if (transaction.type === TransactionType.Expense) {
transaction.expenseCategory = transaction2.categoryId || ''; transaction.expenseCategory = transaction2.categoryId || '';
} else if (transaction.type === transactionConstants.allTransactionTypes.Income) { } else if (transaction.type === TransactionType.Income) {
transaction.incomeCategory = transaction2.categoryId || ''; transaction.incomeCategory = transaction2.categoryId || '';
} else if (transaction.type === transactionConstants.allTransactionTypes.Transfer) { } else if (transaction.type === TransactionType.Transfer) {
transaction.transferCategory = transaction2.categoryId || ''; transaction.transferCategory = transaction2.categoryId || '';
} }
+25 -17
View File
@@ -1,23 +1,25 @@
import colorConstants from '@/consts/color.js'; import { ThemeType } from '@/core/theme.ts';
export function getSystemTheme() { import { type AmountColor, PresetAmountColor } from '@/core/color.ts';
export function getSystemTheme(): ThemeType {
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
return 'dark'; return ThemeType.Dark;
} else { } else {
return 'light'; return ThemeType.Light;
} }
} }
export function getExpenseAndIncomeAmountColor(expenseAmountColorType, incomeAmountColorType, isDarkMode) { export function getExpenseAndIncomeAmountColor(expenseAmountColorType: number, incomeAmountColorType: number, isDarkMode: boolean): AmountColor {
let expenseAmountColor = expenseAmountColorType ? colorConstants.allAmountColorTypesMap[expenseAmountColorType] : null; let expenseAmountColor = expenseAmountColorType ? PresetAmountColor.valueOf(expenseAmountColorType) : null;
let incomeAmountColor = incomeAmountColorType ? colorConstants.allAmountColorTypesMap[incomeAmountColorType] : null; let incomeAmountColor = incomeAmountColorType ? PresetAmountColor.valueOf(incomeAmountColorType) : null;
if (!expenseAmountColor) { if (!expenseAmountColor) {
expenseAmountColor = colorConstants.defaultExpenseAmountColor; expenseAmountColor = PresetAmountColor.DefaultExpenseColor;
} }
if (!incomeAmountColor) { if (!incomeAmountColor) {
incomeAmountColor = colorConstants.defaultIncomeAmountColor; incomeAmountColor = PresetAmountColor.DefaultIncomeColor;
} }
if (isDarkMode) { if (isDarkMode) {
@@ -33,22 +35,28 @@ export function getExpenseAndIncomeAmountColor(expenseAmountColorType, incomeAmo
} }
} }
export function setExpenseAndIncomeAmountColor(expenseAmountColorType, incomeAmountColorType) { export function setExpenseAndIncomeAmountColor(expenseAmountColorType: number, incomeAmountColorType: number): void {
let expenseAmountColor = expenseAmountColorType ? colorConstants.allAmountColorTypesMap[expenseAmountColorType] : null; let expenseAmountColor = expenseAmountColorType ? PresetAmountColor.valueOf(expenseAmountColorType) : null;
let incomeAmountColor = incomeAmountColorType ? colorConstants.allAmountColorTypesMap[incomeAmountColorType] : null; let incomeAmountColor = incomeAmountColorType ? PresetAmountColor.valueOf(incomeAmountColorType) : null;
if (!expenseAmountColor) { if (!expenseAmountColor) {
expenseAmountColor = colorConstants.defaultExpenseAmountColor; expenseAmountColor = PresetAmountColor.DefaultExpenseColor;
} }
if (!incomeAmountColor) { if (!incomeAmountColor) {
incomeAmountColor = colorConstants.defaultIncomeAmountColor; incomeAmountColor = PresetAmountColor.DefaultIncomeColor;
} }
const htmlElement = document.querySelector('html'); const htmlElement = document.querySelector('html');
for (let i = 0; i < colorConstants.allAmountColorsArray.length; i++) { if (!htmlElement) {
const amountColor = colorConstants.allAmountColorsArray[i]; return;
}
const allPresetAmountColors = PresetAmountColor.values();
for (let i = 0; i < allPresetAmountColors.length; i++) {
const amountColor = allPresetAmountColors[i];
if (amountColor.type === expenseAmountColor.type) { if (amountColor.type === expenseAmountColor.type) {
if (!htmlElement.classList.contains(amountColor.expenseClassName)) { if (!htmlElement.classList.contains(amountColor.expenseClassName)) {
@@ -68,7 +76,7 @@ export function setExpenseAndIncomeAmountColor(expenseAmountColorType, incomeAmo
} }
} }
export function startDownloadFile(fileName, fileData) { export function startDownloadFile(fileName: string, fileData: Blob): void {
const dataObjectUrl = URL.createObjectURL(fileData); const dataObjectUrl = URL.createObjectURL(fileData);
const dataLink = document.createElement('a'); const dataLink = document.createElement('a');
+12 -9
View File
@@ -1,8 +1,8 @@
import { f7, f7ready } from 'framework7-vue'; import { f7, f7ready } from 'framework7-vue';
import fontConstants from '@/consts/font.js'; import { FontSize, FONT_SIZE_PREVIEW_CLASSNAME_PREFIX } from '@/core/font.ts';
import { isEnableAnimate } from './settings.js'; import { isEnableAnimate } from '../settings.js';
import { translateError } from './i18n.js'; import { translateError } from '../i18n.js';
export function showAlert(message, confirmCallback, translateFn) { export function showAlert(message, confirmCallback, translateFn) {
f7ready((f7) => { f7ready((f7) => {
@@ -126,9 +126,10 @@ export function autoChangeTextareaSize(el) {
export function setAppFontSize(type) { export function setAppFontSize(type) {
const htmlElement = elements('html'); const htmlElement = elements('html');
const allFontSizes = FontSize.values();
for (let i = 0; i < fontConstants.allFontSizeArray.length; i++) { for (let i = 0; i < allFontSizes.length; i++) {
const fontSizeType = fontConstants.allFontSizeArray[i]; const fontSizeType = allFontSizes[i];
if (fontSizeType.type === type) { if (fontSizeType.type === type) {
if (!htmlElement.hasClass(fontSizeType.className)) { if (!htmlElement.hasClass(fontSizeType.className)) {
@@ -141,15 +142,17 @@ export function setAppFontSize(type) {
} }
export function getFontSizePreviewClassName(type) { export function getFontSizePreviewClassName(type) {
for (let i = 0; i < fontConstants.allFontSizeArray.length; i++) { const allFontSizes = FontSize.values();
const fontSizeType = fontConstants.allFontSizeArray[i];
for (let i = 0; i < allFontSizes.length; i++) {
const fontSizeType = allFontSizes[i];
if (fontSizeType.type === type) { if (fontSizeType.type === type) {
return fontConstants.fontSizePreviewClassNamePrefix + fontSizeType.className; return FONT_SIZE_PREVIEW_CLASSNAME_PREFIX + fontSizeType.className;
} }
} }
return fontConstants.fontSizePreviewClassNamePrefix + fontConstants.defaultFontSize.className; return FONT_SIZE_PREVIEW_CLASSNAME_PREFIX + FontSize.Default.className;
} }
export function scrollToSelectedItem(parentEl, containerSelector, selectedItemSelector) { export function scrollToSelectedItem(parentEl, containerSelector, selectedItemSelector) {
+1 -1
View File
@@ -1,6 +1,6 @@
import CryptoJS from 'crypto-js'; import CryptoJS from 'crypto-js';
import { isString, isObject } from './common.js'; import { isString, isObject } from './common.ts';
import { isEnableApplicationLock } from './settings.js'; import { isEnableApplicationLock } from './settings.js';
import logger from './logger.js'; import logger from './logger.js';
+9 -9
View File
@@ -1,11 +1,11 @@
export function isProduction() { export function isProduction(): boolean {
return process.env.NODE_ENV === 'production'; return __EZBOOKKEEPING_IS_PRODUCTION__;
} }
export function getVersion() { export function getVersion(): string {
const isRelease = !getBuildTime(); const isRelease = !getBuildTime();
const commitHash = __EZBOOKKEEPING_BUILD_COMMIT_HASH__; // eslint-disable-line const commitHash = __EZBOOKKEEPING_BUILD_COMMIT_HASH__;
let version = __EZBOOKKEEPING_VERSION__; // eslint-disable-line let version = __EZBOOKKEEPING_VERSION__;
if (version && (!isRelease || !isProduction())) { if (version && (!isRelease || !isProduction())) {
version += '-dev'; version += '-dev';
@@ -22,18 +22,18 @@ export function getVersion() {
return version; return version;
} }
export function getBuildTime() { export function getBuildTime(): string {
return __EZBOOKKEEPING_BUILD_UNIX_TIME__; // eslint-disable-line return __EZBOOKKEEPING_BUILD_UNIX_TIME__;
} }
export function getMobileVersionPath() { export function getMobileVersionPath(): string {
if (isProduction()) { if (isProduction()) {
return '../mobile'; return '../mobile';
} else { } else {
return 'mobile.html'; return 'mobile.html';
} }
} }
export function getDesktopVersionPath() { export function getDesktopVersionPath(): string {
if (isProduction()) { if (isProduction()) {
return '../desktop'; return '../desktop';
} else { } else {
+2 -2
View File
@@ -6,10 +6,10 @@ import {
arrayBufferToString, arrayBufferToString,
base64encode, base64encode,
base64decode base64decode
} from './common.js'; } from './common.ts';
import { import {
generateRandomString generateRandomString
} from './misc.js'; } from './misc.ts';
const publicKeyCredentialCreationOptionsBaseTemplate = { const publicKeyCredentialCreationOptionsBaseTemplate = {
attestation: "none", attestation: "none",
+10 -2
View File
@@ -2,10 +2,18 @@ import en from './en.json';
import vi from './vi.json'; import vi from './vi.json';
import zhHans from './zh_Hans.json'; import zhHans from './zh_Hans.json';
export const defaultLanguage = 'en'; interface LanguageInfo {
name: string,
displayName: string,
alternativeLanguageTag: string,
aliases?: string[],
content: object
}
export const defaultLanguage: string = 'en';
// To add new languages, please refer to https://ezbookkeeping.mayswind.net/translating // To add new languages, please refer to https://ezbookkeeping.mayswind.net/translating
export const allLanguages = { export const allLanguages: Record<string, LanguageInfo> = {
'en': { 'en': {
name: 'English', name: 'English',
displayName: 'English', displayName: 'English',
+2 -2
View File
@@ -79,7 +79,7 @@ import 'line-awesome/dist/line-awesome/css/line-awesome.css';
import VueDatePicker from '@vuepic/vue-datepicker'; import VueDatePicker from '@vuepic/vue-datepicker';
import '@vuepic/vue-datepicker/dist/main.css'; import '@vuepic/vue-datepicker/dist/main.css';
import { getVersion, getBuildTime } from '@/lib/version.js'; import { getVersion, getBuildTime } from '@/lib/version.ts';
import userstate from '@/lib/userstate.js'; import userstate from '@/lib/userstate.js';
import { import {
getI18nOptions, getI18nOptions,
@@ -93,7 +93,7 @@ import {
showLoading, showLoading,
hideLoading, hideLoading,
routeBackOnError routeBackOnError
} from '@/lib/ui.mobile.js'; } from '@/lib/ui/mobile.js';
import PinCodeInput from '@/components/common/PinCodeInput.vue'; import PinCodeInput from '@/components/common/PinCodeInput.vue';
import MapView from '@/components/common/MapView.vue'; import MapView from '@/components/common/MapView.vue';

Some files were not shown because too many files have changed in this diff Show More