14 changed files with 266 additions and 8 deletions
@ -0,0 +1,120 @@ |
|||
import { |
|||
HttpClient, |
|||
HttpErrorResponse, |
|||
HttpEvent, |
|||
HttpHandler, |
|||
HttpInterceptor, |
|||
HttpRequest |
|||
} from "@angular/common/http"; |
|||
import {Component, Injectable, OnInit, ViewContainerRef} from "@angular/core"; |
|||
import {catchError, Observable, startWith, throwError} from "rxjs"; |
|||
import {MatDialog, MatDialogRef} from "@angular/material/dialog"; |
|||
import {FormControl} from "@angular/forms"; |
|||
import {NodeMiniDTO} from "../entities/NodeMiniDTO"; |
|||
import {MatSnackBar} from "@angular/material/snack-bar"; |
|||
|
|||
|
|||
@Component({ |
|||
selector: "app-auth-dialog", |
|||
template: ` |
|||
<h2 mat-dialog-title>Авторизация</h2> |
|||
<div mat-dialog-content> |
|||
<mat-tab-group> |
|||
<mat-tab label="Через поиск"> |
|||
<div> |
|||
<div> |
|||
<mat-form-field appearance="fill" style="width: 100%"> |
|||
<mat-label>Имя ноды</mat-label> |
|||
<input |
|||
type="text" |
|||
matInput |
|||
[formControl]="myControl" |
|||
[matAutocomplete]="auto" |
|||
> |
|||
<mat-autocomplete #auto="matAutocomplete" [displayWith]="displayNode"> |
|||
<mat-option *ngFor="let node of foundedNodes | async" [value]="node"> |
|||
{{ node.long_name }} ({{node.num}}) |
|||
</mat-option> |
|||
</mat-autocomplete> |
|||
</mat-form-field> |
|||
|
|||
<button mat-button mat-raised-button (click)="sendCodeToNode()">Отправить код на ноду</button> |
|||
</div> |
|||
<mat-divider></mat-divider> |
|||
<div> |
|||
<mat-form-field class="example-full-width" appearance="fill"> |
|||
<mat-label>Код из сообщения</mat-label> |
|||
<input [(ngModel)]="code" matInput maxlength="4" placeholder="Код из сообщения"> |
|||
</mat-form-field> |
|||
<button mat-button (click)="acceptCode()">Проверить код</button> |
|||
</div> |
|||
</div> |
|||
</mat-tab> |
|||
<mat-tab label="Написать боту" disabled> |
|||
<div></div> |
|||
</mat-tab> |
|||
</mat-tab-group> |
|||
</div> |
|||
` |
|||
}) |
|||
export class AuthDialog implements OnInit { |
|||
constructor(private http: HttpClient, |
|||
private dialogRef: MatDialogRef<any>, |
|||
private snack: MatSnackBar) { |
|||
} |
|||
|
|||
ngOnInit(): void { |
|||
this.myControl.valueChanges.subscribe( |
|||
(v) => { |
|||
if (typeof v == "string") |
|||
this.foundedNodes = this.http.get(`api/nodes/search?name=${v}`) as Observable<NodeMiniDTO[]> |
|||
} |
|||
) |
|||
} |
|||
myControl = new FormControl(); |
|||
foundedNodes: Observable<NodeMiniDTO[]> = new Observable<NodeMiniDTO[]>() |
|||
code!: number |
|||
|
|||
acceptCode() { |
|||
this.http.get(`api/auth/code/check?code=${this.code}`) |
|||
// @ts-ignore
|
|||
.subscribe((res:{status:boolean}) => { |
|||
if (res.status) { |
|||
this.dialogRef.close() |
|||
} else { |
|||
this.snack.open("Неправильный код") |
|||
} |
|||
}) |
|||
} |
|||
|
|||
displayNode(node: NodeMiniDTO) { |
|||
if (!node) return '' |
|||
return `${node.long_name} (${node.num})` |
|||
} |
|||
|
|||
sendCodeToNode() { |
|||
let node:NodeMiniDTO = this.myControl.value as NodeMiniDTO |
|||
this.http.get(`api/auth/code?num=${node.num}`).subscribe( |
|||
(res) => this.snack.open(`Код отправлен на ноду ${node.long_name}`) |
|||
) |
|||
} |
|||
} |
|||
|
|||
@Injectable() |
|||
export class AuthInterceptor implements HttpInterceptor { |
|||
constructor(private dialog: MatDialog) {} |
|||
dialogOpened: boolean = false; |
|||
|
|||
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { |
|||
return next.handle(req).pipe( |
|||
catchError((error: HttpErrorResponse) => { |
|||
if (error.status === 401 && !this.dialogOpened) { |
|||
const ref = this.dialog.open(AuthDialog, {disableClose: true, width:"50%"}) |
|||
ref.afterClosed().subscribe((res:any) => this.dialogOpened = false) |
|||
} |
|||
return throwError(() => error); |
|||
}) |
|||
) |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
import {Component} from "@angular/core"; |
|||
|
|||
@Component({ |
|||
selector: "app-bot-commands", |
|||
template: `` |
|||
}) |
|||
export class BotCommandsComponent { |
|||
|
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
import {Component} from "@angular/core"; |
|||
|
|||
@Component({ |
|||
selector: "app-message-history", |
|||
template: `` |
|||
}) |
|||
export class MessageHistoryComponent { |
|||
|
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
import {Component} from "@angular/core"; |
|||
|
|||
@Component({ |
|||
selector: "app-all-nodes", |
|||
template: `` |
|||
}) |
|||
export class AllNodesComponent { |
|||
|
|||
} |
|||
@ -0,0 +1,39 @@ |
|||
import {Component, OnInit} from "@angular/core"; |
|||
import {HttpClient} from "@angular/common/http"; |
|||
import {NodeDTO} from "../../entities/NodeDTO"; |
|||
|
|||
@Component({ |
|||
selector: 'app-direct-nodes', |
|||
styleUrls: ['nodes.styles.scss'], |
|||
template: ` |
|||
<!--<p *ngFor="let node of nodes">{{node.long_name}}</p>--> |
|||
<div class="card-wrapper"> |
|||
<mat-card *ngFor="let node of nodes" style="min-width: 250px"> |
|||
<mat-card-header> |
|||
<mat-card-title>{{node.long_name}}</mat-card-title> |
|||
<mat-card-subtitle>{{node.short_name}} ({{node.num}})</mat-card-subtitle> |
|||
</mat-card-header> |
|||
<mat-card-content> |
|||
<p>график</p> |
|||
</mat-card-content> |
|||
<mat-card-actions> |
|||
<button mat-button *ngIf="node.hops_away > 0">Прыжков: {{node.hops_away}}</button> |
|||
<button mat-button>SNR: {{node.snr}}</button> |
|||
<button mat-button>{{node.ts * 1000 | date:"hh:mm dd.MM.yyyy"}}</button> |
|||
</mat-card-actions> |
|||
</mat-card> |
|||
</div> |
|||
` |
|||
}) |
|||
export class DirectNodesComponent implements OnInit { |
|||
constructor(private http: HttpClient) { |
|||
} |
|||
|
|||
nodes: NodeDTO[] = []; |
|||
|
|||
ngOnInit(): void { |
|||
this.http.get(`api/nodes/direct`).subscribe( |
|||
(res) => this.nodes = res as NodeDTO[] |
|||
) |
|||
} |
|||
} |
|||
@ -0,0 +1,11 @@ |
|||
.card-wrapper { |
|||
display: grid; |
|||
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); |
|||
gap: 8px; |
|||
} |
|||
|
|||
.grid-card { |
|||
width: 100%; |
|||
height: 100%; |
|||
/* Additional styling as needed */ |
|||
} |
|||
@ -0,0 +1,7 @@ |
|||
import {NodeMiniDTO} from "./NodeMiniDTO"; |
|||
|
|||
export interface NodeDTO extends NodeMiniDTO { |
|||
snr: number, |
|||
hops_away: number, |
|||
ts: number |
|||
} |
|||
@ -0,0 +1,5 @@ |
|||
export interface NodeMiniDTO { |
|||
num: number, |
|||
long_name: string, |
|||
short_name: string |
|||
} |
|||
@ -0,0 +1,6 @@ |
|||
{ |
|||
"/api": { |
|||
"target": "http://192.168.3.2:8680/", |
|||
"secure": false |
|||
} |
|||
} |
|||
Loading…
Reference in new issue