move files

This commit is contained in:
MaysWind
2023-08-05 16:51:34 +08:00
parent 7e24492ce8
commit 395bd31898
22 changed files with 48 additions and 41 deletions
@@ -0,0 +1,283 @@
<template>
<v-row>
<v-col cols="12">
<v-card :title="$t('Basic Settings')">
<v-form>
<v-card-text>
<v-row>
<v-col cols="12" md="6">
<v-select
item-title="displayName"
item-value="value"
persistent-placeholder
:label="$t('Theme')"
:placeholder="$t('Theme')"
:items="[
{ value: 'auto', displayName: $t('System Default') },
{ value: 'light', displayName: $t('Light') },
{ value: 'dark', displayName: $t('Dark') }
]"
v-model="theme"
/>
</v-col>
<v-col cols="12" md="6">
<v-autocomplete
item-title="displayNameWithUtcOffset"
item-value="name"
persistent-placeholder
:label="$t('Timezone')"
:placeholder="$t('Timezone')"
:items="allTimezones"
:no-data-text="$t('No results')"
v-model="timeZone"
/>
</v-col>
<v-col cols="12" md="6">
<v-select
item-title="displayName"
item-value="value"
persistent-placeholder
:label="$t('Auto-update Exchange Rates Data')"
:placeholder="$t('Auto-update Exchange Rates Data')"
:items="enableDisableOptions"
v-model="isAutoUpdateExchangeRatesData"
/>
</v-col>
<v-col cols="12" md="6">
<v-select
item-title="displayName"
item-value="value"
persistent-placeholder
:label="$t('Enable Thousands Separator')"
:placeholder="$t('Enable Thousands Separator')"
:items="enableDisableOptions"
v-model="isEnableThousandsSeparator"
/>
</v-col>
<v-col cols="12" md="6">
<v-select
item-title="displayName"
item-value="value"
persistent-placeholder
:label="$t('Currency Display Mode')"
:placeholder="$t('Currency Display Mode')"
:items="[
{ value: allCurrencyDisplayModes.None, displayName: $t('None') },
{ value: allCurrencyDisplayModes.Symbol, displayName: $t('Currency Symbol') },
{ value: allCurrencyDisplayModes.Code, displayName: $t('Currency Code') },
{ value: allCurrencyDisplayModes.Name, displayName: $t('Currency Name') }
]"
v-model="currencyDisplayMode"
/>
</v-col>
<v-col cols="12" md="6">
<v-select
item-title="displayName"
item-value="value"
persistent-placeholder
:label="$t('Show Account Balance')"
:placeholder="$t('Show Account Balance')"
:items="enableDisableOptions"
v-model="showAccountBalance"
/>
</v-col>
</v-row>
</v-card-text>
</v-form>
</v-card>
</v-col>
<v-col cols="12">
<v-card :title="$t('Overview Page')">
<v-form>
<v-card-text>
<v-row>
<v-col cols="12" md="6">
<v-select
item-title="displayName"
item-value="value"
persistent-placeholder
:label="$t('Show Amount')"
:placeholder="$t('Show Amount')"
:items="enableDisableOptions"
v-model="showAmountInHomePage"
/>
</v-col>
</v-row>
</v-card-text>
</v-form>
</v-card>
</v-col>
<v-col cols="12">
<v-card :title="$t('Transaction List Page')">
<v-form>
<v-card-text>
<v-row>
<v-col cols="12" md="6">
<v-select
item-title="displayName"
item-value="value"
persistent-placeholder
:label="$t('Show Monthly Total Amount')"
:placeholder="$t('Show Monthly Total Amount')"
:items="enableDisableOptions"
v-model="showTotalAmountInTransactionListPage"
/>
</v-col>
</v-row>
</v-card-text>
</v-form>
</v-card>
</v-col>
<v-col cols="12">
<v-card :title="$t('Transaction Edit Page')">
<v-form>
<v-card-text>
<v-row>
<v-col cols="12" md="6">
<v-select
item-title="displayName"
item-value="value"
persistent-placeholder
:label="$t('Automatically Add Geolocation')"
:placeholder="$t('Automatically Add Geolocation')"
:items="enableDisableOptions"
v-model="isAutoGetCurrentGeoLocation"
/>
</v-col>
</v-row>
</v-card-text>
</v-form>
</v-card>
</v-col>
</v-row>
</template>
<script>
import { useTheme } from 'vuetify';
import { mapStores } from 'pinia';
import { useRootStore } from '@/stores/index.js';
import { useSettingsStore } from '@/stores/setting.js';
import { useUserStore } from '@/stores/user.js';
import { useTransactionsStore } from '@/stores/transaction.js';
import { useOverviewStore } from '@/stores/overview.js';
import { useStatisticsStore } from '@/stores/statistics.js';
import { useExchangeRatesStore } from '@/stores/exchangeRates.js';
import currencyConstants from '@/consts/currency.js';
import { getSystemTheme } from '@/lib/ui.js';
export default {
computed: {
...mapStores(useRootStore, useSettingsStore, useUserStore, useTransactionsStore, useOverviewStore, useStatisticsStore, useExchangeRatesStore),
enableDisableOptions() {
return this.$locale.getEnableDisableOptions();
},
allTimezones() {
return this.$locale.getAllTimezones(true);
},
allCurrencyDisplayModes() {
return currencyConstants.allCurrencyDisplayModes;
},
theme: {
get: function () {
return this.settingsStore.appSettings.theme;
},
set: function (value) {
if (value !== this.settingsStore.appSettings.theme) {
this.settingsStore.setTheme(value);
if (value === 'light' || value === 'dark') {
this.globalTheme.global.name.value = value;
} else {
this.globalTheme.global.name.value = getSystemTheme();
}
}
}
},
timeZone: {
get: function () {
return this.settingsStore.appSettings.timeZone;
},
set: function (value) {
this.settingsStore.setTimeZone(value);
this.$locale.setTimeZone(value);
this.transactionsStore.updateTransactionListInvalidState(true);
this.overviewStore.updateTransactionOverviewInvalidState(true);
this.statisticsStore.updateTransactionStatisticsInvalidState(true);
}
},
isAutoUpdateExchangeRatesData: {
get: function () {
return this.settingsStore.appSettings.autoUpdateExchangeRatesData;
},
set: function (value) {
this.settingsStore.setAutoUpdateExchangeRatesData(value);
}
},
isEnableThousandsSeparator: {
get: function () {
return this.settingsStore.appSettings.thousandsSeparator;
},
set: function (value) {
this.settingsStore.setEnableThousandsSeparator(value);
}
},
currencyDisplayMode: {
get: function () {
return this.settingsStore.appSettings.currencyDisplayMode;
},
set: function (value) {
this.settingsStore.setCurrencyDisplayMode(value);
}
},
showAccountBalance: {
get: function () {
return this.settingsStore.appSettings.showAccountBalance;
},
set: function (value) {
this.settingsStore.setShowAccountBalance(value);
}
},
showAmountInHomePage: {
get: function () {
return this.settingsStore.appSettings.showAmountInHomePage;
},
set: function (value) {
this.settingsStore.setShowAmountInHomePage(value);
}
},
showTotalAmountInTransactionListPage: {
get: function () {
return this.settingsStore.appSettings.showTotalAmountInTransactionListPage;
},
set: function (value) {
this.settingsStore.setShowTotalAmountInTransactionListPage(value);
}
},
isAutoGetCurrentGeoLocation: {
get: function () {
return this.settingsStore.appSettings.autoGetCurrentGeoLocation;
},
set: function (value) {
this.settingsStore.setAutoGetCurrentGeoLocation(value);
}
}
},
setup() {
const theme = useTheme();
return {
globalTheme: theme
};
}
};
</script>
@@ -0,0 +1,200 @@
<template>
<v-row>
<v-col cols="12">
<v-card :title="$t('Application Lock')">
<v-card-text class="pb-0">
<p class="text-body-1 font-weight-semibold" v-if="!isEnableApplicationLock">
{{ $t('Application lock is not enabled') }}
</p>
<p class="text-body-1" v-if="isEnableApplicationLock">
{{ $t('Application lock has been enabled') }}
</p>
</v-card-text>
<v-card-text v-if="isEnableApplicationLock">
<v-switch inset :disabled="true"
:label="$t('Unlock By PIN Code')"
v-model="isEnableApplicationLock"/>
<v-switch inset
:label="$t('Unlock By WebAuthn')"
:loading="enablingWebAuthn"
v-model="isEnableApplicationLockWebAuthn"/>
</v-card-text>
<v-card-text class="pb-0">
<p class="text-body-1 font-weight-semibold" v-if="!isEnableApplicationLock">
{{ $t('Please input a new 6-digit PIN code. PIN code would encrypt your local data, so you need input this PIN code when you launch this app. If this PIN code is lost, you should re-login.') }}
</p>
<p class="text-body-1 font-weight-semibold" v-if="isEnableApplicationLock">
{{ $t('Please enter your current PIN code when disable application lock.') }}
</p>
</v-card-text>
<v-card-text class="pb-0">
<v-row class="mb-3">
<v-col cols="12" md="4">
<div style="max-width: 428px">
<pin-code-input :secure="true" :length="6" v-model="pinCode" />
</div>
</v-col>
</v-row>
</v-card-text>
<v-card-text>
<v-row>
<v-col cols="12" class="d-flex flex-wrap gap-4">
<v-btn :disabled="!pinCodeValid"
v-if="!isEnableApplicationLock" @click="enable">
{{ $t('Enable Application Lock') }}
</v-btn>
<v-btn :disabled="!pinCodeValid"
v-if="isEnableApplicationLock" @click="disable">
{{ $t('Disable Application Lock') }}
</v-btn>
</v-col>
</v-row>
</v-card-text>
</v-card>
</v-col>
</v-row>
<snack-bar ref="snackbar" />
</template>
<script>
import { mapStores } from 'pinia';
import { useSettingsStore } from '@/stores/setting.js';
import { useUserStore } from '@/stores/user.js';
import logger from '@/lib/logger.js';
import webauthn from '@/lib/webauthn.js';
export default {
data() {
return {
isSupportedWebAuthn: false,
enablingWebAuthn: false,
pinCode: ''
};
},
computed: {
...mapStores(useSettingsStore, useUserStore),
isEnableApplicationLock: {
get: function () {
return this.settingsStore.appSettings.applicationLock;
},
set: function (value) {
this.settingsStore.setEnableApplicationLock(value);
}
},
isEnableApplicationLockWebAuthn: {
get: function () {
return this.settingsStore.appSettings.applicationLockWebAuthn;
},
set: function (value) {
this.settingsStore.setEnableApplicationLockWebAuthn(value);
}
},
pinCodeValid() {
return this.pinCode && this.pinCode.length === 6;
}
},
watch: {
isEnableApplicationLockWebAuthn: function (newValue) {
const self = this;
if (newValue) {
self.enablingWebAuthn = true;
webauthn.registerCredential(
self.$user.getUserAppLockState(),
self.userStore.currentUserInfo,
).then(({ id }) => {
self.enablingWebAuthn = false;
self.$user.saveWebAuthnConfig(id);
self.settingsStore.setEnableApplicationLockWebAuthn(true);
self.$refs.snackbar.showMessage('You have enabled WebAuthn successfully');
}).catch(error => {
logger.error('failed to enable WebAuthn', error);
self.enablingWebAuthn = false;
if (error.notSupported) {
self.$refs.snackbar.showMessage('This device does not support WebAuthn');
} else if (error.name === 'NotAllowedError') {
self.$refs.snackbar.showMessage('User has canceled authentication');
} else if (error.invalid) {
self.$refs.snackbar.showMessage('Failed to enable WebAuthn');
} else {
self.$refs.snackbar.showMessage('User has canceled or this device does not support WebAuthn');
}
self.isEnableApplicationLockWebAuthn = false;
self.settingsStore.setEnableApplicationLockWebAuthn(false);
self.$user.clearWebAuthnConfig();
});
} else {
self.settingsStore.setEnableApplicationLockWebAuthn(false);
self.$user.clearWebAuthnConfig();
}
}
},
created() {
const self = this;
webauthn.isCompletelySupported().then(result => {
self.isSupportedWebAuthn = result;
});
},
methods: {
enable() {
if (this.settingsStore.appSettings.applicationLock) {
this.$refs.snackbar.showMessage('Application lock has been enabled');
return;
}
if (!this.pinCode || this.pinCode.length !== 6) {
this.pinCode = '';
this.$refs.snackbar.showMessage('PIN code is invalid');
return;
}
const user = this.userStore.currentUserInfo;
if (!user || !user.username) {
this.pinCode = '';
this.$refs.snackbar.showMessage('An error has occurred');
return;
}
this.$user.encryptToken(user.username, this.pinCode);
this.settingsStore.setEnableApplicationLock(true);
this.settingsStore.setEnableApplicationLockWebAuthn(false);
this.$user.clearWebAuthnConfig();
this.pinCode = '';
},
disable() {
if (!this.settingsStore.appSettings.applicationLock) {
this.$refs.snackbar.showMessage('Application lock is not enabled');
return;
}
if (!this.$user.isCorrectPinCode(this.pinCode)) {
this.pinCode = '';
this.$refs.snackbar.showMessage('PIN code is wrong');
return;
}
this.pinCode = '';
this.$user.decryptToken();
this.settingsStore.setEnableApplicationLock(false);
this.settingsStore.setEnableApplicationLockWebAuthn(false);
this.$user.clearWebAuthnConfig();
}
}
}
</script>
@@ -0,0 +1,137 @@
<template>
<v-row>
<v-col cols="12">
<v-card :title="$t('Statistics Settings')">
<v-form>
<v-card-text>
<v-row>
<v-col cols="12" md="6">
<v-select
item-title="displayName"
item-value="type"
persistent-placeholder
:label="$t('Default Chart Type')"
:placeholder="$t('Default Chart Type')"
:items="[
{ type: allChartTypes.Pie, displayName: $t('Pie Chart') },
{ type: allChartTypes.Bar, displayName: $t('Bar Chart') }
]"
v-model="defaultChartType"
/>
</v-col>
<v-col cols="12" md="6">
<v-select
item-title="displayName"
item-value="type"
persistent-placeholder
:label="$t('Default Chart Data Type')"
:placeholder="$t('Default Chart Data Type')"
:items="allChartDataTypes"
v-model="defaultChartDataType"
/>
</v-col>
<v-col cols="12" md="6">
<v-select
item-title="displayName"
item-value="type"
persistent-placeholder
:label="$t('Default Date Range')"
:placeholder="$t('Default Date Range')"
:items="allDateRanges"
v-model="defaultDateRange"
/>
</v-col>
<v-col cols="12" md="6">
<v-select
item-title="displayName"
item-value="type"
persistent-placeholder
:label="$t('Default Sort By')"
:placeholder="$t('Default Sort By')"
:items="allSortingTypes"
v-model="defaultSortingType"
/>
</v-col>
</v-row>
</v-card-text>
</v-form>
</v-card>
</v-col>
<v-col cols="12">
<account-filter-settings-card :auto-save="true" :modify-default="true" />
</v-col>
<v-col cols="12">
<category-filter-settings-card :auto-save="true" :modify-default="true" />
</v-col>
</v-row>
</template>
<script>
import { mapStores } from 'pinia';
import { useSettingsStore } from '@/stores/setting.js';
import statisticsConstants from '@/consts/statistics.js';
import AccountFilterSettingsCard from '@/views/desktop/statistics/settings/cards/AccountFilterSettingsCard.vue';
import CategoryFilterSettingsCard from '@/views/desktop/statistics/settings/cards/CategoryFilterSettingsCard.vue';
export default {
components: {
AccountFilterSettingsCard,
CategoryFilterSettingsCard
},
computed: {
...mapStores(useSettingsStore),
allChartTypes() {
return statisticsConstants.allChartTypes;
},
allChartDataTypes() {
return this.$locale.getAllStatisticsChartDataTypes();
},
allSortingTypes() {
return this.$locale.getAllStatisticsSortingTypes();
},
allDateRanges() {
return this.$locale.getAllDateRanges(false);
},
defaultChartType: {
get: function () {
return this.settingsStore.appSettings.statistics.defaultChartType;
},
set: function (value) {
this.settingsStore.setStatisticsDefaultChartType(value);
}
},
defaultChartDataType: {
get: function () {
return this.settingsStore.appSettings.statistics.defaultChartDataType;
},
set: function (value) {
this.settingsStore.setStatisticsDefaultChartDataType(value);
}
},
defaultDateRange: {
get: function () {
return this.settingsStore.appSettings.statistics.defaultDataRangeType;
},
set: function (value) {
this.settingsStore.setStatisticsDefaultDateRange(value);
}
},
defaultSortingType: {
get: function () {
return this.settingsStore.appSettings.statistics.defaultSortingType;
},
set: function (value) {
this.settingsStore.setStatisticsSortingType(value);
}
}
}
};
</script>