Version 5.2.4

This commit is contained in:
Chrystian Huot 2021-08-10 08:17:48 -04:00
parent 3edfa3f9ec
commit fa6d85318a
17 changed files with 1296 additions and 499 deletions

View file

@ -22,6 +22,12 @@ _v5.2.3_
- Change history columns padding from 1px to 6px on the main screen.
- Fix a bug in the admin api where the server crash when saving new config from the admin dashboard.
_v5.2.4_
- Updated to Angular 12.2.
- New update prompt for clients when server is updated.
- Fix unaligned back arrow on the search panel.
# Version 5.1
This one is a big one... **Be sure to backup your config.json and your database.sqlite before updating.**

View file

@ -1,36 +1,20 @@
{
"env": {
"commonjs": true,
"es6": true,
"node": true
},
"extends": "eslint:recommended",
"globals": {
"Atomics": "readonly",
"SharedArrayBuffer": "readonly"
"browser": true,
"es2021": true
},
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 2020,
"ecmaVersion": 12,
"sourceType": "module"
},
"plugins": [
"@typescript-eslint"
],
"rules": {
"linebreak-style": [
"error",
"unix"
],
"max-len": [
"error",
{
"code": 140
}
],
"quotes": [
"error",
"single"
],
"semi": [
"error",
"always"
]
}
}
}

1535
client/package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,26 +1,29 @@
{
"author": "Chrystian Huot <chrystian.huot@saubeo.solutions>",
"dependencies": {
"@angular/animations": "^12.1.4",
"@angular/cdk": "^12.1.4",
"@angular/common": "~12.1.4",
"@angular/compiler": "~12.1.4",
"@angular/core": "~12.1.4",
"@angular/forms": "~12.1.4",
"@angular/material": "^12.1.4",
"@angular/platform-browser": "~12.1.4",
"@angular/platform-browser-dynamic": "~12.1.4",
"@angular/router": "^12.1.4",
"@angular/service-worker": "^12.1.4",
"@angular/animations": "^12.2.0",
"@angular/cdk": "^12.2.0",
"@angular/common": "~12.2.0",
"@angular/compiler": "~12.2.0",
"@angular/core": "~12.2.0",
"@angular/forms": "~12.2.0",
"@angular/material": "^12.2.0",
"@angular/platform-browser": "~12.2.0",
"@angular/platform-browser-dynamic": "~12.2.0",
"@angular/router": "^12.2.0",
"@angular/service-worker": "^12.2.0",
"rxjs": "~6.5.5",
"tslib": "^2.3.0",
"zone.js": "~0.11.4"
},
"devDependencies": {
"@angular-devkit/build-angular": "~12.1.4",
"@angular/cli": "^12.1.4",
"@angular/compiler-cli": "~12.1.4",
"@types/node": "~16.4.10",
"@angular-devkit/build-angular": "~12.2.0",
"@angular/cli": "^12.2.0",
"@angular/compiler-cli": "~12.2.0",
"@types/node": "~16.4.13",
"@typescript-eslint/eslint-plugin": "^4.29.0",
"@typescript-eslint/parser": "^4.29.0",
"eslint": "^7.32.0",
"ts-node": "~10.1.0",
"typescript": "~4.2.4"
},
@ -34,5 +37,5 @@
"build": "ng build --base-href ./ --configuration production",
"start": "ng serve"
},
"version": "5.2.3"
"version": "5.2.4"
}

View file

@ -33,7 +33,7 @@ $background-color: rgb(30, 30, 30);
flex-direction: column;
height: 100%;
&.search .mat-toolbar >  div {
&.search .mat-toolbar > div {
justify-content: flex-end;
}

View file

@ -19,7 +19,7 @@
import { Component, ElementRef, HostListener, OnDestroy, ViewChild } from '@angular/core';
import { MatSidenav } from '@angular/material/sidenav';
import { RdioScannerConfig, RdioScannerEvent, RdioScannerLivefeedMode } from './rdio-scanner';
import { RdioScannerEvent, RdioScannerLivefeedMode } from './rdio-scanner';
import { RdioScannerService } from './rdio-scanner.service';
@Component({
@ -28,8 +28,6 @@ import { RdioScannerService } from './rdio-scanner.service';
templateUrl: './rdio-scanner.component.html',
})
export class RdioScannerComponent implements OnDestroy {
private config: RdioScannerConfig | undefined;
private eventSubscription = this.rdioScannerService.event.subscribe((event: RdioScannerEvent) => this.eventHandler(event));
private livefeedMode: RdioScannerLivefeedMode = RdioScannerLivefeedMode.Offline;
@ -108,10 +106,6 @@ export class RdioScannerComponent implements OnDestroy {
}
private eventHandler(event: RdioScannerEvent): void {
if ('config' in event) {
this.config = event.config;
}
if (event.livefeedMode) {
this.livefeedMode = event.livefeedMode;
}

View file

@ -21,6 +21,7 @@ import { DOCUMENT } from '@angular/common';
import { EventEmitter, Inject, Injectable, OnDestroy } from '@angular/core';
import { interval, Subscription, timer } from 'rxjs';
import { takeWhile } from 'rxjs/operators';
import { AppUpdateService } from '../../shared/update/update.service';
import {
RdioScannerAvoidOptions,
RdioScannerBeepStyle,
@ -54,7 +55,6 @@ enum WebsocketCommand {
LivefeedMap = 'LFM',
Max = 'MAX',
Pin = 'PIN',
Ver = 'VER',
}
@Injectable()
@ -97,7 +97,10 @@ export class RdioScannerService implements OnDestroy {
private websocket: WebSocket | undefined;
constructor(@Inject(DOCUMENT) private document: Document) {
constructor(
private appUpdateService: AppUpdateService,
@Inject(DOCUMENT) private document: Document,
) {
this.bootstrapAudio();
this.restoreLivefeed();
@ -791,7 +794,7 @@ export class RdioScannerService implements OnDestroy {
break;
case WebsocketCommand.Config:
case WebsocketCommand.Config: {
const config = message[1];
this.config = {
@ -818,6 +821,7 @@ export class RdioScannerService implements OnDestroy {
});
break;
}
case WebsocketCommand.Expired:
this.event.emit({ auth: true, expired: true });
@ -915,8 +919,6 @@ export class RdioScannerService implements OnDestroy {
private rebuildLivefeedMap(): void {
const livefeedMap = this.config.systems.reduce((sysMap, sys) => {
const tgs = sys.talkgroups.map((tg) => tg.id.toString());
sysMap[sys.id] = sys.talkgroups.reduce((tgMap, tg) => {
const state = this.livefeedMap && this.livefeedMap[sys.id] && this.livefeedMap[sys.id][tg.id];

View file

@ -23,6 +23,7 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { ExtraOptions, RouterModule, Routes } from '@angular/router';
import { AppLocaleModule } from './locale/locale.module';
import { AppMaterialModule } from './material/material.module';
import { AppUpdateModule } from './update/update.module';
export interface AppSharedModuleConfig {
routerExtraOptions?: ExtraOptions;
@ -33,6 +34,7 @@ export interface AppSharedModuleConfig {
exports: [
AppLocaleModule,
AppMaterialModule,
AppUpdateModule,
CommonModule,
FormsModule,
ReactiveFormsModule,
@ -54,6 +56,7 @@ export class AppSharedModule {
ngModule: AppSharedModule,
providers: [
...AppLocaleModule.forRoot().providers || [],
...AppUpdateModule.forRoot().providers || [],
...RouterModule.forRoot(config.routerRoutes || [], config.routerExtraOptions || {}).providers || [],
],
};

View file

@ -0,0 +1,6 @@
<h1 mat-dialog-title>New version available</h1>
<div mat-dialog-content>A new version of this webapp is available. Would you like to reload the page?</div>
<div mat-dialog-actions>
<button mat-raised-button mat-dialog-close>No</button>
<button mat-raised-button color="primary" mat-dialog-close="true">Yes</button>
</div>

View file

@ -0,0 +1,3 @@
.mat-dialog-actions {
justify-content: space-between;
}

View file

@ -0,0 +1,26 @@
/*
* *****************************************************************************
* Copyright (C) 2019-2021 Chrystian Huot <chrystian.huot@saubeo.solutions>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
* ****************************************************************************
*/
import { Component } from '@angular/core';
@Component({
templateUrl: './update.component.html',
styleUrls: ['./update.component.scss'],
})
export class AppUpdateComponent { }

View file

@ -0,0 +1,44 @@
/*
* *****************************************************************************
* Copyright (C) 2019-2021 Chrystian Huot <chrystian.huot@saubeo.solutions>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
* ****************************************************************************
*/
import { ModuleWithProviders, NgModule } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { MatDialogModule } from '@angular/material/dialog';
import { ServiceWorkerModule } from '@angular/service-worker';
import { AppUpdateComponent } from './update.component';
import { AppUpdateService } from './update.service';
@NgModule({
declarations: [AppUpdateComponent],
imports: [
MatButtonModule,
MatDialogModule,
ServiceWorkerModule,
],
})
export class AppUpdateModule {
static forRoot(): ModuleWithProviders<AppUpdateModule> {
return {
ngModule: AppUpdateModule,
providers: [AppUpdateService],
};
}
// constructor(appUpdateService: AppUpdateService) { }
}

View file

@ -0,0 +1,47 @@
/*
* *****************************************************************************
* Copyright (C) 2019-2021 Chrystian Huot <chrystian.huot@saubeo.solutions>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
* ****************************************************************************
*/
import { Injectable } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { SwUpdate } from '@angular/service-worker';
import { AppUpdateComponent } from './update.component';
@Injectable()
export class AppUpdateService {
constructor(
private matDialog: MatDialog,
private swUpdate: SwUpdate,
) {
swUpdate.available.subscribe(() => this.prompt());
swUpdate.checkForUpdate();
setInterval(() => swUpdate.checkForUpdate(), 5 * 60 * 1000);
}
prompt(): void {
this.matDialog.open(AppUpdateComponent).afterClosed().subscribe((doUpdate) => {
if (doUpdate) {
if (this.swUpdate.isEnabled) {
this.swUpdate.activateUpdate().then(() => document.location.reload());
} else {
document.location.reload();
}
}
});
}
}

View file

@ -14,5 +14,5 @@
"update": "node update"
},
"type": "module",
"version": "5.2.3"
"version": "5.2.4"
}

View file

@ -19,6 +19,6 @@
'use strict';
export const version = '5.2.3';
export const version = '5.2.4';
export default version;

View file

@ -1,6 +1,6 @@
{
"name": "rdio-scanner-server",
"version": "5.2.3",
"version": "5.2.4",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@ -835,9 +835,9 @@
"dev": true
},
"caniuse-lite": {
"version": "1.0.30001248",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001248.tgz",
"integrity": "sha512-NwlQbJkxUFJ8nMErnGtT0QTM2TJ33xgz4KXJSMIrjXIbDVdaYueGyjOrLKRtJC+rTiWfi6j5cnZN1NBiSBJGNw==",
"version": "1.0.30001249",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001249.tgz",
"integrity": "sha512-vcX4U8lwVXPdqzPWi6cAJ3FnQaqXbBqy/GZseKNQzRj37J7qZdGcBtxq/QLFNLLlfsoXLUdHw8Iwenri86Tagw==",
"dev": true
},
"caseless": {
@ -1276,9 +1276,9 @@
"integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
},
"electron-to-chromium": {
"version": "1.3.793",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.793.tgz",
"integrity": "sha512-l9NrGV6Mr4ov5mayYPvIWcwklNw5ROmy6rllzz9dCACw9nKE5y+s5uQk+CBJMetxrWZ6QJFsvEfG6WDcH2IGUg==",
"version": "1.3.799",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.799.tgz",
"integrity": "sha512-V2rbYWdGvSqrg+95KjkVuSi41bGfrhrOzjl1tSi2VLnm0mRe3FsSvhiqidSiSll9WiMhrQAhpDcW/wcqK3c+Yw==",
"dev": true
},
"emoji-regex": {
@ -4382,9 +4382,9 @@
}
},
"webpack": {
"version": "5.48.0",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.48.0.tgz",
"integrity": "sha512-CGe+nfbHrYzbk7SKoYITCgN3LRAG0yVddjNUecz9uugo1QtYdiyrVD8nP1PhkNqPfdxC2hknmmKpP355Epyn6A==",
"version": "5.49.0",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.49.0.tgz",
"integrity": "sha512-XarsANVf28A7Q3KPxSnX80EkCcuOer5hTOEJWJNvbskOZ+EK3pobHarGHceyUZMxpsTHBHhlV7hiQyLZzGosYw==",
"dev": true,
"requires": {
"@types/eslint-scope": "^3.7.0",

View file

@ -24,7 +24,7 @@
"devDependencies": {
"eslint": "^7.32.0",
"nodemon": "^2.0.12",
"webpack": "^5.48.0",
"webpack": "^5.49.0",
"webpack-cli": "^4.7.2",
"webpack-node-externals": "^3.0.0"
},
@ -46,5 +46,5 @@
"start": "nodemon"
},
"type": "module",
"version": "5.2.3"
"version": "5.2.4"
}