From af9cffe21e7e3d43070b0f10e213116c7d7ec145 Mon Sep 17 00:00:00 2001 From: erdemcaygor Date: Tue, 8 Apr 2025 15:15:55 +0300 Subject: [PATCH 01/21] timezone service added --- .../packages/core/src/lib/services/index.ts | 1 + .../core/src/lib/services/timezone.service.ts | 34 +++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 npm/ng-packs/packages/core/src/lib/services/timezone.service.ts diff --git a/npm/ng-packs/packages/core/src/lib/services/index.ts b/npm/ng-packs/packages/core/src/lib/services/index.ts index c47bef3106..2fa7d134b5 100644 --- a/npm/ng-packs/packages/core/src/lib/services/index.ts +++ b/npm/ng-packs/packages/core/src/lib/services/index.ts @@ -23,3 +23,4 @@ export * from './window.service'; export * from './internet-connection-service'; export * from './local-storage-listener.service'; export * from './title-strategy.service'; +export * from './timezone.service'; diff --git a/npm/ng-packs/packages/core/src/lib/services/timezone.service.ts b/npm/ng-packs/packages/core/src/lib/services/timezone.service.ts new file mode 100644 index 0000000000..5862b5be04 --- /dev/null +++ b/npm/ng-packs/packages/core/src/lib/services/timezone.service.ts @@ -0,0 +1,34 @@ +import { Injectable } from '@angular/core'; + +@Injectable({ + providedIn: 'root', +}) +export class TimezoneService { + private readonly cookieKey = '__timezone'; + + getBrowserTimezone(): string { + return Intl.DateTimeFormat().resolvedOptions().timeZone; + } + + getTimezone(): string { + const fromCookie = this.getCookie(this.cookieKey); + return fromCookie || this.getBrowserTimezone(); + } + + setTimezone(timezone: string): void { + document.cookie = `${this.cookieKey}=${timezone}; path=/`; + } + + convertUtcToLocal(date: string | Date): Date { + return new Date(date + 'Z'); + } + + convertLocalToUtc(date: Date): string { + return date.toISOString(); + } + + private getCookie(name: string): string | null { + const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)')); + return match ? decodeURIComponent(match[2]) : null; + } +} From b4db4b3d41281f3b835ab3b67ec10f06215f75eb Mon Sep 17 00:00:00 2001 From: erdemcaygor Date: Tue, 8 Apr 2025 15:27:58 +0300 Subject: [PATCH 02/21] timezone interceptor service added --- .../core/src/lib/interceptors/index.ts | 1 + .../lib/interceptors/timezone.interceptor.ts | 21 +++++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 npm/ng-packs/packages/core/src/lib/interceptors/timezone.interceptor.ts diff --git a/npm/ng-packs/packages/core/src/lib/interceptors/index.ts b/npm/ng-packs/packages/core/src/lib/interceptors/index.ts index d7479a7684..ddcc17e23d 100644 --- a/npm/ng-packs/packages/core/src/lib/interceptors/index.ts +++ b/npm/ng-packs/packages/core/src/lib/interceptors/index.ts @@ -1 +1,2 @@ export * from './api.interceptor'; +export * from './timezone.interceptor'; diff --git a/npm/ng-packs/packages/core/src/lib/interceptors/timezone.interceptor.ts b/npm/ng-packs/packages/core/src/lib/interceptors/timezone.interceptor.ts new file mode 100644 index 0000000000..1a6d7be8a3 --- /dev/null +++ b/npm/ng-packs/packages/core/src/lib/interceptors/timezone.interceptor.ts @@ -0,0 +1,21 @@ +import { inject, Injectable } from '@angular/core'; +import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http'; +import { TimezoneService } from '../services'; +import { Observable } from 'rxjs'; + +@Injectable() +export class TimezoneInterceptor implements HttpInterceptor { + protected readonly timezoneService = inject(TimezoneService); + + intercept(req: HttpRequest, next: HttpHandler): Observable> { + const timezone = this.timezoneService.getTimezone(); + if (timezone) { + req = req.clone({ + setHeaders: { + __timezone: timezone, + }, + }); + } + return next.handle(req); + } +} From 8f2bb4838e225b9567dc6fe4e52f5dbc6bcd650b Mon Sep 17 00:00:00 2001 From: erdemcaygor Date: Tue, 8 Apr 2025 15:58:33 +0300 Subject: [PATCH 03/21] utc-to-local pipe added --- .../packages/core/src/lib/core.module.ts | 3 ++ .../packages/core/src/lib/pipes/index.ts | 1 + .../core/src/lib/pipes/utc-to-local.pipe.ts | 45 +++++++++++++++++++ 3 files changed, 49 insertions(+) create mode 100644 npm/ng-packs/packages/core/src/lib/pipes/utc-to-local.pipe.ts diff --git a/npm/ng-packs/packages/core/src/lib/core.module.ts b/npm/ng-packs/packages/core/src/lib/core.module.ts index 83881a5246..e6e8c3355a 100644 --- a/npm/ng-packs/packages/core/src/lib/core.module.ts +++ b/npm/ng-packs/packages/core/src/lib/core.module.ts @@ -30,6 +30,7 @@ import { ShortTimePipe } from './pipes/short-time.pipe'; import { ShortDatePipe } from './pipes/short-date.pipe'; import { SafeHtmlPipe } from './pipes/safe-html.pipe'; import { provideAbpCoreChild, provideAbpCore, withOptions } from './providers'; +import { UtcToLocalPipe } from './pipes'; const standaloneDirectives = [ AutofocusDirective, @@ -64,6 +65,7 @@ const standaloneDirectives = [ ShortDateTimePipe, ShortTimePipe, ShortDatePipe, + UtcToLocalPipe, ...standaloneDirectives, ], imports: [ @@ -85,6 +87,7 @@ const standaloneDirectives = [ ShortDateTimePipe, ShortTimePipe, ShortDatePipe, + UtcToLocalPipe, ], providers: [LocalizationPipe, provideHttpClient(withInterceptorsFromDi())], }) diff --git a/npm/ng-packs/packages/core/src/lib/pipes/index.ts b/npm/ng-packs/packages/core/src/lib/pipes/index.ts index 1a981ca041..f0c7b4ff60 100644 --- a/npm/ng-packs/packages/core/src/lib/pipes/index.ts +++ b/npm/ng-packs/packages/core/src/lib/pipes/index.ts @@ -5,3 +5,4 @@ export * from './to-injector.pipe'; export * from './short-date.pipe'; export * from './short-time.pipe'; export * from './short-date-time.pipe'; +export * from './utc-to-local.pipe'; diff --git a/npm/ng-packs/packages/core/src/lib/pipes/utc-to-local.pipe.ts b/npm/ng-packs/packages/core/src/lib/pipes/utc-to-local.pipe.ts new file mode 100644 index 0000000000..6e5245fc6e --- /dev/null +++ b/npm/ng-packs/packages/core/src/lib/pipes/utc-to-local.pipe.ts @@ -0,0 +1,45 @@ +import { Pipe, PipeTransform, Injectable, inject } from '@angular/core'; +import { TimezoneService } from '../services'; + +@Injectable() +@Pipe({ + name: 'utcToLocal', + standalone: false, +}) +export class UtcToLocalPipe implements PipeTransform { + protected readonly timezoneService = inject(TimezoneService); + private readonly timezone: string; + + constructor() { + this.timezone = this.timezoneService.getTimezone(); + } + + transform( + value: string | Date | null | undefined, + locale: string = navigator.language, + options?: Intl.DateTimeFormatOptions, + ): string { + if (!value) return ''; + + try { + const utcDate = new Date(value + 'Z'); // Ensure it's treated as UTC + + const formatOptions: Intl.DateTimeFormatOptions = options || { + year: 'numeric', + month: 'short', + day: 'numeric', + hour: '2-digit', + minute: '2-digit', + }; + + const formatter = new Intl.DateTimeFormat(locale, { + ...formatOptions, + timeZone: this.timezone, + }); + + return formatter.format(utcDate); + } catch (err) { + return ''; + } + } +} From 7a56fec99a7a9ce9695b3b0fdb5ae61a962582d2 Mon Sep 17 00:00:00 2001 From: erdemcaygor Date: Tue, 8 Apr 2025 18:45:02 +0300 Subject: [PATCH 04/21] timezone service refactoring --- .../lib/interceptors/timezone.interceptor.ts | 4 +++- .../core/src/lib/services/timezone.service.ts | 19 +++++++++++++++---- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/npm/ng-packs/packages/core/src/lib/interceptors/timezone.interceptor.ts b/npm/ng-packs/packages/core/src/lib/interceptors/timezone.interceptor.ts index 1a6d7be8a3..aa6320f206 100644 --- a/npm/ng-packs/packages/core/src/lib/interceptors/timezone.interceptor.ts +++ b/npm/ng-packs/packages/core/src/lib/interceptors/timezone.interceptor.ts @@ -3,7 +3,9 @@ import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/c import { TimezoneService } from '../services'; import { Observable } from 'rxjs'; -@Injectable() +@Injectable({ + providedIn: 'root', +}) export class TimezoneInterceptor implements HttpInterceptor { protected readonly timezoneService = inject(TimezoneService); diff --git a/npm/ng-packs/packages/core/src/lib/services/timezone.service.ts b/npm/ng-packs/packages/core/src/lib/services/timezone.service.ts index 5862b5be04..de112023d0 100644 --- a/npm/ng-packs/packages/core/src/lib/services/timezone.service.ts +++ b/npm/ng-packs/packages/core/src/lib/services/timezone.service.ts @@ -1,10 +1,21 @@ -import { Injectable } from '@angular/core'; +import { inject, Injectable } from '@angular/core'; +import { DOCUMENT } from '@angular/common'; +import { ConfigStateService } from './config-state.service'; @Injectable({ providedIn: 'root', }) export class TimezoneService { + protected readonly configState = inject(ConfigStateService); + protected readonly document = inject(DOCUMENT); private readonly cookieKey = '__timezone'; + private timeZoneNameFromSettings: string | null | undefined; + + constructor() { + this.configState.getOne$('timing').subscribe(timezoneSettings => { + this.timeZoneNameFromSettings = timezoneSettings?.timeZone?.iana?.timeZoneName; + }); + } getBrowserTimezone(): string { return Intl.DateTimeFormat().resolvedOptions().timeZone; @@ -12,11 +23,11 @@ export class TimezoneService { getTimezone(): string { const fromCookie = this.getCookie(this.cookieKey); - return fromCookie || this.getBrowserTimezone(); + return this.timeZoneNameFromSettings || fromCookie || this.getBrowserTimezone(); } setTimezone(timezone: string): void { - document.cookie = `${this.cookieKey}=${timezone}; path=/`; + this.document.cookie = `${this.cookieKey}=${timezone}; path=/`; } convertUtcToLocal(date: string | Date): Date { @@ -28,7 +39,7 @@ export class TimezoneService { } private getCookie(name: string): string | null { - const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)')); + const match = this.document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)')); return match ? decodeURIComponent(match[2]) : null; } } From eb8b74429cb97a02488a12e85d70fc906b2a06ab Mon Sep 17 00:00:00 2001 From: erdemcaygor Date: Tue, 8 Apr 2025 19:42:09 +0300 Subject: [PATCH 05/21] extensible table timezone support --- .../packages/core/src/lib/core.module.ts | 3 +- .../core/src/lib/pipes/utc-to-local.pipe.ts | 29 +++++++++---------- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/npm/ng-packs/packages/core/src/lib/core.module.ts b/npm/ng-packs/packages/core/src/lib/core.module.ts index e6e8c3355a..4238bcdb1e 100644 --- a/npm/ng-packs/packages/core/src/lib/core.module.ts +++ b/npm/ng-packs/packages/core/src/lib/core.module.ts @@ -65,7 +65,6 @@ const standaloneDirectives = [ ShortDateTimePipe, ShortTimePipe, ShortDatePipe, - UtcToLocalPipe, ...standaloneDirectives, ], imports: [ @@ -74,6 +73,7 @@ const standaloneDirectives = [ ReactiveFormsModule, RouterModule, LocalizationModule, + UtcToLocalPipe, ...standaloneDirectives, ], declarations: [ @@ -87,7 +87,6 @@ const standaloneDirectives = [ ShortDateTimePipe, ShortTimePipe, ShortDatePipe, - UtcToLocalPipe, ], providers: [LocalizationPipe, provideHttpClient(withInterceptorsFromDi())], }) diff --git a/npm/ng-packs/packages/core/src/lib/pipes/utc-to-local.pipe.ts b/npm/ng-packs/packages/core/src/lib/pipes/utc-to-local.pipe.ts index 6e5245fc6e..5667e1a4fc 100644 --- a/npm/ng-packs/packages/core/src/lib/pipes/utc-to-local.pipe.ts +++ b/npm/ng-packs/packages/core/src/lib/pipes/utc-to-local.pipe.ts @@ -1,28 +1,27 @@ import { Pipe, PipeTransform, Injectable, inject } from '@angular/core'; -import { TimezoneService } from '../services'; +import { LocalizationService, TimezoneService } from '../services'; @Injectable() @Pipe({ - name: 'utcToLocal', - standalone: false, + name: 'abpUtcToLocal', }) export class UtcToLocalPipe implements PipeTransform { protected readonly timezoneService = inject(TimezoneService); - private readonly timezone: string; - - constructor() { - this.timezone = this.timezoneService.getTimezone(); - } + protected readonly localizationService = inject(LocalizationService); transform( value: string | Date | null | undefined, - locale: string = navigator.language, options?: Intl.DateTimeFormatOptions, - ): string { + ): string | Date { if (!value) return ''; try { - const utcDate = new Date(value + 'Z'); // Ensure it's treated as UTC + const dateInput = new Date(value); + + if (isNaN(dateInput.getTime())) { + // Invalid date + return ''; + } const formatOptions: Intl.DateTimeFormatOptions = options || { year: 'numeric', @@ -32,14 +31,14 @@ export class UtcToLocalPipe implements PipeTransform { minute: '2-digit', }; - const formatter = new Intl.DateTimeFormat(locale, { + const formatter = new Intl.DateTimeFormat('en-US', { ...formatOptions, - timeZone: this.timezone, + timeZone: this.timezoneService.getTimezone(), }); - return formatter.format(utcDate); + return formatter.format(dateInput); } catch (err) { - return ''; + return value; } } } From 1b4f4fe0ea70fc5c16ee4e92129e82c31d99dca6 Mon Sep 17 00:00:00 2001 From: erdemcaygor Date: Wed, 9 Apr 2025 11:17:06 +0300 Subject: [PATCH 06/21] refactoring --- .../extensible-table/extensible-table.component.ts | 6 ++++++ .../packages/core/src/lib/pipes/utc-to-local.pipe.ts | 4 +++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/npm/ng-packs/packages/components/extensible/src/lib/components/extensible-table/extensible-table.component.ts b/npm/ng-packs/packages/components/extensible/src/lib/components/extensible-table/extensible-table.component.ts index 86de7f0ff2..94b73dba1d 100644 --- a/npm/ng-packs/packages/components/extensible/src/lib/components/extensible-table/extensible-table.component.ts +++ b/npm/ng-packs/packages/components/extensible/src/lib/components/extensible-table/extensible-table.component.ts @@ -31,6 +31,7 @@ import { LocalizationModule, PermissionDirective, PermissionService, + UtcToLocalPipe, } from '@abp/ng.core'; import { AbpVisibleDirective, @@ -64,6 +65,7 @@ const DEFAULT_ACTIONS_COLUMN_WIDTH = 150; NgxDatatableListDirective, PermissionDirective, LocalizationModule, + UtcToLocalPipe, AsyncPipe, NgTemplateOutlet, NgComponentOutlet, @@ -235,4 +237,8 @@ export class ExtensibleTableComponent implements OnChanges, AfterViewIn this.cdr.markForCheck(); }); } + + isDateType(prop: EntityProp) { + return prop.type === ePropType.Date || prop.type === ePropType.DateTime; + } } diff --git a/npm/ng-packs/packages/core/src/lib/pipes/utc-to-local.pipe.ts b/npm/ng-packs/packages/core/src/lib/pipes/utc-to-local.pipe.ts index 5667e1a4fc..3c878cef22 100644 --- a/npm/ng-packs/packages/core/src/lib/pipes/utc-to-local.pipe.ts +++ b/npm/ng-packs/packages/core/src/lib/pipes/utc-to-local.pipe.ts @@ -11,8 +11,10 @@ export class UtcToLocalPipe implements PipeTransform { transform( value: string | Date | null | undefined, + apply: boolean, options?: Intl.DateTimeFormatOptions, ): string | Date { + if (!apply) return value; if (!value) return ''; try { @@ -30,7 +32,7 @@ export class UtcToLocalPipe implements PipeTransform { hour: '2-digit', minute: '2-digit', }; - + console.log(this.timezoneService.getTimezone()); const formatter = new Intl.DateTimeFormat('en-US', { ...formatOptions, timeZone: this.timezoneService.getTimezone(), From 8633edb6508c87cd6166e8a032e31ee8e98480c7 Mon Sep 17 00:00:00 2001 From: erdemcaygor Date: Wed, 9 Apr 2025 11:50:22 +0300 Subject: [PATCH 07/21] refactoring --- .../core/src/lib/interceptors/timezone.interceptor.ts | 3 +++ .../packages/core/src/lib/services/timezone.service.ts | 8 +++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/npm/ng-packs/packages/core/src/lib/interceptors/timezone.interceptor.ts b/npm/ng-packs/packages/core/src/lib/interceptors/timezone.interceptor.ts index aa6320f206..10d32a3672 100644 --- a/npm/ng-packs/packages/core/src/lib/interceptors/timezone.interceptor.ts +++ b/npm/ng-packs/packages/core/src/lib/interceptors/timezone.interceptor.ts @@ -10,6 +10,9 @@ export class TimezoneInterceptor implements HttpInterceptor { protected readonly timezoneService = inject(TimezoneService); intercept(req: HttpRequest, next: HttpHandler): Observable> { + if (!this.timezoneService.isUtcClockEnabled) { + return next.handle(req); + } const timezone = this.timezoneService.getTimezone(); if (timezone) { req = req.clone({ diff --git a/npm/ng-packs/packages/core/src/lib/services/timezone.service.ts b/npm/ng-packs/packages/core/src/lib/services/timezone.service.ts index de112023d0..a7ae4121b2 100644 --- a/npm/ng-packs/packages/core/src/lib/services/timezone.service.ts +++ b/npm/ng-packs/packages/core/src/lib/services/timezone.service.ts @@ -10,11 +10,15 @@ export class TimezoneService { protected readonly document = inject(DOCUMENT); private readonly cookieKey = '__timezone'; private timeZoneNameFromSettings: string | null | undefined; + public isUtcClockEnabled: boolean | undefined; constructor() { this.configState.getOne$('timing').subscribe(timezoneSettings => { this.timeZoneNameFromSettings = timezoneSettings?.timeZone?.iana?.timeZoneName; }); + this.configState.getOne$('clock').subscribe(clock => { + this.isUtcClockEnabled = clock?.kind === 'Utc'; + }); } getBrowserTimezone(): string { @@ -27,7 +31,9 @@ export class TimezoneService { } setTimezone(timezone: string): void { - this.document.cookie = `${this.cookieKey}=${timezone}; path=/`; + if (this.isUtcClockEnabled) { + this.document.cookie = `${this.cookieKey}=${timezone}; path=/`; + } } convertUtcToLocal(date: string | Date): Date { From e7b21110d080fbf6163793721d65a674fbef19dc Mon Sep 17 00:00:00 2001 From: erdemcaygor Date: Wed, 9 Apr 2025 12:16:57 +0300 Subject: [PATCH 08/21] refactoring --- .../core/src/lib/pipes/utc-to-local.pipe.ts | 24 ++++--------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/npm/ng-packs/packages/core/src/lib/pipes/utc-to-local.pipe.ts b/npm/ng-packs/packages/core/src/lib/pipes/utc-to-local.pipe.ts index 3c878cef22..aaa26eb873 100644 --- a/npm/ng-packs/packages/core/src/lib/pipes/utc-to-local.pipe.ts +++ b/npm/ng-packs/packages/core/src/lib/pipes/utc-to-local.pipe.ts @@ -1,5 +1,5 @@ import { Pipe, PipeTransform, Injectable, inject } from '@angular/core'; -import { LocalizationService, TimezoneService } from '../services'; +import { ConfigStateService, LocalizationService, TimezoneService } from '../services'; @Injectable() @Pipe({ @@ -7,13 +7,10 @@ import { LocalizationService, TimezoneService } from '../services'; }) export class UtcToLocalPipe implements PipeTransform { protected readonly timezoneService = inject(TimezoneService); + protected readonly configState = inject(ConfigStateService); protected readonly localizationService = inject(LocalizationService); - transform( - value: string | Date | null | undefined, - apply: boolean, - options?: Intl.DateTimeFormatOptions, - ): string | Date { + transform(value: string | Date | null | undefined, apply: boolean): string | Date { if (!apply) return value; if (!value) return ''; @@ -24,21 +21,10 @@ export class UtcToLocalPipe implements PipeTransform { // Invalid date return ''; } - - const formatOptions: Intl.DateTimeFormatOptions = options || { - year: 'numeric', - month: 'short', - day: 'numeric', - hour: '2-digit', - minute: '2-digit', - }; - console.log(this.timezoneService.getTimezone()); - const formatter = new Intl.DateTimeFormat('en-US', { - ...formatOptions, + const localization = this.configState.getOne('localization'); + return dateInput.toLocaleString(localization?.currentCulture?.cultureName ?? 'en-US', { timeZone: this.timezoneService.getTimezone(), }); - - return formatter.format(dateInput); } catch (err) { return value; } From 4d57345cabfeef58db5a293dcef3f50b85085f28 Mon Sep 17 00:00:00 2001 From: erdemcaygor Date: Wed, 9 Apr 2025 16:57:54 +0300 Subject: [PATCH 09/21] abp-extensible-table props validation according to timezone --- .../extensible-table.component.html | 27 ++++++++++++++----- .../extensible-table.component.ts | 4 --- .../packages/core/src/lib/core.module.ts | 12 ++++++++- .../lib/interceptors/timezone.interceptor.ts | 4 +-- .../core/src/lib/pipes/utc-to-local.pipe.ts | 14 ++++++---- .../core/src/lib/services/timezone.service.ts | 10 ++++--- 6 files changed, 48 insertions(+), 23 deletions(-) diff --git a/npm/ng-packs/packages/components/extensible/src/lib/components/extensible-table/extensible-table.component.html b/npm/ng-packs/packages/components/extensible/src/lib/components/extensible-table/extensible-table.component.html index 471aad0f15..9104caf6ce 100644 --- a/npm/ng-packs/packages/components/extensible/src/lib/components/extensible-table/extensible-table.component.html +++ b/npm/ng-packs/packages/components/extensible/src/lib/components/extensible-table/extensible-table.component.html @@ -49,18 +49,33 @@ @if (!row['_' + prop.name].component) { -
+ } @else { +
+ [ngClass]="entityPropTypeClasses[prop.type]" + [class.pointer]="prop.action" + > + } } @else { @if (!row['_' + prop.name].component) { - @if (prop.type === 'datetime') { + @if (prop.type === 'datetime' || prop.type === 'date' || prop.type === 'time') {
' @@ -158,12 +153,6 @@ export class ExtensibleTableComponent implements OnChanges, AfterViewIn switch (prop.type) { case ePropType.Boolean: return this.getIcon(value); - case ePropType.Date: - return this.getDate(value, getShortDateFormat(this.config)); - case ePropType.Time: - return this.getDate(value, getShortTimeFormat(this.config)); - case ePropType.DateTime: - return this.getDate(value, getShortDateShortTimeFormat(this.config)); case ePropType.Enum: return this.getEnum(value, prop.enumList || []); default: diff --git a/npm/ng-packs/packages/core/src/lib/interceptors/timezone.interceptor.ts b/npm/ng-packs/packages/core/src/lib/interceptors/timezone.interceptor.ts index 1789eff2fb..6d5855433e 100644 --- a/npm/ng-packs/packages/core/src/lib/interceptors/timezone.interceptor.ts +++ b/npm/ng-packs/packages/core/src/lib/interceptors/timezone.interceptor.ts @@ -10,8 +10,7 @@ export class TimezoneInterceptor implements HttpInterceptor { protected readonly timezoneService = inject(TimezoneService); intercept(req: HttpRequest, next: HttpHandler): Observable> { - const timezone = this.timezoneService.getTimezone(); - console.log(timezone); + const timezone = this.timezoneService.timezone; if (timezone) { req = req.clone({ setHeaders: { diff --git a/npm/ng-packs/packages/core/src/lib/pipes/utc-to-local.pipe.ts b/npm/ng-packs/packages/core/src/lib/pipes/utc-to-local.pipe.ts index d0e1452fc5..2d0687a24d 100644 --- a/npm/ng-packs/packages/core/src/lib/pipes/utc-to-local.pipe.ts +++ b/npm/ng-packs/packages/core/src/lib/pipes/utc-to-local.pipe.ts @@ -1,5 +1,7 @@ -import { Pipe, PipeTransform, Injectable, inject } from '@angular/core'; +import { Pipe, PipeTransform, Injectable, inject, LOCALE_ID } from '@angular/core'; import { ConfigStateService, LocalizationService, TimezoneService } from '../services'; +import { getShortDateFormat, getShortDateShortTimeFormat, getShortTimeFormat } from '../utils'; +import { formatDate } from '@angular/common'; @Injectable() @Pipe({ @@ -9,23 +11,51 @@ export class UtcToLocalPipe implements PipeTransform { protected readonly timezoneService = inject(TimezoneService); protected readonly configState = inject(ConfigStateService); protected readonly localizationService = inject(LocalizationService); + protected readonly locale = inject(LOCALE_ID); - transform(value: string | Date | null | undefined): string | Date { + transform( + value: string | Date | null | undefined, + propType: 'date' | 'datetime' | 'time', + ): string | Date { if (!value) return ''; try { - const dateInput = new Date(value); - - if (isNaN(dateInput.getTime())) { - return ''; + let format: string; + switch (propType) { + case 'date': + format = getShortDateFormat(this.configState); + break; + case 'datetime': + format = getShortDateShortTimeFormat(this.configState); + break; + case 'time': + format = getShortTimeFormat(this.configState); + break; + default: + format = getShortDateShortTimeFormat(this.configState); } - const localization = this.configState.getOne('localization'); - const locale = localization?.currentCulture?.cultureName ?? 'en-US'; - const options: Intl.DateTimeFormatOptions = this.timezoneService.isUtcClockEnabled - ? { timeZone: this.timezoneService.getTimezone() } - : undefined; - return dateInput.toLocaleString(locale, options); + if (this.timezoneService.isUtcClockEnabled) { + const timeZone = this.timezoneService.timezone; + const options: Intl.DateTimeFormatOptions = { timeZone }; + let localeStr: string; + switch (propType) { + case 'date': + localeStr = new Date(value).toLocaleDateString(this.locale, options); + break; + case 'datetime': + localeStr = new Date(value).toLocaleString(this.locale, options); + break; + case 'time': + localeStr = new Date(value).toLocaleTimeString(this.locale, options); + break; + default: + localeStr = new Date(value).toLocaleString(this.locale, options); + } + return formatDate(localeStr, format, this.locale); + } else { + return formatDate(value, format, this.locale, format); + } } catch (err) { return value; } diff --git a/npm/ng-packs/packages/core/src/lib/services/timezone.service.ts b/npm/ng-packs/packages/core/src/lib/services/timezone.service.ts index ee3587cfdf..b3b5fe9cff 100644 --- a/npm/ng-packs/packages/core/src/lib/services/timezone.service.ts +++ b/npm/ng-packs/packages/core/src/lib/services/timezone.service.ts @@ -25,7 +25,7 @@ export class TimezoneService { return Intl.DateTimeFormat().resolvedOptions().timeZone; } - getTimezone(): string { + get timezone(): string { if (!this.isUtcClockEnabled) { return this.getBrowserTimezone(); } From eda18d65b3653099e065539ee85edcc6b422ef48 Mon Sep 17 00:00:00 2001 From: erdemcaygor Date: Fri, 11 Apr 2025 11:12:05 +0300 Subject: [PATCH 12/21] refactoring --- .../extensible-table.component.html | 4 +- .../core/src/lib/pipes/utc-to-local.pipe.ts | 65 ++++++++++--------- 2 files changed, 37 insertions(+), 32 deletions(-) diff --git a/npm/ng-packs/packages/components/extensible/src/lib/components/extensible-table/extensible-table.component.html b/npm/ng-packs/packages/components/extensible/src/lib/components/extensible-table/extensible-table.component.html index ad3fbd690a..bcba0967cd 100644 --- a/npm/ng-packs/packages/components/extensible/src/lib/components/extensible-table/extensible-table.component.html +++ b/npm/ng-packs/packages/components/extensible/src/lib/components/extensible-table/extensible-table.component.html @@ -53,8 +53,8 @@
Date: Tue, 22 Apr 2025 14:06:08 +0300 Subject: [PATCH 15/21] timezone http interceptor added to provideAbpCore --- .../core/src/lib/providers/core-module-config.provider.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/npm/ng-packs/packages/core/src/lib/providers/core-module-config.provider.ts b/npm/ng-packs/packages/core/src/lib/providers/core-module-config.provider.ts index 2b44117acb..4e816b6228 100644 --- a/npm/ng-packs/packages/core/src/lib/providers/core-module-config.provider.ts +++ b/npm/ng-packs/packages/core/src/lib/providers/core-module-config.provider.ts @@ -24,6 +24,7 @@ import { DEFAULT_DYNAMIC_LAYOUTS } from '../constants'; import { LocalizationService, LocalStorageListenerService, AbpTitleStrategy } from '../services'; import { DefaultQueueManager, getInitialData, localeInitializer } from '../utils'; import { CookieLanguageProvider, IncludeLocalizationResourcesProvider, LocaleProvider } from './'; +import { TimezoneInterceptor } from '../interceptors'; export enum CoreFeatureKind { Options, @@ -128,6 +129,11 @@ export function provideAbpCore(...features: CoreFeature[]) { provide: TitleStrategy, useExisting: AbpTitleStrategy, }, + { + provide: 'HTTP_INTERCEPTORS', + useClass: TimezoneInterceptor, + multi: true, + }, ]; for (const feature of features) { From ccae5fcbb0056908b4c4cbf8984e7e0717943abc Mon Sep 17 00:00:00 2001 From: erdemcaygor Date: Tue, 22 Apr 2025 14:40:03 +0300 Subject: [PATCH 16/21] timezone http interceptor added to provideAbpCore --- .../core/src/lib/providers/core-module-config.provider.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/npm/ng-packs/packages/core/src/lib/providers/core-module-config.provider.ts b/npm/ng-packs/packages/core/src/lib/providers/core-module-config.provider.ts index 4e816b6228..fafb51ff6d 100644 --- a/npm/ng-packs/packages/core/src/lib/providers/core-module-config.provider.ts +++ b/npm/ng-packs/packages/core/src/lib/providers/core-module-config.provider.ts @@ -1,6 +1,7 @@ import { makeEnvironmentProviders, Provider, inject, provideAppInitializer } from '@angular/core'; import { TitleStrategy } from '@angular/router'; import { + HTTP_INTERCEPTORS, provideHttpClient, withInterceptorsFromDi, withXsrfConfiguration, @@ -130,7 +131,7 @@ export function provideAbpCore(...features: CoreFeature[]) { useExisting: AbpTitleStrategy, }, { - provide: 'HTTP_INTERCEPTORS', + provide: HTTP_INTERCEPTORS, useClass: TimezoneInterceptor, multi: true, }, From 5ab765b0ed5bb3ac727c3284a825c4dade67fe0a Mon Sep 17 00:00:00 2001 From: erdemcaygor Date: Thu, 24 Apr 2025 15:23:46 +0300 Subject: [PATCH 17/21] luxon peer dependency added to core module --- npm/ng-packs/package.json | 1 - npm/ng-packs/packages/core/package.json | 3 +++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/npm/ng-packs/package.json b/npm/ng-packs/package.json index 4583169b7b..e17d6c6f18 100644 --- a/npm/ng-packs/package.json +++ b/npm/ng-packs/package.json @@ -111,7 +111,6 @@ "just-compare": "^2.0.0", "lerna": "^4.0.0", "lint-staged": "^13.0.0", - "luxon": "^3.6.1", "ng-packagr": "~19.1.0", "ng-zorro-antd": "~19.0.0", "nx": "~20.3.0", diff --git a/npm/ng-packs/packages/core/package.json b/npm/ng-packs/packages/core/package.json index b5efd135b9..845925af1a 100644 --- a/npm/ng-packs/packages/core/package.json +++ b/npm/ng-packs/packages/core/package.json @@ -13,6 +13,9 @@ "ts-toolbelt": "^9.0.0", "tslib": "^2.0.0" }, + "peerDependencies": { + "luxon": "^3.5.0" + }, "publishConfig": { "access": "public" }, From 923655aaa75cdcdeb28b6706f9366d517f7deeae Mon Sep 17 00:00:00 2001 From: erdemcaygor Date: Thu, 24 Apr 2025 16:52:20 +0300 Subject: [PATCH 18/21] luxon dependency added to core module --- npm/ng-packs/packages/core/ng-package.json | 3 ++- npm/ng-packs/packages/core/package.json | 6 ++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/npm/ng-packs/packages/core/ng-package.json b/npm/ng-packs/packages/core/ng-package.json index b73dba2fb7..9f9100d2fa 100644 --- a/npm/ng-packs/packages/core/ng-package.json +++ b/npm/ng-packs/packages/core/ng-package.json @@ -9,6 +9,7 @@ "angular-oauth2-oidc", "just-compare", "just-clone", - "ts-toolbelt" + "ts-toolbelt", + "luxon" ] } diff --git a/npm/ng-packs/packages/core/package.json b/npm/ng-packs/packages/core/package.json index 845925af1a..91ed63778d 100644 --- a/npm/ng-packs/packages/core/package.json +++ b/npm/ng-packs/packages/core/package.json @@ -11,10 +11,8 @@ "just-clone": "^6.0.0", "just-compare": "^2.0.0", "ts-toolbelt": "^9.0.0", - "tslib": "^2.0.0" - }, - "peerDependencies": { - "luxon": "^3.5.0" + "tslib": "^2.0.0", + "luxon": "^3.6.1" }, "publishConfig": { "access": "public" From deb7b61fdaf3ca59ebdd81de3c9717f5aab6235d Mon Sep 17 00:00:00 2001 From: Masum ULU <49063256+masum-ulu@users.noreply.github.com> Date: Tue, 29 Apr 2025 09:27:54 +0300 Subject: [PATCH 19/21] Update package.json --- npm/ng-packs/packages/core/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/npm/ng-packs/packages/core/package.json b/npm/ng-packs/packages/core/package.json index 91ed63778d..7a10820ead 100644 --- a/npm/ng-packs/packages/core/package.json +++ b/npm/ng-packs/packages/core/package.json @@ -12,7 +12,7 @@ "just-compare": "^2.0.0", "ts-toolbelt": "^9.0.0", "tslib": "^2.0.0", - "luxon": "^3.6.1" + "luxon": "^3.0.0" }, "publishConfig": { "access": "public" From b4656e6b69d9939cab21704428890d80129f8406 Mon Sep 17 00:00:00 2001 From: Masum ULU <49063256+masum-ulu@users.noreply.github.com> Date: Tue, 29 Apr 2025 09:38:50 +0300 Subject: [PATCH 20/21] Update core.module.ts --- npm/ng-packs/packages/core/src/lib/core.module.ts | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/npm/ng-packs/packages/core/src/lib/core.module.ts b/npm/ng-packs/packages/core/src/lib/core.module.ts index 33d7f0ad94..8fc0b90bbc 100644 --- a/npm/ng-packs/packages/core/src/lib/core.module.ts +++ b/npm/ng-packs/packages/core/src/lib/core.module.ts @@ -90,15 +90,7 @@ const standaloneDirectives = [ ShortTimePipe, ShortDatePipe, ], - providers: [ - LocalizationPipe, - provideHttpClient(withInterceptorsFromDi()), - { - provide: HTTP_INTERCEPTORS, - useClass: TimezoneInterceptor, - multi: true, - }, - ], + providers: [LocalizationPipe, provideHttpClient(withInterceptorsFromDi())], }) export class BaseCoreModule {} From 7f26390ce5dfb7a7bba0b84fceab1377d71d945f Mon Sep 17 00:00:00 2001 From: Masum ULU <49063256+masum-ulu@users.noreply.github.com> Date: Tue, 29 Apr 2025 09:47:23 +0300 Subject: [PATCH 21/21] Update core.module.ts --- npm/ng-packs/packages/core/src/lib/core.module.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/npm/ng-packs/packages/core/src/lib/core.module.ts b/npm/ng-packs/packages/core/src/lib/core.module.ts index 8fc0b90bbc..4505253aba 100644 --- a/npm/ng-packs/packages/core/src/lib/core.module.ts +++ b/npm/ng-packs/packages/core/src/lib/core.module.ts @@ -32,7 +32,6 @@ import { ShortDatePipe } from './pipes/short-date.pipe'; import { SafeHtmlPipe } from './pipes/safe-html.pipe'; import { provideAbpCoreChild, provideAbpCore, withOptions } from './providers'; import { UtcToLocalPipe } from './pipes'; -import { TimezoneInterceptor } from './interceptors'; const standaloneDirectives = [ AutofocusDirective,