allow users to set coordinate display type (#141)

This commit is contained in:
MaysWind
2025-05-27 01:01:55 +08:00
parent e338c7190d
commit 626d3895aa
36 changed files with 516 additions and 144 deletions
+1
View File
@@ -903,6 +903,7 @@ func printUserInfo(user *models.User) {
fmt.Printf("[DigitGroupingSymbol] %s (%d)\n", user.DigitGroupingSymbol, user.DigitGroupingSymbol) fmt.Printf("[DigitGroupingSymbol] %s (%d)\n", user.DigitGroupingSymbol, user.DigitGroupingSymbol)
fmt.Printf("[DigitGrouping] %s (%d)\n", user.DigitGrouping, user.DigitGrouping) fmt.Printf("[DigitGrouping] %s (%d)\n", user.DigitGrouping, user.DigitGrouping)
fmt.Printf("[CurrencyDisplayType] %s (%d)\n", user.CurrencyDisplayType, user.CurrencyDisplayType) fmt.Printf("[CurrencyDisplayType] %s (%d)\n", user.CurrencyDisplayType, user.CurrencyDisplayType)
fmt.Printf("[CoordinateDisplayType] %s (%d)\n", user.CoordinateDisplayType, user.CoordinateDisplayType)
fmt.Printf("[ExpenseAmountColor] %s (%d)\n", user.ExpenseAmountColor, user.ExpenseAmountColor) fmt.Printf("[ExpenseAmountColor] %s (%d)\n", user.ExpenseAmountColor, user.ExpenseAmountColor)
fmt.Printf("[IncomeAmountColor] %s (%d)\n", user.IncomeAmountColor, user.IncomeAmountColor) fmt.Printf("[IncomeAmountColor] %s (%d)\n", user.IncomeAmountColor, user.IncomeAmountColor)
fmt.Printf("[FeatureRestriction] %s (%d)\n", user.FeatureRestriction, user.FeatureRestriction) fmt.Printf("[FeatureRestriction] %s (%d)\n", user.FeatureRestriction, user.FeatureRestriction)
+9
View File
@@ -421,6 +421,15 @@ func (a *UsersApi) UserUpdateProfileHandler(c *core.WebContext) (any, *errs.Erro
userNew.CurrencyDisplayType = core.CURRENCY_DISPLAY_TYPE_INVALID userNew.CurrencyDisplayType = core.CURRENCY_DISPLAY_TYPE_INVALID
} }
if userUpdateReq.CoordinateDisplayType != nil && *userUpdateReq.CoordinateDisplayType != user.CoordinateDisplayType {
user.CoordinateDisplayType = *userUpdateReq.CoordinateDisplayType
userNew.CoordinateDisplayType = *userUpdateReq.CoordinateDisplayType
modifyProfileBasicInfo = true
anythingUpdate = true
} else {
userNew.CoordinateDisplayType = core.COORDINATE_DISPLAY_TYPE_INVALID
}
if userUpdateReq.ExpenseAmountColor != nil && *userUpdateReq.ExpenseAmountColor != user.ExpenseAmountColor { if userUpdateReq.ExpenseAmountColor != nil && *userUpdateReq.ExpenseAmountColor != user.ExpenseAmountColor {
user.ExpenseAmountColor = *userUpdateReq.ExpenseAmountColor user.ExpenseAmountColor = *userUpdateReq.ExpenseAmountColor
userNew.ExpenseAmountColor = *userUpdateReq.ExpenseAmountColor userNew.ExpenseAmountColor = *userUpdateReq.ExpenseAmountColor
+42
View File
@@ -0,0 +1,42 @@
package core
import "fmt"
// CoordinateDisplayType represents the display type of geographic coordinates
type CoordinateDisplayType byte
// Coordinate Display Type
const (
COORDINATE_DISPLAY_TYPE_DEFAULT CoordinateDisplayType = 0
COORDINATE_DISPLAY_TYPE_LATITUDE_LONGITUDE_DECIMAL_DEGREES CoordinateDisplayType = 1
COORDINATE_DISPLAY_TYPE_LONGITUDE_LATITUDE_DECIMAL_DEGREES CoordinateDisplayType = 2
COORDINATE_DISPLAY_TYPE_LATITUDE_LONGITUDE_DECIMAL_MINUTES CoordinateDisplayType = 3
COORDINATE_DISPLAY_TYPE_LONGITUDE_LATITUDE_DECIMAL_MINUTES CoordinateDisplayType = 4
COORDINATE_DISPLAY_TYPE_LATITUDE_LONGITUDE_DEGREES_MINUTES_SECONDS CoordinateDisplayType = 5
COORDINATE_DISPLAY_TYPE_LONGITUDE_LATITUDE_DEGREES_MINUTES_SECONDS CoordinateDisplayType = 6
COORDINATE_DISPLAY_TYPE_INVALID CoordinateDisplayType = 255
)
// String returns a textual representation of the geographic coordinates display type enum
func (d CoordinateDisplayType) String() string {
switch d {
case COORDINATE_DISPLAY_TYPE_DEFAULT:
return "Default"
case COORDINATE_DISPLAY_TYPE_LATITUDE_LONGITUDE_DECIMAL_DEGREES:
return "Latitude Longitude (Decimal Degrees)"
case COORDINATE_DISPLAY_TYPE_LONGITUDE_LATITUDE_DECIMAL_DEGREES:
return "Longitude Latitude (Decimal Degrees)"
case COORDINATE_DISPLAY_TYPE_LATITUDE_LONGITUDE_DECIMAL_MINUTES:
return "Latitude Longitude (Decimal Minutes)"
case COORDINATE_DISPLAY_TYPE_LONGITUDE_LATITUDE_DECIMAL_MINUTES:
return "Longitude Latitude (Decimal Minutes)"
case COORDINATE_DISPLAY_TYPE_LATITUDE_LONGITUDE_DEGREES_MINUTES_SECONDS:
return "Latitude Longitude (Degrees Minutes Seconds)"
case COORDINATE_DISPLAY_TYPE_LONGITUDE_LATITUDE_DEGREES_MINUTES_SECONDS:
return "Longitude Latitude (Degrees Minutes Seconds)"
case COORDINATE_DISPLAY_TYPE_INVALID:
return "Invalid"
default:
return fmt.Sprintf("Invalid(%d)", int(d))
}
}
+95 -91
View File
@@ -82,61 +82,63 @@ func (s AmountColorType) String() string {
// User represents user data stored in database // User represents user data stored in database
type User struct { type User struct {
Uid int64 `xorm:"PK"` Uid int64 `xorm:"PK"`
Username string `xorm:"VARCHAR(32) UNIQUE NOT NULL"` Username string `xorm:"VARCHAR(32) UNIQUE NOT NULL"`
Email string `xorm:"VARCHAR(100) UNIQUE NOT NULL"` Email string `xorm:"VARCHAR(100) UNIQUE NOT NULL"`
Nickname string `xorm:"VARCHAR(64) NOT NULL"` Nickname string `xorm:"VARCHAR(64) NOT NULL"`
Password string `xorm:"VARCHAR(64) NOT NULL"` Password string `xorm:"VARCHAR(64) NOT NULL"`
Salt string `xorm:"VARCHAR(10) NOT NULL"` Salt string `xorm:"VARCHAR(10) NOT NULL"`
CustomAvatarType string `xorm:"VARCHAR(10)"` CustomAvatarType string `xorm:"VARCHAR(10)"`
DefaultAccountId int64 DefaultAccountId int64
TransactionEditScope TransactionEditScope `xorm:"TINYINT NOT NULL"` TransactionEditScope TransactionEditScope `xorm:"TINYINT NOT NULL"`
Language string `xorm:"VARCHAR(10)"` Language string `xorm:"VARCHAR(10)"`
DefaultCurrency string `xorm:"VARCHAR(3) NOT NULL"` DefaultCurrency string `xorm:"VARCHAR(3) NOT NULL"`
FirstDayOfWeek core.WeekDay `xorm:"TINYINT NOT NULL"` FirstDayOfWeek core.WeekDay `xorm:"TINYINT NOT NULL"`
LongDateFormat core.LongDateFormat `xorm:"TINYINT"` LongDateFormat core.LongDateFormat `xorm:"TINYINT"`
ShortDateFormat core.ShortDateFormat `xorm:"TINYINT"` ShortDateFormat core.ShortDateFormat `xorm:"TINYINT"`
LongTimeFormat core.LongTimeFormat `xorm:"TINYINT"` LongTimeFormat core.LongTimeFormat `xorm:"TINYINT"`
ShortTimeFormat core.ShortTimeFormat `xorm:"TINYINT"` ShortTimeFormat core.ShortTimeFormat `xorm:"TINYINT"`
DecimalSeparator core.DecimalSeparator `xorm:"TINYINT"` DecimalSeparator core.DecimalSeparator `xorm:"TINYINT"`
DigitGroupingSymbol core.DigitGroupingSymbol `xorm:"TINYINT"` DigitGroupingSymbol core.DigitGroupingSymbol `xorm:"TINYINT"`
DigitGrouping core.DigitGroupingType `xorm:"TINYINT"` DigitGrouping core.DigitGroupingType `xorm:"TINYINT"`
CurrencyDisplayType core.CurrencyDisplayType `xorm:"TINYINT"` CurrencyDisplayType core.CurrencyDisplayType `xorm:"TINYINT"`
ExpenseAmountColor AmountColorType `xorm:"TINYINT"` CoordinateDisplayType core.CoordinateDisplayType `xorm:"TINYINT"`
IncomeAmountColor AmountColorType `xorm:"TINYINT"` ExpenseAmountColor AmountColorType `xorm:"TINYINT"`
FeatureRestriction core.UserFeatureRestrictions IncomeAmountColor AmountColorType `xorm:"TINYINT"`
Disabled bool FeatureRestriction core.UserFeatureRestrictions
Deleted bool `xorm:"NOT NULL"` Disabled bool
EmailVerified bool `xorm:"NOT NULL"` Deleted bool `xorm:"NOT NULL"`
CreatedUnixTime int64 EmailVerified bool `xorm:"NOT NULL"`
UpdatedUnixTime int64 CreatedUnixTime int64
DeletedUnixTime int64 UpdatedUnixTime int64
LastLoginUnixTime int64 DeletedUnixTime int64
LastLoginUnixTime int64
} }
// UserBasicInfo represents a view-object of user basic info // UserBasicInfo represents a view-object of user basic info
type UserBasicInfo struct { type UserBasicInfo struct {
Username string `json:"username"` Username string `json:"username"`
Email string `json:"email"` Email string `json:"email"`
Nickname string `json:"nickname"` Nickname string `json:"nickname"`
AvatarUrl string `json:"avatar"` AvatarUrl string `json:"avatar"`
AvatarProvider string `json:"avatarProvider,omitempty"` AvatarProvider string `json:"avatarProvider,omitempty"`
DefaultAccountId int64 `json:"defaultAccountId,string"` DefaultAccountId int64 `json:"defaultAccountId,string"`
TransactionEditScope TransactionEditScope `json:"transactionEditScope"` TransactionEditScope TransactionEditScope `json:"transactionEditScope"`
Language string `json:"language"` Language string `json:"language"`
DefaultCurrency string `json:"defaultCurrency"` DefaultCurrency string `json:"defaultCurrency"`
FirstDayOfWeek core.WeekDay `json:"firstDayOfWeek"` FirstDayOfWeek core.WeekDay `json:"firstDayOfWeek"`
LongDateFormat core.LongDateFormat `json:"longDateFormat"` LongDateFormat core.LongDateFormat `json:"longDateFormat"`
ShortDateFormat core.ShortDateFormat `json:"shortDateFormat"` ShortDateFormat core.ShortDateFormat `json:"shortDateFormat"`
LongTimeFormat core.LongTimeFormat `json:"longTimeFormat"` LongTimeFormat core.LongTimeFormat `json:"longTimeFormat"`
ShortTimeFormat core.ShortTimeFormat `json:"shortTimeFormat"` ShortTimeFormat core.ShortTimeFormat `json:"shortTimeFormat"`
DecimalSeparator core.DecimalSeparator `json:"decimalSeparator"` DecimalSeparator core.DecimalSeparator `json:"decimalSeparator"`
DigitGroupingSymbol core.DigitGroupingSymbol `json:"digitGroupingSymbol"` DigitGroupingSymbol core.DigitGroupingSymbol `json:"digitGroupingSymbol"`
DigitGrouping core.DigitGroupingType `json:"digitGrouping"` DigitGrouping core.DigitGroupingType `json:"digitGrouping"`
CurrencyDisplayType core.CurrencyDisplayType `json:"currencyDisplayType"` CurrencyDisplayType core.CurrencyDisplayType `json:"currencyDisplayType"`
ExpenseAmountColor AmountColorType `json:"expenseAmountColor"` CoordinateDisplayType core.CoordinateDisplayType `json:"coordinateDisplayType"`
IncomeAmountColor AmountColorType `json:"incomeAmountColor"` ExpenseAmountColor AmountColorType `json:"expenseAmountColor"`
EmailVerified bool `json:"emailVerified"` IncomeAmountColor AmountColorType `json:"incomeAmountColor"`
EmailVerified bool `json:"emailVerified"`
} }
// UserLoginRequest represents all parameters of user login request // UserLoginRequest represents all parameters of user login request
@@ -177,25 +179,26 @@ type UserResendVerifyEmailRequest struct {
// UserProfileUpdateRequest represents all parameters of user updating profile request // UserProfileUpdateRequest represents all parameters of user updating profile request
type UserProfileUpdateRequest struct { type UserProfileUpdateRequest struct {
Email string `json:"email" binding:"omitempty,notBlank,max=100,validEmail"` Email string `json:"email" binding:"omitempty,notBlank,max=100,validEmail"`
Nickname string `json:"nickname" binding:"omitempty,notBlank,max=64"` Nickname string `json:"nickname" binding:"omitempty,notBlank,max=64"`
Password string `json:"password" binding:"omitempty,min=6,max=128"` Password string `json:"password" binding:"omitempty,min=6,max=128"`
OldPassword string `json:"oldPassword" binding:"omitempty,min=6,max=128"` OldPassword string `json:"oldPassword" binding:"omitempty,min=6,max=128"`
DefaultAccountId int64 `json:"defaultAccountId,string" binding:"omitempty,min=1"` DefaultAccountId int64 `json:"defaultAccountId,string" binding:"omitempty,min=1"`
TransactionEditScope *TransactionEditScope `json:"transactionEditScope" binding:"omitempty,min=0,max=6"` TransactionEditScope *TransactionEditScope `json:"transactionEditScope" binding:"omitempty,min=0,max=6"`
Language string `json:"language" binding:"omitempty,min=2,max=16"` Language string `json:"language" binding:"omitempty,min=2,max=16"`
DefaultCurrency string `json:"defaultCurrency" binding:"omitempty,len=3,validCurrency"` DefaultCurrency string `json:"defaultCurrency" binding:"omitempty,len=3,validCurrency"`
FirstDayOfWeek *core.WeekDay `json:"firstDayOfWeek" binding:"omitempty,min=0,max=6"` FirstDayOfWeek *core.WeekDay `json:"firstDayOfWeek" binding:"omitempty,min=0,max=6"`
LongDateFormat *core.LongDateFormat `json:"longDateFormat" binding:"omitempty,min=0,max=3"` LongDateFormat *core.LongDateFormat `json:"longDateFormat" binding:"omitempty,min=0,max=3"`
ShortDateFormat *core.ShortDateFormat `json:"shortDateFormat" binding:"omitempty,min=0,max=3"` ShortDateFormat *core.ShortDateFormat `json:"shortDateFormat" binding:"omitempty,min=0,max=3"`
LongTimeFormat *core.LongTimeFormat `json:"longTimeFormat" binding:"omitempty,min=0,max=3"` LongTimeFormat *core.LongTimeFormat `json:"longTimeFormat" binding:"omitempty,min=0,max=3"`
ShortTimeFormat *core.ShortTimeFormat `json:"shortTimeFormat" binding:"omitempty,min=0,max=3"` ShortTimeFormat *core.ShortTimeFormat `json:"shortTimeFormat" binding:"omitempty,min=0,max=3"`
DecimalSeparator *core.DecimalSeparator `json:"decimalSeparator" binding:"omitempty,min=0,max=3"` DecimalSeparator *core.DecimalSeparator `json:"decimalSeparator" binding:"omitempty,min=0,max=3"`
DigitGroupingSymbol *core.DigitGroupingSymbol `json:"digitGroupingSymbol" binding:"omitempty,min=0,max=4"` DigitGroupingSymbol *core.DigitGroupingSymbol `json:"digitGroupingSymbol" binding:"omitempty,min=0,max=4"`
DigitGrouping *core.DigitGroupingType `json:"digitGrouping" binding:"omitempty,min=0,max=2"` DigitGrouping *core.DigitGroupingType `json:"digitGrouping" binding:"omitempty,min=0,max=2"`
CurrencyDisplayType *core.CurrencyDisplayType `json:"currencyDisplayType" binding:"omitempty,min=0,max=11"` CurrencyDisplayType *core.CurrencyDisplayType `json:"currencyDisplayType" binding:"omitempty,min=0,max=11"`
ExpenseAmountColor *AmountColorType `json:"expenseAmountColor" binding:"omitempty,min=0,max=4"` CoordinateDisplayType *core.CoordinateDisplayType `json:"coordinateDisplayType" binding:"omitempty,min=0,max=6"`
IncomeAmountColor *AmountColorType `json:"incomeAmountColor" binding:"omitempty,min=0,max=4"` ExpenseAmountColor *AmountColorType `json:"expenseAmountColor" binding:"omitempty,min=0,max=4"`
IncomeAmountColor *AmountColorType `json:"incomeAmountColor" binding:"omitempty,min=0,max=4"`
} }
// UserProfileUpdateResponse represents the data returns to frontend after updating profile // UserProfileUpdateResponse represents the data returns to frontend after updating profile
@@ -255,27 +258,28 @@ func (u *User) CanEditTransactionByTransactionTime(transactionTime int64, utcOff
// ToUserBasicInfo returns a user basic view-object according to database model // ToUserBasicInfo returns a user basic view-object according to database model
func (u *User) ToUserBasicInfo(avatarProvider core.UserAvatarProviderType, avatarUrl string) *UserBasicInfo { func (u *User) ToUserBasicInfo(avatarProvider core.UserAvatarProviderType, avatarUrl string) *UserBasicInfo {
return &UserBasicInfo{ return &UserBasicInfo{
Username: u.Username, Username: u.Username,
Email: u.Email, Email: u.Email,
Nickname: u.Nickname, Nickname: u.Nickname,
AvatarUrl: avatarUrl, AvatarUrl: avatarUrl,
AvatarProvider: string(avatarProvider), AvatarProvider: string(avatarProvider),
DefaultAccountId: u.DefaultAccountId, DefaultAccountId: u.DefaultAccountId,
TransactionEditScope: u.TransactionEditScope, TransactionEditScope: u.TransactionEditScope,
Language: u.Language, Language: u.Language,
DefaultCurrency: u.DefaultCurrency, DefaultCurrency: u.DefaultCurrency,
FirstDayOfWeek: u.FirstDayOfWeek, FirstDayOfWeek: u.FirstDayOfWeek,
LongDateFormat: u.LongDateFormat, LongDateFormat: u.LongDateFormat,
ShortDateFormat: u.ShortDateFormat, ShortDateFormat: u.ShortDateFormat,
LongTimeFormat: u.LongTimeFormat, LongTimeFormat: u.LongTimeFormat,
ShortTimeFormat: u.ShortTimeFormat, ShortTimeFormat: u.ShortTimeFormat,
DecimalSeparator: u.DecimalSeparator, DecimalSeparator: u.DecimalSeparator,
DigitGroupingSymbol: u.DigitGroupingSymbol, DigitGroupingSymbol: u.DigitGroupingSymbol,
DigitGrouping: u.DigitGrouping, DigitGrouping: u.DigitGrouping,
CurrencyDisplayType: u.CurrencyDisplayType, CurrencyDisplayType: u.CurrencyDisplayType,
ExpenseAmountColor: u.ExpenseAmountColor, CoordinateDisplayType: u.CoordinateDisplayType,
IncomeAmountColor: u.IncomeAmountColor, ExpenseAmountColor: u.ExpenseAmountColor,
EmailVerified: u.EmailVerified, IncomeAmountColor: u.IncomeAmountColor,
EmailVerified: u.EmailVerified,
} }
} }
+4
View File
@@ -321,6 +321,10 @@ func (s *UserService) UpdateUser(c core.Context, user *models.User, modifyUserLa
updateCols = append(updateCols, "currency_display_type") updateCols = append(updateCols, "currency_display_type")
} }
if core.COORDINATE_DISPLAY_TYPE_DEFAULT <= user.CoordinateDisplayType && user.CoordinateDisplayType <= core.COORDINATE_DISPLAY_TYPE_LONGITUDE_LATITUDE_DEGREES_MINUTES_SECONDS {
updateCols = append(updateCols, "coordinate_display_type")
}
if models.AMOUNT_COLOR_TYPE_DEFAULT <= user.ExpenseAmountColor && user.ExpenseAmountColor <= models.AMOUNT_COLOR_TYPE_BLACK_OR_WHITE { if models.AMOUNT_COLOR_TYPE_DEFAULT <= user.ExpenseAmountColor && user.ExpenseAmountColor <= models.AMOUNT_COLOR_TYPE_BLACK_OR_WHITE {
updateCols = append(updateCols, "expense_amount_color") updateCols = append(updateCols, "expense_amount_color")
} }
+6 -6
View File
@@ -13,7 +13,7 @@ import { ref, computed, useTemplateRef } from 'vue';
import { useI18n } from '@/locales/helpers.ts'; import { useI18n } from '@/locales/helpers.ts';
import type { MapPosition } from '@/core/map.ts'; import type { Coordinate } from '@/core/coordinate.ts';
import type { MapInstance } from '@/lib/map/base.ts'; import type { MapInstance } from '@/lib/map/base.ts';
import { createMapInstance } from '@/lib/map/index.ts'; import { createMapInstance } from '@/lib/map/index.ts';
@@ -21,18 +21,18 @@ const props = defineProps<{
height?: string; height?: string;
mapClass?: string; mapClass?: string;
mapStyle?: Record<string, string>; mapStyle?: Record<string, string>;
geoLocation?: MapPosition; geoLocation?: Coordinate;
}>(); }>();
const emit = defineEmits<{ const emit = defineEmits<{
(e: 'click', geoLocation: MapPosition): void; (e: 'click', geoLocation: Coordinate): void;
}>(); }>();
const { tt, getCurrentLanguageInfo } = useI18n(); const { tt, getCurrentLanguageInfo } = useI18n();
const mapContainer = useTemplateRef<HTMLElement>('mapContainer'); const mapContainer = useTemplateRef<HTMLElement>('mapContainer');
const mapInstance = ref<MapInstance | null>(createMapInstance()); const mapInstance = ref<MapInstance | null>(createMapInstance());
const initCenter = ref<MapPosition>({ const initCenter = ref<Coordinate>({
latitude: 0, latitude: 0,
longitude: 0 longitude: 0
}); });
@@ -92,7 +92,7 @@ function initMapView(): void {
zoomIn: tt('Zoom in'), zoomIn: tt('Zoom in'),
zoomOut: tt('Zoom out'), zoomOut: tt('Zoom out'),
}, },
onClick: (geoLocation: MapPosition) => { onClick: (geoLocation: Coordinate) => {
emit('click', geoLocation); emit('click', geoLocation);
} }
}); });
@@ -113,7 +113,7 @@ function initMapView(): void {
} }
} }
function setMarkerPosition(geoLocation?: MapPosition): void { function setMarkerPosition(geoLocation?: Coordinate): void {
if (!mapInstance.value) { if (!mapInstance.value) {
return; return;
} }
+7 -7
View File
@@ -39,20 +39,20 @@ import MapView from '@/components/common/MapView.vue';
import { useI18n } from '@/locales/helpers.ts'; import { useI18n } from '@/locales/helpers.ts';
import type { MapPosition } from '@/core/map.ts'; import type { Coordinate } from '@/core/coordinate.ts';
import { isSupportGetGeoLocationByClick } from '@/lib/map/index.ts'; import { isSupportGetGeoLocationByClick } from '@/lib/map/index.ts';
type MapViewType = InstanceType<typeof MapView>; type MapViewType = InstanceType<typeof MapView>;
const props = defineProps<{ const props = defineProps<{
modelValue?: MapPosition; modelValue?: Coordinate;
setGeoLocationByClickMap?: boolean; setGeoLocationByClickMap?: boolean;
show: boolean; show: boolean;
}>(); }>();
const emit = defineEmits<{ const emit = defineEmits<{
(e: 'update:modelValue', value: MapPosition | undefined): void; (e: 'update:modelValue', value: Coordinate | undefined): void;
(e: 'update:setGeoLocationByClickMap', value: boolean): void; (e: 'update:setGeoLocationByClickMap', value: boolean): void;
(e: 'update:show', value: boolean): void; (e: 'update:show', value: boolean): void;
}>(); }>();
@@ -61,7 +61,7 @@ const { tt } = useI18n();
const map = useTemplateRef<MapViewType>('map'); const map = useTemplateRef<MapViewType>('map');
const geoLocation = computed<MapPosition | undefined>({ const geoLocation = computed<Coordinate | undefined>({
get: () => { get: () => {
return props.modelValue; return props.modelValue;
}, },
@@ -70,10 +70,10 @@ const geoLocation = computed<MapPosition | undefined>({
} }
}); });
function updateSpecifiedGeoLocation(mapPosition: MapPosition): void { function updateSpecifiedGeoLocation(coordinate: Coordinate): void {
if (isSupportGetGeoLocationByClick() && props.setGeoLocationByClickMap) { if (isSupportGetGeoLocationByClick() && props.setGeoLocationByClickMap) {
geoLocation.value = mapPosition; geoLocation.value = coordinate;
map.value?.setMarkerPosition(mapPosition); map.value?.setMarkerPosition(coordinate);
} }
} }
+76
View File
@@ -0,0 +1,76 @@
import type { TypeAndName } from '@/core/base.ts';
export interface Coordinate {
latitude: number;
longitude: number;
}
export enum CoordinateDisplayOrder {
LatitudeLongitude = 0,
LongitudeLatitude = 1
}
export enum CoordinateDisplayFormat {
DecimalDegrees = 0,
DecimalMinutes = 1,
DegreesMinutesSeconds = 2
}
export enum CoordinateDirectionFormat {
Signed = 0,
Directional = 1
}
export class CoordinateDisplayType implements TypeAndName {
private static readonly allInstances: CoordinateDisplayType[] = [];
private static readonly allInstancesByType: Record<number, CoordinateDisplayType> = {};
public static readonly SystemDefaultType: number = 0;
public static readonly LatitudeLongitudeDecimalDegrees = new CoordinateDisplayType(1, 'Latitude Longitude D.D°', CoordinateDisplayOrder.LatitudeLongitude, CoordinateDisplayFormat.DecimalDegrees, CoordinateDirectionFormat.Signed);
public static readonly LongitudeLatitudeDecimalDegrees = new CoordinateDisplayType(2, 'Longitude Latitude D.D°', CoordinateDisplayOrder.LongitudeLatitude, CoordinateDisplayFormat.DecimalDegrees, CoordinateDirectionFormat.Signed);
public static readonly LatitudeLongitudeDecimalMinutes = new CoordinateDisplayType(3, 'Latitude Longitude D°M.M\'', CoordinateDisplayOrder.LatitudeLongitude, CoordinateDisplayFormat.DecimalMinutes, CoordinateDirectionFormat.Directional);
public static readonly LongitudeLatitudeDecimalMinutes = new CoordinateDisplayType(4, 'Longitude Latitude D°M.M\'', CoordinateDisplayOrder.LongitudeLatitude, CoordinateDisplayFormat.DecimalMinutes, CoordinateDirectionFormat.Directional);
public static readonly LatitudeLongitudeDegreesMinutesSeconds = new CoordinateDisplayType(5, 'Latitude Longitude D°M\'S"', CoordinateDisplayOrder.LatitudeLongitude, CoordinateDisplayFormat.DegreesMinutesSeconds, CoordinateDirectionFormat.Directional);
public static readonly LongitudeLatitudeDegreesMinutesSeconds = new CoordinateDisplayType(6, 'Longitude Latitude D°M\'S"', CoordinateDisplayOrder.LongitudeLatitude, CoordinateDisplayFormat.DegreesMinutesSeconds, CoordinateDirectionFormat.Directional);
public static readonly Default = CoordinateDisplayType.LatitudeLongitudeDecimalDegrees;
public readonly type: number;
public readonly name: string;
public readonly displayOrder: CoordinateDisplayOrder;
public readonly displayFormat: CoordinateDisplayFormat;
public readonly directionFormat: CoordinateDirectionFormat;
private constructor(type: number, name: string, displayOrder: CoordinateDisplayOrder, displayFormat: CoordinateDisplayFormat, directionFormat: CoordinateDirectionFormat) {
this.type = type;
this.name = name;
this.displayOrder = displayOrder;
this.displayFormat = displayFormat;
this.directionFormat = directionFormat;
CoordinateDisplayType.allInstances.push(this);
CoordinateDisplayType.allInstancesByType[type] = this;
}
public static values(): CoordinateDisplayType[] {
return CoordinateDisplayType.allInstances;
}
public static valueOf(type: number): CoordinateDisplayType | undefined {
return CoordinateDisplayType.allInstancesByType[type];
}
}
export function getNormalizedCoordinate(value: Coordinate): Coordinate {
if (!value) {
return value;
}
const normalizedLatitude = Math.max(-90, Math.min(90, value.latitude));
const normalizedLongitude = ((value.longitude + 180) % 360 + 360) % 360 - 180;
return {
latitude: normalizedLatitude,
longitude: normalizedLongitude
};
}
-4
View File
@@ -1,4 +0,0 @@
export interface MapPosition {
latitude: number;
longitude: number;
}
+56
View File
@@ -0,0 +1,56 @@
import {
type Coordinate,
CoordinateDisplayOrder,
CoordinateDisplayFormat,
CoordinateDirectionFormat,
CoordinateDisplayType,
getNormalizedCoordinate
} from '@/core/coordinate.ts';
export function formatCoordinate(value: Coordinate, coordinateDisplayType: number): string {
if (!value) {
return '';
}
value = getNormalizedCoordinate(value);
const displayType = CoordinateDisplayType.valueOf(coordinateDisplayType) || CoordinateDisplayType.Default;
const formattedLatitude = formatCoordinateValue(value.latitude, 'N', 'S', displayType.displayFormat, displayType.directionFormat);
const formattedLongitude = formatCoordinateValue(value.longitude, 'E', 'W', displayType.displayFormat, displayType.directionFormat);
if (displayType.displayOrder === CoordinateDisplayOrder.LatitudeLongitude) {
return `${formattedLatitude}, ${formattedLongitude}`;
} else if (displayType.displayOrder === CoordinateDisplayOrder.LongitudeLatitude) {
return `${formattedLongitude}, ${formattedLatitude}`;
} else {
return '';
}
}
function formatCoordinateValue(value: number, positiveDirectionName: string, negativeDirectionName: string, displayFormat: CoordinateDisplayFormat, directionFormat: CoordinateDirectionFormat): string {
let prefix = '';
let suffix = '';
if (directionFormat === CoordinateDirectionFormat.Signed) {
prefix = value >= 0 ? '' : '-';
} else if (directionFormat === CoordinateDirectionFormat.Directional) {
suffix = value >= 0 ? positiveDirectionName : negativeDirectionName;
}
value = Math.abs(value);
if (displayFormat === CoordinateDisplayFormat.DecimalDegrees) {
return `${prefix}${value.toFixed(6)}${suffix}`;
} else if (displayFormat === CoordinateDisplayFormat.DecimalMinutes) {
const degrees = Math.floor(value);
const minutes = (value - degrees) * 60;
return `${prefix}${degrees}°${minutes.toFixed(5)}'${suffix}`;
} else if (displayFormat === CoordinateDisplayFormat.DegreesMinutesSeconds) {
const degrees = Math.floor(value);
const minutes = Math.floor((value - degrees) * 60);
const seconds = (value - degrees - minutes / 60) * 3600;
return `${prefix}${degrees}°${minutes}'${seconds.toFixed(4)}"${suffix}`;
} else {
return '';
}
}
+3 -3
View File
@@ -1,6 +1,6 @@
// eslint-disable-next-line @typescript-eslint/ban-ts-comment // eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-nocheck // @ts-nocheck
import type { MapPosition } from '@/core/map.ts'; import type { Coordinate } from '@/core/coordinate.ts';
import type { MapProvider, MapInstance, MapInstanceInitOptions } from './base.ts'; import type { MapProvider, MapInstance, MapInstanceInitOptions } from './base.ts';
import { asyncLoadAssets } from '@/lib/misc.ts'; import { asyncLoadAssets } from '@/lib/misc.ts';
@@ -105,7 +105,7 @@ export class AmapMapInstance implements MapInstance {
this.inited = true; this.inited = true;
} }
public setMapCenterTo(center: MapPosition, zoomLevel: number): void { public setMapCenterTo(center: Coordinate, zoomLevel: number): void {
if (!AmapMapProvider.AMap || !this.amapInstance) { if (!AmapMapProvider.AMap || !this.amapInstance) {
return; return;
} }
@@ -146,7 +146,7 @@ export class AmapMapInstance implements MapInstance {
}); });
} }
public setMapCenterMarker(position: MapPosition): void { public setMapCenterMarker(position: Coordinate): void {
if (!AmapMapProvider.AMap || !this.amapInstance) { if (!AmapMapProvider.AMap || !this.amapInstance) {
return; return;
} }
+3 -3
View File
@@ -1,6 +1,6 @@
// eslint-disable-next-line @typescript-eslint/ban-ts-comment // eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-nocheck // @ts-nocheck
import type { MapPosition } from '@/core/map.ts'; import type { Coordinate } from '@/core/coordinate.ts';
import type { MapProvider, MapInstance, MapInstanceInitOptions } from './base.ts'; import type { MapProvider, MapInstance, MapInstanceInitOptions } from './base.ts';
import { asyncLoadAssets } from '@/lib/misc.ts'; import { asyncLoadAssets } from '@/lib/misc.ts';
@@ -96,7 +96,7 @@ export class BaiduMapInstance implements MapInstance {
this.inited = true; this.inited = true;
} }
public setMapCenterTo(center: MapPosition, zoomLevel: number): void { public setMapCenterTo(center: Coordinate, zoomLevel: number): void {
if (!BaiduMapProvider.BMap || !this.baiduMapInstance) { if (!BaiduMapProvider.BMap || !this.baiduMapInstance) {
return; return;
} }
@@ -141,7 +141,7 @@ export class BaiduMapInstance implements MapInstance {
} }
} }
public setMapCenterMarker(position: MapPosition): void { public setMapCenterMarker(position: Coordinate): void {
if (!BaiduMapProvider.BMap || !this.baiduMapInstance) { if (!BaiduMapProvider.BMap || !this.baiduMapInstance) {
return; return;
} }
+5 -5
View File
@@ -1,4 +1,4 @@
import type { MapPosition } from '@/core/map.ts'; import type { Coordinate } from '@/core/coordinate.ts';
export interface MapProvider { export interface MapProvider {
getWebsite(): string; getWebsite(): string;
@@ -13,18 +13,18 @@ export interface MapInstance {
readonly defaultZoomLevel: number; readonly defaultZoomLevel: number;
readonly minZoomLevel: number; readonly minZoomLevel: number;
initMapInstance(mapContainer: HTMLElement, options: MapInstanceInitOptions): void; initMapInstance(mapContainer: HTMLElement, options: MapInstanceInitOptions): void;
setMapCenterTo(center: MapPosition, zoomLevel: number): void; setMapCenterTo(center: Coordinate, zoomLevel: number): void;
setMapCenterMarker(position: MapPosition): void; setMapCenterMarker(position: Coordinate): void;
removeMapCenterMarker(): void; removeMapCenterMarker(): void;
} }
export interface MapInstanceInitOptions { export interface MapInstanceInitOptions {
readonly language?: string; readonly language?: string;
readonly initCenter: MapPosition; readonly initCenter: Coordinate;
readonly zoomLevel: number; readonly zoomLevel: number;
readonly text: { readonly text: {
readonly zoomIn: string; readonly zoomIn: string;
readonly zoomOut: string; readonly zoomOut: string;
}; };
readonly onClick?: (position: MapPosition) => void; readonly onClick?: (position: Coordinate) => void;
} }
+3 -3
View File
@@ -1,6 +1,6 @@
// eslint-disable-next-line @typescript-eslint/ban-ts-comment // eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-nocheck // @ts-nocheck
import type { MapPosition } from '@/core/map.ts'; import type { Coordinate } from '@/core/coordinate.ts';
import type { MapProvider, MapInstance, MapInstanceInitOptions } from './base.ts'; import type { MapProvider, MapInstance, MapInstanceInitOptions } from './base.ts';
import { asyncLoadAssets } from '@/lib/misc.ts'; import { asyncLoadAssets } from '@/lib/misc.ts';
@@ -94,7 +94,7 @@ export class GoogleMapInstance implements MapInstance {
this.inited = true; this.inited = true;
} }
public setMapCenterTo(center: MapPosition, zoomLevel: number): void { public setMapCenterTo(center: Coordinate, zoomLevel: number): void {
if (!GoogleMapProvider.GoogleMap || !this.googleMapInstance) { if (!GoogleMapProvider.GoogleMap || !this.googleMapInstance) {
return; return;
} }
@@ -106,7 +106,7 @@ export class GoogleMapInstance implements MapInstance {
this.googleMapInstance.setZoom(zoomLevel); this.googleMapInstance.setZoom(zoomLevel);
} }
public setMapCenterMarker(position: MapPosition): void { public setMapCenterMarker(position: Coordinate): void {
if (!GoogleMapProvider.GoogleMap || !this.googleMapInstance) { if (!GoogleMapProvider.GoogleMap || !this.googleMapInstance) {
return; return;
} }
+4 -5
View File
@@ -1,6 +1,6 @@
// eslint-disable-next-line @typescript-eslint/ban-ts-comment // eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-nocheck // @ts-nocheck
import type { MapPosition } from '@/core/map.ts'; import type { Coordinate } from '@/core/coordinate.ts';
import { type LeafletTileSource, type LeafletTileSourceExtraParam, LEAFLET_TILE_SOURCES } from '@/consts/map.ts'; import { type LeafletTileSource, type LeafletTileSourceExtraParam, LEAFLET_TILE_SOURCES } from '@/consts/map.ts';
@@ -97,8 +97,7 @@ export class LeafletMapInstance implements MapInstance {
center: [ options.initCenter.latitude, options.initCenter.longitude ], center: [ options.initCenter.latitude, options.initCenter.longitude ],
zoom: options.zoomLevel, zoom: options.zoomLevel,
attributionControl: false, attributionControl: false,
zoomControl: false, zoomControl: false
worldCopyJump: true
}); });
let tileUrlFormat, tileUrlSubDomains, annotationUrlFormat, annotationUrlSubDomains: string | undefined; let tileUrlFormat, tileUrlSubDomains, annotationUrlFormat, annotationUrlSubDomains: string | undefined;
@@ -180,7 +179,7 @@ export class LeafletMapInstance implements MapInstance {
this.inited = true; this.inited = true;
} }
public setMapCenterTo(center: MapPosition, zoomLevel: number): void { public setMapCenterTo(center: Coordinate, zoomLevel: number): void {
if (!this.leafletInstance) { if (!this.leafletInstance) {
return; return;
} }
@@ -188,7 +187,7 @@ export class LeafletMapInstance implements MapInstance {
this.leafletInstance.setView([ center.latitude, center.longitude ], zoomLevel); this.leafletInstance.setView([ center.latitude, center.longitude ], zoomLevel);
} }
public setMapCenterMarker(position: MapPosition): void { public setMapCenterMarker(position: Coordinate): void {
if (!LeafletMapProvider.Leaflet || !this.leafletInstance) { if (!LeafletMapProvider.Leaflet || !this.leafletInstance) {
return; return;
} }
+7
View File
@@ -1826,6 +1826,13 @@
"Currency Unit": "Währungseinheit", "Currency Unit": "Währungseinheit",
"Currency Name": "Währungsname", "Currency Name": "Währungsname",
"Currency Symbol": "Währungssymbol", "Currency Symbol": "Währungssymbol",
"Geographic Location Format": "Geographic Location Format",
"Latitude Longitude D.D°": "Latitude Longitude D.D°",
"Longitude Latitude D.D°": "Longitude Latitude D.D°",
"Latitude Longitude D°M.M'": "Latitude Longitude D°M.M'",
"Longitude Latitude D°M.M'": "Longitude Latitude D°M.M'",
"Latitude Longitude D°M'S\"": "Latitude Longitude D°M'S\"",
"Longitude Latitude D°M'S\"": "Longitude Latitude D°M'S\"",
"Expense Amount Color": "Farbe des Ausgabenbetrags", "Expense Amount Color": "Farbe des Ausgabenbetrags",
"Income Amount Color": "Farbe des Einnahmenbetrags", "Income Amount Color": "Farbe des Einnahmenbetrags",
"Show Account Balance": "Kontostand anzeigen", "Show Account Balance": "Kontostand anzeigen",
+7
View File
@@ -1826,6 +1826,13 @@
"Currency Unit": "Currency Unit", "Currency Unit": "Currency Unit",
"Currency Name": "Currency Name", "Currency Name": "Currency Name",
"Currency Symbol": "Currency Symbol", "Currency Symbol": "Currency Symbol",
"Geographic Location Format": "Geographic Location Format",
"Latitude Longitude D.D°": "Latitude Longitude D.D°",
"Longitude Latitude D.D°": "Longitude Latitude D.D°",
"Latitude Longitude D°M.M'": "Latitude Longitude D°M.M'",
"Longitude Latitude D°M.M'": "Longitude Latitude D°M.M'",
"Latitude Longitude D°M'S\"": "Latitude Longitude D°M'S\"",
"Longitude Latitude D°M'S\"": "Longitude Latitude D°M'S\"",
"Expense Amount Color": "Expense Amount Color", "Expense Amount Color": "Expense Amount Color",
"Income Amount Color": "Income Amount Color", "Income Amount Color": "Income Amount Color",
"Show Account Balance": "Show Account Balance", "Show Account Balance": "Show Account Balance",
+7
View File
@@ -1826,6 +1826,13 @@
"Currency Unit": "Unidad monetaria", "Currency Unit": "Unidad monetaria",
"Currency Name": "Nombre de moneda", "Currency Name": "Nombre de moneda",
"Currency Symbol": "Símbolo de moneda", "Currency Symbol": "Símbolo de moneda",
"Geographic Location Format": "Geographic Location Format",
"Latitude Longitude D.D°": "Latitude Longitude D.D°",
"Longitude Latitude D.D°": "Longitude Latitude D.D°",
"Latitude Longitude D°M.M'": "Latitude Longitude D°M.M'",
"Longitude Latitude D°M.M'": "Longitude Latitude D°M.M'",
"Latitude Longitude D°M'S\"": "Latitude Longitude D°M'S\"",
"Longitude Latitude D°M'S\"": "Longitude Latitude D°M'S\"",
"Expense Amount Color": "Color del importe del gasto", "Expense Amount Color": "Color del importe del gasto",
"Income Amount Color": "Color del importe del ingreso", "Income Amount Color": "Color del importe del ingreso",
"Show Account Balance": "Mostrar saldo de cuenta", "Show Account Balance": "Mostrar saldo de cuenta",
+25
View File
@@ -46,6 +46,10 @@ import {
CurrencySortingType CurrencySortingType
} from '@/core/currency.ts'; } from '@/core/currency.ts';
import {
CoordinateDisplayType
} from '@/core/coordinate.ts';
import { import {
PresetAmountColor PresetAmountColor
} from '@/core/color.ts'; } from '@/core/color.ts';
@@ -385,6 +389,26 @@ export function useI18n() {
return ret; return ret;
} }
function getLocalizedDisplayNameAndTypeWithSystemDefault(typeAndNames: TypeAndName[], defaultValue: number, defaultType: TypeAndName): TypeAndDisplayName[] {
const ret: TypeAndDisplayName[] = [];
ret.push({
type: defaultValue,
displayName: t('System Default') + (defaultType.name ? ` (${t(defaultType.name)})` : '')
});
for (let i = 0; i < typeAndNames.length; i++) {
const nameAndType = typeAndNames[i];
ret.push({
type: nameAndType.type,
displayName: t(nameAndType.name)
});
}
return ret;
}
function getLocalizedNumeralSeparatorFormats<T extends NumeralSymbolType>(allSeparatorArray: T[], localeDefaultType: T | undefined, systemDefaultType: T, languageDefaultValue: number): LocalizedNumeralSymbolType[] { function getLocalizedNumeralSeparatorFormats<T extends NumeralSymbolType>(allSeparatorArray: T[], localeDefaultType: T | undefined, systemDefaultType: T, languageDefaultValue: number): LocalizedNumeralSymbolType[] {
let defaultSeparatorType: T | undefined = localeDefaultType; let defaultSeparatorType: T | undefined = localeDefaultType;
@@ -1699,6 +1723,7 @@ export function useI18n() {
getAllDigitGroupingTypes, getAllDigitGroupingTypes,
getAllCurrencyDisplayTypes, getAllCurrencyDisplayTypes,
getAllCurrencySortingTypes: () => getLocalizedDisplayNameAndType(CurrencySortingType.values()), getAllCurrencySortingTypes: () => getLocalizedDisplayNameAndType(CurrencySortingType.values()),
getAllCoordinateDisplayTypes: () => getLocalizedDisplayNameAndTypeWithSystemDefault(CoordinateDisplayType.values(), CoordinateDisplayType.SystemDefaultType, CoordinateDisplayType.Default),
getAllExpenseAmountColors: () => getAllExpenseIncomeAmountColors(CategoryType.Expense), getAllExpenseAmountColors: () => getAllExpenseIncomeAmountColors(CategoryType.Expense),
getAllIncomeAmountColors: () => getAllExpenseIncomeAmountColors(CategoryType.Income), getAllIncomeAmountColors: () => getAllExpenseIncomeAmountColors(CategoryType.Income),
getAllAccountCategories, getAllAccountCategories,
+7
View File
@@ -1826,6 +1826,13 @@
"Currency Unit": "Unità valuta", "Currency Unit": "Unità valuta",
"Currency Name": "Nome valuta", "Currency Name": "Nome valuta",
"Currency Symbol": "Simbolo valuta", "Currency Symbol": "Simbolo valuta",
"Geographic Location Format": "Geographic Location Format",
"Latitude Longitude D.D°": "Latitude Longitude D.D°",
"Longitude Latitude D.D°": "Longitude Latitude D.D°",
"Latitude Longitude D°M.M'": "Latitude Longitude D°M.M'",
"Longitude Latitude D°M.M'": "Longitude Latitude D°M.M'",
"Latitude Longitude D°M'S\"": "Latitude Longitude D°M'S\"",
"Longitude Latitude D°M'S\"": "Longitude Latitude D°M'S\"",
"Expense Amount Color": "Colore importo spesa", "Expense Amount Color": "Colore importo spesa",
"Income Amount Color": "Colore importo entrata", "Income Amount Color": "Colore importo entrata",
"Show Account Balance": "Mostra saldo conto", "Show Account Balance": "Mostra saldo conto",
+7
View File
@@ -1826,6 +1826,13 @@
"Currency Unit": "通貨単位", "Currency Unit": "通貨単位",
"Currency Name": "通貨名", "Currency Name": "通貨名",
"Currency Symbol": "通貨記号", "Currency Symbol": "通貨記号",
"Geographic Location Format": "Geographic Location Format",
"Latitude Longitude D.D°": "Latitude Longitude D.D°",
"Longitude Latitude D.D°": "Longitude Latitude D.D°",
"Latitude Longitude D°M.M'": "Latitude Longitude D°M.M'",
"Longitude Latitude D°M.M'": "Longitude Latitude D°M.M'",
"Latitude Longitude D°M'S\"": "Latitude Longitude D°M'S\"",
"Longitude Latitude D°M'S\"": "Longitude Latitude D°M'S\"",
"Expense Amount Color": "支出金額の色", "Expense Amount Color": "支出金額の色",
"Income Amount Color": "収入金額の色", "Income Amount Color": "収入金額の色",
"Show Account Balance": "口座残高を表示", "Show Account Balance": "口座残高を表示",
+7
View File
@@ -1826,6 +1826,13 @@
"Currency Unit": "Единица валюты", "Currency Unit": "Единица валюты",
"Currency Name": "Название валюты", "Currency Name": "Название валюты",
"Currency Symbol": "Символ валюты", "Currency Symbol": "Символ валюты",
"Geographic Location Format": "Geographic Location Format",
"Latitude Longitude D.D°": "Latitude Longitude D.D°",
"Longitude Latitude D.D°": "Longitude Latitude D.D°",
"Latitude Longitude D°M.M'": "Latitude Longitude D°M.M'",
"Longitude Latitude D°M.M'": "Longitude Latitude D°M.M'",
"Latitude Longitude D°M'S\"": "Latitude Longitude D°M'S\"",
"Longitude Latitude D°M'S\"": "Longitude Latitude D°M'S\"",
"Expense Amount Color": "Цвет суммы расхода", "Expense Amount Color": "Цвет суммы расхода",
"Income Amount Color": "Цвет суммы дохода", "Income Amount Color": "Цвет суммы дохода",
"Show Account Balance": "Показать баланс счета", "Show Account Balance": "Показать баланс счета",
+7
View File
@@ -1826,6 +1826,13 @@
"Currency Unit": "Одиниця валюти", "Currency Unit": "Одиниця валюти",
"Currency Name": "Назва валюти", "Currency Name": "Назва валюти",
"Currency Symbol": "Символ валюти", "Currency Symbol": "Символ валюти",
"Geographic Location Format": "Geographic Location Format",
"Latitude Longitude D.D°": "Latitude Longitude D.D°",
"Longitude Latitude D.D°": "Longitude Latitude D.D°",
"Latitude Longitude D°M.M'": "Latitude Longitude D°M.M'",
"Longitude Latitude D°M.M'": "Longitude Latitude D°M.M'",
"Latitude Longitude D°M'S\"": "Latitude Longitude D°M'S\"",
"Longitude Latitude D°M'S\"": "Longitude Latitude D°M'S\"",
"Expense Amount Color": "Колір суми витрат", "Expense Amount Color": "Колір суми витрат",
"Income Amount Color": "Колір суми доходу", "Income Amount Color": "Колір суми доходу",
"Show Account Balance": "Показати баланс рахунку", "Show Account Balance": "Показати баланс рахунку",
+7
View File
@@ -1826,6 +1826,13 @@
"Currency Unit": "Đơn vị tiền tệ", "Currency Unit": "Đơn vị tiền tệ",
"Currency Name": "Tên tiền tệ", "Currency Name": "Tên tiền tệ",
"Currency Symbol": "Ký hiệu tiền tệ", "Currency Symbol": "Ký hiệu tiền tệ",
"Geographic Location Format": "Geographic Location Format",
"Latitude Longitude D.D°": "Latitude Longitude D.D°",
"Longitude Latitude D.D°": "Longitude Latitude D.D°",
"Latitude Longitude D°M.M'": "Latitude Longitude D°M.M'",
"Longitude Latitude D°M.M'": "Longitude Latitude D°M.M'",
"Latitude Longitude D°M'S\"": "Latitude Longitude D°M'S\"",
"Longitude Latitude D°M'S\"": "Longitude Latitude D°M'S\"",
"Expense Amount Color": "Màu số tiền chi tiêu", "Expense Amount Color": "Màu số tiền chi tiêu",
"Income Amount Color": "Màu số tiền thu nhập", "Income Amount Color": "Màu số tiền thu nhập",
"Show Account Balance": "Hiển thị số dư tài khoản", "Show Account Balance": "Hiển thị số dư tài khoản",
+7
View File
@@ -1826,6 +1826,13 @@
"Currency Unit": "货币单位", "Currency Unit": "货币单位",
"Currency Name": "货币名称", "Currency Name": "货币名称",
"Currency Symbol": "货币符号", "Currency Symbol": "货币符号",
"Geographic Location Format": "地理位置格式",
"Latitude Longitude D.D°": "纬度 经度 D.D°",
"Longitude Latitude D.D°": "经度 纬度 D.D°",
"Latitude Longitude D°M.M'": "纬度 经度 D°M.M'",
"Longitude Latitude D°M.M'": "经度 纬度 D°M.M'",
"Latitude Longitude D°M'S\"": "纬度 经度 D°M'S\"",
"Longitude Latitude D°M'S\"": "经度 纬度 D°M'S\"",
"Expense Amount Color": "支出金额颜色", "Expense Amount Color": "支出金额颜色",
"Income Amount Color": "收入金额颜色", "Income Amount Color": "收入金额颜色",
"Show Account Balance": "显示账户余额", "Show Account Balance": "显示账户余额",
+7
View File
@@ -1826,6 +1826,13 @@
"Currency Unit": "貨幣單位", "Currency Unit": "貨幣單位",
"Currency Name": "貨幣名稱", "Currency Name": "貨幣名稱",
"Currency Symbol": "貨幣符號", "Currency Symbol": "貨幣符號",
"Geographic Location Format": "地理位置格式",
"Latitude Longitude D.D°": "緯度 經度 D.D°",
"Longitude Latitude D.D°": "經度 緯度 D.D°",
"Latitude Longitude D°M.M'": "緯度 經度 D°M.M'",
"Longitude Latitude D°M.M'": "經度 緯度 D°M.M'",
"Latitude Longitude D°M'S\"": "緯度 經度 D°M'S\"",
"Longitude Latitude D°M'S\"": "經度 緯度 D°M'S\"",
"Expense Amount Color": "支出金額顏色", "Expense Amount Color": "支出金額顏色",
"Income Amount Color": "收入金額顏色", "Income Amount Color": "收入金額顏色",
"Show Account Balance": "顯示帳戶餘額", "Show Account Balance": "顯示帳戶餘額",
+25 -9
View File
@@ -1,6 +1,6 @@
import type { PartialRecord } from '@/core/base.ts'; import type { PartialRecord } from '@/core/base.ts';
import type { YearMonth, StartEndTime } from '@/core/datetime.ts'; import type { YearMonth, StartEndTime } from '@/core/datetime.ts';
import type { MapPosition } from '@/core/map.ts'; import { type Coordinate, getNormalizedCoordinate } from '@/core/coordinate.ts';
import { TransactionType } from '@/core/transaction.ts'; import { TransactionType } from '@/core/transaction.ts';
import { Account, type AccountInfoResponse } from './account.ts'; import { Account, type AccountInfoResponse } from './account.ts';
@@ -74,7 +74,7 @@ export class Transaction implements TransactionInfoResponse {
} }
public set geoLocation(value: MapPosition) { public set geoLocation(value: Coordinate) {
this._geoLocation = TransactionGeoLocation.of(value); this._geoLocation = TransactionGeoLocation.of(value);
} }
@@ -196,8 +196,20 @@ export class Transaction implements TransactionInfoResponse {
this._pictures = []; this._pictures = [];
} }
public setGeoLocation(geoLocation?: TransactionGeoLocation): void { public getNormalizedGeoLocation(): Coordinate | undefined {
this._geoLocation = geoLocation; if (!this._geoLocation) {
return undefined;
}
return this._geoLocation.toNormalizedCoordinate();
}
public setGeoLocation(geoLocation?: Coordinate): void {
if (geoLocation) {
this._geoLocation = TransactionGeoLocation.createNewGeoLocation(geoLocation.latitude, geoLocation.longitude);
} else {
this._geoLocation = undefined;
}
} }
public setLatitudeAndLongitude(latitude: number, longitude: number): void { public setLatitudeAndLongitude(latitude: number, longitude: number): void {
@@ -228,7 +240,7 @@ export class Transaction implements TransactionInfoResponse {
tagIds: this.tagIds, tagIds: this.tagIds,
pictureIds: this.getPictureIds(), pictureIds: this.getPictureIds(),
comment: this.comment, comment: this.comment,
geoLocation: this.geoLocation, geoLocation: this.getNormalizedGeoLocation(),
clientSessionId: clientSessionId clientSessionId: clientSessionId
}; };
} }
@@ -247,7 +259,7 @@ export class Transaction implements TransactionInfoResponse {
tagIds: this.tagIds, tagIds: this.tagIds,
pictureIds: this.getPictureIds(), pictureIds: this.getPictureIds(),
comment: this.comment, comment: this.comment,
geoLocation: this.geoLocation geoLocation: this.getNormalizedGeoLocation()
}; };
} }
@@ -410,8 +422,12 @@ export class TransactionGeoLocation implements TransactionGeoLocationRequest {
return new TransactionGeoLocation(latitude, longitude); return new TransactionGeoLocation(latitude, longitude);
} }
public static of(mapPosition: MapPosition): TransactionGeoLocation { public static of(coordinate: Coordinate): TransactionGeoLocation {
return new TransactionGeoLocation(mapPosition.latitude, mapPosition.longitude); return new TransactionGeoLocation(coordinate.latitude, coordinate.longitude);
}
public toNormalizedCoordinate(): Coordinate {
return getNormalizedCoordinate(this);
} }
} }
@@ -502,7 +518,7 @@ export interface TransactionListInMonthByPageRequest {
readonly keyword: string; readonly keyword: string;
} }
export type TransactionGeoLocationResponse = MapPosition; export type TransactionGeoLocationResponse = Coordinate;
export interface TransactionInfoResponse { export interface TransactionInfoResponse {
readonly id: string; readonly id: string;
+8
View File
@@ -1,6 +1,7 @@
import { LongDateFormat, ShortDateFormat, LongTimeFormat, ShortTimeFormat } from '@/core/datetime.ts'; import { LongDateFormat, ShortDateFormat, LongTimeFormat, ShortTimeFormat } from '@/core/datetime.ts';
import { DecimalSeparator, DigitGroupingSymbol, DigitGroupingType } from '@/core/numeral.ts'; import { DecimalSeparator, DigitGroupingSymbol, DigitGroupingType } from '@/core/numeral.ts';
import { CurrencyDisplayType } from '@/core/currency.ts'; import { CurrencyDisplayType } from '@/core/currency.ts';
import { CoordinateDisplayType } from '@/core/coordinate.ts';
import { PresetAmountColor } from '@/core/color.ts'; import { PresetAmountColor } from '@/core/color.ts';
import type { LocalizedPresetCategory } from '@/core/category.ts'; import type { LocalizedPresetCategory } from '@/core/category.ts';
import { TransactionEditScopeType } from '@/core/transaction.ts'; import { TransactionEditScopeType } from '@/core/transaction.ts';
@@ -25,6 +26,7 @@ export class User {
public digitGroupingSymbol: number = 0; public digitGroupingSymbol: number = 0;
public digitGrouping: number = 0; public digitGrouping: number = 0;
public currencyDisplayType: number = 0; public currencyDisplayType: number = 0;
public coordinateDisplayType: number = 0;
public expenseAmountColor: number = 0; public expenseAmountColor: number = 0;
public incomeAmountColor: number = 0; public incomeAmountColor: number = 0;
@@ -51,6 +53,7 @@ export class User {
this.digitGroupingSymbol = user.digitGroupingSymbol; this.digitGroupingSymbol = user.digitGroupingSymbol;
this.digitGrouping = user.digitGrouping; this.digitGrouping = user.digitGrouping;
this.currencyDisplayType = user.currencyDisplayType; this.currencyDisplayType = user.currencyDisplayType;
this.coordinateDisplayType = user.coordinateDisplayType;
this.expenseAmountColor = user.expenseAmountColor; this.expenseAmountColor = user.expenseAmountColor;
this.incomeAmountColor = user.incomeAmountColor; this.incomeAmountColor = user.incomeAmountColor;
} }
@@ -87,6 +90,7 @@ export class User {
digitGroupingSymbol: this.digitGroupingSymbol, digitGroupingSymbol: this.digitGroupingSymbol,
digitGrouping: this.digitGrouping, digitGrouping: this.digitGrouping,
currencyDisplayType: this.currencyDisplayType, currencyDisplayType: this.currencyDisplayType,
coordinateDisplayType: this.coordinateDisplayType,
expenseAmountColor: this.expenseAmountColor, expenseAmountColor: this.expenseAmountColor,
incomeAmountColor: this.incomeAmountColor incomeAmountColor: this.incomeAmountColor
}; };
@@ -104,6 +108,7 @@ export class User {
user.digitGroupingSymbol = userInfo.digitGroupingSymbol; user.digitGroupingSymbol = userInfo.digitGroupingSymbol;
user.digitGrouping = userInfo.digitGrouping; user.digitGrouping = userInfo.digitGrouping;
user.currencyDisplayType = userInfo.currencyDisplayType; user.currencyDisplayType = userInfo.currencyDisplayType;
user.coordinateDisplayType = userInfo.coordinateDisplayType;
user.expenseAmountColor = userInfo.expenseAmountColor; user.expenseAmountColor = userInfo.expenseAmountColor;
user.incomeAmountColor = userInfo.incomeAmountColor; user.incomeAmountColor = userInfo.incomeAmountColor;
@@ -134,6 +139,7 @@ export interface UserBasicInfo {
readonly digitGroupingSymbol: number; readonly digitGroupingSymbol: number;
readonly digitGrouping: number; readonly digitGrouping: number;
readonly currencyDisplayType: number; readonly currencyDisplayType: number;
readonly coordinateDisplayType: number;
readonly expenseAmountColor: number; readonly expenseAmountColor: number;
readonly incomeAmountColor: number; readonly incomeAmountColor: number;
readonly emailVerified: boolean; readonly emailVerified: boolean;
@@ -184,6 +190,7 @@ export interface UserProfileUpdateRequest {
readonly digitGroupingSymbol?: number; readonly digitGroupingSymbol?: number;
readonly digitGrouping?: number; readonly digitGrouping?: number;
readonly currencyDisplayType?: number; readonly currencyDisplayType?: number;
readonly coordinateDisplayType?: number;
readonly expenseAmountColor?: number; readonly expenseAmountColor?: number;
readonly incomeAmountColor?: number; readonly incomeAmountColor?: number;
} }
@@ -216,6 +223,7 @@ export const EMPTY_USER_BASIC_INFO: UserBasicInfo = {
digitGroupingSymbol: DigitGroupingSymbol.LanguageDefaultType, digitGroupingSymbol: DigitGroupingSymbol.LanguageDefaultType,
digitGrouping: DigitGroupingType.LanguageDefaultType, digitGrouping: DigitGroupingType.LanguageDefaultType,
currencyDisplayType: CurrencyDisplayType.Default.type, currencyDisplayType: CurrencyDisplayType.Default.type,
coordinateDisplayType: CoordinateDisplayType.Default.type,
expenseAmountColor: PresetAmountColor.DefaultExpenseColor.type, expenseAmountColor: PresetAmountColor.DefaultExpenseColor.type,
incomeAmountColor: PresetAmountColor.DefaultIncomeColor.type, incomeAmountColor: PresetAmountColor.DefaultIncomeColor.type,
emailVerified: false emailVerified: false
+6
View File
@@ -106,6 +106,11 @@ export const useUserStore = defineStore('user', () => {
return userInfo.currencyDisplayType; return userInfo.currencyDisplayType;
}); });
const currentUserCoordinateDisplayType = computed<number>(() => {
const userInfo = currentUserBasicInfo.value || EMPTY_USER_BASIC_INFO;
return userInfo.coordinateDisplayType;
});
const currentUserExpenseAmountColor = computed<number>(() => { const currentUserExpenseAmountColor = computed<number>(() => {
const userInfo = currentUserBasicInfo.value || EMPTY_USER_BASIC_INFO; const userInfo = currentUserBasicInfo.value || EMPTY_USER_BASIC_INFO;
return userInfo.expenseAmountColor; return userInfo.expenseAmountColor;
@@ -324,6 +329,7 @@ export const useUserStore = defineStore('user', () => {
currentUserDigitGroupingSymbol, currentUserDigitGroupingSymbol,
currentUserDigitGrouping, currentUserDigitGrouping,
currentUserCurrencyDisplayType, currentUserCurrencyDisplayType,
currentUserCoordinateDisplayType,
currentUserExpenseAmountColor, currentUserExpenseAmountColor,
currentUserIncomeAmountColor, currentUserIncomeAmountColor,
// functions // functions
@@ -92,6 +92,7 @@ export function useTransactionEditPageBase(type: TransactionEditPageType, initMo
const defaultCurrency = computed<string>(() => userStore.currentUserDefaultCurrency); const defaultCurrency = computed<string>(() => userStore.currentUserDefaultCurrency);
const defaultAccountId = computed<string>(() => userStore.currentUserDefaultAccountId); const defaultAccountId = computed<string>(() => userStore.currentUserDefaultAccountId);
const firstDayOfWeek = computed<number>(() => userStore.currentUserFirstDayOfWeek); const firstDayOfWeek = computed<number>(() => userStore.currentUserFirstDayOfWeek);
const coordinateDisplayType = computed<number>(() => userStore.currentUserCoordinateDisplayType);
const allTimezones = computed<LocalizedTimezoneInfo[]>(() => getAllTimezones(true)); const allTimezones = computed<LocalizedTimezoneInfo[]>(() => getAllTimezones(true));
const allAccounts = computed<Account[]>(() => accountsStore.allPlainAccounts); const allAccounts = computed<Account[]>(() => accountsStore.allPlainAccounts);
@@ -416,8 +417,9 @@ export function useTransactionEditPageBase(type: TransactionEditPageType, initMo
currentTimezoneOffsetMinutes, currentTimezoneOffsetMinutes,
showAccountBalance, showAccountBalance,
defaultCurrency, defaultCurrency,
firstDayOfWeek,
defaultAccountId, defaultAccountId,
firstDayOfWeek,
coordinateDisplayType,
allTimezones, allTimezones,
allAccounts, allAccounts,
allVisibleAccounts, allVisibleAccounts,
@@ -30,6 +30,7 @@ export function useUserProfilePageBase() {
getAllDigitGroupingSymbols, getAllDigitGroupingSymbols,
getAllDigitGroupingTypes, getAllDigitGroupingTypes,
getAllCurrencyDisplayTypes, getAllCurrencyDisplayTypes,
getAllCoordinateDisplayTypes,
getAllExpenseAmountColors, getAllExpenseAmountColors,
getAllIncomeAmountColors, getAllIncomeAmountColors,
getAllTransactionEditScopeTypes, getAllTransactionEditScopeTypes,
@@ -63,6 +64,7 @@ export function useUserProfilePageBase() {
const allDigitGroupingSymbols = computed<TypeAndDisplayName[]>(() => getAllDigitGroupingSymbols()); const allDigitGroupingSymbols = computed<TypeAndDisplayName[]>(() => getAllDigitGroupingSymbols());
const allDigitGroupingTypes = computed<LocalizedDigitGroupingType[]>(() => getAllDigitGroupingTypes()); const allDigitGroupingTypes = computed<LocalizedDigitGroupingType[]>(() => getAllDigitGroupingTypes());
const allCurrencyDisplayTypes = computed<TypeAndDisplayName[]>(() => getAllCurrencyDisplayTypes()); const allCurrencyDisplayTypes = computed<TypeAndDisplayName[]>(() => getAllCurrencyDisplayTypes());
const allCoordinateDisplayTypes = computed<TypeAndDisplayName[]>(() => getAllCoordinateDisplayTypes());
const allExpenseAmountColorTypes = computed<TypeAndDisplayName[]>(() => getAllExpenseAmountColors()); const allExpenseAmountColorTypes = computed<TypeAndDisplayName[]>(() => getAllExpenseAmountColors());
const allIncomeAmountColorTypes = computed<TypeAndDisplayName[]>(() => getAllIncomeAmountColors()); const allIncomeAmountColorTypes = computed<TypeAndDisplayName[]>(() => getAllIncomeAmountColors());
const allTransactionEditScopeTypes = computed<TypeAndDisplayName[]>(() => getAllTransactionEditScopeTypes()); const allTransactionEditScopeTypes = computed<TypeAndDisplayName[]>(() => getAllTransactionEditScopeTypes());
@@ -106,6 +108,7 @@ export function useUserProfilePageBase() {
newProfile.value.digitGroupingSymbol === oldProfile.value.digitGroupingSymbol && newProfile.value.digitGroupingSymbol === oldProfile.value.digitGroupingSymbol &&
newProfile.value.digitGrouping === oldProfile.value.digitGrouping && newProfile.value.digitGrouping === oldProfile.value.digitGrouping &&
newProfile.value.currencyDisplayType === oldProfile.value.currencyDisplayType && newProfile.value.currencyDisplayType === oldProfile.value.currencyDisplayType &&
newProfile.value.coordinateDisplayType === oldProfile.value.coordinateDisplayType &&
newProfile.value.expenseAmountColor === oldProfile.value.expenseAmountColor && newProfile.value.expenseAmountColor === oldProfile.value.expenseAmountColor &&
newProfile.value.incomeAmountColor === oldProfile.value.incomeAmountColor) { newProfile.value.incomeAmountColor === oldProfile.value.incomeAmountColor) {
return 'Nothing has been modified'; return 'Nothing has been modified';
@@ -195,6 +198,7 @@ export function useUserProfilePageBase() {
allDigitGroupingSymbols, allDigitGroupingSymbols,
allDigitGroupingTypes, allDigitGroupingTypes,
allCurrencyDisplayTypes, allCurrencyDisplayTypes,
allCoordinateDisplayTypes,
allExpenseAmountColorTypes, allExpenseAmountColorTypes,
allIncomeAmountColorTypes, allIncomeAmountColorTypes,
allTransactionEditScopeTypes, allTransactionEditScopeTypes,
@@ -690,7 +690,7 @@
</div> </div>
</template> </template>
<template #item.geoLocation="{ item }"> <template #item.geoLocation="{ item }">
<span v-if="item.geoLocation">{{ `(${item.geoLocation.longitude}, ${item.geoLocation.latitude})` }}</span> <span v-if="item.geoLocation">{{ `(${formatCoordinate(item.geoLocation, coordinateDisplayType)})` }}</span>
<span v-else-if="!item.geoLocation">{{ tt('None') }}</span> <span v-else-if="!item.geoLocation">{{ tt('None') }}</span>
</template> </template>
<template #item.tagIds="{ item }"> <template #item.tagIds="{ item }">
@@ -889,6 +889,7 @@ import {
getUtcOffsetByUtcOffsetMinutes, getUtcOffsetByUtcOffsetMinutes,
getTimezoneOffsetMinutes getTimezoneOffsetMinutes
} from '@/lib/datetime.ts'; } from '@/lib/datetime.ts';
import { formatCoordinate } from '@/lib/coordinate.ts';
import { import {
getAccountMapByName getAccountMapByName
} from '@/lib/account.ts'; } from '@/lib/account.ts';
@@ -1015,6 +1016,7 @@ const showAccountBalance = computed<boolean>(() => settingsStore.appSettings.sho
const currentTimezoneOffsetMinutes = computed<number>(() => getTimezoneOffsetMinutes(settingsStore.appSettings.timeZone)); const currentTimezoneOffsetMinutes = computed<number>(() => getTimezoneOffsetMinutes(settingsStore.appSettings.timeZone));
const defaultCurrency = computed<string>(() => userStore.currentUserDefaultCurrency); const defaultCurrency = computed<string>(() => userStore.currentUserDefaultCurrency);
const coordinateDisplayType = computed<number>(() => userStore.currentUserCoordinateDisplayType);
const allSteps = computed<StepBarItem[]>(() => { const allSteps = computed<StepBarItem[]>(() => {
const steps: StepBarItem[] = [ const steps: StepBarItem[] = [
@@ -278,7 +278,7 @@
v-model:menu="geoMenuState" v-model:menu="geoMenuState"
> >
<template #selection> <template #selection>
<span class="cursor-pointer" v-if="transaction.geoLocation">{{ `(${transaction.geoLocation.longitude}, ${transaction.geoLocation.latitude})` }}</span> <span class="cursor-pointer" v-if="transaction.geoLocation">{{ `(${formatCoordinate(transaction.geoLocation, coordinateDisplayType)})` }}</span>
<span class="cursor-pointer" v-else-if="!transaction.geoLocation">{{ geoLocationStatusInfo }}</span> <span class="cursor-pointer" v-else-if="!transaction.geoLocation">{{ geoLocationStatusInfo }}</span>
</template> </template>
@@ -483,7 +483,7 @@ import { useTransactionTagsStore } from '@/stores/transactionTag.ts';
import { useTransactionsStore } from '@/stores/transaction.ts'; import { useTransactionsStore } from '@/stores/transaction.ts';
import { useTransactionTemplatesStore } from '@/stores/transactionTemplate.ts'; import { useTransactionTemplatesStore } from '@/stores/transactionTemplate.ts';
import type { MapPosition } from '@/core/map.ts'; import type { Coordinate } from '@/core/coordinate.ts';
import { CategoryType } from '@/core/category.ts'; import { CategoryType } from '@/core/category.ts';
import { TransactionType, TransactionEditScopeType } from '@/core/transaction.ts'; import { TransactionType, TransactionEditScopeType } from '@/core/transaction.ts';
import { TemplateType, ScheduledTemplateFrequencyType } from '@/core/template.ts'; import { TemplateType, ScheduledTemplateFrequencyType } from '@/core/template.ts';
@@ -499,6 +499,7 @@ import {
getTimezoneOffsetMinutes, getTimezoneOffsetMinutes,
getCurrentUnixTime getCurrentUnixTime
} from '@/lib/datetime.ts'; } from '@/lib/datetime.ts';
import { formatCoordinate } from '@/lib/coordinate.ts';
import { generateRandomUUID } from '@/lib/misc.ts'; import { generateRandomUUID } from '@/lib/misc.ts';
import { import {
getTransactionPrimaryCategoryName, getTransactionPrimaryCategoryName,
@@ -567,6 +568,7 @@ const {
transaction, transaction,
defaultCurrency, defaultCurrency,
defaultAccountId, defaultAccountId,
coordinateDisplayType,
allTimezones, allTimezones,
allVisibleAccounts, allVisibleAccounts,
allAccountsMap, allAccountsMap,
@@ -1073,9 +1075,9 @@ function updateGeoLocation(forceUpdate: boolean): void {
geoLocationStatus.value = GeoLocationStatus.Getting; geoLocationStatus.value = GeoLocationStatus.Getting;
} }
function updateSpecifiedGeoLocation(mapPosition: MapPosition): void { function updateSpecifiedGeoLocation(coordinate: Coordinate): void {
if (isSupportGetGeoLocationByClick() && setGeoLocationByClickMap.value) { if (isSupportGetGeoLocationByClick() && setGeoLocationByClickMap.value) {
transaction.value.setLatitudeAndLongitude(mapPosition.latitude, mapPosition.longitude); transaction.value.setLatitudeAndLongitude(coordinate.latitude, coordinate.longitude);
map.value?.setMarkerPosition(transaction.value.geoLocation); map.value?.setMarkerPosition(transaction.value.geoLocation);
} }
} }
@@ -263,6 +263,25 @@
<v-divider /> <v-divider />
<v-card-text>
<v-row>
<v-col cols="12" md="6">
<v-select
item-title="displayName"
item-value="type"
persistent-placeholder
:disabled="loading || saving"
:label="tt('Geographic Location Format')"
:placeholder="tt('Geographic Location Format')"
:items="allCoordinateDisplayTypes"
v-model="newProfile.coordinateDisplayType"
/>
</v-col>
</v-row>
</v-card-text>
<v-divider />
<v-card-text> <v-card-text>
<v-row> <v-row>
<v-col cols="12" md="6"> <v-col cols="12" md="6">
@@ -360,6 +379,7 @@ const {
allDigitGroupingSymbols, allDigitGroupingSymbols,
allDigitGroupingTypes, allDigitGroupingTypes,
allCurrencyDisplayTypes, allCurrencyDisplayTypes,
allCoordinateDisplayTypes,
allExpenseAmountColorTypes, allExpenseAmountColorTypes,
allIncomeAmountColorTypes, allIncomeAmountColorTypes,
allTransactionEditScopeTypes, allTransactionEditScopeTypes,
+4 -2
View File
@@ -338,7 +338,7 @@
> >
<template #title> <template #title>
<f7-block class="list-item-custom-title no-padding no-margin"> <f7-block class="list-item-custom-title no-padding no-margin">
<span v-if="transaction.geoLocation">{{ `(${transaction.geoLocation.longitude}, ${transaction.geoLocation.latitude})` }}</span> <span v-if="transaction.geoLocation">{{ `(${formatCoordinate(transaction.geoLocation, coordinateDisplayType)})` }}</span>
<span v-else-if="!transaction.geoLocation">{{ geoLocationStatusInfo }}</span> <span v-else-if="!transaction.geoLocation">{{ geoLocationStatusInfo }}</span>
</f7-block> </f7-block>
</template> </template>
@@ -515,6 +515,7 @@ import {
getTimezoneOffset, getTimezoneOffset,
getTimezoneOffsetMinutes getTimezoneOffsetMinutes
} from '@/lib/datetime.ts'; } from '@/lib/datetime.ts';
import { formatCoordinate } from '@/lib/coordinate.ts';
import { generateRandomUUID } from '@/lib/misc.ts'; import { generateRandomUUID } from '@/lib/misc.ts';
import { getTransactionPrimaryCategoryName, getTransactionSecondaryCategoryName } from '@/lib/category.ts'; import { getTransactionPrimaryCategoryName, getTransactionSecondaryCategoryName } from '@/lib/category.ts';
import { setTransactionModelByTransaction } from '@/lib/transaction.ts'; import { setTransactionModelByTransaction } from '@/lib/transaction.ts';
@@ -554,8 +555,9 @@ const {
transaction, transaction,
currentTimezoneOffsetMinutes, currentTimezoneOffsetMinutes,
defaultCurrency, defaultCurrency,
firstDayOfWeek,
defaultAccountId, defaultAccountId,
firstDayOfWeek,
coordinateDisplayType,
allTimezones, allTimezones,
allVisibleAccounts, allVisibleAccounts,
allAccountsMap, allAccountsMap,
@@ -41,6 +41,10 @@
<f7-list-item class="list-item-with-header-and-title list-item-no-item-after" header="Decimal Separator" title="Dot (.)" link="#"></f7-list-item> <f7-list-item class="list-item-with-header-and-title list-item-no-item-after" header="Decimal Separator" title="Dot (.)" link="#"></f7-list-item>
</f7-list> </f7-list>
<f7-list strong inset dividers class="margin-vertical skeleton-text" v-if="loading">
<f7-list-item class="list-item-with-header-and-title list-item-no-item-after" header="Geographic Location Format" title="Coordinate Format" link="#"></f7-list-item>
</f7-list>
<f7-list strong inset dividers class="margin-vertical skeleton-text" v-if="loading"> <f7-list strong inset dividers class="margin-vertical skeleton-text" v-if="loading">
<f7-list-item class="list-item-with-header-and-title list-item-no-item-after" header="Expense Amount Color" title="Amount Color" link="#"></f7-list-item> <f7-list-item class="list-item-with-header-and-title list-item-no-item-after" header="Expense Amount Color" title="Amount Color" link="#"></f7-list-item>
<f7-list-item class="list-item-with-header-and-title list-item-no-item-after" header="Income Amount Color" title="Amount Color" link="#"></f7-list-item> <f7-list-item class="list-item-with-header-and-title list-item-no-item-after" header="Income Amount Color" title="Amount Color" link="#"></f7-list-item>
@@ -365,6 +369,28 @@
</f7-list-item> </f7-list-item>
</f7-list> </f7-list>
<f7-list form strong inset dividers class="margin-vertical" v-if="!loading">
<f7-list-item
link="#"
class="list-item-with-header-and-title list-item-no-item-after"
:header="tt('Geographic Location Format')"
:title="findDisplayNameByType(allCoordinateDisplayTypes, newProfile.coordinateDisplayType)"
@click="showCoordinateDisplayTypePopup = true"
>
<list-item-selection-popup value-type="item"
key-field="type" value-field="type"
title-field="displayName"
:title="tt('Geographic Location Format')"
:enable-filter="true"
:filter-placeholder="tt('Geographic Location Format')"
:filter-no-items-text="tt('No results')"
:items="allCoordinateDisplayTypes"
v-model:show="showCoordinateDisplayTypePopup"
v-model="newProfile.coordinateDisplayType">
</list-item-selection-popup>
</f7-list-item>
</f7-list>
<f7-list form strong inset dividers class="margin-vertical" v-if="!loading"> <f7-list form strong inset dividers class="margin-vertical" v-if="!loading">
<f7-list-item <f7-list-item
link="#" link="#"
@@ -477,6 +503,7 @@ const {
allDigitGroupingSymbols, allDigitGroupingSymbols,
allDigitGroupingTypes, allDigitGroupingTypes,
allCurrencyDisplayTypes, allCurrencyDisplayTypes,
allCoordinateDisplayTypes,
allExpenseAmountColorTypes, allExpenseAmountColorTypes,
allIncomeAmountColorTypes, allIncomeAmountColorTypes,
allTransactionEditScopeTypes, allTransactionEditScopeTypes,
@@ -514,6 +541,7 @@ const showCurrencyDisplayTypePopup = ref<boolean>(false);
const showDigitGroupingPopup = ref<boolean>(false); const showDigitGroupingPopup = ref<boolean>(false);
const showDigitGroupingSymbolPopup = ref<boolean>(false); const showDigitGroupingSymbolPopup = ref<boolean>(false);
const showDecimalSeparatorPopup = ref<boolean>(false); const showDecimalSeparatorPopup = ref<boolean>(false);
const showCoordinateDisplayTypePopup = ref<boolean>(false);
const showExpenseAmountColorPopup = ref<boolean>(false); const showExpenseAmountColorPopup = ref<boolean>(false);
const showIncomeAmountColorPopup = ref<boolean>(false); const showIncomeAmountColorPopup = ref<boolean>(false);
const showMoreActionSheet = ref<boolean>(false); const showMoreActionSheet = ref<boolean>(false);