-<div class="notifications-page-container">
- <div class="notification-section-heading"
- i18n>Notifications</div>
- <div class="row">
- <!-- Left Panel - Notifications List -->
- <div class="col-md-4">
- <!-- Search Bar -->
- <div class="search-container mb-4">
- <cds-search
- [size]="'md'"
- [placeholder]="'Search notifications...'"
- [(ngModel)]="searchText"
- (valueChange)="onSearch($event)">
- </cds-search>
- </div>
- <!-- Notifications List using Carbon Structured List -->
- <cds-structured-list
- class="notifications-list"
- *ngIf="filteredNotifications.length > 0">
- <cds-list-row
- *ngFor="let notification of filteredNotifications"
- [class.active]="selectedNotification === notification"
- (click)="onNotificationSelect(notification)"
- class="notification-row">
- <cds-list-column>
- <div class="notification-item-content">
- <h6 class="notification-title">
- <ng-container *ngIf="notification.prometheusAlert; else regularTitle">
- {{ notification.prometheusAlert.alertName }}
- <cds-tag
- [type]="notification.prometheusAlert.status === 'active' || notification.prometheusAlert.status === 'firing'?'red':
- notification.prometheusAlert.status === 'resolved' ? 'green' : 'blue'"
- [size]="'sm'"
- class="ml-2">
- {{ notification.prometheusAlert.status }}
- </cds-tag>
- </ng-container>
- <ng-template #regularTitle>
- {{ notification.title }}
- </ng-template>
- </h6>
- <small class="notification-meta">
- {{ notification.application }}
- <ng-container *ngIf="notification.prometheusAlert">
- • {{ notification.prometheusAlert.severity }}
- <ng-container *ngIf="notification.prometheusAlert.instance">
- • {{ notification.prometheusAlert.instance }}
- </ng-container>
+<div
+ cdsGrid
+ [useCssGrid]="true"
+ [fullWidth]="true"
+ class="notifications-page__container">
+ <!-- Left Panel - Notifications List -->
+ <div cdsCol
+ [columnNumbers]="{sm: 4, md: 4, lg: 5}">
+ <cds-search
+ cdsRow
+ [size]="'md'"
+ placeholder="Search notifications..."
+ i18n-placeholder
+ [(ngModel)]="searchText"
+ (valueChange)="onSearch($event)">
+ </cds-search>
+ <cds-structured-list
+ cdsRow
+ class="notifications-list"
+ *ngIf="filteredNotifications.length > 0">
+ <cds-list-row
+ *ngFor="let notification of filteredNotifications"
+ [class.active]="selectedNotification === notification"
+ (click)="onNotificationSelect(notification)"
+ class="notification-row">
+ <cds-list-column>
+ <div class="notification-item-content">
+ <h6 class="notification-title">
+ <ng-container *ngIf="notification.prometheusAlert; else regularTitle">
+ {{ notification.prometheusAlert.alertName }}
+ <cds-tag
+ [type]="notification.prometheusAlert.status === 'active' || notification.prometheusAlert.status === 'firing'?'red':
+ notification.prometheusAlert.status === 'resolved' ? 'green' : 'blue'"
+ [size]="'sm'"
+ class="ml-2">
+ {{ notification.prometheusAlert.status }}
+ </cds-tag>
+ </ng-container>
+ <ng-template #regularTitle>
+ {{ notification.title }}
+ </ng-template>
+ </h6>
+ <small class="notification-meta">
+ {{ notification.application }}
+ <ng-container *ngIf="notification.prometheusAlert">
+ • {{ notification.prometheusAlert.severity }}
+ <ng-container *ngIf="notification.prometheusAlert.instance">
+ • {{ notification.prometheusAlert.instance }}
</ng-container>
- </small>
- </div>
- </cds-list-column>
- <cds-list-column nowrap="true">
- <small class="notification-date">{{ formatDate(notification.timestamp) }}</small>
- </cds-list-column>
- </cds-list-row>
- </cds-structured-list>
- <!-- Empty state -->
- <div *ngIf="filteredNotifications.length === 0"
- class="empty-state">
+ </ng-container>
+ </small>
+ </div>
+ </cds-list-column>
+ <cds-list-column nowrap="true">
+ <small class="notification-date">{{ formatDate(notification.timestamp) }}</small>
+ </cds-list-column>
+ </cds-list-row>
+ </cds-structured-list>
+ <div *ngIf="filteredNotifications.length === 0"
+ class="empty-state"
+ cdsRow>
<svg
cdsIcon="notification"
size="48"
<p *ngIf="searchText">No notifications match your search</p>
<p *ngIf="!searchText">No notifications available</p>
</div>
- </div>
- <!-- Right Panel - Notification Details -->
- <div class="col-md-8">
- <div class="notification-section-heading">Notification Details</div>
- <div *ngIf="selectedNotification"
- class="notification-details">
- <div class="notification-section-heading">{{ selectedNotification.title }}</div>
- <!-- Details using Carbon Structured List -->
- <cds-structured-list class="details-list mt-4">
+ </div>
+ <!-- Right Panel - Notifications Details -->
+ <div cdsCol
+ [columnNumbers]="{sm: 12, md: 12, lg: 9}">
+ <div
+ cdsGrid
+ [fullWidth]="true"
+ *ngIf="selectedNotification"
+ class="notification-details">
+ <div cdsCol
+ [columnNumbers]="{sm: 16, md: 16, lg: 16}">
+ <h3 cdsRow>{{ selectedNotification.title }}</h3>
+ <cds-structured-list
+ cdsRow
+ class="details-list mt-4">
<cds-list-row>
<cds-list-column
nowrap="true"
selectedNotification.type === 2 ? 'green' : 'yellow'"
[size]="'sm'">
{{ selectedNotification.type === 0 ? 'Error' :
- selectedNotification.type === 1 ? 'Info' :
- selectedNotification.type === 2 ? 'Success' : 'Warning' }}
+ selectedNotification.type === 1 ? 'Info' :
+ selectedNotification.type === 2 ? 'Success' : 'Warning' }}
</cds-tag>
</cds-list-column>
</cds-list-row>
</ng-container>
<!-- Regular message for non-Prometheus notifications -->
<cds-list-row
+ cdsRow
*ngIf="selectedNotification.message && !selectedNotification.prometheusAlert">
<cds-list-column
nowrap="true"
</cds-list-row>
</cds-structured-list>
</div>
- <div *ngIf="!selectedNotification"
- class="no-selection-state">
- <svg
- cdsIcon="notification"
- size="64"
- class="no-selection-icon"></svg>
- <p>Select a notification to view details</p>
- </div>
</div>
</div>
</div>
// Main container
-.notifications-page-container {
- padding: var(--cds-spacing-05);
+.notifications-page__container {
+ padding-top: var(--cds-spacing-05);
background-color: var(--cds-layer-01);
- min-height: 100vh;
-}
-
-// Section headings
-.notification-section-heading {
- font-size: var(--cds-productive-heading-03-font-size);
- line-height: var(--cds-productive-heading-03-line-height);
- font-weight: var(--cds-productive-heading-03-font-weight);
- color: var(--cds-text-primary);
- margin-bottom: var(--cds-spacing-05);
-}
-
-// Search container
-.search-container {
- cds-search {
- width: 100%;
- }
+ column-gap: 1rem;
}
// Notifications list
border: 1px solid var(--cds-border-subtle);
border-radius: var(--cds-border-radius);
background-color: var(--cds-layer-01);
-
- h4 {
- margin: 0 0 var(--cds-spacing-05) 0;
- font-size: var(--cds-productive-heading-03-font-size);
- line-height: var(--cds-productive-heading-03-line-height);
- font-weight: var(--cds-productive-heading-03-font-weight);
- color: var(--cds-text-primary);
- }
}
// Details list
color: var(--cds-text-secondary);
font-weight: var(--cds-font-weight-semibold);
font-size: var(--cds-body-compact-01-font-size);
- min-width: 120px;
}
cds-list-column:last-child {
}
// Typography
-h1 {
- font-size: var(--cds-productive-heading-05-font-size);
- line-height: var(--cds-productive-heading-05-line-height);
- font-weight: var(--cds-productive-heading-05-font-weight);
- color: var(--cds-text-primary);
- margin-bottom: var(--cds-spacing-03);
-}
h3 {
font-size: var(--cds-productive-heading-03-font-size);
.mt-5 {
margin-top: var(--cds-spacing-06);
}
-
-// Responsive design
-@media (width <= 768px) {
- .notifications-page-container {
- padding: var(--cds-spacing-04);
- }
-
- .notification-details {
- padding: var(--cds-spacing-04);
- }
-
- .details-list {
- .detail-label {
- min-width: auto;
- }
- }
-}
-import { Component, OnInit, OnDestroy, AfterViewInit } from '@angular/core';
+import { Component, OnInit, OnDestroy, AfterViewInit, ChangeDetectorRef, AfterViewChecked } from '@angular/core';
import { Subscription } from 'rxjs';
import { NotificationService } from '~/app/shared/services/notification.service';
import { CdNotification } from '~/app/shared/models/cd-notification';
templateUrl: './notifications-page.component.html',
styleUrls: ['./notifications-page.component.scss']
})
-export class NotificationsPageComponent implements OnInit, OnDestroy, AfterViewInit {
+export class NotificationsPageComponent implements OnInit, OnDestroy, AfterViewInit, AfterViewChecked {
notifications: CdNotification[] = [];
selectedNotification: CdNotification | null = null;
searchText: string = '';
private notificationService: NotificationService,
private prometheusAlertService: PrometheusAlertService,
private prometheusNotificationService: PrometheusNotificationService,
- private authStorageService: AuthStorageService
+ private authStorageService: AuthStorageService,
+ private changeDetectorRef: ChangeDetectorRef
) {}
ngOnInit(): void {
ngAfterViewInit(): void {
this.sub.add(this.notificationService.data$.subscribe(() => {}));
}
+
+ ngAfterViewChecked() {
+ this.changeDetectorRef.detectChanges();
+ }
}