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 {
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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 { 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,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)!;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue