Implement icons

This commit is contained in:
Daniel Ponte 2024-11-23 13:44:42 -05:00
parent d34dc1500d
commit 1653b08a6d
7 changed files with 98 additions and 50 deletions

View file

@ -1,5 +1,5 @@
import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core'; import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
import { provideRouter, withDebugTracing } from '@angular/router'; import { provideRouter, } from '@angular/router';
import { environment } from './../environments/environment'; import { environment } from './../environments/environment';
import { import {
HttpRequest, HttpRequest,
@ -43,7 +43,7 @@ export function authIntercept(
export const appConfig: ApplicationConfig = { export const appConfig: ApplicationConfig = {
providers: [ providers: [
provideZoneChangeDetection({ eventCoalescing: true }), provideZoneChangeDetection({ eventCoalescing: true }),
provideRouter(routes, withDebugTracing()), provideRouter(routes),
provideHttpClient(withInterceptors([apiBaseInterceptor, authIntercept])), provideHttpClient(withInterceptors([apiBaseInterceptor, authIntercept])),
], ],
}; };

View file

@ -1,10 +1,3 @@
import {
matFireTruckOutline,
matLocalPoliceOutline,
matEmergencyOutline,
matDirectionsBusOutline,
} from '@ng-icons/material-icons/outline';
export interface TGID { export interface TGID {
sys: number; sys: number;
tg: number; tg: number;
@ -41,6 +34,18 @@ export interface Metadata {
icon: string | null; icon: string | null;
} }
export interface IconMap {
[name: string]: string;
}
export const iconMapping: IconMap = {
'police': 'matLocalPoliceOutline',
'fire': 'matFireTruckOutline',
'ems': 'matEmergencyOutline',
'bus': 'matDirectionsBusOutline',
'': 'matGroupWorkOutline',
};
export class Talkgroup { export class Talkgroup {
id!: number; id!: number;
system_id!: number; system_id!: number;
@ -79,12 +84,7 @@ export class Talkgroup {
} }
iconMap(icon: string): string { iconMap(icon: string): string {
return { return iconMapping[icon]!;
police: matLocalPoliceOutline,
fire: matFireTruckOutline,
ems: matEmergencyOutline,
bus: matDirectionsBusOutline,
}[icon]!;
} }
} }

View file

@ -1,5 +1,5 @@
<div class="flex"> <div class="flex">
<form [formGroup]="form" (ngSubmit)="submit()"> <form *ngIf="tg" [formGroup]="form" (ngSubmit)="submit()">
<div class="p-1 columns-2"> <div class="p-1 columns-2">
<label class="w-full" for="name">Name: </label <label class="w-full" for="name">Name: </label
><input ><input
@ -7,7 +7,6 @@
type="text" type="text"
class="w-full input input-bordered" class="w-full input input-bordered"
formControlName="name" formControlName="name"
[(ngModel)]="tg.name"
/> />
</div> </div>
<div class="p-1 columns-2"> <div class="p-1 columns-2">
@ -17,7 +16,6 @@
type="text" type="text"
class="w-full input input-bordered" class="w-full input input-bordered"
formControlName="alpha_tag" formControlName="alpha_tag"
[(ngModel)]="tg.alpha_tag"
/> />
</div> </div>
<div class="p-1 columns-2"> <div class="p-1 columns-2">
@ -27,7 +25,6 @@
type="text" type="text"
class="w-full input input-bordered" class="w-full input input-bordered"
formControlName="tg_group" formControlName="tg_group"
[(ngModel)]="tg.tg_group"
/> />
</div> </div>
<div class="p-1 columns-2"> <div class="p-1 columns-2">
@ -37,7 +34,6 @@
type="text" type="text"
class="w-full input input-bordered" class="w-full input input-bordered"
formControlName="frequency" formControlName="frequency"
[(ngModel)]="tg.frequency"
/> />
</div> </div>
<div class="p-1 columns-2"> <div class="p-1 columns-2">
@ -47,7 +43,6 @@
id="alert" id="alert"
type="checkbox" type="checkbox"
formControlName="alert" formControlName="alert"
[(ngModel)]="tg.alert"
class="checkbox" class="checkbox"
/> />
</div> </div>
@ -59,7 +54,6 @@
type="text" type="text"
class="w-full input input-bordered" class="w-full input input-bordered"
formControlName="weight" formControlName="weight"
[(ngModel)]="tg.weight"
/> />
</div> </div>
<div>Rules:</div> <div>Rules:</div>
@ -71,13 +65,10 @@
name="icon" name="icon"
id="icon" id="icon"
formControlName="icon" formControlName="icon"
[(ngModel)]="tg.icon"
> >
<option value=""></option> @for(opt of iconMapping | keyvalue; track opt) {
<option value="police">Police</option> <option value="{{ opt.key }}" [selected]="opt.key == tg.metadata?.icon">{{ opt.key | titlecase }}</option>
<option value="fire">Fire</option> }
<option value="ems">EMS</option>
<option value="bus">Bus</option>
</select> </select>
</div> </div>
<input type="submit" class="btn btn-secondary" value="Save" /> <input type="submit" class="btn btn-secondary" value="Save" />

View file

@ -1,5 +1,5 @@
import { Component, inject } from '@angular/core'; import { Component, inject } from '@angular/core';
import { Talkgroup, TalkgroupUpdate } from '../../talkgroup'; import { Talkgroup, TalkgroupUpdate, IconMap, iconMapping } from '../../talkgroup';
import { TalkgroupService } from '../talkgroups.service'; import { TalkgroupService } from '../talkgroups.service';
import { AlertRuleBuilderComponent } from './alert-rule-builder/alert-rule-builder.component'; import { AlertRuleBuilderComponent } from './alert-rule-builder/alert-rule-builder.component';
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
@ -22,6 +22,7 @@ import { Observable } from 'rxjs';
}) })
export class TalkgroupRecordComponent { export class TalkgroupRecordComponent {
tg!: Talkgroup; tg!: Talkgroup;
iconMapping: IconMap = iconMapping;
tgService: TalkgroupService = inject(TalkgroupService); tgService: TalkgroupService = inject(TalkgroupService);
form!: FormGroup; form!: FormGroup;
@ -39,17 +40,19 @@ export class TalkgroupRecordComponent {
.getTalkgroup(Number(sysId), Number(tgId)) .getTalkgroup(Number(sysId), Number(tgId))
.subscribe((data: Talkgroup) => { .subscribe((data: Talkgroup) => {
this.tg = data; this.tg = data;
this.form = new FormGroup({
name: new FormControl(this.tg.name),
alpha_tag: new FormControl(this.tg.alpha_tag),
tg_group: new FormControl(this.tg.tg_group),
frequency: new FormControl(this.tg.frequency),
alert: new FormControl(this.tg.alert),
weight: new FormControl(this.tg.weight),
icon: new FormControl(this.tg.icon),
});
console.log(this.tg.icon);
}); });
this.form = new FormGroup({
name: new FormControl(''),
alpha_tag: new FormControl(''),
tg_group: new FormControl(''),
frequency: new FormControl(0),
alert: new FormControl(true),
weight: new FormControl(1.0),
icon: new FormControl(''),
});
} }
submit() { submit() {
@ -59,22 +62,22 @@ export class TalkgroupRecordComponent {
id: this.tg.id, id: this.tg.id,
}; };
if (this.form.controls['name'].dirty) { if (this.form.controls['name'].dirty) {
tgu.name = this.tg.name; tgu.name = this.form.controls['name'].value;
} }
if (this.form.controls['alpha_tag'].dirty) { if (this.form.controls['alpha_tag'].dirty) {
tgu.alpha_tag = this.tg.alpha_tag; tgu.alpha_tag = this.form.controls['alpha_tag'].value;
} }
if (this.form.controls['tg_group'].dirty) { if (this.form.controls['tg_group'].dirty) {
tgu.tg_group = this.tg.tg_group; tgu.tg_group = this.form.controls['tg_group'].value;
} }
if (this.form.controls['frequency'].dirty) { if (this.form.controls['frequency'].dirty) {
tgu.frequency = this.tg.frequency; tgu.frequency = this.form.controls['frequency'].value;
} }
if (this.form.controls['alert'].dirty) { if (this.form.controls['alert'].dirty) {
tgu.alert = this.tg.alert; tgu.alert = this.form.controls['alert'].value;
} }
if (this.form.controls['weight'].dirty) { if (this.form.controls['weight'].dirty) {
tgu.weight = Number(this.tg.weight); tgu.weight = Number(this.form.controls['weight'].value);
} }
if (this.form.controls['icon'].dirty) { if (this.form.controls['icon'].dirty) {
if (tgu.metadata == null) { if (tgu.metadata == null) {
@ -83,7 +86,7 @@ export class TalkgroupRecordComponent {
if (this.tg.icon == null || this.tg.icon == '') { 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 { } else {
tgu.metadata = Object.assign(tgu.metadata!, { icon: this.tg.icon }); tgu.metadata = Object.assign(tgu.metadata!, { icon: this.form.controls['icon'] });
} }
} }
this.tgService this.tgService

View file

@ -0,0 +1,2 @@
.tgIcon {
}

View file

@ -6,7 +6,9 @@
<th></th> <th></th>
<th>Sys</th> <th>Sys</th>
<th>Sys ID</th> <th>Sys ID</th>
<th>Group</th>
<th>Name</th> <th>Name</th>
<th>Alpha</th>
<th>TG ID</th> <th>TG ID</th>
<th>Learned</th> <th>Learned</th>
<th></th> <th></th>
@ -15,10 +17,13 @@
<tbody> <tbody>
@for (tg of talkgroups$ | async ; track tg.id) { @for (tg of talkgroups$ | async ; track tg.id) {
<tr> <tr>
<td>{{ tg.icon }}</td> <!-- <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?.name }}</td>
<td>{{ tg.system?.id }}</td> <td>{{ tg.system?.id }}</td>
<td>{{ tg.tg_group }}</td>
<td>{{ tg.name }}</td> <td>{{ tg.name }}</td>
<td>{{ tg.alpha_tag }}</td>
<td>{{ tg.tgid }}</td> <td>{{ tg.tgid }}</td>
<td>{{ tg?.learned ? "Y" : "" }}</td> <td>{{ tg?.learned ? "Y" : "" }}</td>
<td> <td>

View file

@ -1,13 +1,52 @@
import { Component, inject } from '@angular/core'; import { Component, inject, Pipe, PipeTransform } from '@angular/core';
import { TalkgroupService } from './talkgroups.service'; import { TalkgroupService } from './talkgroups.service';
import { NgIconComponent, provideIcons } from '@ng-icons/core'; import { NgIconComponent, provideIcons } from '@ng-icons/core';
import { ionCreateOutline } from '@ng-icons/ionicons'; import { ionCreateOutline } from '@ng-icons/ionicons';
import { Talkgroup } from '../talkgroup'; import {
matFireTruckOutline,
matLocalPoliceOutline,
matEmergencyOutline,
matDirectionsBusOutline,
matGroupWorkOutline,
} from '@ng-icons/material-icons/outline';
import { Talkgroup, iconMapping } from '../talkgroup';
import { ActivatedRoute } from '@angular/router'; import { ActivatedRoute } from '@angular/router';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { switchMap } from 'rxjs/operators'; import { switchMap } from 'rxjs/operators';
import { RouterModule, RouterOutlet, RouterLink } from '@angular/router'; import { RouterModule, RouterOutlet, RouterLink } from '@angular/router';
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
@Pipe({
standalone: true,
name: 'iconify',
})
export class IconifyPipe implements PipeTransform {
transform(value: Talkgroup): Talkgroup {
if (value?.metadata?.icon != null) {
value.iconSvg = iconMapping[value?.metadata?.icon];
} else if (value?.metadata?.icon == undefined) {
value.iconSvg = iconMapping[''];
}
return value;
}
}
@Pipe({
standalone: true,
name: 'sanitizeHtml'
})
export class SanitizeHtmlPipe implements PipeTransform {
constructor(private _sanitizer:DomSanitizer) {
}
transform(v:string):SafeHtml {
return this._sanitizer.bypassSecurityTrustHtml(v);
}
}
@Component({ @Component({
selector: 'talkgroups', selector: 'talkgroups',
@ -18,10 +57,18 @@ import { CommonModule } from '@angular/common';
RouterModule, RouterModule,
RouterLink, RouterLink,
CommonModule, CommonModule,
IconifyPipe,
SanitizeHtmlPipe,
], ],
templateUrl: './talkgroups.component.html', templateUrl: './talkgroups.component.html',
styleUrl: './talkgroups.component.css', styleUrl: './talkgroups.component.css',
providers: [provideIcons({ ionCreateOutline })], providers: [provideIcons({ ionCreateOutline,
matFireTruckOutline,
matLocalPoliceOutline,
matEmergencyOutline,
matDirectionsBusOutline,
matGroupWorkOutline,
})],
}) })
export class TalkgroupsComponent { export class TalkgroupsComponent {
selectedSys: number = 0; selectedSys: number = 0;