Admin UI initial #47

Merged
amigan merged 12 commits from adminui into trunk 2024-11-22 17:07:14 -05:00
9 changed files with 105 additions and 45 deletions
Showing only changes of commit 55fdeaf086 - Show all commits

View file

@ -1,5 +1,10 @@
import { Component, inject } from '@angular/core';
import { RouterModule, RouterOutlet, RouterLink, RouterLinkActive } from '@angular/router';
import {
RouterModule,
RouterOutlet,
RouterLink,
RouterLinkActive,
} from '@angular/router';
import { CommonModule } from '@angular/common';
import { AuthService } from './login/auth.service';
import { NgIconComponent, provideIcons } from '@ng-icons/core';

View file

@ -12,7 +12,10 @@ import { AuthGuard } from './auth.guard';
export const routes: Routes = [
{ path: 'login', component: LoginComponent },
{ path: '', canActivateChild: [AuthGuard], children: [
{
path: '',
canActivateChild: [AuthGuard],
children: [
{ path: '', component: HomeComponent, pathMatch: 'full' },
{ path: 'talkgroups', component: TalkgroupsComponent },
{ path: 'talkgroups/import', component: ImportComponent },
@ -20,5 +23,6 @@ export const routes: Routes = [
{ path: 'calls', component: CallsComponent },
{ path: 'incidents', component: IncidentsComponent },
{ path: 'alerts', component: AlertsComponent },
]},
],
},
];

View file

@ -1,12 +1,22 @@
import { Router, CanActivateFn } from '@angular/router';
import { AuthService } from './login/auth.service'
import { inject } from '@angular/core';
export const AuthGuard: CanActivateFn = (route, state) => {
const router: Router = inject(Router);
const authSvc: AuthService = inject(AuthService);
if (sessionStorage.getItem('jwt') == null) {
let success = false;
authSvc.refresh()
.subscribe((event) => {
if (event?.status == 200) {
success = true;
}
});
router.navigate(['/login']);
return false;
return success;
} else {
return true;
}
};

View file

@ -41,6 +41,17 @@ export class AuthService {
);
}
refresh(): Observable<HttpResponse<Jwt>> {
return this.http.get<Jwt>('/api/refresh', { withCredentials: true, observe: 'response' }).pipe(
tap((event) => {
if (event.status == 200) {
sessionStorage.setItem('jwt', event.body?.jwt.toString() ?? '');
this.loggedIn = true;
}
}),
);
}
getToken(): string | null {
return sessionStorage.getItem('jwt');
}

View file

