diff --git a/src/backend/middlewares/admin/SettingsMWs.ts b/src/backend/middlewares/admin/SettingsMWs.ts index ea443da7..2a24d3d6 100644 --- a/src/backend/middlewares/admin/SettingsMWs.ts +++ b/src/backend/middlewares/admin/SettingsMWs.ts @@ -14,6 +14,7 @@ import { ServerIndexingConfig, ServerJobConfig, ServerPhotoConfig, + ServerPreviewConfig, ServerThumbnailConfig, ServerVideoConfig } from '../../../common/config/private/PrivateConfig'; @@ -101,6 +102,31 @@ export class SettingsMWs { } } + public static async updatePreviewSettings(req: Request, res: Response, next: NextFunction): Promise { + if ((typeof req.body === 'undefined') || (typeof req.body.settings === 'undefined')) { + return next(new ErrorDTO(ErrorCodes.INPUT_ERROR, 'settings is needed')); + } + + try { + await ConfigDiagnostics.testPreviewConfig(req.body.settings as ServerPreviewConfig); + + Config.Server.Preview = (req.body.settings as ServerPreviewConfig); + // only updating explicitly set config (not saving config set by the diagnostics) + const original = await Config.original(); + original.Server.Preview = (req.body.settings as ServerPreviewConfig); + 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 updateVideoSettings(req: Request, res: Response, next: NextFunction): Promise { if ((typeof req.body === 'undefined') || (typeof req.body.settings === 'undefined')) { return next(new ErrorDTO(ErrorCodes.INPUT_ERROR, 'settings is needed')); diff --git a/src/backend/model/diagnostics/ConfigDiagnostics.ts b/src/backend/model/diagnostics/ConfigDiagnostics.ts index c71de4ba..e662fd5e 100644 --- a/src/backend/model/diagnostics/ConfigDiagnostics.ts +++ b/src/backend/model/diagnostics/ConfigDiagnostics.ts @@ -24,8 +24,12 @@ import { ServerDataBaseConfig, ServerJobConfig, ServerPhotoConfig, + ServerPreviewConfig, ServerVideoConfig } from '../../../common/config/private/PrivateConfig'; +import {SearchQueryParser} from '../../../common/SearchQueryParser'; +import {SearchQueryTypes, TextSearch} from '../../../common/entities/SearchQueryDTO'; +import {Utils} from '../../../common/Utils'; const LOG_TAG = '[ConfigDiagnostics]'; @@ -225,6 +229,13 @@ export class ConfigDiagnostics { } + static async testPreviewConfig(settings: ServerPreviewConfig): Promise { + const sp = new SearchQueryParser(); + if (!Utils.equalsFilter(sp.parse(sp.stringify(settings.SearchQuery)), settings.SearchQuery)) { + throw new Error('SearchQuery is not valid'); + } + } + static async runDiagnostics(): Promise { if (Config.Server.Database.type !== DatabaseType.memory) { @@ -315,6 +326,16 @@ export class ConfigDiagnostics { Config.Client.Search.enabled = false; } + + try { + await ConfigDiagnostics.testPreviewConfig(Config.Server.Preview); + } catch (ex) { + const err: Error = ex; + NotificationManager.warning('Preview settings are not valid, resetting search query', err.toString()); + Logger.warn(LOG_TAG, 'Preview settings are not valid, resetting search query', err.toString()); + Config.Server.Preview.SearchQuery = {type: SearchQueryTypes.any_text, text: ''} as TextSearch; + } + try { await ConfigDiagnostics.testFacesConfig(Config.Client.Faces, Config); } catch (ex) { diff --git a/src/backend/routes/admin/SettingsRouter.ts b/src/backend/routes/admin/SettingsRouter.ts index 6b41977d..65623b04 100644 --- a/src/backend/routes/admin/SettingsRouter.ts +++ b/src/backend/routes/admin/SettingsRouter.ts @@ -68,6 +68,12 @@ export class SettingsRouter { SettingsMWs.updateSearchSettings, RenderingMWs.renderOK ); + app.put('/api/settings/preview', + AuthenticationMWs.authenticate, + AuthenticationMWs.authorise(UserRoles.Admin), + SettingsMWs.updatePreviewSettings, + RenderingMWs.renderOK + ); app.put('/api/settings/faces', AuthenticationMWs.authenticate, AuthenticationMWs.authorise(UserRoles.Admin), diff --git a/src/common/config/private/PrivateConfig.ts b/src/common/config/private/PrivateConfig.ts index b8e0ba10..3f6b6ff4 100644 --- a/src/common/config/private/PrivateConfig.ts +++ b/src/common/config/private/PrivateConfig.ts @@ -5,7 +5,7 @@ import {ClientConfig} from '../public/ClientConfig'; import {SubConfigClass} from 'typeconfig/src/decorators/class/SubConfigClass'; import {ConfigProperty} from 'typeconfig/src/decorators/property/ConfigPropoerty'; import {DefaultsJobs} from '../../entities/job/JobDTO'; -import {SearchQueryDTO} from '../../entities/SearchQueryDTO'; +import {SearchQueryDTO, SearchQueryTypes, TextSearch} from '../../entities/SearchQueryDTO'; import {SortingMethods} from '../../entities/SortingMethods'; import {UserRoles} from '../../entities/UserDTO'; @@ -334,7 +334,7 @@ export class ServerPhotoConfig { @SubConfigClass() export class ServerPreviewConfig { @ConfigProperty({type: 'object'}) - SearchQuery: SearchQueryDTO = null; + SearchQuery: SearchQueryDTO = {type: SearchQueryTypes.any_text, text: ''} as TextSearch; @ConfigProperty({arrayType: SortingMethods}) Sorting: SortingMethods[] = [ SortingMethods.descRating, diff --git a/src/frontend/app/app.module.ts b/src/frontend/app/app.module.ts index 3e6140ef..06807470 100644 --- a/src/frontend/app/app.module.ts +++ b/src/frontend/app/app.module.ts @@ -95,7 +95,7 @@ import {GallerySearchQueryEntryComponent} from './ui/gallery/search/query-enrty/ import {StringifySearchQuery} from './pipes/StringifySearchQuery'; import {AutoCompleteService} from './ui/gallery/search/autocomplete.service'; import {SearchQueryParserService} from './ui/gallery/search/search-query-parser.service'; -import {GallerySearchFieldComponent} from './ui/gallery/search/search-field/search-field.gallery.component'; +import {GallerySearchFieldBaseComponent} from './ui/gallery/search/search-field-base/search-field-base.gallery.component'; import {AppRoutingModule} from './app.routing'; import {CookieService} from 'ngx-cookie-service'; import {LeafletMarkerClusterModule} from '@asymmetrik/ngx-leaflet-markercluster'; @@ -112,6 +112,8 @@ import {MDFilesFilterPipe} from './pipes/MDFilesFilterPipe'; import {FileDTOToPathPipe} from './pipes/FileDTOToPathPipe'; import {BlogService} from './ui/gallery/blog/blog.service'; import {PhotoFilterPipe} from './pipes/PhotoFilterPipe'; +import {PreviewSettingsComponent} from './ui/settings/preview/preview.settings.component'; +import {GallerySearchFieldComponent} from './ui/gallery/search/search-field/search-field.gallery.component'; @Injectable() export class MyHammerConfig extends HammerGestureConfig { @@ -206,6 +208,7 @@ Marker.prototype.options.icon = iconDefault; FrameComponent, GallerySearchComponent, GallerySearchQueryEntryComponent, + GallerySearchFieldBaseComponent, GallerySearchFieldComponent, GallerySearchQueryBuilderComponent, GalleryShareComponent, @@ -241,6 +244,7 @@ Marker.prototype.options.icon = iconDefault; JobProgressComponent, JobsSettingsComponent, JobButtonComponent, + PreviewSettingsComponent, // Pipes StringifyRole, diff --git a/src/frontend/app/ui/admin/admin.component.html b/src/frontend/app/ui/admin/admin.component.html index 28ce1e92..807370eb 100644 --- a/src/frontend/app/ui/admin/admin.component.html +++ b/src/frontend/app/ui/admin/admin.component.html @@ -25,7 +25,8 @@ {{notification.details | json}}
- Request: "{{notification.request.method}}", url: "{{notification.request.url}}", status code: "{{notification.request.statusCode}}" + Request: "{{notification.request.method}}", url: "{{notification.request.url}}", status code: + "{{notification.request.statusCode}}"
@@ -74,7 +75,8 @@