feat: Added notification dialog on frontend
This commit is contained in:
@@ -185,7 +185,13 @@ export class AdminCommService {
|
|||||||
},
|
},
|
||||||
outbox: {
|
outbox: {
|
||||||
getSent: () => {
|
getSent: () => {
|
||||||
return this.http.get<any[]>(environment.apiEndpoint+"/admin/notif/outbox", {withCredentials: true})
|
return this.http.get<{_id: string, sentDate: moment.Moment, title: string}[]>(environment.apiEndpoint+"/admin/notif/outbox", {withCredentials: true})
|
||||||
|
},
|
||||||
|
getBody: (id: string) => {
|
||||||
|
return this.http.get(environment.apiEndpoint+`/admin/notif/outbox/${id}/message`, {withCredentials: true, responseType: "text"})
|
||||||
|
},
|
||||||
|
getRcpts: (id: string) => {
|
||||||
|
return this.http.get<{_id: string, uname: string, room?: string, fname?: string, surname?: string}[]>(environment.apiEndpoint+`/admin/notif/outbox/${id}/rcpts`, {withCredentials: true})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
<mat-card>
|
||||||
|
<mat-card-header>
|
||||||
|
<mat-card-title-group>
|
||||||
|
<mat-card-title>
|
||||||
|
{{item.title}}
|
||||||
|
</mat-card-title>
|
||||||
|
<mat-card-subtitle>{{item.sentDate.format('[Wysłano] dddd DD MMMM YYYYr. o HH:mm')}}</mat-card-subtitle>
|
||||||
|
</mat-card-title-group>
|
||||||
|
</mat-card-header>
|
||||||
|
<mat-card-content>
|
||||||
|
<p *ngIf="body">
|
||||||
|
{{body}}
|
||||||
|
</p>
|
||||||
|
<hr>
|
||||||
|
<ul>
|
||||||
|
@for (user of rcpts; track $index) {
|
||||||
|
<li>
|
||||||
|
<span *ngIf="user.room">{{user.room}}: </span>{{user.fname}} {{user.surname}} <span
|
||||||
|
style="color: gray">({{user.uname}})</span>
|
||||||
|
</li>
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
|
</mat-card-content>
|
||||||
|
<mat-card-footer>
|
||||||
|
<mat-card-actions>
|
||||||
|
<button mat-stroked-button (click)="getMessage()" *ngIf="!body">Wczytaj treść</button>
|
||||||
|
<button mat-stroked-button (click)="getRcpts()" *ngIf="!rcpts">Wczytaj odbiorców</button>
|
||||||
|
<mat-spinner diameter="32" color="accent" *ngIf="loading"></mat-spinner>
|
||||||
|
</mat-card-actions>
|
||||||
|
</mat-card-footer>
|
||||||
|
</mat-card>
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
mat-card-title {
|
||||||
|
font-size: 24pt;
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { MessageComponent } from './message.component';
|
||||||
|
|
||||||
|
describe('MessageComponent', () => {
|
||||||
|
let component: MessageComponent;
|
||||||
|
let fixture: ComponentFixture<MessageComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
declarations: [MessageComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(MessageComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import { Component, Input } from '@angular/core';
|
||||||
|
import { AdminCommService } from 'src/app/admin-view/admin-comm.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-message',
|
||||||
|
templateUrl: './message.component.html',
|
||||||
|
styleUrl: './message.component.scss'
|
||||||
|
})
|
||||||
|
export class MessageComponent {
|
||||||
|
@Input() item!: {_id: string, sentDate: moment.Moment, title: string}
|
||||||
|
body?: string
|
||||||
|
rcpts?: {_id: string, uname: string, room?: string, fname?: string, surname?: string}[]
|
||||||
|
loading: boolean = false
|
||||||
|
constructor (readonly acu: AdminCommService) {}
|
||||||
|
|
||||||
|
getMessage() {
|
||||||
|
this.loading = true
|
||||||
|
this.acu.notif.outbox.getBody(this.item._id).subscribe(v => {
|
||||||
|
this.body = v
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
getRcpts() {
|
||||||
|
this.loading = true
|
||||||
|
this.acu.notif.outbox.getRcpts(this.item._id).subscribe(v => {
|
||||||
|
this.rcpts = v
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,28 +1,6 @@
|
|||||||
<p>Wysłane wiadomości:</p>
|
<p>Wysłane wiadomości:</p>
|
||||||
<div class="cardContainer">
|
<div class="cardContainer">
|
||||||
@for (item of messages; track $index) {
|
@for (item of messages; track $index) {
|
||||||
<mat-card>
|
<app-message [item]="item"></app-message>
|
||||||
<mat-card-header>
|
|
||||||
<mat-card-title-group>
|
|
||||||
<mat-card-title>
|
|
||||||
{{item.message.title}}
|
|
||||||
</mat-card-title>
|
|
||||||
<mat-card-subtitle>{{item.sentDate.format('[Wysłano] dddd DD MMMM YYYYr. o HH:mm')}}</mat-card-subtitle>
|
|
||||||
</mat-card-title-group>
|
|
||||||
</mat-card-header>
|
|
||||||
<mat-card-content>
|
|
||||||
<p>
|
|
||||||
{{item.message.body}}
|
|
||||||
</p>
|
|
||||||
<hr>
|
|
||||||
<ul>
|
|
||||||
@for (user of item.rcpt; track $index) {
|
|
||||||
<li>
|
|
||||||
<span *ngIf="user.room">{{user.room}}: </span>{{user.fname}} {{user.surname}} <span style="color: gray" >({{user.uname}})</span>
|
|
||||||
</li>
|
|
||||||
}
|
|
||||||
</ul>
|
|
||||||
</mat-card-content>
|
|
||||||
</mat-card>
|
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
@@ -3,8 +3,4 @@
|
|||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
gap: 1ch;
|
gap: 1ch;
|
||||||
margin: 1ch;
|
margin: 1ch;
|
||||||
}
|
|
||||||
|
|
||||||
mat-card-title {
|
|
||||||
font-size: 24pt;
|
|
||||||
}
|
}
|
||||||
@@ -11,7 +11,11 @@ import * as moment from 'moment';
|
|||||||
})
|
})
|
||||||
export class OutboxComponent implements OnInit {
|
export class OutboxComponent implements OnInit {
|
||||||
|
|
||||||
messages!: any[]
|
messages!: {
|
||||||
|
_id: string;
|
||||||
|
sentDate: moment.Moment;
|
||||||
|
title: string;
|
||||||
|
}[]
|
||||||
|
|
||||||
constructor (private readonly acs: AdminCommService, private toolbar: ToolbarService, private router: Router, private route: ActivatedRoute ) {
|
constructor (private readonly acs: AdminCommService, private toolbar: ToolbarService, private router: Router, private route: ActivatedRoute ) {
|
||||||
this.toolbar.comp = this
|
this.toolbar.comp = this
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import { Link } from '../types/link';
|
|||||||
import { LocalStorageService } from '../services/local-storage.service';
|
import { LocalStorageService } from '../services/local-storage.service';
|
||||||
import { interval } from 'rxjs';
|
import { interval } from 'rxjs';
|
||||||
import { MatSnackBar } from '@angular/material/snack-bar';
|
import { MatSnackBar } from '@angular/material/snack-bar';
|
||||||
|
import { MatDialog } from '@angular/material/dialog';
|
||||||
|
import { NotifDialogComponent } from './notif-dialog/notif-dialog.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-app-view',
|
selector: 'app-app-view',
|
||||||
@@ -25,7 +27,14 @@ export class AppViewComponent implements OnInit {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor (private ac: AuthClient, readonly swPush: SwPush, private us: UpdatesService, private ls: LocalStorageService, private sb: MatSnackBar) {}
|
constructor (
|
||||||
|
private ac: AuthClient,
|
||||||
|
readonly swPush: SwPush,
|
||||||
|
private us: UpdatesService,
|
||||||
|
private ls: LocalStorageService,
|
||||||
|
private sb: MatSnackBar,
|
||||||
|
private dialog: MatDialog
|
||||||
|
) {}
|
||||||
|
|
||||||
subscribeToNotif() {
|
subscribeToNotif() {
|
||||||
if (this.swPush.isEnabled && this.ls.capCheck(4)) {
|
if (this.swPush.isEnabled && this.ls.capCheck(4)) {
|
||||||
@@ -45,6 +54,13 @@ export class AppViewComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
newsCheck() {
|
newsCheck() {
|
||||||
|
if (this.ls.capCheck(4)) {
|
||||||
|
this.us.getNotifCheck().subscribe((s) => {
|
||||||
|
s.forEach(v => {
|
||||||
|
this.dialog.open(NotifDialogComponent, {data: v})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
if (this.ls.newsflag) return;
|
if (this.ls.newsflag) return;
|
||||||
this.us.newsCheck().subscribe((s) => {
|
this.us.newsCheck().subscribe((s) => {
|
||||||
if (s.hash != this.ls.newsCheck.hash) {
|
if (s.hash != this.ls.newsCheck.hash) {
|
||||||
|
|||||||
10
src/app/app-view/notif-dialog/notif-dialog.component.html
Normal file
10
src/app/app-view/notif-dialog/notif-dialog.component.html
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<h1 mat-dialog-title>{{data.message.title}}</h1>
|
||||||
|
<mat-dialog-content>
|
||||||
|
<p>
|
||||||
|
{{data.message.body}}
|
||||||
|
</p>
|
||||||
|
<div>{{data.sentDate.format("[Wysłano] dddd DD MMMM YYYYr. o HH:mm")}}</div>
|
||||||
|
</mat-dialog-content>
|
||||||
|
<mat-dialog-actions align="end">
|
||||||
|
<button mat-raised-button color="primary" (click)="ack()">Odczytano</button>
|
||||||
|
</mat-dialog-actions>
|
||||||
23
src/app/app-view/notif-dialog/notif-dialog.component.spec.ts
Normal file
23
src/app/app-view/notif-dialog/notif-dialog.component.spec.ts
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { NotifDialogComponent } from './notif-dialog.component';
|
||||||
|
|
||||||
|
describe('NotifDialogComponent', () => {
|
||||||
|
let component: NotifDialogComponent;
|
||||||
|
let fixture: ComponentFixture<NotifDialogComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
declarations: [NotifDialogComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(NotifDialogComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
27
src/app/app-view/notif-dialog/notif-dialog.component.ts
Normal file
27
src/app/app-view/notif-dialog/notif-dialog.component.ts
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
import { Component, Inject } from '@angular/core';
|
||||||
|
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||||
|
import * as moment from 'moment';
|
||||||
|
import { UpdatesService } from 'src/app/services/updates.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-notif-dialog',
|
||||||
|
templateUrl: './notif-dialog.component.html',
|
||||||
|
styleUrl: './notif-dialog.component.scss'
|
||||||
|
})
|
||||||
|
export class NotifDialogComponent {
|
||||||
|
|
||||||
|
constructor (
|
||||||
|
@Inject(MAT_DIALOG_DATA) public data: {_id: string, message: {title: string, body: string}, sentDate: moment.Moment},
|
||||||
|
public dialogRef: MatDialogRef<NotifDialogComponent>,
|
||||||
|
private uc: UpdatesService
|
||||||
|
) {
|
||||||
|
data.sentDate = moment(data.sentDate)
|
||||||
|
}
|
||||||
|
|
||||||
|
ack () {
|
||||||
|
this.uc.postInfoAck(this.data._id).subscribe((v) => {
|
||||||
|
this.dialogRef.close()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -83,6 +83,8 @@ import { ExtraComponent } from './app-view/personal/extra/extra.component';
|
|||||||
import { RedirectComponent } from './app-view/personal/extra/redirect/redirect.component';
|
import { RedirectComponent } from './app-view/personal/extra/redirect/redirect.component';
|
||||||
import { OutboxComponent } from './admin-view/notifications/outbox/outbox.component';
|
import { OutboxComponent } from './admin-view/notifications/outbox/outbox.component';
|
||||||
import { ToolbarComponent } from './admin-view/toolbar/toolbar.component';
|
import { ToolbarComponent } from './admin-view/toolbar/toolbar.component';
|
||||||
|
import { MessageComponent } from './admin-view/notifications/outbox/message/message.component';
|
||||||
|
import { NotifDialogComponent } from './app-view/notif-dialog/notif-dialog.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
@@ -130,6 +132,8 @@ import { ToolbarComponent } from './admin-view/toolbar/toolbar.component';
|
|||||||
RedirectComponent,
|
RedirectComponent,
|
||||||
OutboxComponent,
|
OutboxComponent,
|
||||||
ToolbarComponent,
|
ToolbarComponent,
|
||||||
|
MessageComponent,
|
||||||
|
NotifDialogComponent,
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import * as moment from 'moment';
|
|||||||
import { map } from 'rxjs';
|
import { map } from 'rxjs';
|
||||||
import { UKey } from '../types/key';
|
import { UKey } from '../types/key';
|
||||||
import { CleanNote } from '../types/clean-note';
|
import { CleanNote } from '../types/clean-note';
|
||||||
|
import { Status } from '../types/status';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
@@ -55,4 +56,12 @@ export class UpdatesService {
|
|||||||
getClean(date: moment.Moment) {
|
getClean(date: moment.Moment) {
|
||||||
return this.http.get<{grade: number, notes: CleanNote[], tips: string}>(environment.apiEndpoint+`/app/clean/${date.toISOString()}`, {withCredentials: true})
|
return this.http.get<{grade: number, notes: CleanNote[], tips: string}>(environment.apiEndpoint+`/app/clean/${date.toISOString()}`, {withCredentials: true})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getNotifCheck() {
|
||||||
|
return this.http.get<{_id: string, message: {title: string, body: string}, sentDate: moment.Moment}[]>(environment.apiEndpoint+`/app/notif/check`, {withCredentials: true})
|
||||||
|
}
|
||||||
|
|
||||||
|
postInfoAck(id: string) {
|
||||||
|
return this.http.post<Status>(environment.apiEndpoint+`/app/notif/${id}/ack`, undefined, {withCredentials: true})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user