From f340d9417f3ae0b4616f461cfa0441bb123b9540 Mon Sep 17 00:00:00 2001 From: gsd Date: Wed, 11 Feb 2026 19:27:42 +0300 Subject: [PATCH] docker img --- docker-compose.example.yaml | 16 ++++++- ui/Dockerfile | 10 ++++ ui/src/app/auth/AuthInterceptor.ts | 1 + .../messages/MessageHistory.component.ts | 46 +++++++++++++++---- ui/srv.conf | 19 ++++++++ 5 files changed, 81 insertions(+), 11 deletions(-) create mode 100644 ui/Dockerfile create mode 100644 ui/srv.conf diff --git a/docker-compose.example.yaml b/docker-compose.example.yaml index 3fdd123..55cc810 100644 --- a/docker-compose.example.yaml +++ b/docker-compose.example.yaml @@ -39,4 +39,18 @@ services: resources: limits: cpus: "1" - memory: 1024M \ No newline at end of file + memory: 1024M + + meshcenterfrontend: + build: + context: ./ui + dockerfile: Dockerfile + ports: + - 8686:80 + depends_on: + - meshcenterbackend + deploy: + resources: + limits: + cpus: "1" + memory: 1024M \ No newline at end of file diff --git a/ui/Dockerfile b/ui/Dockerfile new file mode 100644 index 0000000..a6c8290 --- /dev/null +++ b/ui/Dockerfile @@ -0,0 +1,10 @@ +FROM node:18-alpine as builder +WORKDIR /build +COPY . . +RUN npm install --reg https://nexus.pblr-nyk.pro/repository/npm/ && \ + npm run ng build +FROM nginx:stable-alpine +COPY --from=builder /build/dist/ui /usr/share/nginx/html +RUN rm /etc/nginx/conf.d/default.conf +COPY srv.conf /etc/nginx/conf.d +CMD ["nginx", "-g", "daemon off;"] diff --git a/ui/src/app/auth/AuthInterceptor.ts b/ui/src/app/auth/AuthInterceptor.ts index c3b104b..1e4e14c 100644 --- a/ui/src/app/auth/AuthInterceptor.ts +++ b/ui/src/app/auth/AuthInterceptor.ts @@ -123,6 +123,7 @@ export class AuthInterceptor implements HttpInterceptor { return next.handle(req).pipe( catchError((error: HttpErrorResponse) => { if (error.status === 401 && !this.dialogOpened) { + this.dialogOpened = true; const ref = this.dialog.open(AuthDialog, {disableClose: true, width:"30%"}) ref.afterClosed().subscribe((res:any) => this.dialogOpened = false) } diff --git a/ui/src/app/components/messages/MessageHistory.component.ts b/ui/src/app/components/messages/MessageHistory.component.ts index bf54acc..299825d 100644 --- a/ui/src/app/components/messages/MessageHistory.component.ts +++ b/ui/src/app/components/messages/MessageHistory.component.ts @@ -1,4 +1,4 @@ -import {Component, OnInit} from "@angular/core"; +import {Component, OnDestroy, OnInit} from "@angular/core"; import {HttpClient} from "@angular/common/http"; import {MessageDTO} from "../../entities/MessageDTO"; import {NodeDTO} from "../../entities/NodeDTO"; @@ -11,7 +11,7 @@ import {Subscription} from "rxjs";
- + {{knownNodes[msg.from.toString()] == null ? msg.from : knownNodes[msg.from.toString()].long_name}} | {{msg.ts * 1000 | date: 'HH:mm:ss dd.MM.yyyy'}} | {{msg.hop_start - msg.hop_limit == 0 ? 'напрямую' : (msg.hop_start - msg.hop_limit) + ' хопов'}} | rssi: {{msg.rx_rssi}} snr: {{msg.rx_snr}} {{msg.decoded_payload}} @@ -19,7 +19,7 @@ import {Subscription} from "rxjs";
` }) -export class MessageHistoryComponent implements OnInit { +export class MessageHistoryComponent implements OnInit, OnDestroy { constructor(private http: HttpClient) {} loading: boolean = false; @@ -28,20 +28,26 @@ export class MessageHistoryComponent implements OnInit { offset = 0; limit = 10; lastMsgTs = 0; - + olderMsgTs = new Date().getTime()/1000; + interval:any = null; knownNodes:KeyValueMap = {} ngOnInit() { this.getMessages(); - setInterval(() => { - //this.newMessagePooler() - }, 1000) + this.interval = setInterval(() => { + this.newMessagePooler() + }, 5000) + } + + ngOnDestroy(): void { + if (this.interval) + clearInterval(this.interval) } tryKnownNodes(nums: number[]) { let notKnownNodes = nums.filter(num => Object.keys(this.knownNodes).indexOf(`${num}`) == -1) if (notKnownNodes.length == 0) return Subscription.EMPTY; - let params = notKnownNodes.length > 1 ? notKnownNodes.join("&nums=") : `$nums=${notKnownNodes.pop()}`; + let params = notKnownNodes.length > 1 ? "&nums=" + notKnownNodes.join("&nums=") : `?nums=${notKnownNodes.pop()}`; return this.http.get(`api/nodes?s=1${params}`).subscribe( (res) => { (res as NodeDTO[]).forEach( @@ -53,7 +59,7 @@ export class MessageHistoryComponent implements OnInit { getMessages() { this.loading = true; - this.http.get(`api/messages?offset=${this.offset}&limit=${this.limit}&after=${this.lastMsgTs}`) + this.http.get(`api/messages?limit=${this.limit}&before=${this.olderMsgTs}`) .subscribe((res) => { let new_msgs = res as MessageDTO[] this.tryKnownNodes(new_msgs.map(msg => msg.from)).add( @@ -62,6 +68,9 @@ export class MessageHistoryComponent implements OnInit { .sort((m1, m2) => m1.ts - m2.ts); if (this.messages.length>0) { + if (this.messages[0].ts < this.olderMsgTs) + this.olderMsgTs = this.messages[0].ts; + if (this.messages[this.messages.length-1].ts > this.lastMsgTs) this.lastMsgTs = this.messages[this.messages.length-1].ts; } @@ -77,7 +86,7 @@ export class MessageHistoryComponent implements OnInit { //ЭХ ВОТ БЫ ВЕБСОКЕТ НО МНЕ ЛЕНЬ newMessagePooler() { - this.http.get(`api/messages?offset=0&limit=10&after=${this.lastMsgTs}`) + this.http.get(`api/messages?limit=10&after=${this.lastMsgTs}&before=2147483647`)//todo 37 year moment .subscribe((res) => { let new_msgs = res as MessageDTO[] this.tryKnownNodes(new_msgs.map(msg => msg.from)).add( @@ -92,4 +101,21 @@ export class MessageHistoryComponent implements OnInit { ) }) } + + numToColor(num:number) { + // Приводим к беззнаковому 32-битному и перемешиваем биты + let n = num >>> 0; + // Мультипликативная хеш-функция с простыми числами + n = (n * 2654435761) >>> 0; // константа из Knuth + n ^= (n >> 16); + n = (n * 0x85EBCA6B) >>> 0; + n ^= (n >> 13); + n = (n * 0xC2B2AE35) >>> 0; + n ^= (n >> 16); + + const r = (n >> 16) & 0xFF; + const g = (n >> 8) & 0xFF; + const b = n & 0xFF; + return `rgba(${r}, ${g}, ${b}, 0.2)` + } } diff --git a/ui/srv.conf b/ui/srv.conf new file mode 100644 index 0000000..35781a5 --- /dev/null +++ b/ui/srv.conf @@ -0,0 +1,19 @@ +server { + listen 80; + listen [::]:80; + server_name localhost; + + root /usr/share/nginx/html; + index index.html index.htm; + + location / { + try_files $uri /index.html; + } + + location /api/ { + proxy_pass http://meshcenterbackend:8680; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + } +}