shareUI
This commit is contained in:
parent
dd2ee06f03
commit
48903bb4a2
4 changed files with 298 additions and 6 deletions
|
@ -6,6 +6,26 @@ import { CallRecord } from '../calls';
|
|||
import { Share, ShareType } from '../shares';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
|
||||
export interface ShareRecord {
|
||||
id: string;
|
||||
entityType: string;
|
||||
entityDate: Date;
|
||||
owner: string;
|
||||
entityID: string;
|
||||
expiration: Date | null;
|
||||
}
|
||||
|
||||
export interface ShareListParams {
|
||||
page: number | null;
|
||||
perPage: number | null;
|
||||
dir: string | null;
|
||||
}
|
||||
|
||||
export interface Shares {
|
||||
shares: ShareRecord[];
|
||||
totalCount: number;
|
||||
}
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
|
@ -28,6 +48,14 @@ export class ShareService {
|
|||
return this.http.get<Share>(`/share/${id}`);
|
||||
}
|
||||
|
||||
deleteShare(id: string): Observable<void> {
|
||||
return this.http.delete<void>(`/api/share/${id}`);
|
||||
}
|
||||
|
||||
getShares(p: ShareListParams): Observable<Shares> {
|
||||
return this.http.post<Shares>('/api/share/', p);
|
||||
}
|
||||
|
||||
getSharedItem(s: Observable<Share>): Observable<ShareType> {
|
||||
return s.pipe(
|
||||
map((res) => {
|
||||
|
|
|
@ -1 +1,82 @@
|
|||
<p>shares works!</p>
|
||||
<div class="tabContainer" *ngIf="!isLoading; else spinner">
|
||||
<table class="sharesTable" mat-table [dataSource]="sharesResult">
|
||||
<ng-container matColumnDef="select">
|
||||
<th mat-header-cell *matHeaderCellDef>
|
||||
<mat-checkbox
|
||||
(change)="$event ? masterToggle() : null"
|
||||
[checked]="selection.hasValue() && isAllSelected()"
|
||||
[indeterminate]="selection.hasValue() && !isAllSelected()"
|
||||
>
|
||||
</mat-checkbox>
|
||||
</th>
|
||||
<td mat-cell *matCellDef="let row">
|
||||
<mat-checkbox
|
||||
(click)="$event.stopPropagation()"
|
||||
(change)="$event ? selection.toggle(row) : null"
|
||||
[checked]="selection.isSelected(row)"
|
||||
>
|
||||
</mat-checkbox>
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="type">
|
||||
<th mat-header-cell *matHeaderCellDef></th>
|
||||
<td mat-cell *matCellDef="let share">
|
||||
@switch (share.entityType) {
|
||||
@case ("incident") {
|
||||
<mat-icon>newspaper</mat-icon>
|
||||
}
|
||||
@case ("call") {
|
||||
<mat-icon>campaign</mat-icon>
|
||||
}
|
||||
}
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="link">
|
||||
<th mat-header-cell *matHeaderCellDef>Link</th>
|
||||
<td mat-cell *matCellDef="let share">
|
||||
<a [href]="'/s/' + share.id"><mat-icon>link</mat-icon></a>
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="date">
|
||||
<th mat-header-cell *matHeaderCellDef>Date</th>
|
||||
<td mat-cell *matCellDef="let share">
|
||||
{{ share.entityDate | fmtDate }}
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="owner">
|
||||
<th mat-header-cell *matHeaderCellDef>Owner</th>
|
||||
<td mat-cell *matCellDef="let share">
|
||||
{{ share.owner }}
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="delete">
|
||||
<th mat-header-cell *matHeaderCellDef>Delete</th>
|
||||
<td mat-cell *matCellDef="let share">
|
||||
<a (click)="deleteShare(share.id)">
|
||||
<mat-icon>delete</mat-icon>
|
||||
</a>
|
||||
</td>
|
||||
</ng-container>
|
||||
<tr mat-header-row *matHeaderRowDef="columns; sticky: true"></tr>
|
||||
<tr mat-row *matRowDef="let myRowData; columns: columns"></tr>
|
||||
</table>
|
||||
</div>
|
||||
<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>
|
||||
<ng-template #spinner>
|
||||
<div class="spinner">
|
||||
<mat-spinner></mat-spinner>
|
||||
</div>
|
||||
</ng-template>
|
||||
|
|
|
@ -1,9 +1,192 @@
|
|||
import { Component } from '@angular/core';
|
||||
import { Component, Pipe, PipeTransform, ViewChild } from '@angular/core';
|
||||
import { CommonModule, AsyncPipe } from '@angular/common';
|
||||
import { RouterLink } from '@angular/router';
|
||||
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
||||
import { MatTableModule } from '@angular/material/table';
|
||||
import {
|
||||
MatPaginator,
|
||||
MatPaginatorModule,
|
||||
PageEvent,
|
||||
} from '@angular/material/paginator';
|
||||
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, Subscription } from 'rxjs';
|
||||
import { switchMap } from 'rxjs/operators';
|
||||
|
||||
import { TalkgroupService } from '../talkgroups/talkgroups.service';
|
||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||
import {
|
||||
FormControl,
|
||||
FormGroup,
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
} from '@angular/forms';
|
||||
import { MatInputModule } from '@angular/material/input';
|
||||
import { debounceTime } from 'rxjs/operators';
|
||||
import { ToolbarContextService } from '../navigation/toolbar-context.service';
|
||||
import {
|
||||
ShareListParams,
|
||||
ShareRecord,
|
||||
ShareService,
|
||||
} from '../share/share.service';
|
||||
import { FmtDatePipe } from '../incidents/incidents.component';
|
||||
|
||||
const reqPageSize = 200;
|
||||
|
||||
@Component({
|
||||
selector: 'app-shares',
|
||||
imports: [],
|
||||
imports: [
|
||||
MatIconModule,
|
||||
MatPaginatorModule,
|
||||
MatTableModule,
|
||||
MatFormFieldModule,
|
||||
ReactiveFormsModule,
|
||||
FormsModule,
|
||||
FmtDatePipe,
|
||||
MatInputModule,
|
||||
MatCheckboxModule,
|
||||
CommonModule,
|
||||
MatProgressSpinnerModule,
|
||||
],
|
||||
templateUrl: './shares.component.html',
|
||||
styleUrl: './shares.component.scss',
|
||||
})
|
||||
export class SharesComponent {}
|
||||
export class SharesComponent {
|
||||
sharesResult = new BehaviorSubject(new Array<ShareRecord>(0));
|
||||
selection = new SelectionModel<ShareRecord>(true, []);
|
||||
|
||||
@ViewChild('paginator') paginator!: MatPaginator;
|
||||
count = 0;
|
||||
curLen = 0;
|
||||
page = 0;
|
||||
perPage = 25;
|
||||
pageSizeOptions = [25, 50, 75, 100, 200];
|
||||
columns = ['select', 'type', 'link', 'date', 'owner', 'delete'];
|
||||
curPage = <PageEvent>{ pageIndex: 0, pageSize: 0 };
|
||||
currentSet!: ShareRecord[];
|
||||
currentServerPage = 0; // page is never 0, forces load
|
||||
isLoading = true;
|
||||
subscriptions = new Subscription();
|
||||
pageWindow = 0;
|
||||
fetchIncidents = new BehaviorSubject<ShareListParams>(
|
||||
this.buildParams(this.curPage, this.curPage.pageIndex),
|
||||
);
|
||||
|
||||
constructor(private sharesSvc: ShareService) {}
|
||||
|
||||
isAllSelected() {
|
||||
const numSelected = this.selection.selected.length;
|
||||
const numRows = this.curLen;
|
||||
return numSelected === numRows;
|
||||
}
|
||||
|
||||
buildParams(p: PageEvent, serverPage: number): ShareListParams {
|
||||
const par: ShareListParams = {
|
||||
page: serverPage,
|
||||
perPage: reqPageSize,
|
||||
dir: 'asc',
|
||||
};
|
||||
|
||||
return par;
|
||||
}
|
||||
|
||||
masterToggle() {
|
||||
this.isAllSelected()
|
||||
? this.selection.clear()
|
||||
: this.sharesResult.value.forEach((row) => this.selection.select(row));
|
||||
}
|
||||
|
||||
setPage(p: PageEvent, force?: boolean) {
|
||||
this.selection.clear();
|
||||
this.curPage = p;
|
||||
if (p && p!.pageSize != this.perPage) {
|
||||
this.perPage = p!.pageSize;
|
||||
}
|
||||
this.getShares(p, force);
|
||||
}
|
||||
|
||||
refresh() {
|
||||
this.selection.clear();
|
||||
this.getShares(this.curPage, true);
|
||||
}
|
||||
|
||||
getShares(p: PageEvent, force?: boolean) {
|
||||
const pageStart = p.pageIndex * p.pageSize;
|
||||
const serverPage = Math.floor(pageStart / reqPageSize) + 1;
|
||||
this.pageWindow = pageStart % reqPageSize;
|
||||
if (serverPage == this.currentServerPage && !force && this.currentSet) {
|
||||
this.sharesResult.next(
|
||||
this.sharesResult
|
||||
? this.currentSet.slice(this.pageWindow, this.pageWindow + p.pageSize)
|
||||
: [],
|
||||
);
|
||||
} else {
|
||||
this.currentServerPage = serverPage;
|
||||
this.fetchIncidents.next(this.buildParams(p, serverPage));
|
||||
}
|
||||
}
|
||||
|
||||
zeroPage(): PageEvent {
|
||||
return <PageEvent>{
|
||||
pageIndex: 0,
|
||||
pageSize: this.curPage.pageSize,
|
||||
};
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.subscriptions.unsubscribe();
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
let cpp = 25;
|
||||
this.perPage = cpp;
|
||||
|
||||
this.setPage(<PageEvent>{
|
||||
pageIndex: 0,
|
||||
pageSize: cpp,
|
||||
});
|
||||
this.subscriptions.add(
|
||||
this.fetchIncidents
|
||||
.pipe(
|
||||
switchMap((params) => {
|
||||
return this.sharesSvc.getShares(params);
|
||||
}),
|
||||
)
|
||||
.subscribe((shares) => {
|
||||
this.isLoading = false;
|
||||
this.count = shares.totalCount;
|
||||
this.currentSet = shares.shares;
|
||||
this.sharesResult.next(
|
||||
this.currentSet
|
||||
? this.currentSet.slice(
|
||||
this.pageWindow,
|
||||
this.pageWindow + this.perPage,
|
||||
)
|
||||
: [],
|
||||
);
|
||||
}),
|
||||
);
|
||||
this.subscriptions.add(
|
||||
this.sharesResult.subscribe((cr) => {
|
||||
this.curLen = cr.length;
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
deleteShare(shareID: string) {
|
||||
if (confirm('Are you sure you want to delete this share?')) {
|
||||
this.sharesSvc.deleteShare(shareID).subscribe({
|
||||
next: () => {
|
||||
this.fetchIncidents.next(
|
||||
this.buildParams(this.curPage, this.curPage.pageIndex),
|
||||
);
|
||||
},
|
||||
error: (err) => {
|
||||
alert(err);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
{
|
||||
"/api": {
|
||||
"/api/": {
|
||||
"target": "http://xenon:3050",
|
||||
"secure": false
|
||||
},
|
||||
"/share": {
|
||||
"/share/": {
|
||||
"target": "http://xenon:3050",
|
||||
"secure": false
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue