diff --git a/client/stillbox/ngsw-config.json b/client/stillbox/ngsw-config.json index fa63476..0a011be 100644 --- a/client/stillbox/ngsw-config.json +++ b/client/stillbox/ngsw-config.json @@ -27,8 +27,7 @@ } } ], - "navigationUrls": - [ + "navigationUrls": [ "/**", "!/**/*.*", "!/**/****", diff --git a/client/stillbox/src/app/calls/calls.component.ts b/client/stillbox/src/app/calls/calls.component.ts index c82e9f4..573dab8 100644 --- a/client/stillbox/src/app/calls/calls.component.ts +++ b/client/stillbox/src/app/calls/calls.component.ts @@ -1,10 +1,4 @@ -import { - Component, - inject, - Pipe, - PipeTransform, - ViewChild, -} from '@angular/core'; +import { Component, inject, ViewChild } from '@angular/core'; import { CommonModule, AsyncPipe } from '@angular/common'; import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; import { MatTableModule } from '@angular/material/table'; @@ -17,13 +11,20 @@ import { PrefsService } from '../prefs/prefs.service'; import { MatIconModule } from '@angular/material/icon'; import { SelectionModel } from '@angular/cdk/collections'; import { MatCheckboxModule } from '@angular/material/checkbox'; -import { BehaviorSubject, Observable, Subscription } from 'rxjs'; -import { map, switchMap } from 'rxjs/operators'; -import { CallsListParams, CallsService } from './calls.service'; +import { BehaviorSubject, Subscription } from 'rxjs'; +import { switchMap } from 'rxjs/operators'; +import { + CallsListParams, + CallsService, + DatePipe, + DownloadURLPipe, + FixedPointPipe, + TalkgroupPipe, + TimePipe, +} from './calls.service'; import { CallRecord } from '../calls'; import { TalkgroupService } from '../talkgroups/talkgroups.service'; -import { Talkgroup } from '../talkgroup'; import { MatFormFieldModule } from '@angular/material/form-field'; import { FormControl, @@ -49,94 +50,6 @@ import { import { IncidentRecord } from '../incidents'; import { SelectIncidentDialogComponent } from '../incidents/select-incident-dialog/select-incident-dialog.component'; -@Pipe({ - name: 'grabDate', - standalone: true, - pure: true, -}) -export class DatePipe implements PipeTransform { - transform(ts: string, args?: any): string { - const timestamp = new Date(ts); - return timestamp.getMonth() + 1 + '/' + timestamp.getDate(); - } -} - -@Pipe({ - name: 'time', - standalone: true, - pure: true, -}) -export class TimePipe implements PipeTransform { - transform(ts: string, args?: any): string { - const timestamp = new Date(ts); - return timestamp.toLocaleTimeString(navigator.language, { - hour: '2-digit', - minute: '2-digit', - hourCycle: 'h23', - }); - } -} - -@Pipe({ - name: 'talkgroup', - standalone: true, - pure: true, -}) -export class TalkgroupPipe implements PipeTransform { - constructor(private tgService: TalkgroupService) {} - - transform(call: CallRecord, field: string): Observable { - return this.tgService.getTalkgroup(call.system_id, call.tgid).pipe( - map((tg: Talkgroup) => { - switch (field) { - case 'alpha': { - return tg.alpha_tag ?? call.tgid; - break; - } - case 'group': { - return tg.tg_group ?? '\u2014'; - break; - } - case 'system': { - return tg.system?.name ?? tg.system_id.toString(); - } - default: { - return tg.name ?? '\u2014'; - break; - } - } - }), - ); - } -} - -@Pipe({ - name: 'fixedPoint', - standalone: true, - pure: true, -}) -export class FixedPointPipe implements PipeTransform { - constructor() {} - - transform(quant: number, divisor: number, places: number): string { - const seconds = quant / divisor; - return seconds.toFixed(places); - } -} - -@Pipe({ - name: 'audioDownloadURL', - standalone: true, - pure: true, -}) -export class DownloadURLPipe implements PipeTransform { - constructor(private callsSvc: CallsService) {} - - transform(call: CallRecord, args?: any): string { - return this.callsSvc.callAudioDownloadURL(call.id); - } -} - const reqPageSize = 200; @Component({ selector: 'app-calls', @@ -144,8 +57,8 @@ const reqPageSize = 200; MatIconModule, FixedPointPipe, TalkgroupPipe, - DatePipe, TimePipe, + DatePipe, MatPaginatorModule, MatTableModule, AsyncPipe, diff --git a/client/stillbox/src/app/calls/calls.service.ts b/client/stillbox/src/app/calls/calls.service.ts index 2792b9e..89cd8fc 100644 --- a/client/stillbox/src/app/calls/calls.service.ts +++ b/client/stillbox/src/app/calls/calls.service.ts @@ -1,8 +1,98 @@ -import { Injectable } from '@angular/core'; +import { Injectable, Pipe, PipeTransform } from '@angular/core'; import { HttpClient } from '@angular/common/http'; -import { Observable } from 'rxjs'; +import { map, Observable } from 'rxjs'; import { CallRecord } from '../calls'; import { environment } from '.././../environments/environment'; +import { TalkgroupService } from '../talkgroups/talkgroups.service'; +import { Talkgroup } from '../talkgroup'; + +@Pipe({ + name: 'grabDate', + standalone: true, + pure: true, +}) +export class DatePipe implements PipeTransform { + transform(ts: string, args?: any): string { + const timestamp = new Date(ts); + return timestamp.getMonth() + 1 + '/' + timestamp.getDate(); + } +} + +@Pipe({ + name: 'time', + standalone: true, + pure: true, +}) +export class TimePipe implements PipeTransform { + transform(ts: string, args?: any): string { + const timestamp = new Date(ts); + return timestamp.toLocaleTimeString(navigator.language, { + hour: '2-digit', + minute: '2-digit', + hourCycle: 'h23', + }); + } +} + +@Pipe({ + name: 'talkgroup', + standalone: true, + pure: true, +}) +export class TalkgroupPipe implements PipeTransform { + constructor(private tgService: TalkgroupService) {} + + transform(call: CallRecord, field: string): Observable { + return this.tgService.getTalkgroup(call.system_id, call.tgid).pipe( + map((tg: Talkgroup) => { + switch (field) { + case 'alpha': { + return tg.alpha_tag ?? call.tgid; + break; + } + case 'group': { + return tg.tg_group ?? '\u2014'; + break; + } + case 'system': { + return tg.system?.name ?? tg.system_id.toString(); + } + default: { + return tg.name ?? '\u2014'; + break; + } + } + }), + ); + } +} + +@Pipe({ + name: 'fixedPoint', + standalone: true, + pure: true, +}) +export class FixedPointPipe implements PipeTransform { + constructor() {} + + transform(quant: number, divisor: number, places: number): string { + const seconds = quant / divisor; + return seconds.toFixed(places); + } +} + +@Pipe({ + name: 'audioDownloadURL', + standalone: true, + pure: true, +}) +export class DownloadURLPipe implements PipeTransform { + constructor(private callsSvc: CallsService) {} + + transform(call: CallRecord, args?: any): string { + return this.callsSvc.callAudioDownloadURL(call.id); + } +} export interface CallsListParams { start: Date | null; diff --git a/client/stillbox/src/app/incidents/incident/incident.component.ts b/client/stillbox/src/app/incidents/incident/incident.component.ts index cd1d21a..d2b13b9 100644 --- a/client/stillbox/src/app/incidents/incident/incident.component.ts +++ b/client/stillbox/src/app/incidents/incident/incident.component.ts @@ -35,7 +35,7 @@ import { TimePipe, DatePipe, DownloadURLPipe, -} from '../../calls/calls.component'; +} from '../../calls/calls.service'; import { CallPlayerComponent } from '../../calls/player/call-player/call-player.component'; import { FmtDatePipe } from '../incidents.component'; import { MatMenuModule } from '@angular/material/menu'; @@ -183,7 +183,8 @@ export class IncidentComponent { ngOnInit() { let incOb: Observable; - if (this.route.component === this.constructor) { // loaded by route + if (this.route.component === this.constructor) { + // loaded by route this.incID = this.route.snapshot.paramMap.get('id')!; incOb = this.incSvc.getIncident(this.incID); } else { diff --git a/client/stillbox/src/app/share/share.component.html b/client/stillbox/src/app/share/share.component.html index 8a7eaf6..7c670e2 100644 --- a/client/stillbox/src/app/share/share.component.html +++ b/client/stillbox/src/app/share/share.component.html @@ -1,10 +1,6 @@ @let sh = share | async; @if (sh == null) { - -} @else if (sh.shareType == 'incident') { - -} @else if (sh.shareType == 'call') { - -} @else { - -} \ No newline at end of file +} @else if (sh.shareType == "incident") { + +} @else if (sh.shareType == "call") { +} @else {} diff --git a/client/stillbox/src/app/share/share.component.spec.ts b/client/stillbox/src/app/share/share.component.spec.ts index 6115935..7a7fe1e 100644 --- a/client/stillbox/src/app/share/share.component.spec.ts +++ b/client/stillbox/src/app/share/share.component.spec.ts @@ -8,9 +8,8 @@ describe('ShareComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ - imports: [ShareComponent] - }) - .compileComponents(); + imports: [ShareComponent], + }).compileComponents(); fixture = TestBed.createComponent(ShareComponent); component = fixture.componentInstance; diff --git a/client/stillbox/src/app/share/share.component.ts b/client/stillbox/src/app/share/share.component.ts index 127f62e..e1557c9 100644 --- a/client/stillbox/src/app/share/share.component.ts +++ b/client/stillbox/src/app/share/share.component.ts @@ -5,19 +5,15 @@ import { Observable, Subscription, switchMap } from 'rxjs'; import { IncidentComponent } from '../incidents/incident/incident.component'; import { AsyncPipe } from '@angular/common'; - @Component({ selector: 'app-share', - imports: [ - AsyncPipe, - IncidentComponent, - ], + imports: [AsyncPipe, IncidentComponent], templateUrl: './share.component.html', - styleUrl: './share.component.scss' + styleUrl: './share.component.scss', }) export class ShareComponent { shareID!: string; - share!: Observable; + share!: Observable; constructor( private route: ActivatedRoute, private shareSvc: ShareService, diff --git a/client/stillbox/src/app/share/share.service.ts b/client/stillbox/src/app/share/share.service.ts index 82433dd..f880ab8 100644 --- a/client/stillbox/src/app/share/share.service.ts +++ b/client/stillbox/src/app/share/share.service.ts @@ -9,26 +9,28 @@ export interface Share { share: ShareType; } @Injectable({ - providedIn: 'root' + providedIn: 'root', }) export class ShareService { + constructor(private http: HttpClient) {} - constructor( - private http: HttpClient, - ) { } - - getShare(id: string): Observable { - return this.http.get(`/share/${id}`, {observe: 'response'}).pipe( + getShare(id: string): Observable { + return this.http + .get(`/share/${id}`, { observe: 'response' }) + .pipe( map((res) => { let typ = res.headers.get('X-Share-Type'); - switch(typ) { + switch (typ) { case 'call': - return {shareType: typ, share: (res.body as ArrayBuffer)}; + return { shareType: typ, share: res.body as ArrayBuffer }; case 'incident': - return {shareType: typ, share: (res.body as IncidentRecord)}; + return { + shareType: typ, + share: res.body as IncidentRecord, + }; } return null; - }) + }), ); } } diff --git a/client/stillbox/src/app/talkgroups/talkgroups.service.ts b/client/stillbox/src/app/talkgroups/talkgroups.service.ts index 7a41161..0896b64 100644 --- a/client/stillbox/src/app/talkgroups/talkgroups.service.ts +++ b/client/stillbox/src/app/talkgroups/talkgroups.service.ts @@ -33,7 +33,10 @@ export class TalkgroupService { private subscriptions = new Subscription(); constructor(private http: HttpClient) { this.tgs$ = this.fetchAll.pipe(switchMap(() => this.getTalkgroups())); - this.tags$ = this.fetchAll.pipe(switchMap(() => this.getAllTags()), shareReplay()); + this.tags$ = this.fetchAll.pipe( + switchMap(() => this.getAllTags()), + shareReplay(), + ); this.fillTgMap(); }