kindof working
This commit is contained in:
parent
67905c92be
commit
de361cf23c
22 changed files with 320 additions and 88 deletions
|
@ -8,9 +8,8 @@ describe('AlertsComponent', () => {
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
imports: [AlertsComponent]
|
imports: [AlertsComponent],
|
||||||
})
|
}).compileComponents();
|
||||||
.compileComponents();
|
|
||||||
|
|
||||||
fixture = TestBed.createComponent(AlertsComponent);
|
fixture = TestBed.createComponent(AlertsComponent);
|
||||||
component = fixture.componentInstance;
|
component = fixture.componentInstance;
|
||||||
|
|
|
@ -5,8 +5,6 @@ import { Component } from '@angular/core';
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [],
|
imports: [],
|
||||||
templateUrl: './alerts.component.html',
|
templateUrl: './alerts.component.html',
|
||||||
styleUrl: './alerts.component.css'
|
styleUrl: './alerts.component.css',
|
||||||
})
|
})
|
||||||
export class AlertsComponent {
|
export class AlertsComponent {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,12 +1,26 @@
|
||||||
<!-- Navbar -->
|
<!-- Navbar -->
|
||||||
<nav class="navbar justify-between bg-base-300">
|
<nav class="navbar justify-between bg-base-300">
|
||||||
<!-- Logo -->
|
<!-- Logo -->
|
||||||
<a class="btn btn-ghost text-lg">
|
<a class="btn btn-ghost text-lg btn-square">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-6">
|
<svg
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M15.362 5.214A8.252 8.252 0 0 1 12 21 8.25 8.25 0 0 1 6.038 7.047 8.287 8.287 0 0 0 9 9.601a8.983 8.983 0 0 1 3.361-6.867 8.21 8.21 0 0 0 3 2.48Z" />
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M12 18a3.75 3.75 0 0 0 .495-7.468 5.99 5.99 0 0 0-1.925 3.547 5.975 5.975 0 0 1-2.133-1.001A3.75 3.75 0 0 0 12 18Z" />
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
stroke-width="1.5"
|
||||||
|
stroke="currentColor"
|
||||||
|
class="size-6"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
d="M15.362 5.214A8.252 8.252 0 0 1 12 21 8.25 8.25 0 0 1 6.038 7.047 8.287 8.287 0 0 0 9 9.601a8.983 8.983 0 0 1 3.361-6.867 8.21 8.21 0 0 0 3 2.48Z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
d="M12 18a3.75 3.75 0 0 0 .495-7.468 5.99 5.99 0 0 0-1.925 3.547 5.975 5.975 0 0 1-2.133-1.001A3.75 3.75 0 0 0 12 18Z"
|
||||||
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<!-- Menu for mobile -->
|
<!-- Menu for mobile -->
|
||||||
|
@ -15,7 +29,10 @@
|
||||||
<i class="fa-solid fa-bars text-lg"></i>
|
<i class="fa-solid fa-bars text-lg"></i>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<ul tabindex="0" class="dropdown-content menu z-[1] bg-base-200 p-6 rounded-box shadow w-56 gap-2">
|
<ul
|
||||||
|
tabindex="0"
|
||||||
|
class="dropdown-content menu z-[1] bg-base-200 p-6 rounded-box shadow w-56 gap-2"
|
||||||
|
>
|
||||||
<li><a>Item</a></li>
|
<li><a>Item</a></li>
|
||||||
<a class="btn btn-sm btn-primary">Do</a>
|
<a class="btn btn-sm btn-primary">Do</a>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -24,31 +41,60 @@
|
||||||
<!-- Menu for desktop -->
|
<!-- Menu for desktop -->
|
||||||
<ul class="hidden menu sm:menu-horizontal gap-2">
|
<ul class="hidden menu sm:menu-horizontal gap-2">
|
||||||
<li><a>Item</a></li>
|
<li><a>Item</a></li>
|
||||||
<a class="btn btn-sm btn-primary">Do</a>
|
@if (auth.loggedIn) {
|
||||||
|
<a (click)="logout()" class="btn btn-sm btn-primary">Logout</a>
|
||||||
|
}
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
<div class="flex overflow-hidden relative">
|
<div class="flex overflow-hidden relative">
|
||||||
<!-- Sidebar -->
|
<!-- Sidebar -->
|
||||||
<aside class="h-screen sticky top-0 flex flex-col overflow-y-auto gap-2 py-6 px-2 bg-base-200">
|
<aside
|
||||||
<a class="btn btn-square btn-ghost btn-secondary text-xl" title="Home" routerLink="/home" routerLinkActive="btn-active">
|
class="h-screen sticky top-0 flex flex-col overflow-y-auto gap-2 py-6 px-2 bg-base-200"
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
class="btn btn-square btn-ghost btn-secondary text-xl"
|
||||||
|
title="Home"
|
||||||
|
routerLink="/home"
|
||||||
|
routerLinkActive="btn-active"
|
||||||
|
>
|
||||||
<ng-icon name="ionHome"></ng-icon>
|
<ng-icon name="ionHome"></ng-icon>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<a routerLink="/calls" routerLinkActive="btn-active" class="btn btn-ghost btn-secondary text-xl" title="Calls">
|
<a
|
||||||
|
routerLink="/calls"
|
||||||
|
routerLinkActive="btn-active"
|
||||||
|
class="btn btn-ghost btn-secondary text-xl"
|
||||||
|
title="Calls"
|
||||||
|
>
|
||||||
<ng-icon name="ionMegaphoneOutline"></ng-icon>
|
<ng-icon name="ionMegaphoneOutline"></ng-icon>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<a class="btn btn-square btn-ghost text-xl" title="Talkgroups" routerLink="/talkgroups" routerLinkActive="btn-active">
|
<a
|
||||||
|
class="btn btn-square btn-ghost text-xl"
|
||||||
|
title="Talkgroups"
|
||||||
|
routerLink="/talkgroups"
|
||||||
|
routerLinkActive="btn-active"
|
||||||
|
>
|
||||||
<ng-icon name="ionChatbubbles"></ng-icon>
|
<ng-icon name="ionChatbubbles"></ng-icon>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<div class="divider my-0"></div>
|
<div class="divider my-0"></div>
|
||||||
|
|
||||||
<a class="btn btn-square btn-ghost text-xl" title="Incidents" routerLink="/incidents" routerLinkActive="btn-active">
|
<a
|
||||||
|
class="btn btn-square btn-ghost text-xl"
|
||||||
|
title="Incidents"
|
||||||
|
routerLink="/incidents"
|
||||||
|
routerLinkActive="btn-active"
|
||||||
|
>
|
||||||
<ng-icon name="ionNewspaperOutline"></ng-icon>
|
<ng-icon name="ionNewspaperOutline"></ng-icon>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<a class="btn btn-square btn-ghost text-xl" title="Alerts" routerLink="/alerts" routerLinkActive="btn-active">
|
<a
|
||||||
|
class="btn btn-square btn-ghost text-xl"
|
||||||
|
title="Alerts"
|
||||||
|
routerLink="/alerts"
|
||||||
|
routerLinkActive="btn-active"
|
||||||
|
>
|
||||||
<ng-icon name="ionAlertCircleOutline"></ng-icon>
|
<ng-icon name="ionAlertCircleOutline"></ng-icon>
|
||||||
</a>
|
</a>
|
||||||
<div class="divider my-0"></div>
|
<div class="divider my-0"></div>
|
||||||
|
@ -57,7 +103,7 @@
|
||||||
<ng-icon name="ionRadioOutline"></ng-icon>
|
<ng-icon name="ionRadioOutline"></ng-icon>
|
||||||
</a>
|
</a>
|
||||||
</aside>
|
</aside>
|
||||||
<div class="container mx-auto px-4">
|
<div class="container mx-auto px-4 flex overflow-auto">
|
||||||
<router-outlet />
|
<router-outlet />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -3,17 +3,47 @@ import { RouterModule, RouterOutlet, RouterLink } from '@angular/router';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { AuthService } from './login/auth.service';
|
import { AuthService } from './login/auth.service';
|
||||||
import { NgIconComponent, provideIcons } from '@ng-icons/core';
|
import { NgIconComponent, provideIcons } from '@ng-icons/core';
|
||||||
import { ionMenuOutline, ionChatbubbles, ionNewspaperOutline, ionAlertCircleOutline, ionRadioOutline, ionHome, ionMegaphoneOutline } from '@ng-icons/ionicons';
|
import {
|
||||||
|
ionMenuOutline,
|
||||||
|
ionChatbubbles,
|
||||||
|
ionNewspaperOutline,
|
||||||
|
ionAlertCircleOutline,
|
||||||
|
ionRadioOutline,
|
||||||
|
ionHome,
|
||||||
|
ionMegaphoneOutline,
|
||||||
|
ionCreateOutline,
|
||||||
|
} from '@ng-icons/ionicons';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-root',
|
selector: 'app-root',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [CommonModule, RouterOutlet, RouterModule, RouterLink, NgIconComponent],
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
RouterOutlet,
|
||||||
|
RouterModule,
|
||||||
|
RouterLink,
|
||||||
|
NgIconComponent,
|
||||||
|
],
|
||||||
templateUrl: './app.component.html',
|
templateUrl: './app.component.html',
|
||||||
styleUrl: './app.component.css',
|
styleUrl: './app.component.css',
|
||||||
providers: [ provideIcons({ ionMenuOutline, ionChatbubbles, ionNewspaperOutline, ionAlertCircleOutline, ionRadioOutline, ionHome, ionMegaphoneOutline })],
|
providers: [
|
||||||
|
provideIcons({
|
||||||
|
ionMenuOutline,
|
||||||
|
ionChatbubbles,
|
||||||
|
ionNewspaperOutline,
|
||||||
|
ionAlertCircleOutline,
|
||||||
|
ionRadioOutline,
|
||||||
|
ionHome,
|
||||||
|
ionMegaphoneOutline,
|
||||||
|
ionCreateOutline,
|
||||||
|
}),
|
||||||
|
],
|
||||||
})
|
})
|
||||||
export class AppComponent {
|
export class AppComponent {
|
||||||
auth: AuthService = inject(AuthService);
|
auth: AuthService = inject(AuthService);
|
||||||
title = 'admin';
|
title = 'admin';
|
||||||
|
|
||||||
|
logout() {
|
||||||
|
this.auth.logout();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,8 @@ import {
|
||||||
withInterceptors,
|
withInterceptors,
|
||||||
} from '@angular/common/http';
|
} from '@angular/common/http';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { isDevMode } from '@angular/core';
|
import { isDevMode, inject } from '@angular/core';
|
||||||
|
import { AuthService } from './login/auth.service';
|
||||||
|
|
||||||
import { routes } from './app.routes';
|
import { routes } from './app.routes';
|
||||||
import { provideHttpClient } from '@angular/common/http';
|
import { provideHttpClient } from '@angular/common/http';
|
||||||
|
@ -26,10 +27,28 @@ export function apiBaseInterceptor(
|
||||||
return next(apiReq);
|
return next(apiReq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function authIntercept(
|
||||||
|
req: HttpRequest<unknown>,
|
||||||
|
next: HttpHandlerFn,
|
||||||
|
): Observable<HttpEvent<unknown>> {
|
||||||
|
let authSvc: AuthService = inject(AuthService);
|
||||||
|
if (authSvc.loggedIn) {
|
||||||
|
req = req.clone({
|
||||||
|
setHeaders: {
|
||||||
|
'Content-Type': 'application/json; charset=utf-8',
|
||||||
|
Accept: 'application/json',
|
||||||
|
Authorization: `Bearer ${authSvc.getToken()}`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return next(req);
|
||||||
|
}
|
||||||
|
|
||||||
export const appConfig: ApplicationConfig = {
|
export const appConfig: ApplicationConfig = {
|
||||||
providers: [
|
providers: [
|
||||||
provideZoneChangeDetection({ eventCoalescing: true }),
|
provideZoneChangeDetection({ eventCoalescing: true }),
|
||||||
provideRouter(routes),
|
provideRouter(routes),
|
||||||
provideHttpClient(withInterceptors([apiBaseInterceptor])),
|
provideHttpClient(withInterceptors([apiBaseInterceptor, authIntercept])),
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,9 +8,8 @@ describe('CallsComponent', () => {
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
imports: [CallsComponent]
|
imports: [CallsComponent],
|
||||||
})
|
}).compileComponents();
|
||||||
.compileComponents();
|
|
||||||
|
|
||||||
fixture = TestBed.createComponent(CallsComponent);
|
fixture = TestBed.createComponent(CallsComponent);
|
||||||
component = fixture.componentInstance;
|
component = fixture.componentInstance;
|
||||||
|
|
|
@ -5,8 +5,6 @@ import { Component } from '@angular/core';
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [],
|
imports: [],
|
||||||
templateUrl: './calls.component.html',
|
templateUrl: './calls.component.html',
|
||||||
styleUrl: './calls.component.css'
|
styleUrl: './calls.component.css',
|
||||||
})
|
})
|
||||||
export class CallsComponent {
|
export class CallsComponent {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,3 +1 @@
|
||||||
<p>
|
<p>This will be a dashboard someday.</p>
|
||||||
This will be a dashboard someday.
|
|
||||||
</p>
|
|
||||||
|
|
|
@ -7,5 +7,4 @@ import { Component } from '@angular/core';
|
||||||
templateUrl: './home.component.html',
|
templateUrl: './home.component.html',
|
||||||
styleUrl: './home.component.css',
|
styleUrl: './home.component.css',
|
||||||
})
|
})
|
||||||
export class HomeComponent {
|
export class HomeComponent {}
|
||||||
}
|
|
||||||
|
|
|
@ -8,9 +8,8 @@ describe('IncidentsComponent', () => {
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
imports: [IncidentsComponent]
|
imports: [IncidentsComponent],
|
||||||
})
|
}).compileComponents();
|
||||||
.compileComponents();
|
|
||||||
|
|
||||||
fixture = TestBed.createComponent(IncidentsComponent);
|
fixture = TestBed.createComponent(IncidentsComponent);
|
||||||
component = fixture.componentInstance;
|
component = fixture.componentInstance;
|
||||||
|
|
|
@ -5,8 +5,6 @@ import { Component } from '@angular/core';
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [],
|
imports: [],
|
||||||
templateUrl: './incidents.component.html',
|
templateUrl: './incidents.component.html',
|
||||||
styleUrl: './incidents.component.css'
|
styleUrl: './incidents.component.css',
|
||||||
})
|
})
|
||||||
export class IncidentsComponent {
|
export class IncidentsComponent {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -41,4 +41,14 @@ export class AuthService {
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getToken(): string | null {
|
||||||
|
return sessionStorage.getItem('jwt');
|
||||||
|
}
|
||||||
|
|
||||||
|
logout() {
|
||||||
|
sessionStorage.removeItem('jwt');
|
||||||
|
this.loggedIn = false;
|
||||||
|
this._router.navigateByUrl('/login');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
30
client/admin/src/app/talkgroup.ts
Normal file
30
client/admin/src/app/talkgroup.ts
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
export interface TGID {
|
||||||
|
sys: number;
|
||||||
|
tg: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AlertRule {
|
||||||
|
times: string[];
|
||||||
|
mult: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface System {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Talkgroup {
|
||||||
|
id: number;
|
||||||
|
system_id: number;
|
||||||
|
tgid: number;
|
||||||
|
name: string;
|
||||||
|
alpha_tag: string;
|
||||||
|
tg_group: string;
|
||||||
|
frequency: number;
|
||||||
|
metadata: Object;
|
||||||
|
tags: string[];
|
||||||
|
alert: boolean;
|
||||||
|
alert_config: Map<TGID, AlertRule[]>;
|
||||||
|
system: System;
|
||||||
|
weight: number;
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
<p>TG comp</p>
|
|
@ -0,0 +1,22 @@
|
||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { TalkgroupRecordComponent } from './talkgroup-record.component';
|
||||||
|
|
||||||
|
describe('TalkgroupRecordComponent', () => {
|
||||||
|
let component: TalkgroupRecordComponent;
|
||||||
|
let fixture: ComponentFixture<TalkgroupRecordComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
imports: [TalkgroupRecordComponent],
|
||||||
|
}).compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(TalkgroupRecordComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,16 @@
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { Talkgroup } from '../../talkgroup';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'talkgroup-record',
|
||||||
|
standalone: true,
|
||||||
|
imports: [],
|
||||||
|
templateUrl: './talkgroup-record.component.html',
|
||||||
|
styleUrl: './talkgroup-record.component.css',
|
||||||
|
})
|
||||||
|
export class TalkgroupRecordComponent {
|
||||||
|
tg: Talkgroup;
|
||||||
|
constructor(tg: Talkgroup) {
|
||||||
|
this.tg = tg;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1 +1,26 @@
|
||||||
<p>talkgroups works!</p>
|
<div class="w-3/5 justify-center overflow-x-auto">
|
||||||
|
<table class="table">
|
||||||
|
<!-- head -->
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Sys</th>
|
||||||
|
<th>Sys ID</th>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>TG ID</th>
|
||||||
|
<th></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<!-- row 1 -->
|
||||||
|
@for (tg of tgs; track tg.id) {
|
||||||
|
<tr>
|
||||||
|
<td>{{ tg.system.name }}</td>
|
||||||
|
<td>{{ tg.system.id }}</td>
|
||||||
|
<td>{{ tg.name }}</td>
|
||||||
|
<td>{{ tg.tgid }}</td>
|
||||||
|
<td><ng-icon name="ionCreateOutline"></ng-icon></td>
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
|
@ -8,9 +8,8 @@ describe('TalkgroupsComponent', () => {
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
imports: [TalkgroupsComponent]
|
imports: [TalkgroupsComponent],
|
||||||
})
|
}).compileComponents();
|
||||||
.compileComponents();
|
|
||||||
|
|
||||||
fixture = TestBed.createComponent(TalkgroupsComponent);
|
fixture = TestBed.createComponent(TalkgroupsComponent);
|
||||||
component = fixture.componentInstance;
|
component = fixture.componentInstance;
|
||||||
|
|
|
@ -1,12 +1,26 @@
|
||||||
import { Component } from '@angular/core';
|
import { Component, inject } from '@angular/core';
|
||||||
|
import { TalkgroupService } from './talkgroups.service';
|
||||||
|
import { Talkgroup } from '../talkgroup';
|
||||||
|
import { NgIconComponent, provideIcons } from '@ng-icons/core';
|
||||||
|
import { ionCreateOutline } from '@ng-icons/ionicons';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-talkgroups',
|
selector: 'talkgroups',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [],
|
imports: [NgIconComponent],
|
||||||
templateUrl: './talkgroups.component.html',
|
templateUrl: './talkgroups.component.html',
|
||||||
styleUrl: './talkgroups.component.css'
|
styleUrl: './talkgroups.component.css',
|
||||||
|
providers: [provideIcons({ ionCreateOutline })],
|
||||||
})
|
})
|
||||||
export class TalkgroupsComponent {
|
export class TalkgroupsComponent {
|
||||||
|
tgs: Talkgroup[] = [];
|
||||||
|
tgService: TalkgroupService = inject(TalkgroupService);
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.getTalkgroups();
|
||||||
|
}
|
||||||
|
|
||||||
|
getTalkgroups() {
|
||||||
|
this.tgService.getTalkgroups().subscribe((tgs) => (this.tgs = tgs));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
16
client/admin/src/app/talkgroups/talkgroups.service.spec.ts
Normal file
16
client/admin/src/app/talkgroups/talkgroups.service.spec.ts
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { APIService } from './api.service';
|
||||||
|
|
||||||
|
describe('APIService', () => {
|
||||||
|
let service: APIService;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({});
|
||||||
|
service = TestBed.inject(APIService);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be created', () => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
16
client/admin/src/app/talkgroups/talkgroups.service.ts
Normal file
16
client/admin/src/app/talkgroups/talkgroups.service.ts
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { HttpClient } from '@angular/common/http';
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
import { Talkgroup } from '../talkgroup';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root',
|
||||||
|
})
|
||||||
|
export class TalkgroupService {
|
||||||
|
loggedIn: boolean = false;
|
||||||
|
constructor(private http: HttpClient) {}
|
||||||
|
|
||||||
|
getTalkgroups(): Observable<Talkgroup[]> {
|
||||||
|
return this.http.get<Talkgroup[]>('/api/talkgroup/');
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue