move the "Timezone Used for Date Range" option from insights explorer settings into each exploration

This commit is contained in:
MaysWind
2026-01-03 20:42:16 +08:00
parent cc0996e0d2
commit 526d7e50ec
9 changed files with 130 additions and 102 deletions
@@ -53,14 +53,13 @@ export const ALL_APPLICATION_CLOUD_SETTINGS: CategorizedApplicationCloudSettingI
{
categoryName: 'Insights Explorer Page',
items: [
{ settingKey: 'insightsExplorerDefaultDateRangeType', settingName: 'Default Date Range', mobile: false, desktop: true },
{ settingKey: 'timezoneUsedForInsightsExplorerPage', settingName: 'Timezone Used for Date Range', mobile: false, desktop: true },
{ settingKey: 'insightsExplorerDefaultDateRangeType', settingName: 'Default Date Range', mobile: false, desktop: true }
]
},
{
categoryName: 'Account List Page',
items: [
{ settingKey: 'totalAmountExcludeAccountIds', settingName: 'Accounts Included in Total', mobile: true, desktop: true },
{ settingKey: 'totalAmountExcludeAccountIds', settingName: 'Accounts Included in Total', mobile: true, desktop: true }
]
},
{
@@ -240,18 +240,6 @@
v-model="insightsExplorerDefaultDateRangeType"
/>
</v-col>
<v-col cols="12" md="6">
<v-select
item-title="displayName"
item-value="type"
persistent-placeholder
:label="tt('Timezone Used for Date Range')"
:placeholder="tt('Timezone Used for Date Range')"
:items="allTimezoneTypesUsedForStatistics"
v-model="timezoneUsedForInsightsExplorerPage"
/>
</v-col>
</v-row>
</v-card-text>
</v-form>
@@ -339,7 +327,6 @@ import { useAppSettingPageBase } from '@/views/base/settings/AppSettingsPageBase
import { useSettingsStore } from '@/stores/setting.ts';
import { useAccountsStore } from '@/stores/account.ts';
import { useTransactionCategoriesStore } from '@/stores/transactionCategory.ts';
import { useExplorersStore } from '@/stores/explorer.ts';
import type { LocalizedSwitchOption } from '@/core/base.ts';
import { ThemeType } from '@/core/theme.ts';
@@ -383,7 +370,6 @@ const {
const settingsStore = useSettingsStore();
const accountsStore = useAccountsStore();
const transactionCategoriesStore = useTransactionCategoriesStore();
const explorersStore = useExplorersStore();
const snackbar = useTemplateRef<SnackBarType>('snackbar');
@@ -419,14 +405,6 @@ const insightsExplorerDefaultDateRangeType = computed<number>({
set: (value) => settingsStore.setInsightsExplorerDefaultDateRangeType(value)
});
const timezoneUsedForInsightsExplorerPage = computed<number>({
get: () => settingsStore.appSettings.timezoneUsedForInsightsExplorerPage,
set: (value: number) => {
settingsStore.setTimezoneUsedForInsightsExplorerPage(value);
explorersStore.updateTransactionExplorerInvalidState(true);
}
});
function init(): void {
loadingAccounts.value = true;
+30 -4
View File
@@ -77,15 +77,25 @@
</v-btn>
<v-spacer/>
<v-btn density="comfortable" color="default" variant="text" class="ms-2"
:disabled="loading" :icon="true"
v-if="activeTab === 'table' || activeTab === 'chart'">
:disabled="loading" :icon="true">
<v-icon :icon="mdiDotsVertical" />
<v-menu activator="parent">
<v-list>
<v-list-subheader :title="tt('Timezone Used for Date Range')"
v-if="activeTab === 'query'"/>
<template v-if="activeTab === 'query'">
<v-list-item :key="timezoneType.type" :value="timezoneType.type"
:prepend-icon="timezoneTypeIconMap[timezoneType.type]"
:append-icon="(query.timezoneUsedForDateRange === timezoneType.type ? mdiCheck : undefined)"
:title="timezoneType.displayName"
v-for="timezoneType in allTimezoneTypesUsedForDateRange"
@click="updateTimezoneUsedForDateRange(timezoneType.type)"></v-list-item>
</template>
<v-list-item :prepend-icon="mdiExport"
:title="tt('Export Results')"
:disabled="loading || !filteredTransactions || filteredTransactions.length < 1"
@click="exportResults"></v-list-item>
@click="exportResults"
v-if="activeTab === 'table' || activeTab === 'chart'"></v-list-item>
</v-list>
</v-menu>
</v-btn>
@@ -144,9 +154,10 @@ import { useTransactionCategoriesStore } from '@/stores/transactionCategory.ts';
import { useTransactionTagsStore } from '@/stores/transactionTag.ts';
import { type TransactionExplorerPartialFilter, type TransactionExplorerFilter, useExplorersStore } from '@/stores/explorer.ts';
import type { NameNumeralValue } from '@/core/base.ts';
import type { NameNumeralValue, TypeAndDisplayName } from '@/core/base.ts';
import type { NumeralSystem } from '@/core/numeral.ts';
import { type WeekDayValue, type LocalizedDateRange, DateRangeScene, DateRange } from '@/core/datetime.ts';
import { TimezoneTypeForStatistics } from '@/core/timezone.ts';
import {
type TransactionInsightDataItem
@@ -166,6 +177,8 @@ import {
mdiCheck,
mdiRefresh,
mdiDotsVertical,
mdiHomeClockOutline,
mdiInvoiceTextClockOutline,
mdiExport
} from '@mdi/js';
@@ -191,6 +204,7 @@ const display = useDisplay();
const {
tt,
getAllDateRanges,
getAllTimezoneTypesUsedForStatistics,
getCurrentNumeralSystemType,
formatDateTimeToLongDateTime,
formatDateRange
@@ -202,6 +216,11 @@ const transactionCategoriesStore = useTransactionCategoriesStore();
const transactionTagsStore = useTransactionTagsStore();
const explorersStore = useExplorersStore();
const timezoneTypeIconMap = {
[TimezoneTypeForStatistics.ApplicationTimezone.type]: mdiHomeClockOutline,
[TimezoneTypeForStatistics.TransactionTimezone.type]: mdiInvoiceTextClockOutline
};
const snackbar = useTemplateRef<SnackBarType>('snackbar');
const explorerDataTableTab = useTemplateRef<ExplorerDataTableTabType>('explorerDataTableTab');
const explorerChartTab = useTemplateRef<ExplorerChartTabType>('explorerChartTab');
@@ -224,6 +243,7 @@ const query = computed<TransactionExplorerFilter>(() => explorersStore.transacti
const filteredTransactions = computed<TransactionInsightDataItem[]>(() => explorersStore.filteredTransactions);
const allDateRanges = computed<LocalizedDateRange[]>(() => getAllDateRanges(DateRangeScene.InsightsExplorer, true));
const allTimezoneTypesUsedForDateRange = computed<TypeAndDisplayName[]>(() => getAllTimezoneTypesUsedForStatistics());
const canShiftDateRange = computed<boolean>(() => query.value.dateRangeType !== DateRange.All.type);
const displayQueryDateRangeName = computed<string>(() => formatDateRange(query.value.dateRangeType, query.value.startTime, query.value.endTime));
const displayQueryStartTime = computed<string>(() => formatDateTimeToLongDateTime(parseDateTimeFromUnixTime(query.value.startTime)));
@@ -337,6 +357,12 @@ function reload(force: boolean): Promise<unknown> | null {
});
}
function updateTimezoneUsedForDateRange(timezoneType: number): void {
explorersStore.updateTransactionExplorerFilter({
timezoneUsedForDateRange: timezoneType
});
}
function exportResults(): void {
if (activeTab.value === 'table' && filteredTransactions.value) {
const results = explorerDataTableTab.value?.buildExportResults();
@@ -80,7 +80,6 @@
/>
<pie-chart
:items="categoryDimensionTransactionExplorerData && categoryDimensionTransactionExplorerData.length ? categoryDimensionTransactionExplorerData : []"
:min-valid-percent="0.0001"
:show-value="true"
:show-percent="true"
:enable-click-item="true"
@@ -152,7 +151,7 @@ import {
} from '@/lib/common.ts';
import {
parseDateTimeFromUnixTime
parseDateTimeFromString
} from '@/lib/datetime.ts';
interface InsightsExplorerDataTableTabProps {
@@ -184,7 +183,7 @@ const {
formatDateTimeToGregorianLikeShortYear,
formatDateTimeToGregorianLikeShortYearMonth,
formatDateTimeToGregorianLikeYearQuarter,
formatDateTimeToGregorianLikeFiscalYear,
formatGregorianYearToGregorianLikeFiscalYear,
formatAmountToLocalizedNumerals,
formatAmountToWesternArabicNumeralsWithoutDigitGrouping
} = useI18n();
@@ -238,18 +237,21 @@ function getCategoriedDataDisplayName(info: CategoriedInfo | SeriesedInfo): stri
let name: string = '';
let needI18n: boolean | undefined = false;
let i18nParameters: Record<string, unknown> | undefined = undefined;
let dimessionType: TransactionExplorerDataDimensionType = TransactionExplorerDataDimension.None.value;
let dimessionType: TransactionExplorerDimensionType = TransactionExplorerDimensionType.Other;
let dimession: TransactionExplorerDataDimensionType = TransactionExplorerDataDimension.None.value;
if ('categoryName' in info) {
name = info.categoryName;
needI18n = info.categoryNameNeedI18n;
i18nParameters = info.categoryNameI18nParameters;
dimessionType = explorersStore.transactionExplorerFilter.categoryDimension;
dimessionType = info.categoryIdType;
dimession = explorersStore.transactionExplorerFilter.categoryDimension;
} else if ('seriesName' in info) {
name = info.seriesName;
needI18n = info.seriesNameNeedI18n;
i18nParameters = info.seriesNameI18nParameters;
dimessionType = explorersStore.transactionExplorerFilter.seriesDimension;
dimessionType = info.seriesIdType;
dimession = explorersStore.transactionExplorerFilter.seriesDimension;
}
let displayName: string = name;
@@ -262,32 +264,40 @@ function getCategoriedDataDisplayName(info: CategoriedInfo | SeriesedInfo): stri
}
// convert the name to formatted date time if needed
if (dimessionType === TransactionExplorerDataDimension.DateTime.value) {
displayName = formatDateTimeToShortDateTime(parseDateTimeFromUnixTime(parseInt(name)));
} else if (dimessionType === TransactionExplorerDataDimension.DateTimeByYearMonthDay.value) {
displayName = formatDateTimeToShortDate(parseDateTimeFromUnixTime(parseInt(name)));
} else if (dimessionType === TransactionExplorerDataDimension.DateTimeByYearMonth.value) {
displayName = formatDateTimeToGregorianLikeShortYearMonth(parseDateTimeFromUnixTime(parseInt(name)));
} else if (dimessionType === TransactionExplorerDataDimension.DateTimeByYearQuarter.value) {
displayName = formatDateTimeToGregorianLikeYearQuarter(parseDateTimeFromUnixTime(parseInt(name)));
} else if (dimessionType === TransactionExplorerDataDimension.DateTimeByYear.value) {
displayName = formatDateTimeToGregorianLikeShortYear(parseDateTimeFromUnixTime(parseInt(name)));
} else if (dimessionType === TransactionExplorerDataDimension.DateTimeByFiscalYear.value) {
displayName = formatDateTimeToGregorianLikeFiscalYear(parseDateTimeFromUnixTime(parseInt(name)));
} else if (dimessionType === TransactionExplorerDataDimension.DateTimeByDayOfWeek.value) {
if (dimession === TransactionExplorerDataDimension.DateTime.value) {
const dateTime = parseDateTimeFromString(name, dimessionType);
displayName = dateTime ? formatDateTimeToShortDateTime(dateTime) : tt('Unknown');
} else if (dimession === TransactionExplorerDataDimension.DateTimeByYearMonthDay.value) {
const dateTime = parseDateTimeFromString(name, dimessionType);
displayName = dateTime ? formatDateTimeToShortDate(dateTime) : tt('Unknown');
} else if (dimession === TransactionExplorerDataDimension.DateTimeByYearMonth.value) {
const dateTime = parseDateTimeFromString(name, dimessionType);
displayName = dateTime ? formatDateTimeToGregorianLikeShortYearMonth(dateTime) : tt('Unknown');
} else if (dimession === TransactionExplorerDataDimension.DateTimeByYearQuarter.value) {
const parts = name.split('-');
const year = parts.length === 2 ? parts[0] : '';
const quarter = parts.length === 2 ? parseInt(parts[1] as string) : 0;
const dateTime = year && quarter ? parseDateTimeFromString(`${year}-${quarter * 3}`, TransactionExplorerDimensionType.YearMonth) : undefined;
displayName = dateTime ? formatDateTimeToGregorianLikeYearQuarter(dateTime) : tt('Unknown');
} else if (dimession === TransactionExplorerDataDimension.DateTimeByYear.value) {
const dateTime = parseDateTimeFromString(name, dimessionType);
displayName = dateTime ? formatDateTimeToGregorianLikeShortYear(dateTime) : tt('Unknown');
} else if (dimession === TransactionExplorerDataDimension.DateTimeByFiscalYear.value) {
displayName = formatGregorianYearToGregorianLikeFiscalYear(parseInt(name));
} else if (dimession === TransactionExplorerDataDimension.DateTimeByDayOfWeek.value) {
const weekDay = WeekDay.parse(name);
displayName = weekDay ? getWeekdayLongName(weekDay) : tt('Unknown');
} else if (dimessionType === TransactionExplorerDataDimension.DateTimeByDayOfMonth.value) {
} else if (dimession === TransactionExplorerDataDimension.DateTimeByDayOfMonth.value) {
displayName = getMonthdayShortName(parseInt(name));
} else if (dimessionType === TransactionExplorerDataDimension.DateTimeByMonthOfYear.value) {
} else if (dimession === TransactionExplorerDataDimension.DateTimeByMonthOfYear.value) {
const month = Month.valueOf(parseInt(name));
displayName = month ? getMonthLongName(month.name) : tt('Unknown');
} else if (dimessionType === TransactionExplorerDataDimension.DateTimeByQuarterOfYear.value) {
} else if (dimession === TransactionExplorerDataDimension.DateTimeByQuarterOfYear.value) {
displayName = getQuarterName(parseInt(name));
}
if (dimessionType === TransactionExplorerDataDimension.SourceAmount.value
|| dimessionType === TransactionExplorerDataDimension.DestinationAmount.value) {
if (dimession === TransactionExplorerDataDimension.SourceAmount.value
|| dimession === TransactionExplorerDataDimension.DestinationAmount.value) {
if (name !== '' && name !== 'none' && Number.isFinite(parseInt(name))) {
displayName = formatAmountToLocalizedNumerals(parseInt(name));
}
@@ -15,6 +15,7 @@
<span>{{ getDisplayDateTime(item) }}</span>
<v-chip class="ms-1" variant="flat" color="secondary" size="x-small"
v-if="!isSameAsDefaultTimezoneOffsetMinutes(item)">{{ getDisplayTimezone(item) }}</v-chip>
<v-tooltip activator="parent" v-if="!isSameAsDefaultTimezoneOffsetMinutes(item)">{{ getDisplayTimeInDefaultTimezone(item) }}</v-tooltip>
</template>
<template #item.type="{ item }">
<v-chip label variant="outlined" size="x-small"
@@ -79,6 +80,7 @@ import { useI18n } from '@/locales/helpers.ts';
import { useUserStore } from '@/stores/user.ts';
import { useExplorersStore } from '@/stores/explorer.ts';
import type { NumeralSystem } from '@/core/numeral.ts';
import { TransactionType } from '@/core/transaction.ts';
import {
@@ -108,6 +110,7 @@ const emit = defineEmits<{
const {
tt,
getCurrentNumeralSystemType,
formatDateTimeToLongDateTime,
formatDateTimeToGregorianDefaultDateTime,
formatAmountToWesternArabicNumeralsWithoutDigitGrouping,
@@ -119,6 +122,7 @@ const explorersStore = useExplorersStore();
const currentPage = ref<number>(1);
const numeralSystem = computed<NumeralSystem>(() => getCurrentNumeralSystemType());
const defaultCurrency = computed<string>(() => userStore.currentUserDefaultCurrency);
const filteredTransactions = computed<TransactionInsightDataItem[]>(() => explorersStore.filteredTransactions);
@@ -172,6 +176,13 @@ function getDisplayTimezone(transaction: TransactionInsightDataItem): string {
return `UTC${getUtcOffsetByUtcOffsetMinutes(transaction.utcOffset)}`;
}
function getDisplayTimeInDefaultTimezone(transaction: TransactionInsightDataItem): string {
const timezoneOffsetMinutes = getTimezoneOffsetMinutes(transaction.time);
const dateTime = parseDateTimeFromUnixTimeWithTimezoneOffset(transaction.time, timezoneOffsetMinutes);
const utcOffset = numeralSystem.value.replaceWesternArabicDigitsToLocalizedDigits(getUtcOffsetByUtcOffsetMinutes(timezoneOffsetMinutes));
return `${formatDateTimeToLongDateTime(dateTime)} (UTC${utcOffset})`;
}
function getDisplayTransactionType(transaction: TransactionInsightDataItem): string {
if (transaction.type === TransactionType.ModifyBalance) {
return tt('Modify Balance');