feat: Added notifications outbox to admin panel
This commit is contained in:
@@ -182,6 +182,11 @@ export class AdminCommService {
|
|||||||
},
|
},
|
||||||
getGroups: () => {
|
getGroups: () => {
|
||||||
return this.http.get<Group[]>(environment.apiEndpoint+"/admin/notif/groups", {withCredentials: true})
|
return this.http.get<Group[]>(environment.apiEndpoint+"/admin/notif/groups", {withCredentials: true})
|
||||||
|
},
|
||||||
|
outbox: {
|
||||||
|
getSent: () => {
|
||||||
|
return this.http.get<any[]>(environment.apiEndpoint+"/admin/notif/outbox", {withCredentials: true})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|||||||
@@ -1,17 +1,4 @@
|
|||||||
<mat-toolbar color="accent">
|
<app-toolbar [drawer]="drawer"/>
|
||||||
<button mat-icon-button (click)="drawer.toggle()"><mat-icon>menu</mat-icon></button>
|
|
||||||
<span>{{title.getTitle()}}</span>
|
|
||||||
<span style="flex: 1 1 auto"></span>
|
|
||||||
<button mat-icon-button *ngIf="toolbar.menu" [matMenuTriggerFor]="menu"><mat-icon>more_vert</mat-icon></button>
|
|
||||||
</mat-toolbar>
|
|
||||||
<mat-menu #menu="matMenu">
|
|
||||||
@for (item of toolbar.menu; track $index) {
|
|
||||||
<button mat-menu-item *ngIf="item.check" (click)="toolbar.comp[item.fn]()">
|
|
||||||
<mat-icon *ngIf="item.icon">{{item.icon}}</mat-icon>
|
|
||||||
<span>{{item.title}}</span>
|
|
||||||
</button>
|
|
||||||
}
|
|
||||||
</mat-menu>
|
|
||||||
<mat-sidenav-container>
|
<mat-sidenav-container>
|
||||||
<mat-sidenav #drawer mode="over" autoFocus="false">
|
<mat-sidenav #drawer mode="over" autoFocus="false">
|
||||||
<mat-nav-list>
|
<mat-nav-list>
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import { Title } from '@angular/platform-browser';
|
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { LocalStorageService } from '../services/local-storage.service';
|
import { LocalStorageService } from '../services/local-storage.service';
|
||||||
import { Link } from '../types/link';
|
import { Link } from '../types/link';
|
||||||
import { ToolbarService } from './toolbar.service';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-admin-view',
|
selector: 'app-admin-view',
|
||||||
@@ -26,7 +24,7 @@ export class AdminViewComponent {
|
|||||||
public get LINKS(): Link[] {
|
public get LINKS(): Link[] {
|
||||||
return this._LINKS.filter(v => v.enabled);
|
return this._LINKS.filter(v => v.enabled);
|
||||||
}
|
}
|
||||||
constructor(readonly title: Title, readonly router: Router, readonly ls: LocalStorageService, protected toolbar: ToolbarService) { }
|
constructor(readonly router: Router, readonly ls: LocalStorageService) { }
|
||||||
goNormal() {
|
goNormal() {
|
||||||
this.router.navigateByUrl('app')
|
this.router.navigateByUrl('app')
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { ToolbarService } from '../../toolbar.service';
|
import { ToolbarService } from '../../toolbar/toolbar.service';
|
||||||
import { Router, ActivatedRoute } from '@angular/router';
|
import { Router, ActivatedRoute } from '@angular/router';
|
||||||
import { MatTableDataSource } from '@angular/material/table';
|
import { MatTableDataSource } from '@angular/material/table';
|
||||||
import { AdminCommService } from '../../admin-comm.service';
|
import { AdminCommService } from '../../admin-comm.service';
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import * as moment from 'moment';
|
|||||||
import { FormArray, FormBuilder } from '@angular/forms';
|
import { FormArray, FormBuilder } from '@angular/forms';
|
||||||
import { weekendFilter } from 'src/app/fd.da';
|
import { weekendFilter } from 'src/app/fd.da';
|
||||||
import { MatSnackBar } from '@angular/material/snack-bar';
|
import { MatSnackBar } from '@angular/material/snack-bar';
|
||||||
import { ToolbarService } from '../toolbar.service';
|
import { ToolbarService } from '../toolbar/toolbar.service';
|
||||||
import { ActivatedRoute, Router } from '@angular/router';
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
import { MatDialog } from '@angular/material/dialog';
|
import { MatDialog } from '@angular/material/dialog';
|
||||||
import { AttendenceComponent } from './attendence/attendence.component';
|
import { AttendenceComponent } from './attendence/attendence.component';
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core';
|
import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core';
|
||||||
import { ToolbarService } from '../../toolbar.service';
|
import { ToolbarService } from '../../toolbar/toolbar.service';
|
||||||
import { ActivatedRoute, Router } from '@angular/router';
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
import { AdminCommService } from '../../admin-comm.service';
|
import { AdminCommService } from '../../admin-comm.service';
|
||||||
import * as moment from 'moment';
|
import * as moment from 'moment';
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
<!-- TODO: Remake the notifications module -->
|
|
||||||
<form [formGroup]="form" (ngSubmit)="submit()">
|
<form [formGroup]="form" (ngSubmit)="submit()">
|
||||||
<div formGroupName="recp">
|
<div formGroupName="recp">
|
||||||
<mat-radio-group formControlName="type">
|
<mat-radio-group formControlName="type">
|
||||||
|
|||||||
@@ -1,20 +1,31 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnDestroy, OnInit } from '@angular/core';
|
||||||
import { FormControl, FormGroup } from '@angular/forms';
|
import { FormControl, FormGroup } from '@angular/forms';
|
||||||
import { AdminCommService } from '../admin-comm.service';
|
import { AdminCommService } from '../admin-comm.service';
|
||||||
import { Notification } from 'src/app/types/notification';
|
import { Notification } from 'src/app/types/notification';
|
||||||
import { Group } from 'src/app/types/group';
|
import { Group } from 'src/app/types/group';
|
||||||
import { LocalStorageService } from 'src/app/services/local-storage.service';
|
import { LocalStorageService } from 'src/app/services/local-storage.service';
|
||||||
|
import { ToolbarService } from '../toolbar/toolbar.service';
|
||||||
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-notifications',
|
selector: 'app-notifications',
|
||||||
templateUrl: './notifications.component.html',
|
templateUrl: './notifications.component.html',
|
||||||
styleUrls: ['./notifications.component.scss']
|
styleUrls: ['./notifications.component.scss']
|
||||||
})
|
})
|
||||||
export class NotificationsComponent implements OnInit {
|
export class NotificationsComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
groups!: Group[]
|
groups!: Group[]
|
||||||
|
|
||||||
constructor (private readonly acs: AdminCommService, readonly ls: LocalStorageService) { }
|
constructor (private readonly acs: AdminCommService, readonly ls: LocalStorageService, private toolbar: ToolbarService, private router: Router, private route: ActivatedRoute ) {
|
||||||
|
this.toolbar.comp = this
|
||||||
|
this.toolbar.menu = [
|
||||||
|
{ title: "Wysłane", fn: "outbox", icon: "outbox" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
outbox() {
|
||||||
|
this.router.navigate(["outbox"], { relativeTo: this.route })
|
||||||
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.acs.notif.getGroups().subscribe((v) => {
|
this.acs.notif.getGroups().subscribe((v) => {
|
||||||
@@ -22,6 +33,15 @@ export class NotificationsComponent implements OnInit {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ngOnDestroy(): void {
|
||||||
|
this.toolbar.comp = undefined
|
||||||
|
this.toolbar.menu = undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
public inbox() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
success?: { sent: number; possible: number; };
|
success?: { sent: number; possible: number; };
|
||||||
|
|
||||||
form = new FormGroup<NotificationForm>({
|
form = new FormGroup<NotificationForm>({
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<p>Wysłane wiadomości:</p>
|
||||||
|
<div class="cardContainer">
|
||||||
|
@for (item of messages; track $index) {
|
||||||
|
<mat-card>
|
||||||
|
<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>
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
.cardContainer {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 1ch;
|
||||||
|
margin: 1ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
mat-card-title {
|
||||||
|
font-size: 24pt;
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { OutboxComponent } from './outbox.component';
|
||||||
|
|
||||||
|
describe('OutboxComponent', () => {
|
||||||
|
let component: OutboxComponent;
|
||||||
|
let fixture: ComponentFixture<OutboxComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
declarations: [OutboxComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(OutboxComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
38
src/app/admin-view/notifications/outbox/outbox.component.ts
Normal file
38
src/app/admin-view/notifications/outbox/outbox.component.ts
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { AdminCommService } from '../../admin-comm.service';
|
||||||
|
import { Router, ActivatedRoute } from '@angular/router';
|
||||||
|
import { ToolbarService } from '../../toolbar/toolbar.service';
|
||||||
|
import * as moment from 'moment';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-outbox',
|
||||||
|
templateUrl: './outbox.component.html',
|
||||||
|
styleUrl: './outbox.component.scss'
|
||||||
|
})
|
||||||
|
export class OutboxComponent implements OnInit {
|
||||||
|
|
||||||
|
messages!: any[]
|
||||||
|
|
||||||
|
constructor (private readonly acs: AdminCommService, private toolbar: ToolbarService, private router: Router, private route: ActivatedRoute ) {
|
||||||
|
this.toolbar.comp = this
|
||||||
|
this.toolbar.menu = [
|
||||||
|
{ title: "Powiadomienia", fn: "goBack", icon: "arrow_back" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
goBack() {
|
||||||
|
this.router.navigate(['../'], {relativeTo: this.route})
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.acs.notif.outbox.getSent().subscribe((v) => {
|
||||||
|
this.messages = v.map(i => {
|
||||||
|
return {
|
||||||
|
...i,
|
||||||
|
sentDate: moment(i.sentDate)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
14
src/app/admin-view/toolbar/toolbar.component.html
Normal file
14
src/app/admin-view/toolbar/toolbar.component.html
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<mat-toolbar color="accent">
|
||||||
|
<button mat-icon-button (click)="drawer.toggle()"><mat-icon>menu</mat-icon></button>
|
||||||
|
<span>{{title.getTitle()}}</span>
|
||||||
|
<span style="flex: 1 1 auto"></span>
|
||||||
|
<button mat-icon-button *ngIf="toolbar.menu" [matMenuTriggerFor]="menu" (click)="openMenu()"><mat-icon>more_vert</mat-icon></button>
|
||||||
|
</mat-toolbar>
|
||||||
|
<mat-menu #menu="matMenu">
|
||||||
|
@for (item of _menu; track $index) {
|
||||||
|
<button mat-menu-item *ngIf="item.check ?? true" (click)="toolbar.comp[item.fn]()">
|
||||||
|
<mat-icon *ngIf="item.icon">{{item.icon}}</mat-icon>
|
||||||
|
<span>{{item.title}}</span>
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
</mat-menu>
|
||||||
0
src/app/admin-view/toolbar/toolbar.component.scss
Normal file
0
src/app/admin-view/toolbar/toolbar.component.scss
Normal file
23
src/app/admin-view/toolbar/toolbar.component.spec.ts
Normal file
23
src/app/admin-view/toolbar/toolbar.component.spec.ts
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { ToolbarComponent } from './toolbar.component';
|
||||||
|
|
||||||
|
describe('ToolbarComponent', () => {
|
||||||
|
let component: ToolbarComponent;
|
||||||
|
let fixture: ComponentFixture<ToolbarComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
declarations: [ToolbarComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(ToolbarComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
26
src/app/admin-view/toolbar/toolbar.component.ts
Normal file
26
src/app/admin-view/toolbar/toolbar.component.ts
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import { Component, Input, ViewChild } from '@angular/core';
|
||||||
|
import { MatDrawer } from '@angular/material/sidenav';
|
||||||
|
import { Title } from '@angular/platform-browser';
|
||||||
|
import { ToolbarService } from './toolbar.service';
|
||||||
|
import { MatMenuTrigger } from '@angular/material/menu';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-toolbar',
|
||||||
|
templateUrl: './toolbar.component.html',
|
||||||
|
styleUrl: './toolbar.component.scss'
|
||||||
|
})
|
||||||
|
export class ToolbarComponent {
|
||||||
|
@Input() drawer!: MatDrawer;
|
||||||
|
@ViewChild(MatMenuTrigger) trigger!: MatMenuTrigger;
|
||||||
|
|
||||||
|
protected _menu?: typeof this.toolbar.menu
|
||||||
|
|
||||||
|
constructor(readonly title: Title, protected toolbar: ToolbarService) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
openMenu () {
|
||||||
|
this._menu = this.toolbar.menu
|
||||||
|
this.trigger.openMenu()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,9 +6,6 @@ import { Injectable } from '@angular/core';
|
|||||||
export class ToolbarService {
|
export class ToolbarService {
|
||||||
|
|
||||||
public comp?: any;
|
public comp?: any;
|
||||||
public menu?: {title: string, check: boolean, icon?: string, fn: string}[]
|
public menu?: {title: string, check?: boolean, icon?: string, fn: string}[]
|
||||||
|
|
||||||
constructor() { }
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -19,6 +19,7 @@ import { SummaryComponent } from './admin-view/grades/summary/summary.component'
|
|||||||
import { SettingsComponent } from './admin-view/settings/settings.component';
|
import { SettingsComponent } from './admin-view/settings/settings.component';
|
||||||
import { AttendenceSummaryComponent } from './admin-view/grades/attendence-summary/attendence-summary.component';
|
import { AttendenceSummaryComponent } from './admin-view/grades/attendence-summary/attendence-summary.component';
|
||||||
import { NotificationsComponent } from './admin-view/notifications/notifications.component';
|
import { NotificationsComponent } from './admin-view/notifications/notifications.component';
|
||||||
|
import { OutboxComponent } from './admin-view/notifications/outbox/outbox.component';
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
{path: "", redirectTo: "login", pathMatch: "full"},
|
{path: "", redirectTo: "login", pathMatch: "full"},
|
||||||
@@ -33,7 +34,10 @@ const routes: Routes = [
|
|||||||
{path: "news", title: "Edytowanie wiadomości", component: NewsEditComponent},
|
{path: "news", title: "Edytowanie wiadomości", component: NewsEditComponent},
|
||||||
{path: "menu", title: "Edytowanie jadłospisu", component: MenuNewComponent},
|
{path: "menu", title: "Edytowanie jadłospisu", component: MenuNewComponent},
|
||||||
{path: "accounts", title: "Użytkownicy", component: AccountMgmtComponent},
|
{path: "accounts", title: "Użytkownicy", component: AccountMgmtComponent},
|
||||||
{path: "notifications", title: "Powiadomienia", component: NotificationsComponent},
|
{path: "notifications", children: [
|
||||||
|
{path: "", pathMatch: "full", title: "Powiadomienia", component: NotificationsComponent},
|
||||||
|
{path: "outbox", title: "Wysłane", component: OutboxComponent}
|
||||||
|
]},
|
||||||
{path: "groups", title: "Grupy", component: GroupsComponent},
|
{path: "groups", title: "Grupy", component: GroupsComponent},
|
||||||
{path: "keys", title: "Klucze", component: AdminKeyComponent},
|
{path: "keys", title: "Klucze", component: AdminKeyComponent},
|
||||||
{path: "grades", children: [
|
{path: "grades", children: [
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
<h1>Domyślna strona po logowaniu</h1>
|
<h1 mat-dialog-title>Domyślna strona po logowaniu</h1>
|
||||||
<mat-dialog-content>
|
<mat-dialog-content>
|
||||||
<p>Wpisz link względem /ipwa/ w poniższym polu.</p>
|
<p>Wpisz link względem /ipwa/ w poniższym polu.</p>
|
||||||
<p>Przykład: /app/menu</p>
|
<p>Przykład: /app/menu</p>
|
||||||
|
<p style="color: red">Jeśli nie wiesz co tu wpisać, najlepiej nie zmieniaj tego ustawienia</p>
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<input matInput type="text" [(ngModel)]="redirect">
|
<input matInput type="text" [(ngModel)]="redirect">
|
||||||
<mat-label>Link</mat-label>
|
<mat-label>Link</mat-label>
|
||||||
|
|||||||
@@ -81,6 +81,8 @@ import { AboutComponent } from './app-view/personal/about/about.component';
|
|||||||
import { environment } from 'src/environments/environment';
|
import { environment } from 'src/environments/environment';
|
||||||
import { ExtraComponent } from './app-view/personal/extra/extra.component';
|
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 { ToolbarComponent } from './admin-view/toolbar/toolbar.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
@@ -126,6 +128,8 @@ import { RedirectComponent } from './app-view/personal/extra/redirect/redirect.c
|
|||||||
AboutComponent,
|
AboutComponent,
|
||||||
ExtraComponent,
|
ExtraComponent,
|
||||||
RedirectComponent,
|
RedirectComponent,
|
||||||
|
OutboxComponent,
|
||||||
|
ToolbarComponent,
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
|
|||||||
Reference in New Issue
Block a user