audio
This commit is contained in:
parent
b39069c893
commit
4bf6efa8cc
6 changed files with 163 additions and 112 deletions
|
@ -1,9 +1,9 @@
|
||||||
export interface CallRecord {
|
export interface CallRecord {
|
||||||
id: string;
|
id: string;
|
||||||
call_date: Date;
|
call_date: Date;
|
||||||
duration: number;
|
duration: number;
|
||||||
system_id: number;
|
system_id: number;
|
||||||
tgid: number;
|
tgid: number;
|
||||||
system_name: string;
|
system_name: string;
|
||||||
tg_name: string;
|
tg_name: string;
|
||||||
};
|
}
|
||||||
|
|
|
@ -1,50 +1,60 @@
|
||||||
<div class="toolbar">
|
<div class="toolbar">
|
||||||
<table mat-table [dataSource]="dataSource">
|
<mat-form-field subscriptSizing="dynamic" class="filterBox">
|
||||||
<ng-container matColumnDef="play">
|
<mat-label>Start</mat-label>
|
||||||
<th mat-header-cell *matHeaderCellDef><mat-icon>play_arrow</mat-icon></th>
|
<input
|
||||||
<td mat-cell *matCellDef="let call">
|
matInput
|
||||||
<!-- player here -->
|
type="datetime-local"
|
||||||
</td>
|
name="start"
|
||||||
</ng-container>
|
placeholder="Start date"
|
||||||
<ng-container matColumnDef="date">
|
[formControl]="start"
|
||||||
<th mat-header-cell *matHeaderCellDef>Date</th>
|
/>
|
||||||
<td mat-cell *matCellDef="let call">
|
</mat-form-field>
|
||||||
{{ call.call_date | date }}
|
</div>
|
||||||
</td>
|
<table mat-table [dataSource]="dataSource">
|
||||||
</ng-container>
|
<ng-container matColumnDef="play">
|
||||||
<ng-container matColumnDef="time">
|
<th mat-header-cell *matHeaderCellDef><mat-icon>play_arrow</mat-icon></th>
|
||||||
<th mat-header-cell *matHeaderCellDef>Time</th>
|
<td mat-cell *matCellDef="let call">
|
||||||
<td mat-cell *matCellDef="let call">
|
<a (click)="playAudio($event, call)"><mat-icon>play_arrow</mat-icon></a>
|
||||||
{{ call.call_date | time }}
|
</td>
|
||||||
</td>
|
</ng-container>
|
||||||
</ng-container>
|
<ng-container matColumnDef="date">
|
||||||
<ng-container matColumnDef="talkgroup">
|
<th mat-header-cell *matHeaderCellDef>Date</th>
|
||||||
<th mat-header-cell *matHeaderCellDef>Talkgroup</th>
|
<td mat-cell *matCellDef="let call">
|
||||||
<td mat-cell *matCellDef="let call">
|
{{ call.call_date | date }}
|
||||||
{{ call | alphaTag | async }}
|
</td>
|
||||||
</td>
|
</ng-container>
|
||||||
</ng-container>
|
<ng-container matColumnDef="time">
|
||||||
<ng-container matColumnDef="duration">
|
<th mat-header-cell *matHeaderCellDef>Time</th>
|
||||||
<th mat-header-cell *matHeaderCellDef>Duration</th>
|
<td mat-cell *matCellDef="let call">
|
||||||
<td mat-cell *matCellDef="let call">
|
{{ call.call_date | time }}
|
||||||
{{ call | duration }}
|
</td>
|
||||||
</td>
|
</ng-container>
|
||||||
</ng-container>
|
<ng-container matColumnDef="talkgroup">
|
||||||
<tr mat-header-row *matHeaderRowDef="columns; sticky: true"></tr>
|
<th mat-header-cell *matHeaderCellDef>Talkgroup</th>
|
||||||
<tr mat-row *matRowDef="let myRowData; columns: columns"></tr>
|
<td mat-cell *matCellDef="let call">
|
||||||
</table>
|
{{ call | alphaTag | async }}
|
||||||
<div class="pagFoot">
|
</td>
|
||||||
<mat-paginator
|
</ng-container>
|
||||||
#paginator
|
<ng-container matColumnDef="duration">
|
||||||
class="paginator"
|
<th mat-header-cell *matHeaderCellDef class="durationHdr">Duration</th>
|
||||||
(page)="setPage($event)"
|
<td mat-cell *matCellDef="let call" class="duration">
|
||||||
[length]="count"
|
{{ call | duration }}
|
||||||
showFirstLastButtons="true"
|
</td>
|
||||||
[pageSize]="curPage.pageSize"
|
</ng-container>
|
||||||
[pageSizeOptions]="pageSizeOptions"
|
<tr mat-header-row *matHeaderRowDef="columns; sticky: true"></tr>
|
||||||
[pageIndex]="curPage.pageIndex"
|
<tr mat-row *matRowDef="let myRowData; columns: columns"></tr>
|
||||||
aria-label="Select page"
|
</table>
|
||||||
>
|
<div class="pagFoot">
|
||||||
</mat-paginator>
|
<mat-paginator
|
||||||
</div>
|
#paginator
|
||||||
</div>
|
class="paginator"
|
||||||
|
(page)="setPage($event)"
|
||||||
|
[length]="count"
|
||||||
|
showFirstLastButtons="true"
|
||||||
|
[pageSize]="curPage.pageSize"
|
||||||
|
[pageSizeOptions]="pageSizeOptions"
|
||||||
|
[pageIndex]="curPage.pageIndex"
|
||||||
|
aria-label="Select page"
|
||||||
|
>
|
||||||
|
</mat-paginator>
|
||||||
|
</div>
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
.filterBox {
|
||||||
|
width: 240px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.duration {
|
||||||
|
text-align: right;
|
||||||
|
padding-right: 4em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.durationHdr,
|
||||||
|
.duration {
|
||||||
|
max-width: 3em;
|
||||||
|
}
|
|
@ -25,50 +25,52 @@ import { MatChipsModule } from '@angular/material/chips';
|
||||||
import { SelectionModel } from '@angular/cdk/collections';
|
import { SelectionModel } from '@angular/cdk/collections';
|
||||||
import { MatCheckboxModule } from '@angular/material/checkbox';
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||||
import { Observable, Subscription } from 'rxjs';
|
import { Observable, Subscription } from 'rxjs';
|
||||||
import {
|
import { map } from 'rxjs/operators';
|
||||||
map,
|
import { CallsListParams, CallsService } from './calls.service';
|
||||||
} from 'rxjs/operators';
|
import { CallRecord } from '../calls';
|
||||||
import {
|
|
||||||
CallsListParams,
|
|
||||||
CallsService,
|
|
||||||
} from './calls.service';
|
|
||||||
import {
|
|
||||||
CallRecord,
|
|
||||||
} from '../calls';
|
|
||||||
|
|
||||||
import {
|
import { TalkgroupService } from '../talkgroups/talkgroups.service';
|
||||||
TalkgroupService,
|
|
||||||
} from '../talkgroups/talkgroups.service';
|
|
||||||
import { Talkgroup } from '../talkgroup';
|
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({
|
@Pipe({
|
||||||
name: 'date',
|
name: 'date',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
pure: true
|
pure: true,
|
||||||
})
|
})
|
||||||
export class DatePipe implements PipeTransform {
|
export class DatePipe implements PipeTransform {
|
||||||
transform(ts: string, args?: any): string {
|
transform(ts: string, args?: any): string {
|
||||||
const timestamp = new Date(ts);
|
const timestamp = new Date(ts);
|
||||||
return (timestamp.getMonth() + 1) +"/"+ (timestamp.getDay());
|
return timestamp.getMonth() + 1 + '/' + timestamp.getDay();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Pipe({
|
@Pipe({
|
||||||
name: 'time',
|
name: 'time',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
pure: true
|
pure: true,
|
||||||
})
|
})
|
||||||
export class TimePipe implements PipeTransform {
|
export class TimePipe implements PipeTransform {
|
||||||
transform(ts: string, args?: any): string {
|
transform(ts: string, args?: any): string {
|
||||||
const timestamp = new Date(ts);
|
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({
|
@Pipe({
|
||||||
name: 'alphaTag',
|
name: 'alphaTag',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
pure: true
|
pure: true,
|
||||||
})
|
})
|
||||||
export class AlphaTagPipe implements PipeTransform {
|
export class AlphaTagPipe implements PipeTransform {
|
||||||
constructor(private tgService: TalkgroupService) {}
|
constructor(private tgService: TalkgroupService) {}
|
||||||
|
@ -77,7 +79,7 @@ export class AlphaTagPipe implements PipeTransform {
|
||||||
return this.tgService.getTalkgroup(call.system_id, call.tgid).pipe(
|
return this.tgService.getTalkgroup(call.system_id, call.tgid).pipe(
|
||||||
map((tg: Talkgroup) => {
|
map((tg: Talkgroup) => {
|
||||||
return tg.alpha_tag;
|
return tg.alpha_tag;
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -85,7 +87,7 @@ export class AlphaTagPipe implements PipeTransform {
|
||||||
@Pipe({
|
@Pipe({
|
||||||
name: 'duration',
|
name: 'duration',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
pure: true
|
pure: true,
|
||||||
})
|
})
|
||||||
export class DurationPipe implements PipeTransform {
|
export class DurationPipe implements PipeTransform {
|
||||||
constructor(callsSvc: CallsService) {}
|
constructor(callsSvc: CallsService) {}
|
||||||
|
@ -108,6 +110,10 @@ export class DurationPipe implements PipeTransform {
|
||||||
MatPaginatorModule,
|
MatPaginatorModule,
|
||||||
MatTableModule,
|
MatTableModule,
|
||||||
AsyncPipe,
|
AsyncPipe,
|
||||||
|
MatFormFieldModule,
|
||||||
|
ReactiveFormsModule,
|
||||||
|
FormsModule,
|
||||||
|
MatInputModule,
|
||||||
],
|
],
|
||||||
templateUrl: './calls.component.html',
|
templateUrl: './calls.component.html',
|
||||||
styleUrl: './calls.component.scss',
|
styleUrl: './calls.component.scss',
|
||||||
|
@ -119,23 +125,30 @@ export class CallsComponent {
|
||||||
page = 0;
|
page = 0;
|
||||||
perPage = 25;
|
perPage = 25;
|
||||||
pageSizeOptions = [25, 50, 75, 100, 200, 500];
|
pageSizeOptions = [25, 50, 75, 100, 200, 500];
|
||||||
columns = [
|
columns = ['play', 'date', 'time', 'talkgroup', 'duration'];
|
||||||
'play',
|
curPage = <PageEvent>{ pageIndex: 0, pageSize: 0 };
|
||||||
'date',
|
start = new FormControl(
|
||||||
'time',
|
new Date(new Date().setDate(new Date().getDate() - 7)),
|
||||||
'talkgroup',
|
);
|
||||||
'duration',
|
end = new FormControl(null);
|
||||||
];
|
|
||||||
curPage = <PageEvent>({pageIndex: 0, pageSize: 0});
|
|
||||||
|
|
||||||
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) {
|
setPage(p: PageEvent) {
|
||||||
this.curPage = p;
|
this.curPage = p;
|
||||||
const current = new Date();
|
const current = new Date();
|
||||||
const start: Date = new Date(new Date().setDate(current.getDate() - 7));
|
|
||||||
const par: CallsListParams = {
|
const par: CallsListParams = {
|
||||||
start: start,
|
start: this.start.value,
|
||||||
page: p.pageIndex,
|
page: p.pageIndex,
|
||||||
perPage: p.pageSize,
|
perPage: p.pageSize,
|
||||||
end: null,
|
end: null,
|
||||||
|
@ -149,11 +162,20 @@ export class CallsComponent {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
zeroPage(): PageEvent {
|
||||||
this.setPage(<PageEvent>({
|
return <PageEvent>{
|
||||||
pageIndex: 0,
|
pageIndex: 0,
|
||||||
pageSize: 25,
|
pageSize: this.curPage.pageSize,
|
||||||
}));
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.start.valueChanges.subscribe(() => {
|
||||||
|
this.setPage(this.zeroPage());
|
||||||
|
});
|
||||||
|
this.setPage(<PageEvent>{
|
||||||
|
pageIndex: 0,
|
||||||
|
pageSize: 25,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,14 @@
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { HttpClient, HttpResponse } from '@angular/common/http';
|
import { HttpClient, HttpResponse } from '@angular/common/http';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import {
|
import { CallRecord } from '../calls';
|
||||||
CallRecord,
|
import { environment } from '.././../environments/environment';
|
||||||
} from '../calls';
|
|
||||||
|
|
||||||
export interface CallsListParams {
|
export interface CallsListParams {
|
||||||
start: Date|null;
|
start: Date | null;
|
||||||
end: Date|null;
|
end: Date | null;
|
||||||
tagsAny: string[]|null;
|
tagsAny: string[] | null;
|
||||||
tagsNot: string[]|null;
|
tagsNot: string[] | null;
|
||||||
dir: string;
|
dir: string;
|
||||||
page: number;
|
page: number;
|
||||||
perPage: number;
|
perPage: number;
|
||||||
|
@ -20,16 +19,17 @@ export interface CallsPaginated {
|
||||||
count: number;
|
count: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root',
|
||||||
})
|
})
|
||||||
export class CallsService {
|
export class CallsService {
|
||||||
|
constructor(private http: HttpClient) {}
|
||||||
constructor(private http: HttpClient) { }
|
|
||||||
|
|
||||||
getCalls(p: CallsListParams): Observable<CallsPaginated> {
|
getCalls(p: CallsListParams): Observable<CallsPaginated> {
|
||||||
return this.http.post<CallsPaginated>('/api/call/', p);
|
return this.http.post<CallsPaginated>('/api/call/', p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
callAudioURL(id: string): string {
|
||||||
|
return environment.baseUrl + '/api/call/' + id;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,10 +30,14 @@ export class TalkgroupService {
|
||||||
}
|
}
|
||||||
|
|
||||||
getTalkgroup(sys: number, tg: number): Observable<Talkgroup> {
|
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)) {
|
if (!this._getTalkgroup.get(tgid)) {
|
||||||
this._getTalkgroup.set(tgid, this.http.
|
this._getTalkgroup.set(
|
||||||
get<Talkgroup>(`/api/talkgroup/${sys}/${tg}`).pipe(shareReplay()));
|
tgid,
|
||||||
|
this.http
|
||||||
|
.get<Talkgroup>(`/api/talkgroup/${sys}/${tg}`)
|
||||||
|
.pipe(shareReplay()),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this._getTalkgroup.get(tgid)!;
|
return this._getTalkgroup.get(tgid)!;
|
||||||
|
@ -67,11 +71,13 @@ export class TalkgroupService {
|
||||||
}
|
}
|
||||||
|
|
||||||
putTalkgroup(tu: TalkgroupUpdate): Observable<Talkgroup> {
|
putTalkgroup(tu: TalkgroupUpdate): Observable<Talkgroup> {
|
||||||
let tgid = <TGID>({sys: tu.system_id, tg: tu.tgid});
|
let tgid = <TGID>{ sys: tu.system_id, tg: tu.tgid };
|
||||||
this._getTalkgroup.set(tgid, this.http.put<Talkgroup>(
|
this._getTalkgroup.set(
|
||||||
`/api/talkgroup/${tu.system_id}/${tu.tgid}`,
|
tgid,
|
||||||
tu,
|
this.http
|
||||||
).pipe(shareReplay()));
|
.put<Talkgroup>(`/api/talkgroup/${tu.system_id}/${tu.tgid}`, tu)
|
||||||
|
.pipe(shareReplay()),
|
||||||
|
);
|
||||||
|
|
||||||
return this._getTalkgroup.get(tgid)!;
|
return this._getTalkgroup.get(tgid)!;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue