Skip to content
This repository has been archived by the owner on Jan 19, 2023. It is now read-only.

Commit

Permalink
Use cds-alert for alerts
Browse files Browse the repository at this point in the history
- Add button group to alerts

[#2303]

Signed-off-by: Vikram Yadav <[email protected]>
  • Loading branch information
Vikram Yadav committed May 10, 2021
1 parent bd0c4c8 commit 2b58b7f
Show file tree
Hide file tree
Showing 14 changed files with 155 additions and 119 deletions.
2 changes: 1 addition & 1 deletion internal/printer/pod.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ func createPodSummaryStatus(pod *corev1.Pod) (*component.Summary, error) {
sections.AddText("QoS", string(pod.Status.QOSClass))

if pod.DeletionTimestamp != nil {
summary.SetAlert(component.NewAlert(component.AlertTypeError, "Pod is being deleted"))
summary.SetAlert(component.NewAlert(component.AlertStatusError, component.AlertTypeDefault, "Pod is being deleted", false, nil))

sections = append(sections, component.SummarySection{
Header: "Status: Terminating",
Expand Down
40 changes: 27 additions & 13 deletions pkg/view/component/alert.go
Original file line number Diff line number Diff line change
@@ -1,28 +1,42 @@
package component

type AlertStatus string

const (
// AlertStatusError is an error alert.
AlertStatusError AlertStatus = "error"
// AlertStatusWarning is a warning alert.
AlertStatusWarning AlertStatus = "warning"
// AlertStatusInfo is an info alert.
AlertStatusInfo AlertStatus = "info"
// AlertStatusSuccess is a success alert.
AlertStatusSuccess AlertStatus = "success"
)

type AlertType string

const (
// AlertTypeError is an error alert.
AlertTypeError AlertType = "error"
// AlertTypeWarning is a warning alert.
AlertTypeWarning AlertType = "warning"
// AlertTypeInfo is an info alert.
AlertTypeInfo AlertType = "info"
// AlertTypeSuccess is a success alert.
AlertTypeSuccess AlertType = "success"
AlertTypeBanner AlertType = "banner"
AlertTypeDefault AlertType = "default"
AlertTypeLight AlertType = "light"
)

// Alert is an alert. It can be used in components which support alerts.
type Alert struct {
Type AlertType `json:"type"`
Message string `json:"message"`
Status AlertStatus `json:"status"`
Type AlertType `json:"type"`
Message string `json:"message"`
Closable bool `json:"closable"`
ButtonGroup *ButtonGroup `json:"buttonGroup"`
}

// NewAlert creates an instance of Alert.
func NewAlert(alertType AlertType, message string) Alert {
func NewAlert(alertStatus AlertStatus, alertType AlertType, message string, closable bool, buttonGroup *ButtonGroup) Alert {
return Alert{
Type: alertType,
Message: message,
Status: alertStatus,
Type: alertType,
Message: message,
ButtonGroup: buttonGroup,
Closable: closable,
}
}
10 changes: 7 additions & 3 deletions pkg/view/component/alert_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,14 @@ import (
)

func TestAlert(t *testing.T) {
got := NewAlert(AlertTypeSuccess, "message")
buttonGroup := NewButtonGroup()
got := NewAlert(AlertStatusSuccess, AlertTypeDefault, "message", true, buttonGroup)
expected := Alert{
Type: AlertTypeSuccess,
Message: "message",
Status: AlertStatusSuccess,
Type: AlertTypeDefault,
Message: "message",
Closable: true,
ButtonGroup: buttonGroup,
}

assert.Equal(t, got, expected)
Expand Down
3 changes: 2 additions & 1 deletion pkg/view/component/card_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ func TestCard_SetAlert(t *testing.T) {
card := NewCard(TitleFromString("card"))

alert := Alert{
Type: AlertTypeError,
Status: AlertStatusError,
Type: AlertTypeBanner,
Message: "error",
}

Expand Down
3 changes: 2 additions & 1 deletion pkg/view/component/summary_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,8 @@ func Test_Summary_Marshal(t *testing.T) {
Base: newBase(TypeSummary, TitleFromString("my summary")),
Config: SummaryConfig{
Alert: &Alert{
Type: AlertTypeInfo,
Status: AlertStatusInfo,
Type: AlertTypeDefault,
Message: "info",
},
Sections: []SummarySection{
Expand Down
7 changes: 5 additions & 2 deletions pkg/view/component/testdata/config_card_list.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,11 @@
}
],
"alert": {
"type": "warning",
"message": "warning"
"status": "warning",
"type": "banner",
"message": "warning",
"closable": false,
"buttonGroup": null
}
}
}
Expand Down
5 changes: 4 additions & 1 deletion pkg/view/component/testdata/summary.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,11 @@
},
"config": {
"alert": {
"status": "info",
"type": "default",
"message": "info",
"type": "info"
"buttonGroup": null,
"closable": false
},
"sections": [
{
Expand Down
3 changes: 2 additions & 1 deletion pkg/view/component/unmarshal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,8 @@ func Test_unmarshal(t *testing.T) {
},
},
Alert: &Alert{
Type: AlertTypeWarning,
Status: AlertStatusWarning,
Type: AlertTypeBanner,
Message: "warning",
},
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
<div [ngClass]="['alert', alertClass]" role="alert">
<div class="alert-items">
<div class="alert-item static">
<div class="alert-icon-wrapper">
<clr-icon [attr.shape]="shape" class="alert-icon"></clr-icon>
</div>
<span class="alert-text">{{ message }}</span>
</div>
</div>
</div>
<cds-alert-group type="{{type}}" status="{{status}}" *ngIf="showAlert">
<cds-alert [closable]="closable" (closeChange)="close()">
{{message}}
</cds-alert>
<app-button-group [view]="buttonGroup" *ngIf="buttonGroup">
</app-button-group>
</cds-alert-group>
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';

import { AlertComponent } from './alert.component';
import { ButtonGroupComponent } from '../button-group/button-group.component';
import { ButtonComponent } from '../button/button.component';
import { By } from '@angular/platform-browser';
import { DebugElement } from '@angular/core';
import { OctantTooltipComponent } from '../octant-tooltip/octant-tooltip';
import { windowProvider, WindowToken } from '../../../../../window';

describe('AlertComponent', () => {
let component: AlertComponent;
Expand All @@ -12,7 +15,13 @@ describe('AlertComponent', () => {
beforeEach(
waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [AlertComponent, OctantTooltipComponent],
declarations: [
AlertComponent,
OctantTooltipComponent,
ButtonGroupComponent,
ButtonComponent,
],
providers: [{ provide: WindowToken, useFactory: windowProvider }],
}).compileComponents();
})
);
Expand All @@ -23,7 +32,23 @@ describe('AlertComponent', () => {

component.alert = {
message: 'message',
type: 'warning',
type: 'default',
status: 'error',
closable: true,
buttonGroup: {
metadata: { type: 'buttonGroup' },
config: {
buttons: [
{
metadata: { type: 'button' },
config: {
payload: {},
name: 'Alert Button',
},
},
],
},
},
};

fixture.detectChanges();
Expand All @@ -33,18 +58,19 @@ describe('AlertComponent', () => {
expect(component).toBeTruthy();
});

it('sets the alert style', () => {
const el: DebugElement = fixture.debugElement.query(By.css('div'));
expect(el.classes.hasOwnProperty('alert-warning')).toBeTruthy();
});

it('sets the proper icon', () => {
const el: DebugElement = fixture.debugElement.query(By.css('.alert-icon'));
expect(el.attributes.shape).toEqual('exclamation-triangle');
it('sets the alert type', () => {
expect(component.status).toBe('danger');
});

it('sets the message', () => {
const el: DebugElement = fixture.debugElement.query(By.css('.alert-text'));
const el: DebugElement = fixture.debugElement.query(By.css('cds-alert'));
expect(el.nativeElement.textContent.trim()).toBe('message');
});

it('sets button group', () => {
const el: DebugElement = fixture.debugElement.query(
By.css('app-button-group app-button')
);
expect(el.nativeElement.textContent.trim()).toContain('Alert Button');
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import {
Input,
OnInit,
} from '@angular/core';

import '@cds/core/alert/register.js';
import { Alert } from '../../../models/content';

const alertLookup = {
Expand All @@ -13,13 +15,6 @@ const alertLookup = {
success: 'success',
};

const alertShapes = {
danger: 'exclamation-circle',
warning: 'exclamation-triangle',
info: 'info-circle',
success: 'check-circle',
};

@Component({
selector: 'app-alert',
templateUrl: './alert.component.html',
Expand All @@ -28,20 +23,27 @@ const alertShapes = {
})
export class AlertComponent implements OnInit {
@Input() alert: Alert;
shape = '';
alertClass = '';
message = '';
alertType = '';
status = '';
type = '';
closable = false;
buttonGroup = null;
showAlert = false;

constructor() {}

ngOnInit(): void {
if (this.alert) {
const alertClass = alertLookup[this.alert.type] || alertLookup.error;
this.shape = alertShapes[alertClass];
this.alertClass = `alert-${alertClass}`;
this.type = this.alert.type || 'default';
this.message = this.alert.message;
this.alertType = this.alert.type;
this.status = alertLookup[this.alert.status] || alertLookup.error;
this.closable = this.alert.closable;
this.buttonGroup = this.alert.buttonGroup;
this.showAlert = true;
}
}

close(): void {
this.showAlert = false;
}
}
5 changes: 4 additions & 1 deletion web/src/app/modules/shared/models/content.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,11 @@ export interface AnnotationsView extends View {
}

export interface Alert {
type: string;
status: string;
type?: string;
message: string;
closable?: boolean;
buttonGroup?: ButtonGroupView;
}

export interface CardView extends View {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,60 +2,6 @@
<div class="progress loop"><progress></progress></div>
</ng-container>

<ng-container *ngIf="!loading && error">
<div class="alert alert-app-level alert-danger">
<div class="alert-items">
<div class="alert-item static">
<div class="alert-icon-wrapper">
<clr-icon class="alert-icon" shape="exclamation-circle"></clr-icon>
</div>
<div class="alert-text">
{{ error }}
</div>
</div>
</div>
</div>
</ng-container>

<ng-container *ngIf="!loading && warning">
<clr-alert
[clrAlertType]="'warning'"
(clrAlertClosedChange)="onWarningClose()"
[clrAlertIcon]="'exclamation-triangle'"
[clrAlertAppLevel]="true"
>
<clr-alert-item>
<span class="alert-text">
{{ warning }}
</span>
</clr-alert-item>
</clr-alert>
</ng-container>

<ng-container *ngIf="!loading && info">
<clr-alert
[clrAlertType]="'info'"
[clrAlertIcon]="'info-circle'"
[clrAlertAppLevel]="true"
>
<clr-alert-item>
<span class="alert-text">
{{ info }}
</span>
</clr-alert-item>
</clr-alert>
</ng-container>

<ng-container *ngIf="!loading && success">
<clr-alert
[clrAlertType]="'success'"
[clrAlertIcon]="'check-circle'"
[clrAlertAppLevel]="true"
>
<clr-alert-item>
<span class="alert-text">
{{ success }}
</span>
</clr-alert-item>
</clr-alert>
<ng-container *ngIf="!loading && hasAlert()">
<app-alert [alert]="alertConfig"></app-alert>
</ng-container>
Loading

0 comments on commit 2b58b7f

Please sign in to comment.