@ -52,7 +52,7 @@ export interface Talkgroup {
export interface TalkgroupUI extends Talkgroup {
selected?: boolean;
};
}
export interface TalkgroupUpdate {
id: number;

View file

@ -5,9 +5,15 @@
class="w-full textarea textarea-bordered"
placeholder="Paste RadioReference page here"
formControlName="contents"
cols="40" rows="15"
cols="40"
rows="15"
></textarea>
<input type="number" class="input input-bordered" formControlName="systemID" id="systemID" />
<input
type="number"
class="input input-bordered"
formControlName="systemID"
id="systemID"
/>
<input type="submit" class="btn btn-primary" value="Preview" />
</form>
<button class="btn btn-secondary" (click)="save()">Save</button>
@ -16,7 +22,16 @@
<table class="table">
<thead>
<tr>
<th><input type="checkbox" class="checkbox" [checked]="isAllSelected()" (change)="selectAllTGs($event)" [(ngModel)]="selectAll" name="selectAll" /></th>
<th>
<input
type="checkbox"
class="checkbox"
[checked]="isAllSelected()"
(change)="selectAllTGs($event)"
[(ngModel)]="selectAll"
name="selectAll"
/>
</th>
<th>Sys</th>
<th>Sys ID</th>
<th>Group</th>
@ -29,7 +44,14 @@
<tbody>
@for (tg of tgs; track tg.id) {
<tr>
<td><input type="checkbox" class="checkbox" [(ngModel)]="tg.selected" value="{{tg.name}}" (change)="isAllSelected()">
<td>
<input
type="checkbox"
class="checkbox"
[(ngModel)]="tg.selected"
value="{{ tg.name }}"
(change)="isAllSelected()"
/>
</td>
<td>{{ tg.system?.name }}</td>
<td>{{ tg.system?.id }}</td>
@ -37,7 +59,7 @@
<td>{{ tg.alpha_tag }}</td>
<td>{{ tg.name }}</td>
<td>{{ tg.tgid }}</td>
<td>{{ tg?.metadata?.encrypted ? 'E' : '' }}</td>
<td>{{ tg?.metadata?.encrypted ? "E" : "" }}</td>
</tr>
}
</tbody>

View file

@ -1,7 +1,12 @@
import { Component, inject } from '@angular/core';
import { TalkgroupService } from '../talkgroups.service';
import { Talkgroup, TalkgroupUI, TalkgroupUpdate } from '../../talkgroup';
import { FormGroup, FormControl, ReactiveFormsModule, FormsModule } from '@angular/forms';
import {
FormGroup,
FormControl,
ReactiveFormsModule,
FormsModule,
} from '@angular/forms';
import { CommonModule } from '@angular/common';
import { Router, ActivatedRoute } from '@angular/router';
import { catchError, of } from 'rxjs';
@ -33,7 +38,8 @@ export class ImportComponent {
submit() {
let content = this.form.controls['contents'].value;
let sysID = Number(this.form.controls['systemID'].value);
this.tgService.importRR(sysID, content)
this.tgService
.importRR(sysID, content)
.pipe(
catchError(() => {
return of(null);
@ -46,11 +52,11 @@ export class ImportComponent {
}
isAllSelected() {
return this.tgs.every(_ => _.selected);
return this.tgs.every((_) => _.selected);
}
selectAllTGs(ev: any) {
this.tgs.forEach(x => x.selected = ev.target.checked);
this.tgs.forEach((x) => (x.selected = ev.target.checked));
}
save() {
@ -62,8 +68,9 @@ export class ImportComponent {
toImport.push(ct);
}
});
this.tgService.putTalkgroups(sysID, toImport).
pipe(
this.tgService
.putTalkgroups(sysID, toImport)
.pipe(
catchError(() => {
return of(null);
}),
@ -71,7 +78,5 @@ export class ImportComponent {
.subscribe((event) => {
this.tgs = event!;
});
}
}

View file

@ -18,7 +18,7 @@
<td>{{ tg.system?.id }}</td>
<td>{{ tg.name }}</td>
<td>{{ tg.tgid }}</td>
<td>{{ tg?.learned ? 'Y' : '' }}</td>
<td>{{ tg?.learned ? "Y" : "" }}</td>
<td>
<a routerLink="/talkgroups/{{ tg.system?.id }}/{{ tg.tgid }}"
><ng-icon name="ionCreateOutline"></ng-icon

View file

@ -19,8 +19,11 @@ export class TalkgroupService {
}
importRR(sysID: number, content: string): Observable<Talkgroup[]> {
return this.http.post<Talkgroup[]>('/api/talkgroup/import',
{systemID: sysID, type: 'radioreference', body: content});
return this.http.post<Talkgroup[]>('/api/talkgroup/import', {
systemID: sysID,
type: 'radioreference',
body: content,
});
}
putTalkgroup(tu: TalkgroupUpdate): Observable<Talkgroup> {
@ -30,10 +33,10 @@ export class TalkgroupService {
);
}
putTalkgroups(sysID: Number, tgs: TalkgroupUpdate[]): Observable<Talkgroup[]> {
return this.http.put<Talkgroup[]>(
`/api/talkgroup/${sysID}`,
tgs,
);
putTalkgroups(
sysID: Number,
tgs: TalkgroupUpdate[],
): Observable<Talkgroup[]> {
return this.http.put<Talkgroup[]>(`/api/talkgroup/${sysID}`, tgs);
}
}