Skip to content
Snippets Groups Projects
Commit bbfc6e67 authored by paf's avatar paf
Browse files

Get rid of build-in Alert-component in favour of Alert-Component from IQB-Components

parent 36bbda88
No related branches found
No related tags found
No related merge requests found
...@@ -37,7 +37,6 @@ import { StatusCardComponent } from './app-root/status-card/status-card.componen ...@@ -37,7 +37,6 @@ import { StatusCardComponent } from './app-root/status-card/status-card.componen
import { TestStarterComponent } from './app-root/test-starter/test-starter.component'; import { TestStarterComponent } from './app-root/test-starter/test-starter.component';
import { MonitorStarterComponent } from './app-root/monitor-starter/monitor-starter.component'; import { MonitorStarterComponent } from './app-root/monitor-starter/monitor-starter.component';
import { LegalNoticeComponent } from './app-root/legal-notice/legal-notice.component'; import { LegalNoticeComponent } from './app-root/legal-notice/legal-notice.component';
import { AlertModule } from './shared/alert/alert.module';
@NgModule({ @NgModule({
declarations: [ declarations: [
...@@ -77,8 +76,7 @@ import { AlertModule } from './shared/alert/alert.module'; ...@@ -77,8 +76,7 @@ import { AlertModule } from './shared/alert/alert.module';
HttpClientModule, HttpClientModule,
RouterModule, RouterModule,
AppRoutingModule, AppRoutingModule,
IqbComponentsModule.forRoot(), IqbComponentsModule.forRoot()
AlertModule
], ],
providers: [ providers: [
BackendService, BackendService,
......
...@@ -30,7 +30,6 @@ import { ...@@ -30,7 +30,6 @@ import {
unitTestExampleSessions, unitTestExampleSessions,
unitTestCommandResponse unitTestCommandResponse
} from './unit-test-example-data.spec'; } from './unit-test-example-data.spec';
import { AlertModule } from '../shared/alert/alert.module';
class MockMatDialog { class MockMatDialog {
open(): { afterClosed: () => Observable<{ action: boolean }> } { open(): { afterClosed: () => Observable<{ action: boolean }> } {
...@@ -103,8 +102,7 @@ describe('GroupMonitorComponent', () => { ...@@ -103,8 +102,7 @@ describe('GroupMonitorComponent', () => {
MatRadioModule, MatRadioModule,
MatCheckboxModule, MatCheckboxModule,
MatTableModule, MatTableModule,
MatSlideToggleModule, MatSlideToggleModule
AlertModule
], ],
providers: [ providers: [
{ provide: TestSessionManager, useValue: new MockTestSessionManagerService() }, { provide: TestSessionManager, useValue: new MockTestSessionManagerService() },
......
...@@ -23,7 +23,6 @@ import { BackendService } from './backend.service'; ...@@ -23,7 +23,6 @@ import { BackendService } from './backend.service';
import { BookletService } from './booklet/booklet.service'; import { BookletService } from './booklet/booklet.service';
import { TestSessionComponent } from './test-session/test-session.component'; import { TestSessionComponent } from './test-session/test-session.component';
import { TestSessionManager } from './test-session-manager/test-session-manager.service'; import { TestSessionManager } from './test-session-manager/test-session-manager.service';
import { AlertModule } from '../shared/alert/alert.module';
@NgModule({ @NgModule({
declarations: [ declarations: [
...@@ -48,8 +47,7 @@ import { AlertModule } from '../shared/alert/alert.module'; ...@@ -48,8 +47,7 @@ import { AlertModule } from '../shared/alert/alert.module';
MatSidenavModule, MatSidenavModule,
MatCheckboxModule, MatCheckboxModule,
MatSlideToggleModule, MatSlideToggleModule,
IqbComponentsModule, IqbComponentsModule
AlertModule
], ],
providers: [ providers: [
BackendService, BackendService,
......
<div class="alert">
<div class="vertical-align-middle">
<mat-icon class="alert-{{level}}">{{icons[level]}}</mat-icon>
<span [innerHTML]="displayText$ | async"></span>
</div>
</div>
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { MatIconModule } from '@angular/material/icon';
import { SimpleChange } from '@angular/core';
import { AlertComponent } from './alert.component';
describe('AlertComponent', () => {
let component: AlertComponent;
let fixture: ComponentFixture<AlertComponent>;
let returnedTexts: string[] = [];
const changeAttributeText = (value: string) => {
const previousValue = component.text;
component.text = value;
if (previousValue !== value) {
component.ngOnChanges({ text: new SimpleChange(previousValue, value, false) });
}
};
const changeAttributeCustomtext = (value: string) => {
const previousValue = component.customtext;
component.customtext = value;
if (previousValue !== value) {
component.ngOnChanges({ customtext: new SimpleChange(previousValue, value, false) });
}
};
const changeAttributeReplacements = (value: string[]) => {
const previousValue = component.replacements;
component.replacements = value;
if (JSON.stringify(previousValue) !== JSON.stringify(value)) {
component.ngOnChanges({ replacements: new SimpleChange(previousValue, value, false) });
}
};
const updateCustomText = (key: string, value: string): void => {
// eslint-disable-next-line @typescript-eslint/dot-notation
component['cts']['addCustomTexts']({ [key]: value });
};
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
imports: [
MatIconModule
]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(AlertComponent);
component = fixture.componentInstance;
returnedTexts = [];
component.displayText$.subscribe(text => returnedTexts.push(text));
});
it('should create', () => {
expect(component).toBeTruthy();
});
it('should update on input change', () => {
changeAttributeText('A');
changeAttributeText('B');
changeAttributeText('B');
changeAttributeText('C');
expect(returnedTexts).toEqual(['A', 'B', 'C']);
});
it('should highlight ticks', () => {
changeAttributeText('A `in ticks` A');
changeAttributeText('B');
changeAttributeText('C `in ticks` C');
expect(returnedTexts).toEqual([
'A <span class=\'highlight\'>in ticks</span> A',
'B',
'C <span class=\'highlight\'>in ticks</span> C'
]);
});
it('should use and update the customtext if given', () => {
changeAttributeText('text value');
updateCustomText('customtext key', 'customtext value');
changeAttributeCustomtext('customtext key');
changeAttributeText('text value change is ignored as long as customtext is given and an existing key');
updateCustomText('customtext key', 'customtext value updated');
changeAttributeCustomtext('missing key');
updateCustomText('missing key', 'missing key got a value');
changeAttributeText('text value is used as defaultvalue for customtext');
updateCustomText('empty key', '');
changeAttributeCustomtext('empty key');
updateCustomText('customtext key', 'replacement: %s');
changeAttributeCustomtext('customtext key');
changeAttributeReplacements(['something']);
changeAttributeReplacements(['something else']);
updateCustomText('customtext key', 'replacement in ticks: `%s`');
// returnedTexts.forEach(s => console.log(s));
expect(returnedTexts).toEqual([
'text value',
'customtext value',
'customtext value updated',
'text value change is ignored as long as customtext is given and an existing key',
'missing key got a value',
'text value is used as defaultvalue for customtext',
'replacement: %s',
'replacement: something',
'replacement: something else',
'replacement in ticks: <span class=\'highlight\'>something else</span>'
]);
});
});
import {
Component, Input, OnChanges, SimpleChanges, ViewEncapsulation
} from '@angular/core';
import { CustomtextPipe, CustomtextService } from 'iqb-components';
import {
Observable, ReplaySubject, Subject, Subscription
} from 'rxjs';
import { map } from 'rxjs/operators';
@Component({
selector: 'alert',
templateUrl: 'alert.component.html',
styleUrls: ['alert.css'],
encapsulation: ViewEncapsulation.None
})
export class AlertComponent implements OnChanges {
@Input() text: string;
@Input() customtext: string;
@Input() replacements: string[];
@Input() level: 'error' | 'warning' | 'info' | 'success';
icons = {
error: 'error',
warning: 'warning',
info: 'info',
success: 'check_circle'
};
get displayText$(): Observable<string> {
return this._displayText$
.pipe(
map(text => this.highlightTicks(text || ''))
);
}
private _displayText$: Subject<string>;
private customTextSubscription: Subscription;
constructor(
private cts: CustomtextService
) {
this._displayText$ = new ReplaySubject<string>();
}
ngOnChanges(changes: SimpleChanges): void {
if (!this.customtext) {
this.unsubscribeCustomText();
if (changes.text) {
this._displayText$.next(this.text);
}
} else if (changes.customtext || changes.replacements) {
this.unsubscribeCustomText();
this.subscribeCustomText();
}
}
private subscribeCustomText(): void {
this.customTextSubscription = this.getCustomtext()
.subscribe(text => this._displayText$.next(text));
}
private unsubscribeCustomText(): void {
if (this.customTextSubscription) {
this.customTextSubscription.unsubscribe();
this.customTextSubscription = null;
}
}
getCustomtext(): Observable<string> {
return new CustomtextPipe(this.cts)
.transform(this.text, this.customtext, ...(this.replacements || []));
}
private highlightTicks = (text: string): string => text.replace(
/\u0060([^\u0060]+)\u0060/g,
(match, match2) => `<span class='highlight'>${match2}</span>`
);
}
.alert {
margin-bottom: 2px;
}
.vertical-align-middle {
display: inline-flex;
vertical-align: middle;
align-items: center;
}
.alert-error {
color: #821324;
}
.alert-warning {
color: goldenrod;
}
.alert-info {
color: blue;
}
.alert-success {
color: green;
}
.highlight {
color: #003333;
font-style: italic;
}
mat-icon {
margin-right: 0.2em
}
import { NgModule } from '@angular/core';
import { MatIconModule } from '@angular/material/icon';
import { IqbComponentsModule } from 'iqb-components';
import { CommonModule } from '@angular/common';
import { AlertComponent } from './alert.component';
@NgModule({
imports: [
MatIconModule,
IqbComponentsModule,
CommonModule
],
exports: [
AlertComponent
],
declarations: [AlertComponent]
})
export class AlertModule { }
...@@ -36,7 +36,6 @@ import { ...@@ -36,7 +36,6 @@ import {
import { SettingsComponent } from './settings/settings.component'; import { SettingsComponent } from './settings/settings.component';
import { AppConfigComponent } from './settings/app-config.component'; import { AppConfigComponent } from './settings/app-config.component';
import { EditCustomTextsComponent } from './settings/edit-custom-texts.component'; import { EditCustomTextsComponent } from './settings/edit-custom-texts.component';
import { AlertModule } from '../shared/alert/alert.module';
import { EditCustomTextComponent } from './settings/edit-custom-text.component'; import { EditCustomTextComponent } from './settings/edit-custom-text.component';
@NgModule({ @NgModule({
...@@ -79,8 +78,7 @@ import { EditCustomTextComponent } from './settings/edit-custom-text.component'; ...@@ -79,8 +78,7 @@ import { EditCustomTextComponent } from './settings/edit-custom-text.component';
MatCardModule, MatCardModule,
MatNativeDateModule, MatNativeDateModule,
MatDatepickerModule, MatDatepickerModule,
FlexLayoutModule, FlexLayoutModule
AlertModule
], ],
exports: [ exports: [
SuperadminComponent SuperadminComponent
......
...@@ -9,7 +9,6 @@ import { IqbComponentsModule } from 'iqb-components'; ...@@ -9,7 +9,6 @@ import { IqbComponentsModule } from 'iqb-components';
import { IqbFilesUploadComponent } from './iqbFilesUpload/iqbFilesUpload.component'; import { IqbFilesUploadComponent } from './iqbFilesUpload/iqbFilesUpload.component';
import { IqbFilesUploadQueueComponent } from './iqbFilesUploadQueue/iqbFilesUploadQueue.component'; import { IqbFilesUploadQueueComponent } from './iqbFilesUploadQueue/iqbFilesUploadQueue.component';
import { IqbFilesUploadInputForDirective } from './iqbFilesUploadInputFor/iqbFilesUploadInputFor.directive'; import { IqbFilesUploadInputForDirective } from './iqbFilesUploadInputFor/iqbFilesUploadInputFor.directive';
import { AlertModule } from '../../../shared/alert/alert.module';
@NgModule({ @NgModule({
imports: [ imports: [
...@@ -18,8 +17,7 @@ import { AlertModule } from '../../../shared/alert/alert.module'; ...@@ -18,8 +17,7 @@ import { AlertModule } from '../../../shared/alert/alert.module';
MatIconModule, MatIconModule,
MatCardModule, MatCardModule,
IqbComponentsModule, IqbComponentsModule,
CommonModule, CommonModule
AlertModule
], ],
declarations: [ declarations: [
IqbFilesUploadComponent, IqbFilesUploadComponent,
......
...@@ -29,7 +29,6 @@ import { FilesComponent } from './files/files.component'; ...@@ -29,7 +29,6 @@ import { FilesComponent } from './files/files.component';
import { ResultsComponent } from './results/results.component'; import { ResultsComponent } from './results/results.component';
import { SyscheckComponent } from './syscheck/syscheck.component'; import { SyscheckComponent } from './syscheck/syscheck.component';
import { IqbFilesModule } from './files/iqb-files'; import { IqbFilesModule } from './files/iqb-files';
import { AlertModule } from '../shared/alert/alert.module';
@NgModule({ @NgModule({
imports: [ imports: [
...@@ -56,8 +55,7 @@ import { AlertModule } from '../shared/alert/alert.module'; ...@@ -56,8 +55,7 @@ import { AlertModule } from '../shared/alert/alert.module';
IqbComponentsModule, IqbComponentsModule,
MatCardModule, MatCardModule,
FlexLayoutModule, FlexLayoutModule,
IqbFilesModule, IqbFilesModule
AlertModule
], ],
exports: [ exports: [
WorkspaceComponent WorkspaceComponent
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment