Skip to content

Commit b17f296

Browse files
author
motorox
committed
Merge branch 'MaterialDesign' into updateversions
2 parents ae0bedc + 9ba915b commit b17f296

31 files changed

+1381
-104
lines changed

HamEvent/.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,11 @@ UpgradeLog*.htm
196196
*.mdf
197197
*.ldf
198198

199+
# SQLite files
200+
*.db-shm
201+
*.db-wal
202+
203+
199204
# Business Intelligence projects
200205
*.rdl.data
201206
*.bim.layout
Lines changed: 4 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,6 @@
1-
<div class="min-100 d-flex flex-column" style="height:100%">
2-
3-
<header>
4-
<app-nav-menu></app-nav-menu>
5-
</header>
6-
7-
<div class="flex-fill">
8-
<main>
9-
<router-outlet></router-outlet>
10-
</main>
11-
</div>
12-
13-
14-
<footer class="px-3 d-flex flex-wrap justify-content-between align-items-center py-3 my-4 border-top">
15-
<p class="col-md-4 mb-0 text-body-secondary">© {{'Copyright' | translate}}</p>
16-
17-
18-
<ul class="nav col-md-4 justify-content-end">
19-
<li class="nav-item my-auto"> <a class="nav-link justify-content-center" href="http://yo2kqt.ro" target="_blank">yo2kqt.ro</a></li>
20-
<li class="nav-item">
21-
<a class="btn btn-outline-light btn-floating m-1"
22-
href="https://github.com/bogdanbrudiu/HamSpecialEvent" target="_blank"
23-
role="button">
24-
<img width="40" height="40" alt="GitHub Logomark" class="height-auto" src="https://github.githubassets.com/assets/GitHub-Mark-ea2971cee799.png">
25-
</a>
26-
</li>
27-
</ul>
28-
</footer>
29-
30-
1+
<div>
2+
<app-nav-menu></app-nav-menu>
3+
<router-outlet></router-outlet>
4+
<app-footer></app-footer>
315
</div>
326

HamEvent/ClientApp/src/app/app.component.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,16 @@ import { Component, Inject } from '@angular/core';
33
import { Title } from '@angular/platform-browser';
44
import { ActivatedRoute, NavigationEnd, Router, RouterState } from '@angular/router';
55
import { TranslateService } from '@ngx-translate/core';
6+
import { NavMenuComponent } from './nav-menu/nav-menu.component';
7+
68
declare let gtag: Function;
79
@Component({
810
selector: 'app-root',
911
templateUrl: './app.component.html'
1012
})
1113
export class AppComponent {
1214
constructor(private router: Router, private titleService: Title,
13-
@Inject(DOCUMENT) private document: Document, translate: TranslateService) {
15+
@Inject(DOCUMENT) private document: Document, private translate: TranslateService) {
1416
// this language will be used as a fallback when a translation isn't found in the current language
1517
translate.setDefaultLang('en');
1618

@@ -41,4 +43,7 @@ export class AppComponent {
4143
}
4244
return data;
4345
}
46+
onLanguageChanged(lang: string) {
47+
this.translate.use(lang);
48+
}
4449
}

HamEvent/ClientApp/src/app/app.module.ts

