Paginate, new table
This commit is contained in:
parent
a4fc8f7cca
commit
20104c59af
8 changed files with 253 additions and 131 deletions
|
@ -163,37 +163,6 @@
|
|||
</svg>
|
||||
</button>
|
||||
<!-- End Navigation Toggle -->
|
||||
|
||||
<!-- Breadcrumb -->
|
||||
<ol class="ms-3 flex items-center whitespace-nowrap">
|
||||
<li
|
||||
class="flex items-center text-sm text-gray-800 dark:text-neutral-400"
|
||||
>
|
||||
Application Layout
|
||||
<svg
|
||||
class="shrink-0 mx-3 overflow-visible size-2.5 text-gray-400 dark:text-neutral-500"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M5 1L10.6869 7.16086C10.8637 7.35239 10.8637 7.64761 10.6869 7.83914L5 14"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
/>
|
||||
</svg>
|
||||
</li>
|
||||
<li
|
||||
class="text-sm font-semibold text-gray-800 truncate dark:text-neutral-400"
|
||||
aria-current="page"
|
||||
>
|
||||
Dashboard
|
||||
</li>
|
||||
</ol>
|
||||
<!-- End Breadcrumb -->
|
||||
</div>
|
||||
</div>
|
||||
<!-- End Breadcrumb -->
|
||||
|
@ -289,14 +258,16 @@
|
|||
|
||||
<!-- Content -->
|
||||
@if (auth.loggedIn) {
|
||||
<div class="w-full lg:ps-64">
|
||||
<div class="p-4 sm:p-6 space-y-4 sm:space-y-6">
|
||||
<div class="container w-full lg:ps-64">
|
||||
<div
|
||||
class="object-contain object-scale-down p-4 sm:p-6 space-y-4 sm:space-y-6"
|
||||
>
|
||||
<router-outlet />
|
||||
</div>
|
||||
</div>
|
||||
} @else {
|
||||
<div class="w-full">
|
||||
<div class="p-4 sm:p-6 space-y-4 sm:space-y-6">
|
||||
<div class="object-contain p-4 sm:p-6 space-y-4 sm:space-y-6">
|
||||
<router-outlet />
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
|
||||
import { provideRouter, } from '@angular/router';
|
||||
import { provideRouter } from '@angular/router';
|
||||
import { environment } from './../environments/environment';
|
||||
import {
|
||||
HttpRequest,
|
||||
|
|
|
@ -34,15 +34,15 @@ export interface Metadata {
|
|||
icon: string | null;
|
||||
}
|
||||
|
||||
export interface IconMap {
|
||||
export interface IconMap {
|
||||
[name: string]: string;
|
||||
}
|
||||
}
|
||||
|
||||
export const iconMapping: IconMap = {
|
||||
'police': 'matLocalPoliceOutline',
|
||||
'fire': 'matFireTruckOutline',
|
||||
'ems': 'matEmergencyOutline',
|
||||
'bus': 'matDirectionsBusOutline',
|
||||
police: 'matLocalPoliceOutline',
|
||||
fire: 'matFireTruckOutline',
|
||||
ems: 'matEmergencyOutline',
|
||||
bus: 'matDirectionsBusOutline',
|
||||
'': 'matGroupWorkOutline',
|
||||
};
|
||||
|
||||
|
|
|
@ -60,14 +60,14 @@
|
|||
<alert-rule-builder [rules]="tg.alert_config" />
|
||||
<div>
|
||||
<label for="icon">Icon: </label>
|
||||
<select
|
||||
class="select"
|
||||
name="icon"
|
||||
id="icon"
|
||||
formControlName="icon"
|
||||
<select class="select" name="icon" id="icon" formControlName="icon">
|
||||
@for (opt of iconMapping | keyvalue; track opt) {
|
||||
<option
|
||||
value="{{ opt.key }}"
|
||||
[selected]="opt.key == tg.metadata?.icon"
|
||||
>
|
||||
@for(opt of iconMapping | keyvalue; track opt) {
|
||||
<option value="{{ opt.key }}" [selected]="opt.key == tg.metadata?.icon">{{ opt.key | titlecase }}</option>
|
||||
{{ opt.key | titlecase }}
|
||||
</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
import { Component, inject } from '@angular/core';
|
||||
import { Talkgroup, TalkgroupUpdate, IconMap, iconMapping } from '../../talkgroup';
|
||||
import {
|
||||
Talkgroup,
|
||||
TalkgroupUpdate,
|
||||
IconMap,
|
||||
iconMapping,
|
||||
} from '../../talkgroup';
|
||||
import { TalkgroupService } from '../talkgroups.service';
|
||||
import { AlertRuleBuilderComponent } from './alert-rule-builder/alert-rule-builder.component';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
@ -51,8 +56,6 @@ export class TalkgroupRecordComponent {
|
|||
});
|
||||
console.log(this.tg.icon);
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
submit() {
|
||||
|
@ -84,9 +87,11 @@ export class TalkgroupRecordComponent {
|
|||
tgu.metadata = {};
|
||||
}
|
||||
if (this.tg.icon == null || this.tg.icon == '') {
|
||||
tgu.metadata = Object.assign(tgu.metadata, {icon: undefined});
|
||||
tgu.metadata = Object.assign(tgu.metadata, { icon: undefined });
|
||||
} else {
|
||||
tgu.metadata = Object.assign(tgu.metadata!, { icon: this.form.controls['icon'] });
|
||||
tgu.metadata = Object.assign(tgu.metadata!, {
|
||||
icon: this.form.controls['icon'],
|
||||
});
|
||||
}
|
||||
}
|
||||
this.tgService
|
||||
|
|
|
@ -1,33 +1,102 @@
|
|||
<a href="#" class="btn btn-primary" routerLink="/talkgroups/import">Import</a>
|
||||
<div class="w-100 justify-center overflow-x-auto">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<a href="#" class="btn btn-primary" routerLink="/talkgroups/import">Import</a>
|
||||
<div class="rounded-lg border border-gray-200 dark:border-gray-700">
|
||||
<div class="overflow-x-auto rounded-t-lg">
|
||||
<table
|
||||
class="min-w-full divide-y-2 divide-gray-200 bg-white text-sm dark:divide-gray-700 dark:bg-gray-900"
|
||||
>
|
||||
<thead class="ltr:text-left">
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>Sys</th>
|
||||
<th>Sys ID</th>
|
||||
<th>Group</th>
|
||||
<th>Name</th>
|
||||
<th>Alpha</th>
|
||||
<th>TG ID</th>
|
||||
<th>Learned</th>
|
||||
<th></th>
|
||||
<th
|
||||
class="whitespace-nowrap px-4 py-2 font-medium text-gray-900 dark:text-white"
|
||||
></th>
|
||||
<th
|
||||
class="whitespace-nowrap px-4 py-2 font-medium text-gray-900 dark:text-white"
|
||||
>
|
||||
Sys
|
||||
</th>
|
||||
<th
|
||||
class="whitespace-nowrap px-4 py-2 font-medium text-gray-900 dark:text-white"
|
||||
>
|
||||
Sys ID
|
||||
</th>
|
||||
<th
|
||||
class="whitespace-nowrap px-4 py-2 font-medium text-gray-900 dark:text-white"
|
||||
>
|
||||
Group
|
||||
</th>
|
||||
<th
|
||||
class="whitespace-nowrap px-4 py-2 font-medium text-gray-900 dark:text-white"
|
||||
>
|
||||
Name
|
||||
</th>
|
||||
<th
|
||||
class="whitespace-nowrap px-4 py-2 font-medium text-gray-900 dark:text-white"
|
||||
>
|
||||
Alpha Tag
|
||||
</th>
|
||||
<th
|
||||
class="whitespace-nowrap px-4 py-2 font-medium text-gray-900 dark:text-white"
|
||||
>
|
||||
TG ID
|
||||
</th>
|
||||
<th
|
||||
class="whitespace-nowrap px-4 py-2 font-medium text-gray-900 dark:text-white"
|
||||
>
|
||||
Learned
|
||||
</th>
|
||||
<th
|
||||
class="whitespace-nowrap px-4 py-2 font-medium text-gray-900 dark:text-white"
|
||||
></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
<tbody class="divide-y divide-gray-200 dark:divide-gray-700">
|
||||
@let tgs = talkgroups$ | async;
|
||||
@for (tg of tgs?.talkgroups ; track tg.id) {
|
||||
@for (tg of tgs?.talkgroups; track tg.id) {
|
||||
<tr>
|
||||
<!-- <td class="tgIcon" [innerHTML]="(tg | iconify).iconSvg! | sanitizeHtml"></td> -->
|
||||
<td class="tgIcon"><ng-icon [name]="(tg | iconify).iconSvg!"></ng-icon></td>
|
||||
<td>{{ tg.system?.name }}</td>
|
||||
<td>{{ tg.system?.id }}</td>
|
||||
<td>{{ tg.tg_group }}</td>
|
||||
<td>{{ tg.name }}</td>
|
||||
<td>{{ tg.alpha_tag }}</td>
|
||||
<td>{{ tg.tgid }}</td>
|
||||
<td>{{ tg?.learned ? "Y" : "" }}</td>
|
||||
<td>
|
||||
<td class="tgIcon">
|
||||
<ng-icon [name]="(tg | iconify).iconSvg!"></ng-icon>
|
||||
</td>
|
||||
<td
|
||||
class="whitespace-nowrap px-4 py-2 font-medium text-gray-900 dark:text-white"
|
||||
>
|
||||
{{ tg.system?.name }}
|
||||
</td>
|
||||
<td
|
||||
class="whitespace-nowrap px-4 py-2 text-gray-700 dark:text-gray-200"
|
||||
>
|
||||
{{ tg.system?.id }}
|
||||
</td>
|
||||
<td
|
||||
class="whitespace-nowrap px-4 py-2 text-gray-700 dark:text-gray-200"
|
||||
>
|
||||
{{ tg.tg_group }}
|
||||
</td>
|
||||
<td
|
||||
class="whitespace-nowrap px-4 py-2 text-gray-700 dark:text-gray-200"
|
||||
>
|
||||
{{ tg.name }}
|
||||
</td>
|
||||
<td
|
||||
class="whitespace-nowrap px-4 py-2 text-gray-700 dark:text-gray-200"
|
||||
>
|
||||
{{ tg.alpha_tag }}
|
||||
</td>
|
||||
<td
|
||||
class="whitespace-nowrap px-4 py-2 text-gray-700 dark:text-gray-200"
|
||||
>
|
||||
{{ tg.tgid }}
|
||||
</td>
|
||||
<td
|
||||
class="whitespace-nowrap px-4 py-2 text-gray-700 dark:text-gray-200"
|
||||
>
|
||||
{{ tg?.learned ? "Y" : "" }}
|
||||
</td>
|
||||
<td
|
||||
class="whitespace-nowrap px-4 py-2 text-gray-700 dark:text-gray-200"
|
||||
>
|
||||
<a routerLink="/talkgroups/{{ tg.system?.id }}/{{ tg.tgid }}"
|
||||
><ng-icon name="ionCreateOutline"></ng-icon
|
||||
></a>
|
||||
|
@ -36,10 +105,75 @@
|
|||
}
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="w-100">
|
||||
Total: {{ tgs?.count }}
|
||||
<button class="btn btn-primary" (click)="prevPage()" [class.btn-ghost]="page == 1"><ng-icon name="ionChevronBack"></ng-icon></button>
|
||||
Page {{ page }} of {{ totalPages }}
|
||||
<button class="btn btn-primary" (click)="nextPage()" [class.btn-ghost]="page == totalPages"><ng-icon name="ionChevronForward"></ng-icon></button>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="rounded-b-lg border-t border-gray-200 px-4 py-2 dark:border-gray-700"
|
||||
>
|
||||
<ol class="flex justify-end gap-1 text-xs font-medium">
|
||||
<li>
|
||||
<button
|
||||
(click)="prevPage()"
|
||||
[class.btn-ghost]="page == 1"
|
||||
class="inline-flex size-8 items-center justify-center rounded border border-gray-100 bg-white text-gray-900 rtl:rotate-180 dark:border-gray-800 dark:bg-gray-900 dark:text-white"
|
||||
>
|
||||
<span class="sr-only">Prev Page</span>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="size-3"
|
||||
viewBox="0 0 20 20"
|
||||
fill="currentColor"
|
||||
>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
d="M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z"
|
||||
clip-rule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
</li>
|
||||
|
||||
@for (pgn of [].constructor(totalPages); track i; let i = $index) {
|
||||
@if (i != page) {
|
||||
<li>
|
||||
<button
|
||||
(click)="setPage(i + 1)"
|
||||
class="block size-8 rounded border border-gray-100 bg-white text-center leading-8 text-gray-900 dark:border-gray-800 dark:bg-gray-900 dark:text-white"
|
||||
>
|
||||
{{ i + 1 }}
|
||||
</button>
|
||||
</li>
|
||||
} @else {
|
||||
<li
|
||||
class="block size-8 rounded border-blue-600 bg-blue-600 text-center leading-8 dark:text-white"
|
||||
>
|
||||
{{ i + 1 }}
|
||||
</li>
|
||||
}
|
||||
}
|
||||
|
||||
<li>
|
||||
<button
|
||||
(click)="nextPage()"
|
||||
[class.btn-ghost]="page == totalPages"
|
||||
class="inline-flex size-8 items-center justify-center rounded border border-gray-100 bg-white text-gray-900 rtl:rotate-180 dark:border-gray-800 dark:bg-gray-900 dark:text-white"
|
||||
>
|
||||
<span class="sr-only">Next Page</span>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="size-3"
|
||||
viewBox="0 0 20 20"
|
||||
fill="currentColor"
|
||||
>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z"
|
||||
clip-rule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
import { Component, inject, Pipe, PipeTransform } from '@angular/core';
|
||||
import { TalkgroupService, TalkgroupsPaginated } from './talkgroups.service';
|
||||
import { NgIconComponent, provideIcons } from '@ng-icons/core';
|
||||
import { ionCreateOutline, ionChevronBack, ionChevronForward } from '@ng-icons/ionicons';
|
||||
import {
|
||||
ionCreateOutline,
|
||||
ionChevronBack,
|
||||
ionChevronForward,
|
||||
} from '@ng-icons/ionicons';
|
||||
import {
|
||||
matFireTruckOutline,
|
||||
matLocalPoliceOutline,
|
||||
|
@ -17,7 +21,6 @@ import { RouterModule, RouterOutlet, RouterLink } from '@angular/router';
|
|||
import { CommonModule } from '@angular/common';
|
||||
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
|
||||
|
||||
|
||||
@Pipe({
|
||||
standalone: true,
|
||||
name: 'iconify',
|
||||
|
@ -35,19 +38,16 @@ export class IconifyPipe implements PipeTransform {
|
|||
|
||||
@Pipe({
|
||||
standalone: true,
|
||||
name: 'sanitizeHtml'
|
||||
name: 'sanitizeHtml',
|
||||
})
|
||||
export class SanitizeHtmlPipe implements PipeTransform {
|
||||
constructor(private _sanitizer: DomSanitizer) {}
|
||||
|
||||
constructor(private _sanitizer:DomSanitizer) {
|
||||
}
|
||||
|
||||
transform(v:string):SafeHtml {
|
||||
transform(v: string): SafeHtml {
|
||||
return this._sanitizer.bypassSecurityTrustHtml(v);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'talkgroups',
|
||||
standalone: true,
|
||||
|
@ -62,7 +62,9 @@ export class SanitizeHtmlPipe implements PipeTransform {
|
|||
],
|
||||
templateUrl: './talkgroups.component.html',
|
||||
styleUrl: './talkgroups.component.css',
|
||||
providers: [provideIcons({ ionCreateOutline,
|
||||
providers: [
|
||||
provideIcons({
|
||||
ionCreateOutline,
|
||||
matFireTruckOutline,
|
||||
matLocalPoliceOutline,
|
||||
matEmergencyOutline,
|
||||
|
@ -70,7 +72,8 @@ export class SanitizeHtmlPipe implements PipeTransform {
|
|||
matGroupWorkOutline,
|
||||
ionChevronBack,
|
||||
ionChevronForward,
|
||||
})],
|
||||
}),
|
||||
],
|
||||
})
|
||||
export class TalkgroupsComponent {
|
||||
selectedSys: number = 0;
|
||||
|
@ -97,15 +100,24 @@ export class TalkgroupsComponent {
|
|||
}
|
||||
}
|
||||
|
||||
setPage(p: number) {
|
||||
if (p <= this.totalPages && p > 0) {
|
||||
this.page = p;
|
||||
this.fetchTGs();
|
||||
}
|
||||
}
|
||||
|
||||
fetchTGs() {
|
||||
this.talkgroups$ = this.route.paramMap.pipe(
|
||||
switchMap((params) => {
|
||||
this.selectedSys = Number(params.get('sys'));
|
||||
this.selectedId = Number(params.get('tg'));
|
||||
return this.tgService.getTalkgroupsPag({page: this.page, perPage: this.perPage}).pipe(
|
||||
return this.tgService
|
||||
.getTalkgroupsPag({ page: this.page, perPage: this.perPage })
|
||||
.pipe(
|
||||
tap((event) => {
|
||||
this.totalPages = Math.ceil(event.count/this.perPage);
|
||||
})
|
||||
this.totalPages = Math.ceil(event.count / this.perPage);
|
||||
}),
|
||||
);
|
||||
}),
|
||||
);
|
||||
|
|
Loading…
Reference in a new issue