diff --git a/backend/middlewares/AdminMWs.ts b/backend/middlewares/AdminMWs.ts index 4b5b727..d01e0bf 100644 --- a/backend/middlewares/AdminMWs.ts +++ b/backend/middlewares/AdminMWs.ts @@ -253,6 +253,30 @@ export class AdminMWs { return next(new ErrorDTO(ErrorCodes.SETTINGS_ERROR, 'Settings error: ' + JSON.stringify(err, null, ' '), err)); } } + public static async updateFacesSettings(req: Request, res: Response, next: NextFunction) { + if ((typeof req.body === 'undefined') || (typeof req.body.settings === 'undefined')) { + return next(new ErrorDTO(ErrorCodes.INPUT_ERROR, 'settings is needed')); + } + + try { + // only updating explicitly set config (not saving config set by the diagnostics) + const original = Config.original(); + await ConfigDiagnostics.testFacesConfig(req.body.settings, original); + + Config.Client.Faces = req.body.settings; + original.Client.Faces = req.body.settings; + original.save(); + await ConfigDiagnostics.runDiagnostics(); + Logger.info(LOG_TAG, 'new config:'); + Logger.info(LOG_TAG, JSON.stringify(Config, null, '\t')); + return next(); + } catch (err) { + if (err instanceof Error) { + return next(new ErrorDTO(ErrorCodes.SETTINGS_ERROR, 'Settings error: ' + err.toString(), err)); + } + return next(new ErrorDTO(ErrorCodes.SETTINGS_ERROR, 'Settings error: ' + JSON.stringify(err, null, ' '), err)); + } + } public static async updateAuthenticationSettings(req: Request, res: Response, next: NextFunction) { diff --git a/backend/model/diagnostics/ConfigDiagnostics.ts b/backend/model/diagnostics/ConfigDiagnostics.ts index 6c6d666..d98f2ad 100644 --- a/backend/model/diagnostics/ConfigDiagnostics.ts +++ b/backend/model/diagnostics/ConfigDiagnostics.ts @@ -127,6 +127,13 @@ export class ConfigDiagnostics { } + static async testFacesConfig(faces: ClientConfig.FacesConfig, config: IPrivateConfig) { + if (faces.enabled === true && + config.Server.database.type === DatabaseType.memory) { + throw new Error('Memory Database do not support faces'); + } + } + static async testSearchConfig(search: ClientConfig.SearchConfig, config: IPrivateConfig) { if (search.enabled === true && config.Server.database.type === DatabaseType.memory) { @@ -260,6 +267,16 @@ export class ConfigDiagnostics { Config.Client.Search.enabled = false; } + try { + await ConfigDiagnostics.testFacesConfig(Config.Client.Faces, Config); + } catch (ex) { + const err: Error = ex; + NotificationManager.warning('Faces are not supported with these settings. Disabling temporally. ' + + 'Please adjust the config properly.', err.toString()); + Logger.warn(LOG_TAG, 'Faces are not supported with these settings, switching off..', err.toString()); + Config.Client.Faces.enabled = false; + } + try { await ConfigDiagnostics.testSharingConfig(Config.Client.Sharing, Config); } catch (ex) { diff --git a/backend/routes/AdminRouter.ts b/backend/routes/AdminRouter.ts index ea6b165..0dceb68 100644 --- a/backend/routes/AdminRouter.ts +++ b/backend/routes/AdminRouter.ts @@ -109,6 +109,12 @@ export class AdminRouter { AdminMWs.updateSearchSettings, RenderingMWs.renderOK ); + app.put('/api/settings/faces', + AuthenticationMWs.authenticate, + AuthenticationMWs.authorise(UserRoles.Admin), + AdminMWs.updateFacesSettings, + RenderingMWs.renderOK + ); app.put('/api/settings/share', AuthenticationMWs.authenticate, AuthenticationMWs.authorise(UserRoles.Admin), diff --git a/frontend/app/app.module.ts b/frontend/app/app.module.ts index 5b3fc5a..b497d0b 100644 --- a/frontend/app/app.module.ts +++ b/frontend/app/app.module.ts @@ -80,6 +80,7 @@ import {FaceComponent} from './ui/faces/face/face.component'; import {VersionService} from './model/version.service'; import { DirectoriesComponent } from './ui/gallery/directories/directories.component'; import {ControlsLightboxComponent} from './ui/gallery/lightbox/controls/controls.lightbox.gallery.component'; +import {FacesSettingsComponent} from './ui/settings/faces/faces.settings.component'; @Injectable() @@ -178,6 +179,7 @@ export function translationsFactory(locale: string) { ShareSettingsComponent, RandomPhotoSettingsComponent, BasicSettingsComponent, + FacesSettingsComponent, OtherSettingsComponent, IndexingSettingsComponent, DuplicateComponent, diff --git a/frontend/app/ui/admin/admin.component.html b/frontend/app/ui/admin/admin.component.html index d2b03fd..48fb3dd 100644 --- a/frontend/app/ui/admin/admin.component.html +++ b/frontend/app/ui/admin/admin.component.html @@ -62,6 +62,8 @@ [simplifiedMode]="simplifiedMode"> + diff --git a/frontend/app/ui/faces/faces.component.css b/frontend/app/ui/faces/faces.component.css index 901e3e8..4b7c6d9 100644 --- a/frontend/app/ui/faces/faces.component.css +++ b/frontend/app/ui/faces/faces.component.css @@ -2,3 +2,12 @@ app-face { margin: 2px; display: inline-block; } + +.no-face-msg{ + height: 100vh; + text-align: center; +} + +.no-face-msg h2{ + color: #6c757d; +} diff --git a/frontend/app/ui/faces/faces.component.html b/frontend/app/ui/faces/faces.component.html index fb2f8d4..47be3ed 100644 --- a/frontend/app/ui/faces/faces.component.html +++ b/frontend/app/ui/faces/faces.component.html @@ -4,9 +4,17 @@ -
+
+ +
+
+

:( No faces to show. +

+
+
diff --git a/frontend/app/ui/frame/frame.component.html b/frontend/app/ui/frame/frame.component.html index 2c9ea00..d4e204d 100644 --- a/frontend/app/ui/frame/frame.component.html +++ b/frontend/app/ui/frame/frame.component.html @@ -15,10 +15,10 @@ -