This commit is contained in:
Daniel Ponte 2024-12-19 23:53:00 -05:00
parent b39069c893
commit 4bf6efa8cc
6 changed files with 163 additions and 112 deletions

View file

@ -1,9 +1,9 @@
export interface CallRecord {
id: string;
call_date: Date;
duration: number;
system_id: number;
tgid: number;
system_name: string;
tg_name: string;
};
id: string;
call_date: Date;
duration: number;
system_id: number;
tgid: number;
system_name: string;
tg_name: string;
}

View file

@ -1,50 +1,60 @@
<div class="toolbar">
<table mat-table [dataSource]="dataSource">
<ng-container matColumnDef="play">
<th mat-header-cell *matHeaderCellDef><mat-icon>play_arrow</mat-icon></th>
<td mat-cell *matCellDef="let call">
<!-- player here -->
</td>
</ng-container>
<ng-container matColumnDef="date">
<th mat-header-cell *matHeaderCellDef>Date</th>
<td mat-cell *matCellDef="let call">
{{ call.call_date | date }}
</td>
</ng-container>
<ng-container matColumnDef="time">
<th mat-header-cell *matHeaderCellDef>Time</th>
<td mat-cell *matCellDef="let call">
{{ call.call_date | time }}
</td>
</ng-container>
<ng-container matColumnDef="talkgroup">
<th mat-header-cell *matHeaderCellDef>Talkgroup</th>
<td mat-cell *matCellDef="let call">
{{ call | alphaTag | async }}
</td>
</ng-container>
<ng-container matColumnDef="duration">
<th mat-header-cell *matHeaderCellDef>Duration</th>
<td mat-cell *matCellDef="let call">
{{ call | duration }}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="columns; sticky: true"></tr>
<tr mat-row *matRowDef="let myRowData; columns: columns"></tr>
</table>
<div class="pagFoot">
<mat-paginator
#paginator
class="paginator"
(page)="setPage($event)"
[length]="count"
showFirstLastButtons="true"
[pageSize]="curPage.pageSize"
[pageSizeOptions]="pageSizeOptions"
[pageIndex]="curPage.pageIndex"
aria-label="Select page"
>
</mat-paginator>
</div>
</div>
<mat-form-field subscriptSizing="dynamic" class="filterBox">
<mat-label>Start</mat-label>
<input
matInput
type="datetime-local"
name="start"
placeholder="Start date"
[formControl]="start"
/>
</mat-form-field>
</div>
<table mat-table [dataSource]="dataSource">
<ng-container matColumnDef="play">
<th mat-header-cell *matHeaderCellDef><mat-icon>play_arrow</mat-icon></th>
<td mat-cell *matCellDef="let call">
<a (click)="playAudio($event, call)"><mat-icon>play_arrow</mat-icon></a>
</td>
</ng-container>
<ng-container matColumnDef="date">
<th mat-header-cell *matHeaderCellDef>Date</th>
<td mat-cell *matCellDef="let call">
{{ call.call_date | date }}
</td>
</ng-container>
<ng-container matColumnDef="time">
<th mat-header-cell *matHeaderCellDef>Time</th>
<td mat-cell *matCellDef="let call">
{{ call.call_date | time }}
</td>
</ng-container>
<ng-container matColumnDef="talkgroup">
<th mat-header-cell *matHeaderCellDef>Talkgroup</th>
<td mat-cell *matCellDef="let call">
{{ call | alphaTag | async }}
</td>
</ng-container>
<ng-container matColumnDef="duration">
<th mat-header-cell *matHeaderCellDef class="durationHdr">Duration</th>
<td mat-cell *matCellDef="let call" class="duration">
{{ call | duration }}
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="columns; sticky: true"></tr>
<tr mat-row *matRowDef="let myRowData; columns: columns"></tr>
</table>
<div class="pagFoot">
<mat-paginator
#paginator
class="paginator"
(page)="setPage($event)"
[length]="count"
showFirstLastButtons="true"
[pageSize]="curPage.pageSize"
[pageSizeOptions]="pageSizeOptions"
[pageIndex]="curPage.pageIndex"
aria-label="Select page"
>
</mat-paginator>
</div>

View file

@ -0,0 +1,13 @@
.filterBox {
width: 240px;
}
.duration {
text-align: right;
padding-right: 4em;
}
.durationHdr,
.duration {
max-width: 3em;
}

View file

@ -25,50 +25,52 @@ import { MatChipsModule } from '@angular/material/chips';
import { SelectionModel } from '@angular/cdk/collections';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { Observable, Subscription } from 'rxjs';
import {
map,
} from 'rxjs/operators';
import {
CallsListParams,
CallsService,
} from './calls.service';
import {
CallRecord,
} from '../calls';
import { map } from 'rxjs/operators';
import { CallsListParams, CallsService } from './calls.service';
import { CallRecord } from '../calls';
import {
TalkgroupService,
} from '../talkgroups/talkgroups.service';
import { TalkgroupService } from '../talkgroups/talkgroups.service';
import { Talkgroup } from '../talkgroup';
import { MatFormField, MatFormFieldModule } from '@angular/material/form-field';
import {
FormGroup,
FormControl,
FormsModule,
ReactiveFormsModule,
} from '@angular/forms';
import { MatInputModule } from '@angular/material/input';
@Pipe({
name: 'date',
standalone: true,
pure: true
pure: true,
})
export class DatePipe implements PipeTransform {
transform(ts: string, args?: any): string {
const timestamp = new Date(ts);
return (timestamp.getMonth() + 1) +"/"+ (timestamp.getDay());
return timestamp.getMonth() + 1 + '/' + timestamp.getDay();
}
}
@Pipe({
name: 'time',
standalone: true,
pure: 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'});
return timestamp.toLocaleTimeString(navigator.language, {
hour: '2-digit',
minute: '2-digit',
});
}
}
@Pipe({
name: 'alphaTag',
standalone: true,
pure: true
pure: true,
})
export class AlphaTagPipe implements PipeTransform {
constructor(private tgService: TalkgroupService) {}
@ -77,7 +79,7 @@ export class AlphaTagPipe implements PipeTransform {
return this.tgService.getTalkgroup(call.system_id, call.tgid).pipe(
map((tg: Talkgroup) => {
return tg.alpha_tag;
})
}),
);
}
}
@ -85,7 +87,7 @@ export class AlphaTagPipe implements PipeTransform {
@Pipe({
name: 'duration',
standalone: true,
pure: true
pure: true,
})
export class DurationPipe implements PipeTransform {
constructor(callsSvc: CallsService) {}
@ -108,6 +110,10 @@ export class DurationPipe implements PipeTransform {
MatPaginatorModule,
MatTableModule,
AsyncPipe,
MatFormFieldModule,
ReactiveFormsModule,
FormsModule,
MatInputModule,
],
templateUrl: './calls.component.html',
styleUrl: './calls.component.scss',
@ -119,23 +125,30 @@ export class CallsComponent {
page = 0;
perPage = 25;
pageSizeOptions = [25, 50, 75, 100, 200, 500];
columns = [
'play',
'date',
'time',
'talkgroup',
'duration',
];
curPage = <PageEvent>({pageIndex: 0, pageSize: 0});
columns = ['play', 'date', 'time', 'talkgroup', 'duration'];
curPage = <PageEvent>{ pageIndex: 0, pageSize: 0 };
start = new FormControl(
new Date(new Date().setDate(new Date().getDate() - 7)),
);
end = new FormControl(null);
constructor(private callsSvc: CallsService) {}
constructor(
private callsSvc: CallsService,
private prefsSvc: PrefsService,
) {}
playAudio(ev: Event, call: CallRecord) {
let au = new Audio();
au.src = this.callsSvc.callAudioURL(call.id);
au.load();
au.play();
}
setPage(p: PageEvent) {
this.curPage = p;
const current = new Date();
const start: Date = new Date(new Date().setDate(current.getDate() - 7));
const par: CallsListParams = {
start: start,
start: this.start.value,
page: p.pageIndex,
perPage: p.pageSize,
end: null,
@ -149,11 +162,20 @@ export class CallsComponent {
});
}
ngOnInit() {
this.setPage(<PageEvent>({
zeroPage(): PageEvent {
return <PageEvent>{
pageIndex: 0,
pageSize: 25,
}));
pageSize: this.curPage.pageSize,
};
}
ngOnInit() {
this.start.valueChanges.subscribe(() => {
this.setPage(this.zeroPage());
});
this.setPage(<PageEvent>{
pageIndex: 0,
pageSize: 25,
});
}
}

View file

@ -1,15 +1,14 @@
import { Injectable } from '@angular/core';
import { HttpClient, HttpResponse } from '@angular/common/http';
import { Observable } from 'rxjs';
import {
CallRecord,
} from '../calls';
import { CallRecord } from '../calls';
import { environment } from '.././../environments/environment';
export interface CallsListParams {
start: Date|null;
end: Date|null;
tagsAny: string[]|null;
tagsNot: string[]|null;
start: Date | null;
end: Date | null;
tagsAny: string[] | null;
tagsNot: string[] | null;
dir: string;
page: number;
perPage: number;
@ -20,16 +19,17 @@ export interface CallsPaginated {
count: number;
}
@Injectable({
providedIn: 'root'
providedIn: 'root',
})
export class CallsService {
constructor(private http: HttpClient) { }
constructor(private http: HttpClient) {}
getCalls(p: CallsListParams): Observable<CallsPaginated> {
return this.http.post<CallsPaginated>('/api/call/', p);
}
callAudioURL(id: string): string {
return environment.baseUrl + '/api/call/' + id;
}
}

View file

@ -30,10 +30,14 @@ export class TalkgroupService {
}
getTalkgroup(sys: number, tg: number): Observable<Talkgroup> {
let tgid = <TGID>({sys: sys, tg: tg});
let tgid = <TGID>{ sys: sys, tg: tg };
if (!this._getTalkgroup.get(tgid)) {
this._getTalkgroup.set(tgid, this.http.
get<Talkgroup>(`/api/talkgroup/${sys}/${tg}`).pipe(shareReplay()));
this._getTalkgroup.set(
tgid,
this.http
.get<Talkgroup>(`/api/talkgroup/${sys}/${tg}`)
.pipe(shareReplay()),
);
}
return this._getTalkgroup.get(tgid)!;
@ -67,11 +71,13 @@ export class TalkgroupService {
}
putTalkgroup(tu: TalkgroupUpdate): Observable<Talkgroup> {
let tgid = <TGID>({sys: tu.system_id, tg: tu.tgid});
this._getTalkgroup.set(tgid, this.http.put<Talkgroup>(
`/api/talkgroup/${tu.system_id}/${tu.tgid}`,
tu,
).pipe(shareReplay()));
let tgid = <TGID>{ sys: tu.system_id, tg: tu.tgid };
this._getTalkgroup.set(
tgid,
this.http
.put<Talkgroup>(`/api/talkgroup/${tu.system_id}/${tu.tgid}`, tu)
.pipe(shareReplay()),
);
return this._getTalkgroup.get(tgid)!;
}