Преглед изворни кода

integrated ngbToastModule; first draft of alert-themed toasts (WIP)

Christian Kahlau пре 2 година
родитељ
комит
0280851020

+ 13 - 0
ng/src/app/app.component.html

@@ -9,3 +9,16 @@
 <ng-container>
   <app-confirm-modal *ngFor="let modal of cmpService.confirmModals" (ref)="modal.ref($event)"></app-confirm-modal>
 </ng-container>
+
+<div class="position-fixed top-0 end-0 m-1" style="z-index: 1200">
+  <ngb-toast
+    *ngFor="let toast of toastService.toasts"
+    [header]="toast.header"
+    [autohide]="true"
+    [delay]="toast.delay || 5000"
+    (hidden)="toastService.remove(toast.id)">
+    <div class="alert alert-{{ toast.alertClass }}">
+      {{ toast.message }}
+    </div>
+  </ngb-toast>
+</div>

+ 2 - 1
ng/src/app/app.component.ts

@@ -2,6 +2,7 @@ import { Component, OnInit } from '@angular/core';
 
 import { ComponentService } from './services/component.service';
 import { ServerApiService } from './services/server-api.service';
+import { ToastService } from './services/toast.service';
 
 @Component({
   selector: 'app-root',
@@ -9,7 +10,7 @@ import { ServerApiService } from './services/server-api.service';
   styleUrls: ['./app.component.scss']
 })
 export class AppComponent implements OnInit {
-  constructor(private apiService: ServerApiService, public cmpService: ComponentService) {}
+  constructor(private apiService: ServerApiService, public cmpService: ComponentService, public toastService: ToastService) {}
 
   async ngOnInit() {
     try {

+ 2 - 1
ng/src/app/app.module.ts

@@ -3,7 +3,7 @@ import { NgModule } from '@angular/core';
 import { FormsModule, ReactiveFormsModule } from '@angular/forms';
 import { BrowserModule } from '@angular/platform-browser';
 import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
-import { NgbAccordionModule, NgbModalModule, NgbNavModule } from '@ng-bootstrap/ng-bootstrap';
+import { NgbAccordionModule, NgbModalModule, NgbNavModule, NgbToastModule } from '@ng-bootstrap/ng-bootstrap';
 import { NgChartsModule } from 'ng2-charts';
 
 import { AppRoutingModule } from './app-routing.module';
@@ -65,6 +65,7 @@ import { StatusColorPipe } from './pipes/status-color.pipe';
     NgbAccordionModule,
     NgbModalModule,
     NgbNavModule,
+    NgbToastModule,
     NgChartsModule,
     ReactiveFormsModule
   ],

+ 5 - 3
ng/src/app/pages/admin-panel/admin-service-checks-page/admin-service-checks-page.component.ts

@@ -1,4 +1,5 @@
 import { Component, ViewChild } from '@angular/core';
+import { ValidationErrors } from '@angular/forms';
 import { ActivatedRoute, Router } from '@angular/router';
 import { faAngleRight, faPlus, faSave, faServer, faTrashAlt } from '@fortawesome/free-solid-svg-icons';
 import { NgbAccordion, NgbPanelChangeEvent } from '@ng-bootstrap/ng-bootstrap';
@@ -7,7 +8,7 @@ import { ServiceCheckFormComponent } from 'src/app/components/service-check-form
 import { ComponentService } from 'src/app/services/component.service';
 import { ServiceApiService } from 'src/app/services/service-api.service';
 import { ServerApiService } from 'src/app/services/server-api.service';
-import { ValidationErrors } from '@angular/forms';
+import { ToastService } from 'src/app/services/toast.service';
 
 @Component({
   selector: 'app-admin-service-checks-page',
@@ -33,7 +34,8 @@ export class AdminServiceChecksPageComponent {
     private cmpService: ComponentService,
     route: ActivatedRoute,
     private router: Router,
-    private serviceApi: ServiceApiService
+    private serviceApi: ServiceApiService,
+    private toastService: ToastService
   ) {
     apiService.serverConfigs$.subscribe(data => {
       this.serverConfigs = data;
@@ -128,7 +130,7 @@ export class AdminServiceChecksPageComponent {
       if (error.type === 'validation') {
         const invalid: ValidationErrors = error.errors;
         Object.entries(invalid).forEach(entry => {
-          this.cmpService.openConfirmModal({ buttonTitles: { no: null, yes: 'OK' }, modalContent: { title: entry[0], message: entry[1] } });
+          this.toastService.error(entry[1], entry[0], 180000);
         });
       }
       console.error(error);

+ 16 - 0
ng/src/app/services/toast.service.spec.ts

@@ -0,0 +1,16 @@
+import { TestBed } from '@angular/core/testing';
+
+import { ToastService } from './toast.service';
+
+describe('ToastService', () => {
+  let service: ToastService;
+
+  beforeEach(() => {
+    TestBed.configureTestingModule({});
+    service = TestBed.inject(ToastService);
+  });
+
+  it('should be created', () => {
+    expect(service).toBeTruthy();
+  });
+});

+ 53 - 0
ng/src/app/services/toast.service.ts

@@ -0,0 +1,53 @@
+import { Injectable } from '@angular/core';
+import { v4 as uuid } from 'uuid';
+
+interface ToastOptions {
+  id: string;
+  header: string;
+  message: string;
+  alertClass: 'danger' | 'warning' | 'info';
+  delay?: number;
+}
+
+@Injectable({
+  providedIn: 'root'
+})
+export class ToastService {
+  public toasts: ToastOptions[] = [];
+
+  constructor() {}
+
+  public error(message: string, header: string, delay?: number) {
+    this.toasts.push({
+      id: uuid(),
+      message,
+      header,
+      alertClass: 'danger',
+      delay
+    });
+  }
+
+  public warning(message: string, header: string, delay?: number) {
+    this.toasts.push({
+      id: uuid(),
+      message,
+      header,
+      alertClass: 'warning',
+      delay
+    });
+  }
+  public info(message: string, header: string, delay?: number) {
+    this.toasts.push({
+      id: uuid(),
+      message,
+      header,
+      alertClass: 'info',
+      delay
+    });
+  }
+
+  public remove(id: string) {
+    const idx = this.toasts.findIndex(t => t.id === id);
+    if (idx >= 0) this.toasts.splice(idx, 1);
+  }
+}

+ 3 - 1
ng/tsconfig.app.json

@@ -3,7 +3,9 @@
   "extends": "./tsconfig.json",
   "compilerOptions": {
     "outDir": "./out-tsc/app",
-    "types": []
+    "types": [
+      "@angular/localize"
+    ]
   },
   "files": ["src/main.ts", "src/polyfills.ts"],
   "include": ["src/**/*.d.ts", "../common/**/*.d.ts"]

+ 3 - 0
ng/tsconfig.json

@@ -22,6 +22,9 @@
       "es2020",
       "dom"
     ],
+    "types": [
+      "@angular/localize"
+    ],
     "useDefineForClassFields": false
   },
   "angularCompilerOptions": {

+ 2 - 1
ng/tsconfig.spec.json

@@ -4,7 +4,8 @@
   "compilerOptions": {
     "outDir": "./out-tsc/spec",
     "types": [
-      "jasmine"
+      "jasmine",
+      "@angular/localize"
     ]
   },
   "files": [