1
0
mirror of https://github.com/bpatrik/pigallery2.git synced 2025-11-23 22:24:44 +02:00

Trigger autoReload on UI when Client config changed or app reloaded #1078

This commit is contained in:
Patrik J. Braun
2025-11-21 20:37:00 +01:00
parent 8f31bc836e
commit 9c6e194af6
8 changed files with 80 additions and 7 deletions

View File

@@ -2,8 +2,37 @@ import {NextFunction, Request, Response} from 'express';
import {ObjectManagers} from '../model/ObjectManagers'; import {ObjectManagers} from '../model/ObjectManagers';
import {ErrorCodes, ErrorDTO} from '../../common/entities/Error'; import {ErrorCodes, ErrorDTO} from '../../common/entities/Error';
import {CustomHeaders} from '../../common/CustomHeaders'; import {CustomHeaders} from '../../common/CustomHeaders';
import {Config} from '../../common/config/private/Config';
import * as crypto from 'crypto';
export class VersionMWs { export class VersionMWs {
/**
* This version data is mainly used to trigger page reload on the client side
*/
public static async injectAppVersion(
req: Request,
res: Response,
next: NextFunction
): Promise<void> {
try {
const clientConfigStr = JSON.stringify(Config.getClientConfig());
const hash = crypto.createHash('md5').update(Config.Environment.upTime + clientConfigStr).digest('hex');
res.header(
CustomHeaders.appVersion,
hash
);
next();
} catch (err) {
return next(
new ErrorDTO(
ErrorCodes.GENERAL_ERROR,
'Can not get app version',
err.toString()
)
);
}
}
/** /**
* This version data is mainly used on the client side to invalidate the cache * This version data is mainly used on the client side to invalidate the cache
*/ */

View File

@@ -85,11 +85,7 @@ export class PublicRouter {
} as UserDTO; } as UserDTO;
} }
const confCopy = Config.toJSON({ const confCopy = Config.getClientConfig();
attachVolatile: true,
skipTags: {secret: true} as TAGS,
keepTags: {client: true}
}) as unknown as ClientConfig;
// Escaping html tags, like <script></script> // Escaping html tags, like <script></script>
confCopy.Server.customHTMLHead = confCopy.Server.customHTMLHead =
confCopy.Server.customHTMLHead confCopy.Server.customHTMLHead

View File

@@ -10,9 +10,11 @@ import {NotificationRouter} from './NotificationRouter';
import {ErrorRouter} from './ErrorRouter'; import {ErrorRouter} from './ErrorRouter';
import {AlbumRouter} from './AlbumRouter'; import {AlbumRouter} from './AlbumRouter';
import {ExtensionRouter} from './admin/ExtensionRouter'; import {ExtensionRouter} from './admin/ExtensionRouter';
import {VersionMWs} from '../middlewares/VersionMWs';
export class Router { export class Router {
public static route(app: Express): void { public static route(app: Express): void {
app.use(VersionMWs.injectAppVersion);
PublicRouter.route(app); PublicRouter.route(app);
AdminRouter.route(app); AdminRouter.route(app);

View File

@@ -1,3 +1,4 @@
export class CustomHeaders { export class CustomHeaders {
public static dataVersion = 'PI-GALLERY2-DATA-VERSION'; public static dataVersion = 'PI-GALLERY2-DATA-VERSION';
public static appVersion = 'PI-GALLERY2-APP-VERSION';
} }

View File

@@ -5,7 +5,7 @@ import * as path from 'path';
import {ConfigClass} from 'typeconfig/node'; import {ConfigClass} from 'typeconfig/node';
import {IConfigClass} from 'typeconfig/common'; import {IConfigClass} from 'typeconfig/common';
import {PasswordHelper} from '../../../backend/model/PasswordHelper'; import {PasswordHelper} from '../../../backend/model/PasswordHelper';
import {TAGS} from '../public/ClientConfig'; import {ClientConfig, TAGS} from '../public/ClientConfig';
declare const process: any; declare const process: any;
const upTime = new Date().toISOString(); const upTime = new Date().toISOString();
@@ -87,5 +87,13 @@ export class PrivateConfigClass extends ServerConfig {
this.Environment.isDocker = !!process.env.PI_DOCKER; this.Environment.isDocker = !!process.env.PI_DOCKER;
} }
getClientConfig() {
return (this as unknown as IConfigClass<TAGS>).toJSON({
attachVolatile: true,
skipTags: {secret: true} as TAGS,
keepTags: {client: true}
}) as unknown as ClientConfig;
}
} }

File diff suppressed because one or more lines are too long

View File

@@ -113,6 +113,11 @@ export class NetworkService {
res.headers.get(CustomHeaders.dataVersion) res.headers.get(CustomHeaders.dataVersion)
); );
} }
if (res.headers.has(CustomHeaders.appVersion)) {
this.versionService.onNewAppVersion(
res.headers.get(CustomHeaders.appVersion)
);
}
if (msg.error) { if (msg.error) {
if (msg.error.code) { if (msg.error.code) {
(msg.error as any).title = ErrorCodes[msg.error.code]; (msg.error as any).title = ErrorCodes[msg.error.code];

View File

@@ -1,12 +1,16 @@
import {Injectable} from '@angular/core'; import {Injectable} from '@angular/core';
import {BehaviorSubject} from 'rxjs'; import {BehaviorSubject} from 'rxjs';
import {Router} from '@angular/router';
import {Config} from '../../../common/config/public/Config';
@Injectable() @Injectable()
export class VersionService { export class VersionService {
public version: BehaviorSubject<string>; public version: BehaviorSubject<string>;
public appVersion: BehaviorSubject<string>;
constructor() { constructor(private router: Router) {
this.version = new BehaviorSubject<string>(null); this.version = new BehaviorSubject<string>(null);
this.appVersion = new BehaviorSubject<string>(null);
} }
public onNewVersion(version: string): void { public onNewVersion(version: string): void {
@@ -15,4 +19,21 @@ export class VersionService {
} }
this.version.next(version); this.version.next(version);
} }
public onNewAppVersion(version: string): void {
if (this.appVersion.value === version) {
return;
}
if(!this.appVersion.value) {
this.appVersion.next(version);
return;
}
if(Config.Server.reloadClientOnServerUpdate)
// do not reload on the settings page
if(this.router.url.startsWith('/admin')) {
return;
}
console.log('App version changed. Reloading site.');
window.location.reload();
}
} }