From 94e929abf4145c3afb58e2d1dd439fb5797e41bd Mon Sep 17 00:00:00 2001 From: JaySoni1 Date: Wed, 22 Oct 2025 16:52:08 +0530 Subject: [PATCH] WEB-185 Made on date and checked on date should show full datetime with timezone information or explicitly convert the epoch time to UTC! --- src/app/pipes/datetime-format.pipe.ts | 43 +++--- .../audit-trails/audit-trails.component.html | 122 ++++++++++++------ .../audit-trails/audit-trails.component.scss | 11 ++ .../audit-trails/audit-trails.component.ts | 82 ++++++++++-- .../view-audit/view-audit.component.html | 2 +- .../view-audit/view-audit.component.ts | 4 +- 6 files changed, 196 insertions(+), 68 deletions(-) diff --git a/src/app/pipes/datetime-format.pipe.ts b/src/app/pipes/datetime-format.pipe.ts index 4042033da..5ee05ded6 100644 --- a/src/app/pipes/datetime-format.pipe.ts +++ b/src/app/pipes/datetime-format.pipe.ts @@ -1,25 +1,32 @@ import { Pipe, PipeTransform } from '@angular/core'; -import { SettingsService } from 'app/settings/settings.service'; -import moment from 'moment'; +import moment, { Moment } from 'moment'; -@Pipe({ name: 'datetimeFormat' }) +@Pipe({ name: 'datetimeFormat', standalone: true }) export class DatetimeFormatPipe implements PipeTransform { - constructor(private settingsService: SettingsService) {} - - transform(value: any, datetimeFormat?: string): any { - const defaultDateFormat = this.settingsService.dateFormat.replace('dd', 'DD'); - if (typeof value === 'undefined') { - return ''; - } - let dateVal; - if (value instanceof Array) { - dateVal = moment(value.join('-'), 'YYYY-MM-DD HH:mm:ss'); + transform(value: unknown, datetimeFormat?: string): string { + if (value == null || value === '') return ''; + let dateVal: Moment; + if (Array.isArray(value)) { + const [ + y, + m, + d, + hh, + mm, + ss + ] = value as number[]; + if (hh != null) { + dateVal = moment({ year: y, month: (m ?? 1) - 1, date: d, hour: hh, minute: mm ?? 0, second: ss ?? 0 }); + } else { + dateVal = moment({ year: y, month: (m ?? 1) - 1, date: d }); + } + } else if (typeof value === 'number' && value < 1e12) { + // epoch seconds + dateVal = moment.unix(value); } else { - dateVal = moment(value); + dateVal = moment(value as any); } - if (datetimeFormat == null) { - return dateVal.format(defaultDateFormat + ' HH:mm:ss'); - } - return dateVal.format(datetimeFormat); + const fmt = datetimeFormat ?? 'YYYY-MM-DDTHH:mm:ssZ'; + return dateVal.format(fmt); } } diff --git a/src/app/system/audit-trails/audit-trails.component.html b/src/app/system/audit-trails/audit-trails.component.html index 5b4235048..e6e078e81 100644 --- a/src/app/system/audit-trails/audit-trails.component.html +++ b/src/app/system/audit-trails/audit-trails.component.html @@ -5,7 +5,7 @@ -
+
{{ 'labels.inputs.Resource ID' | translate }} @@ -43,45 +43,89 @@ - - {{ 'labels.inputs.Maker From Date' | translate }} - - - - +
+ + {{ 'labels.inputs.Maker From Date' | translate }} + + + + - - {{ 'labels.inputs.Maker To Date' | translate }} - - - - + + {{ 'labels.inputs.Time' | translate }} + + +
- - {{ 'labels.inputs.Checker From Date' | translate }} - - - - +
+ + {{ 'labels.inputs.Maker To Date' | translate }} + + + + - - {{ 'labels.inputs.Checked To Date' | translate }} - - - - + + {{ 'labels.inputs.Time' | translate }} + + +
+ +
+ + {{ 'labels.inputs.Checker From Date' | translate }} + + + + + + + {{ 'labels.inputs.Time' | translate }} + + +
+ +
+ + {{ 'labels.inputs.Checked To Date' | translate }} + + + + + + + {{ 'labels.inputs.Time' | translate }} + + +
@@ -151,7 +195,7 @@ {{ 'labels.inputs.Made Date' | translate }} - {{ auditTrail.madeOnDate | dateFormat }} + {{ auditTrail.madeOnDate | datetimeFormat }} @@ -161,7 +205,7 @@ {{ 'labels.inputs.Checked Date' | translate }} - {{ auditTrail.checkedOnDate | dateFormat }} + {{ auditTrail.checkedOnDate | datetimeFormat }} diff --git a/src/app/system/audit-trails/audit-trails.component.scss b/src/app/system/audit-trails/audit-trails.component.scss index 24edb63bb..7f9edb6a2 100644 --- a/src/app/system/audit-trails/audit-trails.component.scss +++ b/src/app/system/audit-trails/audit-trails.component.scss @@ -5,3 +5,14 @@ table { cursor: pointer; } } + +.flex-38 { + .time-input { + font-size: 14px; + width: 100%; + } +} + +.gap-8px { + gap: 8px; +} diff --git a/src/app/system/audit-trails/audit-trails.component.ts b/src/app/system/audit-trails/audit-trails.component.ts index a8cb0c561..d8195de93 100644 --- a/src/app/system/audit-trails/audit-trails.component.ts +++ b/src/app/system/audit-trails/audit-trails.component.ts @@ -32,7 +32,7 @@ import { MatRowDef, MatRow } from '@angular/material/table'; -import { DateFormatPipe } from '../../pipes/date-format.pipe'; +import { DatetimeFormatPipe } from '../../pipes/datetime-format.pipe'; import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module'; /** @@ -62,7 +62,7 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module'; MatRow, MatPaginator, AsyncPipe, - DateFormatPipe + DatetimeFormatPipe ] }) export class AuditTrailsComponent implements OnInit, AfterViewInit { @@ -153,8 +153,12 @@ export class AuditTrailsComponent implements OnInit, AfterViewInit { user = new UntypedFormControl(''); /** From date form control. */ fromDate = new UntypedFormControl(); + /** From time form control. */ + fromTime = new UntypedFormControl(); /** Checked from date form control. */ checkedFromDate = new UntypedFormControl(); + /** Checked from time form control. */ + checkedFromTime = new UntypedFormControl(); /** Processing result form control. */ processingResult = new UntypedFormControl(); /** Action name form control. */ @@ -163,8 +167,12 @@ export class AuditTrailsComponent implements OnInit, AfterViewInit { resourceId = new UntypedFormControl(''); /** To date form control. */ toDate = new UntypedFormControl(); + /** To time form control. */ + toTime = new UntypedFormControl(); /** Checked to date form control. */ checkedToDate = new UntypedFormControl(); + /** Checked to time form control. */ + checkedToTime = new UntypedFormControl(); /** Entity name form control. */ entityName = new UntypedFormControl(); /** Checker form control. */ @@ -230,7 +238,17 @@ export class AuditTrailsComponent implements OnInit, AfterViewInit { debounceTime(500), distinctUntilChanged(), tap((filterValue) => { - this.applyFilter(this.getDate(filterValue), 'makerDateTimeFrom'); + this.applyFilter(this.getDateTime(filterValue, this.fromTime.value), 'makerDateTimeFrom'); + }) + ) + .subscribe(); + + this.fromTime.valueChanges + .pipe( + debounceTime(500), + distinctUntilChanged(), + tap((timeValue) => { + this.applyFilter(this.getDateTime(this.fromDate.value, timeValue), 'makerDateTimeFrom'); }) ) .subscribe(); @@ -240,7 +258,17 @@ export class AuditTrailsComponent implements OnInit, AfterViewInit { debounceTime(500), distinctUntilChanged(), tap((filterValue) => { - this.applyFilter(this.getDate(filterValue), 'makerDateTimeTo'); + this.applyFilter(this.getDateTime(filterValue, this.toTime.value), 'makerDateTimeTo'); + }) + ) + .subscribe(); + + this.toTime.valueChanges + .pipe( + debounceTime(500), + distinctUntilChanged(), + tap((timeValue) => { + this.applyFilter(this.getDateTime(this.toDate.value, timeValue), 'makerDateTimeTo'); }) ) .subscribe(); @@ -250,7 +278,17 @@ export class AuditTrailsComponent implements OnInit, AfterViewInit { debounceTime(500), distinctUntilChanged(), tap((filterValue) => { - this.applyFilter(this.getDate(filterValue), 'checkerDateTimeFrom'); + this.applyFilter(this.getDateTime(filterValue, this.checkedFromTime.value), 'checkerDateTimeFrom'); + }) + ) + .subscribe(); + + this.checkedFromTime.valueChanges + .pipe( + debounceTime(500), + distinctUntilChanged(), + tap((timeValue) => { + this.applyFilter(this.getDateTime(this.checkedFromDate.value, timeValue), 'checkerDateTimeFrom'); }) ) .subscribe(); @@ -260,7 +298,17 @@ export class AuditTrailsComponent implements OnInit, AfterViewInit { debounceTime(500), distinctUntilChanged(), tap((filterValue) => { - this.applyFilter(this.getDate(filterValue), 'checkerDateTimeTo'); + this.applyFilter(this.getDateTime(filterValue, this.checkedToTime.value), 'checkerDateTimeTo'); + }) + ) + .subscribe(); + + this.checkedToTime.valueChanges + .pipe( + debounceTime(500), + distinctUntilChanged(), + tap((timeValue) => { + this.applyFilter(this.getDateTime(this.checkedToDate.value, timeValue), 'checkerDateTimeTo'); }) ) .subscribe(); @@ -502,8 +550,9 @@ export class AuditTrailsComponent implements OnInit, AfterViewInit { let csv = response.pageItems.map((row: any) => headerCode.map((fieldName) => (fieldName === 'madeOnDate' || fieldName === 'checkedOnDate') && - JSON.stringify(row[fieldName], replacer) !== '""' - ? this.dateUtils.formatDate(JSON.stringify(row[fieldName], replacer), dateFormat) + row[fieldName] != null && + row[fieldName] !== '' + ? JSON.stringify(this.dateUtils.formatDate(row[fieldName], 'YYYY-MM-DDTHH:mm:ssZ')) : JSON.stringify(row[fieldName], replacer) ) ); @@ -530,4 +579,21 @@ export class AuditTrailsComponent implements OnInit, AfterViewInit { const dateFormat = this.settingsService.dateFormat; return this.dateUtils.formatDate(timestamp, dateFormat); } + private getDateTime(date: Date, timeStr: string): string { + if (!date) { + return ''; + } + const result = new Date(date); + if (timeStr) { + const [ + hours, + minutes, + seconds + ] = timeStr.split(':').map(Number); + result.setHours(hours || 0); + result.setMinutes(minutes || 0); + result.setSeconds(seconds || 0); + } + return this.dateUtils.formatDate(result, 'YYYY-MM-DDTHH:mm:ssZ'); + } } diff --git a/src/app/system/audit-trails/view-audit/view-audit.component.html b/src/app/system/audit-trails/view-audit/view-audit.component.html index 068654783..d76dcc241 100644 --- a/src/app/system/audit-trails/view-audit/view-audit.component.html +++ b/src/app/system/audit-trails/view-audit/view-audit.component.html @@ -57,7 +57,7 @@
- {{ auditTrailData.madeOnDate | dateFormat }} + {{ auditTrailData.madeOnDate | datetimeFormat }}
diff --git a/src/app/system/audit-trails/view-audit/view-audit.component.ts b/src/app/system/audit-trails/view-audit/view-audit.component.ts index 4821db813..d4cccee9f 100644 --- a/src/app/system/audit-trails/view-audit/view-audit.component.ts +++ b/src/app/system/audit-trails/view-audit/view-audit.component.ts @@ -16,7 +16,7 @@ import { MatRowDef, MatRow } from '@angular/material/table'; -import { DateFormatPipe } from '../../../pipes/date-format.pipe'; +import { DatetimeFormatPipe } from '../../../pipes/datetime-format.pipe'; import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module'; /** @@ -40,7 +40,7 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module'; MatHeaderRow, MatRowDef, MatRow, - DateFormatPipe + DatetimeFormatPipe ] }) export class ViewAuditComponent implements OnInit {