Lines changed: 49 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms';
44
import { RouterModule } from '@angular/router';
55
import { TranslateModule, TranslateLoader } from '@ngx-translate/core';
66
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
7-
import { HttpClient, provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
7+
import { HttpClient, HttpClientModule, provideHttpClient, withInterceptorsFromDi } from '@angular/common/http';
88
import { NgxPaginationModule } from 'ngx-pagination';
99

1010
import { AppComponent } from './app.component';
@@ -17,16 +17,30 @@ import { EventTopComponent } from './eventtop/eventtop.component';
1717
import { AdminQSOsComponent } from './adminqsos/adminqsos.component';
1818
import { AdminEventComponent } from './adminevent/adminevent.component';
1919
import { DashboardComponent } from './dashboard/dashboard.component';
20+
import { LanguageSelectorComponent } from './language-selector/language-selector.component';
2021
import { EventCardComponent } from './event-card/event-card.component';
2122
import { FooterComponent } from './footer/footer.component'; // Import the new footer component
23+
import { MatIconModule } from '@angular/material/icon';
24+
import { FlexLayoutModule } from '@angular/flex-layout';
25+
import { MatButtonModule } from '@angular/material/button';
26+
import { MatOptionModule } from '@angular/material/core';
27+
import { MatFormFieldModule } from '@angular/material/form-field';
28+
import { MatSelectModule } from '@angular/material/select';
29+
import { MatToolbarModule } from '@angular/material/toolbar';
30+
import { MatTooltipModule } from '@angular/material/tooltip';
31+
import { MatTableModule } from '@angular/material/table';
32+
import { MatMenuModule } from "@angular/material/menu";
33+
import { MatDividerModule } from "@angular/material/divider";
34+
import { MatExpansionModule } from '@angular/material/expansion';
35+
import { MatGridListModule } from '@angular/material/grid-list';
36+
import { provideAnimations } from '@angular/platform-browser/animations';
2237

2338
export function createTranslateLoader(http: HttpClient) {
2439
return new TranslateHttpLoader(http, './assets/i18n/', '.json');
2540
}
2641

2742
@NgModule({ declarations: [
2843
AppComponent,
29-
NavMenuComponent,
3044
QSOsComponent,
3145
EventTopComponent,
3246
DashboardComponent
@@ -40,17 +54,40 @@ export function createTranslateLoader(http: HttpClient) {
4054
deps: [HttpClient]
4155
}
4256
}),
43-
NgxPaginationModule,
57+
NgxPaginationModule,
58+
NavMenuComponent,
59+
FooterComponent,
60+
EventCardComponent,
61+
LanguageSelectorComponent,
62+
MatIconModule,
63+
MatToolbarModule,
64+
MatButtonModule,
65+
MatOptionModule,
66+
MatSelectModule,
67+
MatFormFieldModule,
68+
MatTableModule,
69+
MatMenuModule,
70+
MatDividerModule,
71+
FlexLayoutModule,
72+
MatExpansionModule,
73+
MatGridListModule,
74+
MatTooltipModule,
75+
NgxPaginationModule,
76+
HttpClientModule,
4477
FormsModule,
4578
ReactiveFormsModule,
4679
RouterModule.forRoot([
47-
{ path: 'Home', component: HomeComponent, pathMatch: 'full' },
48-
{ path: '', component: EventsComponent, pathMatch: 'full' },
49-
{ path: 'Events', component: EventsComponent, pathMatch: 'full' },
50-
{ path: ':id/top', component: EventTopComponent, pathMatch: 'full' },
51-
{ path: ':id/live', component: DashboardComponent, pathMatch: 'full' },
52-
{ path: ':id/:secret/edit', component: AdminEventComponent, pathMatch: 'full' },
53-
{ path: ':id/:secret', component: AdminQSOsComponent, pathMatch: 'full' },
54-
{ path: ':id', component: QSOsComponent, pathMatch: 'full' },
55-
])], providers: [provideHttpClient(withInterceptorsFromDi())] })
80+
{ path: '', component: HomeComponent, pathMatch: 'full' },
81+
{ path: 'events', component: EventsComponent, pathMatch: 'full' },
82+
{
83+
path: 'event',
84+
loadChildren: () => import('./event/event.module').then((m) => m.EventModule),
85+
},
86+
// { path: 'Events', component: EventsComponent, pathMatch: 'full' },
87+
// { path: ':id/top', component: EventTopComponent, pathMatch: 'full' },
88+
// { path: ':id/live', component: DashboardComponent, pathMatch: 'full' },
89+
// { path: ':id/:secret/edit', component: AdminEventComponent, pathMatch: 'full' },
90+
// { path: ':id/:secret', component: AdminQSOsComponent, pathMatch: 'full' },
91+
// { path: ':id', component: QSOsComponent, pathMatch: 'full' },
92+
])], providers: [ provideAnimations(), provideHttpClient(withInterceptorsFromDi())] })
5693
export class AppModule { }
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
<div class="px-4 text-center border-bottom">
2+
3+
<h1 class="display-4 fw-bold text-body-emphasis" *ngIf="event">{{event.name}}</h1>
4+
<div class="col mx-auto">
5+
<p *ngIf="event" [innerHTML]="event.description"></p>
6+
<nav class="navbar navbar-expand navbar-light bg-light">
7+
<div class="container-fluid">
8+
<div class="collapse navbar-collapse" id="topnavbar">
9+
<ul class="navbar-nav">
10+
<li class="nav-item" *ngIf="event">
11+
<a [routerLink]="['/',eventId]" class="nav-link" routerLinkActive="active"
12+
[routerLinkActiveOptions]="{exact:true}">{{'QSOs' | translate}}</a>
13+
</li>
14+
<li class="nav-item" *ngIf="event && event.hasTop">
15+
<a [routerLink]="['/',eventId,'top']" class="nav-link" routerLinkActive="active"
16+
[routerLinkActiveOptions]="{exact:true}">{{'Event Top' | translate}}</a>
17+
</li>
18+
<li class="nav-item" *ngIf="event && isLive">
19+
<a [routerLink]="['/',eventId,'live']" class="nav-link" routerLinkActive="active"
20+
[routerLinkActiveOptions]="{exact:true}">{{'Live' | translate}}</a>
21+
</li>
22+
</ul>
23+
</div>
24+
</div>
25+
<div class="container-fluid">
26+
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#tableMenu" aria-controls="tableMenu" aria-expanded="false" aria-label="Toggle navigation">
27+
<span class="navbar-toggler-icon"></span>
28+
</button>
29+
</div>
30+
</nav>
31+
32+
33+
<p *ngIf="!Operators?.length"><em>{{'No entries...' | translate}}</em></p>
34+
<table class='table table-striped' aria-labelledby="tableLabel" *ngIf="Operators.length">
35+
<thead>
36+
<tr>
37+
<th>{{'Callsign' | translate}}</th>
38+
<th [ngClass]="{'table-success' : bandStatus('160')}">160</th>
39+
<th [ngClass]="{'table-success' : bandStatus('80')}">80</th>
40+
<th [ngClass]="{'table-success' : bandStatus('60')}">60</th>
41+
<th [ngClass]="{'table-success' : bandStatus('40')}">40</th>
42+
<th [ngClass]="{'table-success' : bandStatus('30')}">30</th>
43+
<th [ngClass]="{'table-success' : bandStatus('20')}">20</th>
44+
<th [ngClass]="{'table-success' : bandStatus('17')}">17</th>
45+
<th [ngClass]="{'table-success' : bandStatus('15')}">15</th>
46+
<th [ngClass]="{'table-success' : bandStatus('12')}">12</th>
47+
<th [ngClass]="{'table-success' : bandStatus('10')}">10</th>
48+
</tr>
49+
</thead>
50+
<tbody>
51+
<tr *ngFor="let operator of Operators">
52+
<td>{{ operator.callsign }}</td>
53+
<td>{{ status(operator, "160") }}</td>
54+
<td>{{ status(operator, "80") }}</td>
55+
<td>{{ status(operator, "60") }}</td>
56+
<td>{{ status(operator, "40") }}</td>
57+
<td>{{ status(operator, "30") }}</td>
58+
<td>{{ status(operator, "20") }}</td>
59+
<td>{{ status(operator, "17") }}</td>
60+
<td>{{ status(operator, "15") }}</td>
61+
<td>{{ status(operator, "12") }}</td>
62+
<td>{{ status(operator, "10") }}</td>
63+
</tr>
64+
</tbody>
65+
</table>
66+
<br />
67+
68+
<table class='table table-striped' aria-labelledby="tableLabel" *ngIf="QSOs.length">
69+
<thead>
70+
<tr>
71+
<th>{{'Callsign 1' | translate}}</th>
72+
<th>{{'Callsign 2' | translate}}</th>
73+
<!--<th>RST1</th>
74+
<th>RST2</th>-->
75+
<th>{{'Mode' | translate}}</th>
76+
<th>{{'Band' | translate}}</th>
77+
<th>{{'Timestamp' | translate}}</th>
78+
</tr>
79+
</thead>
80+
<tbody>
81+
<tr *ngFor="let QSO of QSOs">
82+
<td>{{ QSO.callsign1 }}</td>
83+
<td>{{ QSO.callsign2 }}</td>
84+
<td>{{ QSO.mode }}</td>
85+
<td>{{ QSO.band }}</td>
86+
<td>{{ QSO.timestamp }}</td>
87+
</tr>
88+
</tbody>
89+
</table>
90+
</div>
91+
92+
</div>
93+
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import { Component } from '@angular/core';
2+
import { ActivatedRoute, Router, RouterLinkActive, RouterLink } from '@angular/router';
3+
import { EventsService, HamEvent } from '../../events.service';
4+
import { Operator, QSO, QSOsService } from '../../qsos.service';
5+
import { TranslateModule } from '@ngx-translate/core';
6+
import { ExtendedModule } from '@angular/flex-layout/extended';
7+
import { NgIf, NgClass, NgFor } from '@angular/common';
8+
9+
@Component({
10+
selector: 'app-dashboard',
11+
templateUrl: './dashboard.component.html',
12+
standalone: true,
13+
imports: [NgIf, RouterLinkActive, RouterLink, NgClass, ExtendedModule, NgFor, TranslateModule]
14+
})
15+
export class DashboardComponent {
16+
public eventId: string = '';
17+
public event: HamEvent | undefined;
18+
public isLive: boolean = false;
19+
public Operators: Operator[] = [];
20+
public QSOs: QSO[] = [];
21+
interval: any;
22+
23+
constructor(private routes: ActivatedRoute, private eventsService: EventsService, private qsosService: QSOsService, private router: Router) {
24+
25+
}
26+
bandStatus(band: string): boolean {
27+
if (this.Operators) {
28+
for (let operator of this.Operators) {
29+
if (this.status(operator, band) != "") {
30+
return true;
31+
}
32+
}
33+
}
34+
return false;
35+
}
36+
status(operator: Operator, band: string): string {
37+
if (operator.lastQSOs.filter(qso => qso.band.startsWith(band)).length > 0) {
38+
return operator.lastQSOs.filter(qso => qso.band.startsWith(band))[0].freq + "/" + operator.lastQSOs.filter(qso => qso.band.startsWith(band))[0].mode;
39+
}
40+
return "";
41+
}
42+
ngOnInit() {
43+
this.routes.paramMap.subscribe(params => {
44+
this.eventId = params.get('id')!;
45+
this.eventsService.getEvent(this.eventId).subscribe(
46+
(response) => {
47+
this.event = response;
48+
console.log(response);
49+
},
50+
(error) => {
51+
console.log(error);
52+
}
53+
);
54+
this.qsosService.getLive(this.eventId).subscribe(
55+
(response) => {
56+
this.loadLive(response);
57+
},
58+
(error) => {
59+
console.log(error);
60+
}
61+
);
62+
this.interval = setInterval(() => {
63+
this.qsosService.getLive(this.eventId).subscribe(
64+
(response) => {
65+
this.loadLive(response);
66+
},
67+
(error) => {
68+
console.log(error);
69+
}
70+
);
71+
}, 10000);
72+
});
73+
}
74+
private loadLive(response: any) {
75+
this.isLive = response != null && (<Array<any>>response).length > 0;
76+
this.Operators = response;
77+
this.QSOs = [];
78+
this.Operators.forEach((operator) => {
79+
this.QSOs = this.QSOs.concat(operator.lastQSOs);
80+
});
81+
this.QSOs.sort((n1, n2) => new Date(n1.timestamp) > new Date(n2.timestamp) ? -1 : 1);
82+
console.log(response);
83+
}
84+
85+
ngOnDestroy() {
86+
if (this.interval) {
87+
clearInterval(this.interval);
88+
}
89+
}
90+
}

0 commit comments

Comments
 (0)