Browse Source

Prepare for localized date format

pull/803/head
Thomas 3 years ago
parent
commit
2ac5fb71a1
  1. 1
      apps/api/src/app/user/interfaces/user-settings.interface.ts
  2. 2
      apps/api/src/app/user/user.service.ts
  3. 12
      apps/client/src/app/adapter/date-formats.ts
  4. 2
      apps/client/src/app/components/admin-market-data-detail/admin-market-data-detail.component.html
  5. 5
      apps/client/src/app/components/admin-market-data-detail/admin-market-data-detail.component.ts
  6. 19
      apps/client/src/app/components/admin-market-data/admin-market-data.component.ts
  7. 5
      apps/client/src/app/components/admin-market-data/admin-market-data.html
  8. 2
      apps/client/src/app/components/admin-market-data/admin-market-data.module.ts
  9. 2
      apps/client/src/app/components/admin-overview/admin-overview.component.ts
  10. 3
      apps/client/src/app/pages/account/account-page.component.ts
  11. 8
      apps/client/src/app/pages/account/account-page.html
  12. 2
      apps/client/src/app/pages/account/account-page.module.ts
  13. 1
      libs/common/src/lib/config.ts
  14. 29
      libs/common/src/lib/helper.ts
  15. 2
      libs/ui/src/lib/activities-table/activities-table.component.html
  16. 2
      libs/ui/src/lib/activities-table/activities-table.component.ts
  17. 17
      libs/ui/src/lib/value/value.component.ts

1
apps/api/src/app/user/interfaces/user-settings.interface.ts

@ -1,5 +1,6 @@
export interface UserSettings {
emergencyFund?: number;
locale?: string;
isNewCalculationEngine?: boolean;
isRestrictedView?: boolean;
}

2
apps/api/src/app/user/user.service.ts

@ -63,7 +63,7 @@ export class UserService {
accounts: Account,
settings: {
...(<UserSettings>Settings.settings),
locale,
locale: (<UserSettings>Settings.settings).locale ?? locale,
baseCurrency: Settings?.currency ?? UserService.DEFAULT_CURRENCY,
viewMode: Settings?.viewMode ?? ViewMode.DEFAULT
}

12
apps/client/src/app/adapter/date-formats.ts

@ -1,16 +1,14 @@
import {
DEFAULT_DATE_FORMAT,
DEFAULT_DATE_FORMAT_MONTH_YEAR
} from '@ghostfolio/common/config';
import { DEFAULT_DATE_FORMAT_MONTH_YEAR } from '@ghostfolio/common/config';
import { getDateFormatString } from '@ghostfolio/common/helper';
export const DateFormats = {
display: {
dateInput: DEFAULT_DATE_FORMAT,
dateInput: getDateFormatString(),
monthYearLabel: DEFAULT_DATE_FORMAT_MONTH_YEAR,
dateA11yLabel: DEFAULT_DATE_FORMAT,
dateA11yLabel: getDateFormatString(),
monthYearA11yLabel: DEFAULT_DATE_FORMAT_MONTH_YEAR
},
parse: {
dateInput: DEFAULT_DATE_FORMAT
dateInput: getDateFormatString()
}
};

2
apps/client/src/app/components/admin-market-data-detail/admin-market-data-detail.component.html

@ -25,7 +25,7 @@
}"
[title]="
(itemByMonth.key + '-' + (i + 1 < 10 ? '0' + (i + 1) : i + 1)
| date: defaultDateFormat) ?? ''
| date: dateFormat) ?? ''
"
(click)="
onOpenMarketDataDetail({

5
apps/client/src/app/components/admin-market-data-detail/admin-market-data-detail.component.ts

@ -8,8 +8,7 @@ import {
Output
} from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { DEFAULT_DATE_FORMAT } from '@ghostfolio/common/config';
import { DATE_FORMAT } from '@ghostfolio/common/helper';
import { DATE_FORMAT, getDateFormatString } from '@ghostfolio/common/helper';
import { LineChartItem } from '@ghostfolio/ui/line-chart/interfaces/line-chart.interface';
import { DataSource, MarketData } from '@prisma/client';
import {
@ -40,8 +39,8 @@ export class AdminMarketDataDetailComponent implements OnChanges, OnInit {
@Output() marketDataChanged = new EventEmitter<boolean>();
public dateFormat = getDateFormatString();
public days = Array(31);
public defaultDateFormat = DEFAULT_DATE_FORMAT;
public deviceType: string;
public historicalDataItems: LineChartItem[];
public marketDataByMonth: {

19
apps/client/src/app/components/admin-market-data/admin-market-data.component.ts

@ -7,8 +7,8 @@ import {
} from '@angular/core';
import { AdminService } from '@ghostfolio/client/services/admin.service';
import { DataService } from '@ghostfolio/client/services/data.service';
import { DEFAULT_DATE_FORMAT } from '@ghostfolio/common/config';
import { UniqueAsset } from '@ghostfolio/common/interfaces';
import { UserService } from '@ghostfolio/client/services/user/user.service';
import { UniqueAsset, User } from '@ghostfolio/common/interfaces';
import { AdminMarketDataItem } from '@ghostfolio/common/interfaces/admin-market-data.interface';
import { DataSource, MarketData } from '@prisma/client';
import { Subject } from 'rxjs';
@ -23,9 +23,9 @@ import { takeUntil } from 'rxjs/operators';
export class AdminMarketDataComponent implements OnDestroy, OnInit {
public currentDataSource: DataSource;
public currentSymbol: string;
public defaultDateFormat = DEFAULT_DATE_FORMAT;
public marketData: AdminMarketDataItem[] = [];
public marketDataDetails: MarketData[] = [];
public user: User;
private unsubscribeSubject = new Subject<void>();
@ -35,8 +35,17 @@ export class AdminMarketDataComponent implements OnDestroy, OnInit {
public constructor(
private adminService: AdminService,
private changeDetectorRef: ChangeDetectorRef,
private dataService: DataService
) {}
private dataService: DataService,
private userService: UserService
) {
this.userService.stateChanged
.pipe(takeUntil(this.unsubscribeSubject))
.subscribe((state) => {
if (state?.user) {
this.user = state.user;
}
});
}
/**
* Initializes the controller

5
apps/client/src/app/components/admin-market-data/admin-market-data.html

@ -21,7 +21,10 @@
<td class="mat-cell px-1 py-2">{{ item.symbol }}</td>
<td class="mat-cell px-1 py-2">{{ item.dataSource }}</td>
<td class="mat-cell px-1 py-2">
{{ (item.date | date: defaultDateFormat) ?? '' }}
<gf-value
[locale]="user?.settings?.locale"
[value]="item.date ?? ''"
></gf-value>
</td>
<td class="mat-cell px-1 py-2">{{ item.activityCount }}</td>
<td class="mat-cell px-1 py-2">{{ item.marketDataItemCount }}</td>

2
apps/client/src/app/components/admin-market-data/admin-market-data.module.ts

@ -3,6 +3,7 @@ import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { MatMenuModule } from '@angular/material/menu';
import { GfAdminMarketDataDetailModule } from '@ghostfolio/client/components/admin-market-data-detail/admin-market-data-detail.module';
import { GfValueModule } from '@ghostfolio/ui/value';
import { AdminMarketDataComponent } from './admin-market-data.component';
@ -11,6 +12,7 @@ import { AdminMarketDataComponent } from './admin-market-data.component';
imports: [
CommonModule,
GfAdminMarketDataDetailModule,
GfValueModule,
MatButtonModule,
MatMenuModule
],

2
apps/client/src/app/components/admin-overview/admin-overview.component.ts

@ -5,7 +5,6 @@ import { CacheService } from '@ghostfolio/client/services/cache.service';
import { DataService } from '@ghostfolio/client/services/data.service';
import { UserService } from '@ghostfolio/client/services/user/user.service';
import {
DEFAULT_DATE_FORMAT,
PROPERTY_COUPONS,
PROPERTY_CURRENCIES,
PROPERTY_IS_READ_ONLY_MODE,
@ -35,7 +34,6 @@ export class AdminOverviewComponent implements OnDestroy, OnInit {
public customCurrencies: string[];
public dataGatheringInProgress: boolean;
public dataGatheringProgress: number;
public defaultDateFormat = DEFAULT_DATE_FORMAT;
public exchangeRates: { label1: string; label2: string; value: number }[];
public hasPermissionForSubscription: boolean;
public hasPermissionForSystemMessage: boolean;

3
apps/client/src/app/pages/account/account-page.component.ts

@ -20,7 +20,7 @@ import { CreateAccessDto } from '@ghostfolio/api/app/access/create-access.dto';
import { DataService } from '@ghostfolio/client/services/data.service';
import { UserService } from '@ghostfolio/client/services/user/user.service';
import { WebAuthnService } from '@ghostfolio/client/services/web-authn.service';
import { DEFAULT_DATE_FORMAT, baseCurrency } from '@ghostfolio/common/config';
import { baseCurrency } from '@ghostfolio/common/config';
import { Access, User } from '@ghostfolio/common/interfaces';
import { hasPermission, permissions } from '@ghostfolio/common/permissions';
import { DeviceDetectorService } from 'ngx-device-detector';
@ -45,7 +45,6 @@ export class AccountPageComponent implements OnDestroy, OnInit {
public coupon: number;
public couponId: string;
public currencies: string[] = [];
public defaultDateFormat = DEFAULT_DATE_FORMAT;
public deviceType: string;
public hasPermissionForSubscription: boolean;
public hasPermissionToCreateAccess: boolean;

8
apps/client/src/app/pages/account/account-page.html

@ -24,8 +24,12 @@
></ion-icon>
</div>
<div *ngIf="user?.subscription?.type === 'Premium'">
Valid until {{ user?.subscription?.expiresAt | date:
defaultDateFormat }}
Valid until
<gf-value
class="d-inline-block"
[locale]="user?.settings?.locale"
[value]="user?.subscription?.expiresAt"
></gf-value>
</div>
<div *ngIf="user?.subscription?.type === 'Basic'">
<ng-container *ngIf="hasPermissionForSubscription">

2
apps/client/src/app/pages/account/account-page.module.ts

@ -10,6 +10,7 @@ import { MatSelectModule } from '@angular/material/select';
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
import { RouterModule } from '@angular/router';
import { GfPortfolioAccessTableModule } from '@ghostfolio/client/components/access-table/access-table.module';
import { GfValueModule } from '@ghostfolio/ui/value';
import { AccountPageRoutingModule } from './account-page-routing.module';
import { AccountPageComponent } from './account-page.component';
@ -24,6 +25,7 @@ import { GfCreateOrUpdateAccessDialogModule } from './create-or-update-access-di
FormsModule,
GfCreateOrUpdateAccessDialogModule,
GfPortfolioAccessTableModule,
GfValueModule,
MatButtonModule,
MatCardModule,
MatDialogModule,

1
libs/common/src/lib/config.ts

@ -44,7 +44,6 @@ export const warnColorRgb = {
export const ASSET_SUB_CLASS_EMERGENCY_FUND = 'EMERGENCY_FUND';
export const DEFAULT_DATE_FORMAT = 'dd.MM.yyyy';
export const DEFAULT_DATE_FORMAT_MONTH_YEAR = 'MMM yyyy';
export const PROPERTY_COUPONS = 'COUPONS';

29
libs/common/src/lib/helper.ts

@ -2,7 +2,7 @@ import * as currencies from '@dinero.js/currencies';
import { DataSource } from '@prisma/client';
import { getDate, getMonth, getYear, parse, subDays } from 'date-fns';
import { ghostfolioScraperApiSymbolPrefix } from './config';
import { ghostfolioScraperApiSymbolPrefix, locale } from './config';
export function capitalize(aString: string) {
return aString.charAt(0).toUpperCase() + aString.slice(1).toLowerCase();
@ -44,6 +44,33 @@ export function getCssVariable(aCssVariable: string) {
);
}
export function getDateFormatString(aLocale?: string) {
const formatObject = new Intl.DateTimeFormat(aLocale).formatToParts(
new Date()
);
return formatObject
.map((object) => {
switch (object.type) {
case 'day':
return 'dd';
case 'month':
return 'MM';
case 'year':
return 'yyyy';
default:
return object.value;
}
})
.join('');
}
export function getLocale() {
return navigator.languages?.length
? navigator.languages[0]
: navigator.language ?? locale;
}
export function getTextColor() {
const cssVariable = getCssVariable(
window.matchMedia('(prefers-color-scheme: dark)').matches

2
libs/ui/src/lib/activities-table/activities-table.component.html

@ -71,7 +71,7 @@
</th>
<td *matCellDef="let element" class="px-1" mat-cell>
<div class="d-flex">
{{ element.date | date: defaultDateFormat }}
<gf-value [locale]="locale" [value]="element.date"></gf-value>
</div>
</td>
<td *matFooterCellDef class="px-1" i18n mat-footer-cell>Total</td>

2
libs/ui/src/lib/activities-table/activities-table.component.ts

@ -20,7 +20,6 @@ import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table';
import { Router } from '@angular/router';
import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface';
import { DEFAULT_DATE_FORMAT } from '@ghostfolio/common/config';
import { UniqueAsset } from '@ghostfolio/common/interfaces';
import { OrderWithAccount } from '@ghostfolio/common/types';
import Big from 'big.js';
@ -63,7 +62,6 @@ export class ActivitiesTableComponent implements OnChanges, OnDestroy {
@ViewChild(MatSort) sort: MatSort;
public dataSource: MatTableDataSource<Activity> = new MatTableDataSource();
public defaultDateFormat = DEFAULT_DATE_FORMAT;
public displayedColumns = [];
public endOfToday = endOfToday();
public filters$: Subject<string[]> = new BehaviorSubject([]);

17
libs/ui/src/lib/value/value.component.ts

@ -4,8 +4,8 @@ import {
Input,
OnChanges
} from '@angular/core';
import { DEFAULT_DATE_FORMAT, locale } from '@ghostfolio/common/config';
import { format, isDate, parseISO } from 'date-fns';
import { getLocale } from '@ghostfolio/common/helper';
import { isDate, parseISO } from 'date-fns';
import { isNumber } from 'lodash';
@Component({
@ -21,7 +21,7 @@ export class ValueComponent implements OnChanges {
@Input() isCurrency = false;
@Input() isPercent = false;
@Input() label = '';
@Input() locale = locale;
@Input() locale = getLocale();
@Input() position = '';
@Input() precision: number | undefined;
@Input() size: 'large' | 'medium' | 'small' = 'small';
@ -102,10 +102,13 @@ export class ValueComponent implements OnChanges {
try {
if (isDate(parseISO(this.value))) {
this.formattedValue = format(
new Date(<string>this.value),
DEFAULT_DATE_FORMAT
);
this.formattedValue = new Date(
<string>this.value
).toLocaleDateString(this.locale, {
day: '2-digit',
month: '2-digit',
year: 'numeric'
});
}
} catch {
this.formattedValue = this.value;

Loading…
Cancel
Save