diff --git a/frontend/src/app/features/in-app-notifications/entry/actors-line/in-app-notification-actors-line.component.html b/frontend/src/app/features/in-app-notifications/entry/actors-line/in-app-notification-actors-line.component.html index 16ebc61cac34..1d6adf2d0b30 100644 --- a/frontend/src/app/features/in-app-notifications/entry/actors-line/in-app-notification-actors-line.component.html +++ b/frontend/src/app/features/in-app-notifications/entry/actors-line/in-app-notification-actors-line.component.html @@ -1,8 +1,6 @@ -
+
diff --git a/frontend/src/app/features/in-app-notifications/entry/actors-line/in-app-notification-actors-line.component.sass b/frontend/src/app/features/in-app-notifications/entry/actors-line/in-app-notification-actors-line.component.sass index 92a4de952732..376f23ed350a 100644 --- a/frontend/src/app/features/in-app-notifications/entry/actors-line/in-app-notification-actors-line.component.sass +++ b/frontend/src/app/features/in-app-notifications/entry/actors-line/in-app-notification-actors-line.component.sass @@ -7,11 +7,6 @@ align-items: center color: var(--fgColor-muted) - &--date - @include text-shortener - max-width: 100% - line-height: 1rem - &--container @include text-shortener display: flex diff --git a/frontend/src/app/features/in-app-notifications/entry/relative-time/in-app-notification-relative-time.component.html b/frontend/src/app/features/in-app-notifications/entry/relative-time/in-app-notification-relative-time.component.html new file mode 100644 index 000000000000..982ee91f405a --- /dev/null +++ b/frontend/src/app/features/in-app-notifications/entry/relative-time/in-app-notification-relative-time.component.html @@ -0,0 +1,5 @@ +
+
diff --git a/frontend/src/app/features/in-app-notifications/entry/relative-time/in-app-notification-relative-time.component.sass b/frontend/src/app/features/in-app-notifications/entry/relative-time/in-app-notification-relative-time.component.sass new file mode 100644 index 000000000000..547e9c4b48d7 --- /dev/null +++ b/frontend/src/app/features/in-app-notifications/entry/relative-time/in-app-notification-relative-time.component.sass @@ -0,0 +1,6 @@ +@import "helpers" + +.op-ian-relative-time + @include text-shortener + max-width: 100% + line-height: 1rem diff --git a/frontend/src/app/features/in-app-notifications/entry/relative-time/in-app-notification-relative-time.component.ts b/frontend/src/app/features/in-app-notifications/entry/relative-time/in-app-notification-relative-time.component.ts new file mode 100644 index 000000000000..3f3b1801cff4 --- /dev/null +++ b/frontend/src/app/features/in-app-notifications/entry/relative-time/in-app-notification-relative-time.component.ts @@ -0,0 +1,63 @@ +import { + ChangeDetectionStrategy, + Component, + Input, + OnInit, + ViewEncapsulation, +} from '@angular/core'; +import { TimezoneService } from 'core-app/core/datetime/timezone.service'; +import { I18nService } from 'core-app/core/i18n/i18n.service'; +import { INotification } from 'core-app/core/state/in-app-notifications/in-app-notification.model'; +import { Observable, timer } from 'rxjs'; +import { distinctUntilChanged, map } from 'rxjs/operators'; + +@Component({ + selector: 'op-in-app-notification-relative-time', + templateUrl: './in-app-notification-relative-time.component.html', + styleUrls: ['./in-app-notification-relative-time.component.sass'], + changeDetection: ChangeDetectionStrategy.OnPush, + encapsulation: ViewEncapsulation.None, +}) +export class InAppNotificationRelativeTimeComponent implements OnInit { + @Input() notification:INotification; + @Input() hasActorByLine:boolean = true; + + // Fixed notification time + fixedTime:string; + + // Format relative elapsed time (n seconds/minutes/hours ago) + // at an interval for auto updating + relativeTime$:Observable; + + text = { + updated_by_at: (age:string):string => this.I18n.t( + 'js.notifications.center.text_update_date_by', + { date: age }, + ), + }; + + constructor( + private I18n:I18nService, + private timezoneService:TimezoneService, + ) { } + + ngOnInit():void { + this.buildTime(); + } + + private buildTime() { + this.fixedTime = this.timezoneService.formattedDatetime(this.notification.createdAt); + this.relativeTime$ = timer(0, 10000) + .pipe( + map(() => { + const time = this.timezoneService.formattedRelativeDateTime(this.notification.createdAt); + if (this.hasActorByLine && this.notification._links.actor) { + return this.text.updated_by_at(time); + } + + return time; + }), + distinctUntilChanged(), + ); + } +} diff --git a/frontend/src/app/features/in-app-notifications/in-app-notifications.module.ts b/frontend/src/app/features/in-app-notifications/in-app-notifications.module.ts index aade9f5cc27e..2839fd792a19 100644 --- a/frontend/src/app/features/in-app-notifications/in-app-notifications.module.ts +++ b/frontend/src/app/features/in-app-notifications/in-app-notifications.module.ts @@ -1,31 +1,32 @@ -import { NgModule } from '@angular/core'; -import { OpSharedModule } from 'core-app/shared/shared.module'; +import { ScrollingModule } from '@angular/cdk/scrolling'; import { CommonModule } from '@angular/common'; -import { IconModule } from 'core-app/shared/components/icon/icon.module'; +import { NgModule } from '@angular/core'; import { InAppNotificationBellComponent, } from 'core-app/features/in-app-notifications/bell/in-app-notification-bell.component'; -import { - InAppNotificationEntryComponent, -} from 'core-app/features/in-app-notifications/entry/in-app-notification-entry.component'; -import { OpenprojectPrincipalRenderingModule } from 'core-app/shared/components/principal/principal-rendering.module'; -import { ScrollingModule } from '@angular/cdk/scrolling'; +import { IanBellService } from 'core-app/features/in-app-notifications/bell/state/ian-bell.service'; import { InAppNotificationCenterComponent, } from 'core-app/features/in-app-notifications/center/in-app-notification-center.component'; +import { IanCenterService } from 'core-app/features/in-app-notifications/center/state/ian-center.service'; +import { + InAppNotificationsDateAlertsUpsaleComponent, +} from 'core-app/features/in-app-notifications/date-alerts-upsale/ian-date-alerts-upsale.component'; +import { + InAppNotificationEntryComponent, +} from 'core-app/features/in-app-notifications/entry/in-app-notification-entry.component'; import { OpenprojectWorkPackagesModule } from 'core-app/features/work-packages/openproject-work-packages.module'; -import { DynamicModule } from 'ng-dynamic-component'; -import { InAppNotificationStatusComponent } from './entry/status/in-app-notification-status.component'; +import { IconModule } from 'core-app/shared/components/icon/icon.module'; import { OpenprojectContentLoaderModule, } from 'core-app/shared/components/op-content-loader/openproject-content-loader.module'; -import { IanBellService } from 'core-app/features/in-app-notifications/bell/state/ian-bell.service'; +import { OpenprojectPrincipalRenderingModule } from 'core-app/shared/components/principal/principal-rendering.module'; +import { OpSharedModule } from 'core-app/shared/shared.module'; +import { DynamicModule } from 'ng-dynamic-component'; import { InAppNotificationActorsLineComponent } from './entry/actors-line/in-app-notification-actors-line.component'; import { InAppNotificationDateAlertComponent } from './entry/date-alert/in-app-notification-date-alert.component'; -import { - InAppNotificationsDateAlertsUpsaleComponent, -} from 'core-app/features/in-app-notifications/date-alerts-upsale/ian-date-alerts-upsale.component'; -import { IanCenterService } from 'core-app/features/in-app-notifications/center/state/ian-center.service'; +import { InAppNotificationRelativeTimeComponent } from './entry/relative-time/in-app-notification-relative-time.component'; +import { InAppNotificationStatusComponent } from './entry/status/in-app-notification-status.component'; @NgModule({ declarations: [ @@ -36,6 +37,7 @@ import { IanCenterService } from 'core-app/features/in-app-notifications/center/ InAppNotificationActorsLineComponent, InAppNotificationDateAlertComponent, InAppNotificationsDateAlertsUpsaleComponent, + InAppNotificationRelativeTimeComponent, ], imports: [ OpSharedModule,