From 81068b6d66fcab6d77e42e0d02cca79095d783f3 Mon Sep 17 00:00:00 2001 From: "Patrik J. Braun" Date: Mon, 11 Sep 2023 18:57:51 +0200 Subject: [PATCH] improving linting --- src/backend/Logger.ts | 14 +- src/backend/ProjectPath.ts | 2 +- src/backend/middlewares/AlbumMWs.ts | 56 +- src/backend/middlewares/GalleryMWs.ts | 172 ++-- src/backend/middlewares/NotificationMWs.ts | 6 +- src/backend/middlewares/PersonMWs.ts | 88 +- src/backend/middlewares/RenderingMWs.ts | 70 +- src/backend/middlewares/ServerTimingMWs.ts | 24 +- src/backend/middlewares/SharingMWs.ts | 164 ++-- src/backend/middlewares/VersionMWs.ts | 28 +- src/backend/middlewares/admin/AdminMWs.ts | 174 ++-- src/backend/middlewares/admin/SettingsMWs.ts | 4 +- .../thumbnail/PhotoConverterMWs.ts | 18 +- .../thumbnail/ThumbnailGeneratorMWs.ts | 136 +-- .../middlewares/user/AuthenticationMWs.ts | 138 ++-- src/backend/middlewares/user/UserMWs.ts | 48 +- .../user/UserRequestConstrainsMWs.ts | 40 +- src/backend/model/DiskManger.ts | 25 +- src/backend/model/Localizations.ts | 10 +- src/backend/model/NotifocationManager.ts | 9 +- src/backend/model/ObjectManagers.ts | 6 +- src/backend/model/PasswordHelper.ts | 7 +- src/backend/model/database/AlbumManager.ts | 64 +- src/backend/model/database/CoverManager.ts | 164 ++-- src/backend/model/database/GalleryManager.ts | 310 +++---- src/backend/model/database/IObjectManager.ts | 2 +- src/backend/model/database/IndexingManager.ts | 264 +++--- src/backend/model/database/LocationManager.ts | 12 +- src/backend/model/database/PersonManager.ts | 50 +- src/backend/model/database/SQLConnection.ts | 116 ++- src/backend/model/database/SearchManager.ts | 782 +++++++++--------- src/backend/model/database/SharingManager.ts | 48 +- src/backend/model/database/VersionManager.ts | 34 +- .../database/enitites/DirectoryEntity.ts | 38 +- .../model/database/enitites/EntityUtils.ts | 14 +- .../model/database/enitites/FileEntity.ts | 2 +- .../model/database/enitites/MediaEntity.ts | 14 +- .../model/database/enitites/PersonEntry.ts | 16 +- .../database/enitites/PersonJunctionTable.ts | 4 +- .../model/database/enitites/PhotoEntity.ts | 15 +- .../model/database/enitites/SharingEntity.ts | 14 +- .../model/database/enitites/VersionEntity.ts | 2 +- .../model/database/enitites/VideoEntity.ts | 16 +- .../enitites/album/AlbumBaseEntity.ts | 2 +- .../enitites/album/SavedSearchEntity.ts | 13 +- .../model/diagnostics/ConfigDiagnostics.ts | 226 ++--- .../model/fileprocessing/PhotoProcessing.ts | 144 ++-- .../model/fileprocessing/VideoProcessing.ts | 56 +- src/backend/model/jobs/JobManager.ts | 76 +- src/backend/model/jobs/JobProgressManager.ts | 29 +- src/backend/model/jobs/JobRepository.ts | 6 +- .../model/jobs/jobs/AlbumCoverFillingJob.ts | 6 +- src/backend/model/jobs/jobs/FileJob.ts | 118 +-- .../model/jobs/jobs/GPXCompressionJob.ts | 2 +- src/backend/model/jobs/jobs/IJob.ts | 6 +- src/backend/model/jobs/jobs/IJobListener.ts | 12 +- src/backend/model/jobs/jobs/IndexingJob.ts | 14 +- src/backend/model/jobs/jobs/Job.ts | 36 +- src/backend/model/jobs/jobs/JobProgress.ts | 13 +- .../model/jobs/jobs/PhotoConvertingJob.ts | 14 +- .../model/jobs/jobs/TempFolderCleaningJob.ts | 8 +- .../model/jobs/jobs/ThumbnailGenerationJob.ts | 24 +- src/backend/model/jobs/jobs/TopPickSendJob.ts | 6 +- .../model/jobs/jobs/VideoConvertingJob.ts | 10 +- .../mediamessengers/EmailMediaMessenger.ts | 52 +- .../model/threading/DiskMangerWorker.ts | 104 +-- src/backend/model/threading/MetadataLoader.ts | 150 ++-- src/backend/model/threading/PhotoWorker.ts | 42 +- src/backend/model/threading/TaskExecuter.ts | 5 +- src/backend/model/threading/TaskQue.ts | 16 +- src/backend/model/threading/ThreadPool.ts | 32 +- .../model/threading/VideoConverterWorker.ts | 34 +- src/backend/model/threading/Worker.ts | 4 +- src/backend/routes/AlbumRouter.ts | 54 +- src/backend/routes/ErrorRouter.ts | 76 +- src/backend/routes/GalleryRouter.ts | 358 ++++---- src/backend/routes/LoggerRouter.ts | 22 +- src/backend/routes/NotificationRouter.ts | 28 +- src/backend/routes/PersonRouter.ts | 80 +- src/backend/routes/PublicRouter.ts | 172 ++-- src/backend/routes/Router.ts | 22 +- src/backend/routes/SharingRouter.ts | 86 +- src/backend/routes/UserRouter.ts | 94 +-- src/backend/routes/admin/AdminRouter.ts | 72 +- src/backend/routes/admin/SettingsRouter.ts | 30 +- src/backend/server.ts | 58 +- src/common/SearchQueryParser.ts | 270 +++--- src/common/SupportedFormats.ts | 10 +- src/common/Utils.ts | 16 +- src/common/config/private/Config.ts | 12 +- src/common/config/private/MessagingConfig.ts | 21 +- src/common/config/private/PrivateConfig.ts | 542 ++++++------ src/common/config/public/Config.ts | 6 +- src/common/entities/AutoCompleteItem.ts | 5 +- src/common/entities/ConentWrapper.ts | 42 +- src/common/entities/DirectoryDTO.ts | 15 +- src/common/entities/DuplicatesDTO.ts | 2 +- src/common/entities/Error.ts | 14 +- src/common/entities/LoginCredential.ts | 9 +- src/common/entities/MediaDTO.ts | 22 +- src/common/entities/Message.ts | 2 +- src/common/entities/PasswordChangeRequest.ts | 8 +- src/common/entities/PhotoDTO.ts | 4 +- src/common/entities/SearchQueryDTO.ts | 30 +- src/common/entities/SearchResultDTO.ts | 8 +- src/common/entities/SharingDTO.ts | 2 +- src/common/entities/UserDTO.ts | 16 +- .../entities/UserModificationRequest.ts | 3 +- src/common/entities/VideoDTO.ts | 4 +- src/common/entities/album/AlbumBaseDTO.ts | 2 +- src/common/entities/album/SavedSearchDTO.ts | 6 +- src/common/entities/job/JobScheduleDTO.ts | 34 +- src/common/event/EventLimit.ts | 9 +- .../app/model/backendtext.service.spec.ts | 24 +- src/frontend/app/model/backendtext.service.ts | 6 +- src/frontend/app/model/navigation.service.ts | 8 +- .../network/autehentication.service.spec.ts | 78 +- .../model/network/authentication.service.ts | 18 +- .../app/model/network/helper/auth.guard.ts | 25 +- .../model/network/helper/csrf.interceptor.ts | 20 +- .../model/network/helper/error.interceptor.ts | 38 +- .../app/model/network/network.service.spec.ts | 297 ++++--- .../app/model/network/network.service.ts | 66 +- .../app/model/network/user.service.spec.ts | 52 +- .../app/model/network/user.service.ts | 16 +- .../app/model/notification.service.ts | 41 +- src/frontend/app/model/page.helper.ts | 34 +- src/frontend/app/model/pi-title.service.ts | 4 +- src/frontend/app/model/query.service.ts | 22 +- .../app/model/seededRandom.service.ts | 2 +- src/frontend/app/model/theme.service.ts | 4 +- src/frontend/app/model/version.service.ts | 4 +- src/frontend/app/pipes/DurationPipe.ts | 6 +- src/frontend/app/pipes/FileDTOToPathPipe.ts | 16 +- .../app/pipes/FileDTOToRelativePathPipe.ts | 14 +- src/frontend/app/pipes/FileSizePipe.ts | 4 +- src/frontend/app/pipes/GPXFilesFilterPipe.ts | 10 +- src/frontend/app/pipes/MDFilesFilterPipe.ts | 10 +- src/frontend/app/pipes/PhotoFilterPipe.ts | 14 +- src/frontend/app/pipes/SafeHTMLPipe.ts | 2 +- src/frontend/app/pipes/StringifyRolePipe.ts | 6 +- .../app/pipes/StringifySearchQuery.ts | 11 +- src/frontend/app/pipes/StringifySearchType.ts | 4 +- src/frontend/app/ui/EnumTranslations.ts | 2 +- src/frontend/app/ui/admin/admin.component.ts | 18 +- .../app/ui/albums/album/album.component.ts | 42 +- .../app/ui/albums/albums.component.ts | 12 +- src/frontend/app/ui/albums/albums.service.ts | 10 +- .../saved-search-popup.component.ts | 13 +- .../app/ui/duplicates/duplicates.component.ts | 164 ++-- .../app/ui/duplicates/duplicates.service.ts | 10 +- .../photo/photo.duplicates.component.ts | 14 +- src/frontend/app/ui/faces/Person.ts | 14 +- .../app/ui/faces/face/face.component.ts | 50 +- src/frontend/app/ui/faces/faces.component.ts | 24 +- src/frontend/app/ui/faces/faces.service.ts | 22 +- src/frontend/app/ui/frame/frame.component.ts | 18 +- src/frontend/app/ui/gallery/Media.ts | 46 +- src/frontend/app/ui/gallery/MediaIcon.ts | 64 +- .../ui/gallery/blog/blog.gallery.component.ts | 1 - .../app/ui/gallery/blog/blog.service.ts | 32 +- .../app/ui/gallery/content.service.ts | 12 +- .../app/ui/gallery/contentLoader.service.ts | 30 +- .../directories/directories.component.ts | 6 +- .../directory/directory.gallery.component.ts | 19 +- .../filter/filter.gallery.component.ts | 54 +- .../app/ui/gallery/fullscreen.service.ts | 10 +- .../app/ui/gallery/gallery.component.ts | 78 +- src/frontend/app/ui/gallery/grid/GridMedia.ts | 8 +- .../loading.photo.grid.gallery.component.ts | 2 +- .../photo/photo.grid.gallery.component.ts | 52 +- .../controls.lightbox.gallery.component.ts | 38 +- .../info-panel.lightbox.gallery.component.ts | 82 +- .../lightbox/lightbox.gallery.component.ts | 232 +++--- .../media/media.lightbox.gallery.component.ts | 62 +- .../app/ui/gallery/map/MarkerFactory.ts | 4 +- .../lightbox.map.gallery.component.ts | 253 +++--- .../ui/gallery/map/map.gallery.component.ts | 54 +- .../app/ui/gallery/map/map.service.ts | 30 +- .../ui/gallery/navigator/sorting.service.ts | 4 +- .../app/ui/gallery/overlay.service.ts | 8 +- .../random-query-builder.gallery.component.ts | 26 +- .../gallery/search/AutoCompleteRenderItem.ts | 16 +- .../ui/gallery/search/autocomplete.service.ts | 208 ++--- .../query-bulder.gallery.component.ts | 35 +- .../query-entry.search.gallery.component.ts | 8 +- .../search-field-base.gallery.component.html | 4 +- .../search-field-base.gallery.component.ts | 106 +-- .../search-field.gallery.component.ts | 31 +- .../search/search-query-parser.service.ts | 9 +- .../search/search.gallery.component.ts | 28 +- src/frontend/app/ui/gallery/share.service.ts | 45 +- .../gallery/share/share.gallery.component.ts | 50 +- .../app/ui/gallery/thumbnailLoader.service.ts | 80 +- .../ui/gallery/thumbnailManager.service.ts | 61 +- .../app/ui/language/language.component.ts | 2 +- src/frontend/app/ui/login/login.component.ts | 4 +- .../app/ui/settings/scheduled-jobs.service.ts | 70 +- .../app/ui/settings/settings.service.ts | 27 +- .../sharings-list/sharings-list.component.ts | 2 - .../settings-entry.component.ts | 85 +- ...sorting-method.settings-entry.component.ts | 8 +- .../settings/template/template.component.ts | 50 +- .../app/ui/settings/users/users.component.ts | 27 +- .../button/job-button.settings.component.ts | 36 +- .../job-progress.settings.component.ts | 72 +- .../settings/workflow/workflow.component.ts | 80 +- .../ui/sharelogin/share-login.component.ts | 10 +- .../datepicker.component.ts | 2 +- .../timepicker.component.ts | 2 +- 210 files changed, 5138 insertions(+), 5242 deletions(-) diff --git a/src/backend/Logger.ts b/src/backend/Logger.ts index ec7f449a..0d2c19fd 100644 --- a/src/backend/Logger.ts +++ b/src/backend/Logger.ts @@ -1,5 +1,5 @@ -import { Config } from '../common/config/private/Config'; -import { LogLevel } from '../common/config/private/PrivateConfig'; +import {Config} from '../common/config/private/Config'; +import {LogLevel} from '../common/config/private/PrivateConfig'; export type logFN = (...args: (string | number)[]) => void; @@ -7,7 +7,7 @@ const forcedDebug = process.env['NODE_ENV'] === 'debug'; if (forcedDebug === true) { console.log( - 'NODE_ENV environmental variable is set to debug, forcing all logs to print' + 'NODE_ENV environmental variable is set to debug, forcing all logs to print' ); } @@ -55,10 +55,10 @@ export class Logger { const date = new Date().toLocaleString(); let LOG_TAG = ''; if ( - args.length > 0 && - typeof args[0] === 'string' && - args[0].startsWith('[') && - args[0].endsWith(']') + args.length > 0 && + typeof args[0] === 'string' && + args[0].startsWith('[') && + args[0].endsWith(']') ) { LOG_TAG = args[0]; args.shift(); diff --git a/src/backend/ProjectPath.ts b/src/backend/ProjectPath.ts index 4cf11b1f..99d5e030 100644 --- a/src/backend/ProjectPath.ts +++ b/src/backend/ProjectPath.ts @@ -1,6 +1,6 @@ import * as path from 'path'; import * as fs from 'fs'; -import { Config } from '../common/config/private/Config'; +import {Config} from '../common/config/private/Config'; class ProjectPathClass { public Root: string; diff --git a/src/backend/middlewares/AlbumMWs.ts b/src/backend/middlewares/AlbumMWs.ts index bae840f7..50cf469c 100644 --- a/src/backend/middlewares/AlbumMWs.ts +++ b/src/backend/middlewares/AlbumMWs.ts @@ -6,28 +6,28 @@ import {Config} from '../../common/config/private/Config'; export class AlbumMWs { public static async listAlbums( - req: Request, - res: Response, - next: NextFunction + req: Request, + res: Response, + next: NextFunction ): Promise { if (Config.Album.enabled === false) { return next(); } try { req.resultPipe = - await ObjectManagers.getInstance().AlbumManager.getAlbums(); + await ObjectManagers.getInstance().AlbumManager.getAlbums(); return next(); } catch (err) { return next( - new ErrorDTO(ErrorCodes.ALBUM_ERROR, 'Error during listing albums', err) + new ErrorDTO(ErrorCodes.ALBUM_ERROR, 'Error during listing albums', err) ); } } public static async deleteAlbum( - req: Request, - res: Response, - next: NextFunction + req: Request, + res: Response, + next: NextFunction ): Promise { if (Config.Album.enabled === false) { return next(); @@ -37,52 +37,52 @@ export class AlbumMWs { } try { await ObjectManagers.getInstance().AlbumManager.deleteAlbum( - parseInt(req.params['id'], 10) + parseInt(req.params['id'], 10) ); req.resultPipe = 'ok'; return next(); } catch (err) { return next( - new ErrorDTO( - ErrorCodes.ALBUM_ERROR, - 'Error during deleting albums', - err - ) + new ErrorDTO( + ErrorCodes.ALBUM_ERROR, + 'Error during deleting albums', + err + ) ); } } public static async createSavedSearch( - req: Request, - res: Response, - next: NextFunction + req: Request, + res: Response, + next: NextFunction ): Promise { if (Config.Album.enabled === false) { return next(); } if ( - typeof req.body === 'undefined' || - typeof req.body.name !== 'string' || - typeof req.body.searchQuery !== 'object' + typeof req.body === 'undefined' || + typeof req.body.name !== 'string' || + typeof req.body.searchQuery !== 'object' ) { return next( - new ErrorDTO(ErrorCodes.INPUT_ERROR, 'updateSharing filed is missing') + new ErrorDTO(ErrorCodes.INPUT_ERROR, 'updateSharing filed is missing') ); } try { await ObjectManagers.getInstance().AlbumManager.addSavedSearch( - req.body.name, - req.body.searchQuery + req.body.name, + req.body.searchQuery ); req.resultPipe = 'ok'; return next(); } catch (err) { return next( - new ErrorDTO( - ErrorCodes.ALBUM_ERROR, - 'Error during creating saved search albums', - err - ) + new ErrorDTO( + ErrorCodes.ALBUM_ERROR, + 'Error during creating saved search albums', + err + ) ); } } diff --git a/src/backend/middlewares/GalleryMWs.ts b/src/backend/middlewares/GalleryMWs.ts index 82b41a25..4a8c107f 100644 --- a/src/backend/middlewares/GalleryMWs.ts +++ b/src/backend/middlewares/GalleryMWs.ts @@ -21,14 +21,14 @@ import {SortByTypes} from '../../common/entities/SortingMethods'; export class GalleryMWs { @ServerTime('1.db', 'List Directory') public static async listDirectory( - req: Request, - res: Response, - next: NextFunction + req: Request, + res: Response, + next: NextFunction ): Promise { const directoryName = req.params['directory'] || '/'; const absoluteDirectoryName = path.join( - ProjectPath.ImageFolder, - directoryName + ProjectPath.ImageFolder, + directoryName ); try { if ((await fsp.stat(absoluteDirectoryName)).isDirectory() === false) { @@ -40,57 +40,57 @@ export class GalleryMWs { try { const directory = - await ObjectManagers.getInstance().GalleryManager.listDirectory( - directoryName, - parseInt( - req.query[QueryParams.gallery.knownLastModified] as string, - 10 - ), - parseInt( - req.query[QueryParams.gallery.knownLastScanned] as string, - 10 - ) - ); + await ObjectManagers.getInstance().GalleryManager.listDirectory( + directoryName, + parseInt( + req.query[QueryParams.gallery.knownLastModified] as string, + 10 + ), + parseInt( + req.query[QueryParams.gallery.knownLastScanned] as string, + 10 + ) + ); if (directory == null) { req.resultPipe = new ContentWrapper(null, null, true); return next(); } if ( - req.session['user'].permissions && - req.session['user'].permissions.length > 0 && - req.session['user'].permissions[0] !== '/*' + req.session['user'].permissions && + req.session['user'].permissions.length > 0 && + req.session['user'].permissions[0] !== '/*' ) { directory.directories = directory.directories.filter((d): boolean => - UserDTOUtils.isDirectoryAvailable(d, req.session['user'].permissions) + UserDTOUtils.isDirectoryAvailable(d, req.session['user'].permissions) ); } req.resultPipe = new ContentWrapper(directory, null); return next(); } catch (err) { return next( - new ErrorDTO( - ErrorCodes.GENERAL_ERROR, - 'Error during listing the directory', - err - ) + new ErrorDTO( + ErrorCodes.GENERAL_ERROR, + 'Error during listing the directory', + err + ) ); } } @ServerTime('1.zip', 'Zip Directory') public static async zipDirectory( - req: Request, - res: Response, - next: NextFunction + req: Request, + res: Response, + next: NextFunction ): Promise { if (Config.Gallery.NavBar.enableDownloadZip === false) { return next(); } const directoryName = req.params['directory'] || '/'; const absoluteDirectoryName = path.join( - ProjectPath.ImageFolder, - directoryName + ProjectPath.ImageFolder, + directoryName ); try { if ((await fsp.stat(absoluteDirectoryName)).isDirectory() === false) { @@ -133,16 +133,16 @@ export class GalleryMWs { return next(); } catch (err) { return next( - new ErrorDTO(ErrorCodes.GENERAL_ERROR, 'Error creating zip', err) + new ErrorDTO(ErrorCodes.GENERAL_ERROR, 'Error creating zip', err) ); } } @ServerTime('3.pack', 'pack result') public static cleanUpGalleryResults( - req: Request, - res: Response, - next: NextFunction + req: Request, + res: Response, + next: NextFunction ): void { if (!req.resultPipe) { return next(); @@ -157,14 +157,14 @@ export class GalleryMWs { if (cw.directory) { const removeVideos = (dir: ParentDirectoryDTO): void => { dir.media = dir.media.filter( - (m): boolean => !MediaDTOUtils.isVideo(m) + (m): boolean => !MediaDTOUtils.isVideo(m) ); }; removeVideos(cw.directory); } if (cw.searchResult) { cw.searchResult.media = cw.searchResult.media.filter( - (m): boolean => !MediaDTOUtils.isVideo(m) + (m): boolean => !MediaDTOUtils.isVideo(m) ); } } @@ -175,16 +175,16 @@ export class GalleryMWs { } public static async loadFile( - req: Request, - res: Response, - next: NextFunction + req: Request, + res: Response, + next: NextFunction ): Promise { if (!req.params['mediaPath']) { return next(); } const fullMediaPath = path.join( - ProjectPath.ImageFolder, - req.params['mediaPath'] + ProjectPath.ImageFolder, + req.params['mediaPath'] ); // check if file exist @@ -194,11 +194,11 @@ export class GalleryMWs { } } catch (e) { return next( - new ErrorDTO( - ErrorCodes.GENERAL_ERROR, - 'no such file:' + req.params['mediaPath'], - 'can\'t find file: ' + fullMediaPath - ) + new ErrorDTO( + ErrorCodes.GENERAL_ERROR, + 'no such file:' + req.params['mediaPath'], + 'can\'t find file: ' + fullMediaPath + ) ); } @@ -207,9 +207,9 @@ export class GalleryMWs { } public static async loadBestFitVideo( - req: Request, - res: Response, - next: NextFunction + req: Request, + res: Response, + next: NextFunction ): Promise { if (!req.resultPipe) { return next(); @@ -217,7 +217,7 @@ export class GalleryMWs { const fullMediaPath = req.resultPipe as string; const convertedVideo = - VideoProcessing.generateConvertedFilePath(fullMediaPath); + VideoProcessing.generateConvertedFilePath(fullMediaPath); // check if transcoded video exist try { @@ -232,52 +232,52 @@ export class GalleryMWs { @ServerTime('1.db', 'Search') public static async search( - req: Request, - res: Response, - next: NextFunction + req: Request, + res: Response, + next: NextFunction ): Promise { if ( - Config.Search.enabled === false || - !req.params['searchQueryDTO'] + Config.Search.enabled === false || + !req.params['searchQueryDTO'] ) { return next(); } const query: SearchQueryDTO = JSON.parse( - req.params['searchQueryDTO'] as string + req.params['searchQueryDTO'] as string ); try { const result = await ObjectManagers.getInstance().SearchManager.search( - query + query ); result.directories.forEach( - (dir): MediaDTO[] => (dir.media = dir.media || []) + (dir): MediaDTO[] => (dir.media = dir.media || []) ); req.resultPipe = new ContentWrapper(null, result); return next(); } catch (err) { if (err instanceof LocationLookupException) { return next( - new ErrorDTO( - ErrorCodes.LocationLookUp_ERROR, - 'Cannot find location: ' + err.location, - err - ) + new ErrorDTO( + ErrorCodes.LocationLookUp_ERROR, + 'Cannot find location: ' + err.location, + err + ) ); } return next( - new ErrorDTO(ErrorCodes.GENERAL_ERROR, 'Error during searching', err) + new ErrorDTO(ErrorCodes.GENERAL_ERROR, 'Error during searching', err) ); } } @ServerTime('1.db', 'Autocomplete') public static async autocomplete( - req: Request, - res: Response, - next: NextFunction + req: Request, + res: Response, + next: NextFunction ): Promise { if (Config.Search.AutoComplete.enabled === false) { return next(); @@ -292,53 +292,53 @@ export class GalleryMWs { } try { req.resultPipe = - await ObjectManagers.getInstance().SearchManager.autocomplete( - req.params['text'], - type - ); + await ObjectManagers.getInstance().SearchManager.autocomplete( + req.params['text'], + type + ); return next(); } catch (err) { return next( - new ErrorDTO(ErrorCodes.GENERAL_ERROR, 'Error during searching', err) + new ErrorDTO(ErrorCodes.GENERAL_ERROR, 'Error during searching', err) ); } } public static async getRandomImage( - req: Request, - res: Response, - next: NextFunction + req: Request, + res: Response, + next: NextFunction ): Promise { if ( - Config.RandomPhoto.enabled === false || - !req.params['searchQueryDTO'] + Config.RandomPhoto.enabled === false || + !req.params['searchQueryDTO'] ) { return next(); } try { const query: SearchQueryDTO = JSON.parse( - req.params['searchQueryDTO'] as string + req.params['searchQueryDTO'] as string ); const photos = - await ObjectManagers.getInstance().SearchManager.getNMedia(query, [{method: SortByTypes.Random, ascending: null}], 1, true); + await ObjectManagers.getInstance().SearchManager.getNMedia(query, [{method: SortByTypes.Random, ascending: null}], 1, true); if (!photos || photos.length !== 1) { return next(new ErrorDTO(ErrorCodes.INPUT_ERROR, 'No photo found')); } req.params['mediaPath'] = path.join( - photos[0].directory.path, - photos[0].directory.name, - photos[0].name + photos[0].directory.path, + photos[0].directory.name, + photos[0].name ); return next(); } catch (e) { return next( - new ErrorDTO( - ErrorCodes.GENERAL_ERROR, - 'Can\'t get random photo: ' + e.toString() - ) + new ErrorDTO( + ErrorCodes.GENERAL_ERROR, + 'Can\'t get random photo: ' + e.toString() + ) ); } } diff --git a/src/backend/middlewares/NotificationMWs.ts b/src/backend/middlewares/NotificationMWs.ts index 180f8f97..060ac6fb 100644 --- a/src/backend/middlewares/NotificationMWs.ts +++ b/src/backend/middlewares/NotificationMWs.ts @@ -1,6 +1,6 @@ -import { NextFunction, Request, Response } from 'express'; -import { UserRoles } from '../../common/entities/UserDTO'; -import { NotificationManager } from '../model/NotifocationManager'; +import {NextFunction, Request, Response} from 'express'; +import {UserRoles} from '../../common/entities/UserDTO'; +import {NotificationManager} from '../model/NotifocationManager'; export class NotificationMWs { public static list(req: Request, res: Response, next: NextFunction): void { diff --git a/src/backend/middlewares/PersonMWs.ts b/src/backend/middlewares/PersonMWs.ts index 9e71a7f6..65bc3eee 100644 --- a/src/backend/middlewares/PersonMWs.ts +++ b/src/backend/middlewares/PersonMWs.ts @@ -1,17 +1,15 @@ -import { NextFunction, Request, Response } from 'express'; -import { ErrorCodes, ErrorDTO } from '../../common/entities/Error'; -import { ObjectManagers } from '../model/ObjectManagers'; -import { - PersonDTO, -} from '../../common/entities/PersonDTO'; -import { Utils } from '../../common/Utils'; +import {NextFunction, Request, Response} from 'express'; +import {ErrorCodes, ErrorDTO} from '../../common/entities/Error'; +import {ObjectManagers} from '../model/ObjectManagers'; +import {PersonDTO,} from '../../common/entities/PersonDTO'; +import {Utils} from '../../common/Utils'; import {PersonEntry} from '../model/database/enitites/PersonEntry'; export class PersonMWs { public static async updatePerson( - req: Request, - res: Response, - next: NextFunction + req: Request, + res: Response, + next: NextFunction ): Promise { if (!req.params['name']) { return next(); @@ -19,26 +17,26 @@ export class PersonMWs { try { req.resultPipe = - await ObjectManagers.getInstance().PersonManager.updatePerson( - req.params['name'] as string, - req.body as PersonDTO - ); + await ObjectManagers.getInstance().PersonManager.updatePerson( + req.params['name'] as string, + req.body as PersonDTO + ); return next(); } catch (err) { return next( - new ErrorDTO( - ErrorCodes.PERSON_ERROR, - 'Error during updating a person', - err - ) + new ErrorDTO( + ErrorCodes.PERSON_ERROR, + 'Error during updating a person', + err + ) ); } } public static async getPerson( - req: Request, - res: Response, - next: NextFunction + req: Request, + res: Response, + next: NextFunction ): Promise { if (!req.params['name']) { return next(); @@ -46,45 +44,45 @@ export class PersonMWs { try { req.resultPipe = await ObjectManagers.getInstance().PersonManager.get( - req.params['name'] as string + req.params['name'] as string ); return next(); } catch (err) { return next( - new ErrorDTO( - ErrorCodes.PERSON_ERROR, - 'Error during updating a person', - err - ) + new ErrorDTO( + ErrorCodes.PERSON_ERROR, + 'Error during updating a person', + err + ) ); } } public static async listPersons( - req: Request, - res: Response, - next: NextFunction + req: Request, + res: Response, + next: NextFunction ): Promise { try { req.resultPipe = - await ObjectManagers.getInstance().PersonManager.getAll(); + await ObjectManagers.getInstance().PersonManager.getAll(); return next(); } catch (err) { return next( - new ErrorDTO( - ErrorCodes.PERSON_ERROR, - 'Error during listing persons', - err - ) + new ErrorDTO( + ErrorCodes.PERSON_ERROR, + 'Error during listing persons', + err + ) ); } } public static async cleanUpPersonResults( - req: Request, - res: Response, - next: NextFunction + req: Request, + res: Response, + next: NextFunction ): Promise { if (!req.resultPipe) { return next(); @@ -98,11 +96,11 @@ export class PersonMWs { return next(); } catch (err) { return next( - new ErrorDTO( - ErrorCodes.PERSON_ERROR, - 'Error during removing sample photo from all persons', - err - ) + new ErrorDTO( + ErrorCodes.PERSON_ERROR, + 'Error during removing sample photo from all persons', + err + ) ); } } diff --git a/src/backend/middlewares/RenderingMWs.ts b/src/backend/middlewares/RenderingMWs.ts index b1edfea0..f15dab70 100644 --- a/src/backend/middlewares/RenderingMWs.ts +++ b/src/backend/middlewares/RenderingMWs.ts @@ -14,9 +14,9 @@ const forcedDebug = process.env['NODE_ENV'] === 'debug'; export class RenderingMWs { public static renderResult( - req: Request, - res: Response, - next: NextFunction + req: Request, + res: Response, + next: NextFunction ): void { if (typeof req.resultPipe === 'undefined') { return next(); @@ -26,9 +26,9 @@ export class RenderingMWs { } public static renderSessionUser( - req: Request, - res: Response, - next: NextFunction + req: Request, + res: Response, + next: NextFunction ): void { if (!req.session['user']) { return next(new ErrorDTO(ErrorCodes.GENERAL_ERROR, 'User not exists')); @@ -51,9 +51,9 @@ export class RenderingMWs { } public static renderSharing( - req: Request, - res: Response, - next: NextFunction + req: Request, + res: Response, + next: NextFunction ): void { if (!req.resultPipe) { return next(); @@ -65,9 +65,9 @@ export class RenderingMWs { } public static renderSharingList( - req: Request, - res: Response, - next: NextFunction + req: Request, + res: Response, + next: NextFunction ): void { if (!req.resultPipe) { return next(); @@ -82,9 +82,9 @@ export class RenderingMWs { } public static renderFile( - req: Request, - res: Response, - next: NextFunction + req: Request, + res: Response, + next: NextFunction ): void { if (!req.resultPipe) { return next(); @@ -96,36 +96,36 @@ export class RenderingMWs { } public static renderOK( - req: Request, - res: Response + req: Request, + res: Response ): void { const message = new Message(null, 'ok'); res.json(message); } public static async renderConfig( - req: Request, - res: Response + req: Request, + res: Response ): Promise { const originalConf = await Config.original(); // These are sensitive information, do not send to the client side originalConf.Server.sessionSecret = null; const message = new Message( - null, - originalConf.toJSON({ - attachState: true, - attachVolatile: true, - skipTags: {secret: true} as TAGS - }) as PrivateConfigClass + null, + originalConf.toJSON({ + attachState: true, + attachVolatile: true, + skipTags: {secret: true} as TAGS + }) as PrivateConfigClass ); res.json(message); } public static renderError( - err: Error, - req: Request, - res: Response, - next: NextFunction + err: Error, + req: Request, + res: Response, + next: NextFunction ): void { if (err instanceof ErrorDTO) { if (err.details) { @@ -136,12 +136,12 @@ export class RenderingMWs { // hide error details for non developers if ( - !( - forcedDebug || - (req.session && - req.session['user'] && - req.session['user'].role >= UserRoles.Developer) - ) + !( + forcedDebug || + (req.session && + req.session['user'] && + req.session['user'].role >= UserRoles.Developer) + ) ) { delete err.detailsStr; } diff --git a/src/backend/middlewares/ServerTimingMWs.ts b/src/backend/middlewares/ServerTimingMWs.ts index 34fc11e5..c5b7d79a 100644 --- a/src/backend/middlewares/ServerTimingMWs.ts +++ b/src/backend/middlewares/ServerTimingMWs.ts @@ -22,9 +22,9 @@ export class ServerTimeEntry { export const ServerTime = (id: string, name: string) => { return ( - target: unknown, - propertyName: string, - descriptor: TypedPropertyDescriptor<(req: unknown, res: unknown, next: () => void) => void> + target: unknown, + propertyName: string, + descriptor: TypedPropertyDescriptor<(req: unknown, res: unknown, next: () => void) => void> ): void => { if (Config.Server.Log.logServerTiming === false) { return; @@ -40,8 +40,8 @@ export const ServerTime = (id: string, name: string) => { }); }; descriptor.value = new Function( - 'action', - 'return function ' + m.name + '(...args){ action(...args) };' + 'action', + 'return function ' + m.name + '(...args){ action(...args) };' )(customAction); }; }; @@ -53,19 +53,19 @@ export class ServerTimingMWs { * Add server timing */ public static async addServerTiming( - req: Request, - res: Response, - next: NextFunction + req: Request, + res: Response, + next: NextFunction ): Promise { if ( - (Config.Server.Log.logServerTiming === false && !forcedDebug) || - !req.timing + (Config.Server.Log.logServerTiming === false && !forcedDebug) || + !req.timing ) { return next(); } const l = Object.entries(req.timing) - .filter((e) => e[1].endTime) - .map((e) => `${e[0]};dur=${e[1].endTime};desc="${e[1].name}"`); + .filter((e) => e[1].endTime) + .map((e) => `${e[0]};dur=${e[1].endTime};desc="${e[1].name}"`); res.header('Server-Timing', l.join(', ')); next(); } diff --git a/src/backend/middlewares/SharingMWs.ts b/src/backend/middlewares/SharingMWs.ts index 0895d3a1..15bdb672 100644 --- a/src/backend/middlewares/SharingMWs.ts +++ b/src/backend/middlewares/SharingMWs.ts @@ -9,9 +9,9 @@ import {UserRoles} from '../../common/entities/UserDTO'; export class SharingMWs { public static async getSharing( - req: Request, - res: Response, - next: NextFunction + req: Request, + res: Response, + next: NextFunction ): Promise { if (Config.Sharing.enabled === false) { return next(); @@ -20,33 +20,33 @@ export class SharingMWs { try { req.resultPipe = - await ObjectManagers.getInstance().SharingManager.findOne(sharingKey); + await ObjectManagers.getInstance().SharingManager.findOne(sharingKey); return next(); } catch (err) { return next( - new ErrorDTO( - ErrorCodes.GENERAL_ERROR, - 'Error during retrieving sharing link', - err - ) + new ErrorDTO( + ErrorCodes.GENERAL_ERROR, + 'Error during retrieving sharing link', + err + ) ); } } public static async createSharing( - req: Request, - res: Response, - next: NextFunction + req: Request, + res: Response, + next: NextFunction ): Promise { if (Config.Sharing.enabled === false) { return next(); } if ( - typeof req.body === 'undefined' || - typeof req.body.createSharing === 'undefined' + typeof req.body === 'undefined' || + typeof req.body.createSharing === 'undefined' ) { return next( - new ErrorDTO(ErrorCodes.INPUT_ERROR, 'createSharing filed is missing') + new ErrorDTO(ErrorCodes.INPUT_ERROR, 'createSharing filed is missing') ); } const createSharing: CreateSharingDTO = req.body.createSharing; @@ -71,45 +71,45 @@ export class SharingMWs { password: createSharing.password, creator: req.session['user'], expires: - createSharing.valid >= 0 // if === -1 its forever - ? Date.now() + createSharing.valid - : new Date(9999, 0, 1).getTime(), // never expire + createSharing.valid >= 0 // if === -1 its forever + ? Date.now() + createSharing.valid + : new Date(9999, 0, 1).getTime(), // never expire includeSubfolders: createSharing.includeSubfolders, timeStamp: Date.now(), }; try { req.resultPipe = - await ObjectManagers.getInstance().SharingManager.createSharing( - sharing - ); + await ObjectManagers.getInstance().SharingManager.createSharing( + sharing + ); return next(); } catch (err) { console.warn(err); return next( - new ErrorDTO( - ErrorCodes.GENERAL_ERROR, - 'Error during creating sharing link', - err - ) + new ErrorDTO( + ErrorCodes.GENERAL_ERROR, + 'Error during creating sharing link', + err + ) ); } } public static async updateSharing( - req: Request, - res: Response, - next: NextFunction + req: Request, + res: Response, + next: NextFunction ): Promise { if (Config.Sharing.enabled === false) { return next(); } if ( - typeof req.body === 'undefined' || - typeof req.body.updateSharing === 'undefined' + typeof req.body === 'undefined' || + typeof req.body.updateSharing === 'undefined' ) { return next( - new ErrorDTO(ErrorCodes.INPUT_ERROR, 'updateSharing filed is missing') + new ErrorDTO(ErrorCodes.INPUT_ERROR, 'updateSharing filed is missing') ); } const updateSharing: CreateSharingDTO = req.body.updateSharing; @@ -119,14 +119,14 @@ export class SharingMWs { path: directoryName, sharingKey: '', password: - updateSharing.password && updateSharing.password !== '' - ? updateSharing.password - : null, + updateSharing.password && updateSharing.password !== '' + ? updateSharing.password + : null, creator: req.session['user'], expires: - updateSharing.valid >= 0 // if === -1 its forever - ? Date.now() + updateSharing.valid - : new Date(9999, 0, 1).getTime(), // never expire + updateSharing.valid >= 0 // if === -1 its forever + ? Date.now() + updateSharing.valid + : new Date(9999, 0, 1).getTime(), // never expire includeSubfolders: updateSharing.includeSubfolders, timeStamp: Date.now(), }; @@ -134,36 +134,36 @@ export class SharingMWs { try { const forceUpdate = req.session['user'].role >= UserRoles.Admin; req.resultPipe = - await ObjectManagers.getInstance().SharingManager.updateSharing( - sharing, - forceUpdate - ); + await ObjectManagers.getInstance().SharingManager.updateSharing( + sharing, + forceUpdate + ); return next(); } catch (err) { return next( - new ErrorDTO( - ErrorCodes.GENERAL_ERROR, - 'Error during updating sharing link', - err - ) + new ErrorDTO( + ErrorCodes.GENERAL_ERROR, + 'Error during updating sharing link', + err + ) ); } } public static async deleteSharing( - req: Request, - res: Response, - next: NextFunction + req: Request, + res: Response, + next: NextFunction ): Promise { if (Config.Sharing.enabled === false) { return next(); } if ( - typeof req.params === 'undefined' || - typeof req.params['sharingKey'] === 'undefined' + typeof req.params === 'undefined' || + typeof req.params['sharingKey'] === 'undefined' ) { return next( - new ErrorDTO(ErrorCodes.INPUT_ERROR, 'sharingKey is missing') + new ErrorDTO(ErrorCodes.INPUT_ERROR, 'sharingKey is missing') ); } const sharingKey: string = req.params['sharingKey']; @@ -177,49 +177,49 @@ export class SharingMWs { } } req.resultPipe = - await ObjectManagers.getInstance().SharingManager.deleteSharing( - sharingKey - ); + await ObjectManagers.getInstance().SharingManager.deleteSharing( + sharingKey + ); req.resultPipe = 'ok'; return next(); } catch (err) { return next( - new ErrorDTO( - ErrorCodes.GENERAL_ERROR, - 'Error during deleting sharing', - err - ) + new ErrorDTO( + ErrorCodes.GENERAL_ERROR, + 'Error during deleting sharing', + err + ) ); } } public static async listSharing( - req: Request, - res: Response, - next: NextFunction + req: Request, + res: Response, + next: NextFunction ): Promise { if (Config.Sharing.enabled === false) { return next(); } try { req.resultPipe = - await ObjectManagers.getInstance().SharingManager.listAll(); + await ObjectManagers.getInstance().SharingManager.listAll(); return next(); } catch (err) { return next( - new ErrorDTO( - ErrorCodes.GENERAL_ERROR, - 'Error during listing shares', - err - ) + new ErrorDTO( + ErrorCodes.GENERAL_ERROR, + 'Error during listing shares', + err + ) ); } } public static async listSharingForDir( - req: Request, - res: Response, - next: NextFunction + req: Request, + res: Response, + next: NextFunction ): Promise { if (Config.Sharing.enabled === false) { return next(); @@ -229,19 +229,19 @@ export class SharingMWs { try { if (req.session['user'].role >= UserRoles.Admin) { req.resultPipe = - await ObjectManagers.getInstance().SharingManager.listAllForDir(dir); + await ObjectManagers.getInstance().SharingManager.listAllForDir(dir); } else { req.resultPipe = - await ObjectManagers.getInstance().SharingManager.listAllForDir(dir, req.session['user']); + await ObjectManagers.getInstance().SharingManager.listAllForDir(dir, req.session['user']); } return next(); } catch (err) { return next( - new ErrorDTO( - ErrorCodes.GENERAL_ERROR, - 'Error during listing shares', - err - ) + new ErrorDTO( + ErrorCodes.GENERAL_ERROR, + 'Error during listing shares', + err + ) ); } } @@ -249,8 +249,8 @@ export class SharingMWs { private static generateKey(): string { function s4(): string { return Math.floor((1 + Math.random()) * 0x10000) - .toString(16) - .substring(1); + .toString(16) + .substring(1); } return s4() + s4(); diff --git a/src/backend/middlewares/VersionMWs.ts b/src/backend/middlewares/VersionMWs.ts index e1933a8a..f2572dc9 100644 --- a/src/backend/middlewares/VersionMWs.ts +++ b/src/backend/middlewares/VersionMWs.ts @@ -1,30 +1,30 @@ -import { NextFunction, Request, Response } from 'express'; -import { ObjectManagers } from '../model/ObjectManagers'; -import { ErrorCodes, ErrorDTO } from '../../common/entities/Error'; -import { CustomHeaders } from '../../common/CustomHeaders'; +import {NextFunction, Request, Response} from 'express'; +import {ObjectManagers} from '../model/ObjectManagers'; +import {ErrorCodes, ErrorDTO} from '../../common/entities/Error'; +import {CustomHeaders} from '../../common/CustomHeaders'; export class VersionMWs { /** * This version data is mainly used on the client side to invalidate the cache */ public static async injectGalleryVersion( - req: Request, - res: Response, - next: NextFunction + req: Request, + res: Response, + next: NextFunction ): Promise { try { res.header( - CustomHeaders.dataVersion, - await ObjectManagers.getInstance().VersionManager.getDataVersion() + CustomHeaders.dataVersion, + await ObjectManagers.getInstance().VersionManager.getDataVersion() ); next(); } catch (err) { return next( - new ErrorDTO( - ErrorCodes.GENERAL_ERROR, - 'Can not get data version', - err.toString() - ) + new ErrorDTO( + ErrorCodes.GENERAL_ERROR, + 'Can not get data version', + err.toString() + ) ); } } diff --git a/src/backend/middlewares/admin/AdminMWs.ts b/src/backend/middlewares/admin/AdminMWs.ts index d57fba10..e7bc288a 100644 --- a/src/backend/middlewares/admin/AdminMWs.ts +++ b/src/backend/middlewares/admin/AdminMWs.ts @@ -1,19 +1,19 @@ -import { NextFunction, Request, Response } from 'express'; -import { ErrorCodes, ErrorDTO } from '../../../common/entities/Error'; -import { ObjectManagers } from '../../model/ObjectManagers'; -import { StatisticDTO } from '../../../common/entities/settings/StatisticDTO'; +import {NextFunction, Request, Response} from 'express'; +import {ErrorCodes, ErrorDTO} from '../../../common/entities/Error'; +import {ObjectManagers} from '../../model/ObjectManagers'; +import {StatisticDTO} from '../../../common/entities/settings/StatisticDTO'; export class AdminMWs { public static async loadStatistic( - req: Request, - res: Response, - next: NextFunction + req: Request, + res: Response, + next: NextFunction ): Promise { const galleryManager = ObjectManagers.getInstance() - .GalleryManager; + .GalleryManager; const personManager = ObjectManagers.getInstance() - .PersonManager; + .PersonManager; try { req.resultPipe = { directories: await galleryManager.countDirectories(), @@ -26,57 +26,57 @@ export class AdminMWs { } catch (err) { if (err instanceof Error) { return next( - new ErrorDTO( - ErrorCodes.GENERAL_ERROR, - 'Error while getting statistic: ' + err.toString(), - err - ) + new ErrorDTO( + ErrorCodes.GENERAL_ERROR, + 'Error while getting statistic: ' + err.toString(), + err + ) ); } return next( - new ErrorDTO( - ErrorCodes.GENERAL_ERROR, - 'Error while getting statistic', - err - ) + new ErrorDTO( + ErrorCodes.GENERAL_ERROR, + 'Error while getting statistic', + err + ) ); } } public static async getDuplicates( - req: Request, - res: Response, - next: NextFunction + req: Request, + res: Response, + next: NextFunction ): Promise { try { req.resultPipe = await ObjectManagers.getInstance() - .GalleryManager.getPossibleDuplicates(); + .GalleryManager.getPossibleDuplicates(); return next(); } catch (err) { if (err instanceof Error) { return next( - new ErrorDTO( - ErrorCodes.GENERAL_ERROR, - 'Error while getting duplicates: ' + err.toString(), - err - ) + new ErrorDTO( + ErrorCodes.GENERAL_ERROR, + 'Error while getting duplicates: ' + err.toString(), + err + ) ); } return next( - new ErrorDTO( - ErrorCodes.GENERAL_ERROR, - 'Error while getting duplicates', - err - ) + new ErrorDTO( + ErrorCodes.GENERAL_ERROR, + 'Error while getting duplicates', + err + ) ); } } public static async startJob( - req: Request, - res: Response, - next: NextFunction + req: Request, + res: Response, + next: NextFunction ): Promise { try { const id = req.params['id']; @@ -84,29 +84,29 @@ export class AdminMWs { const soloRun: boolean = req.body.soloRun; const allowParallelRun: boolean = req.body.allowParallelRun; await ObjectManagers.getInstance().JobManager.run( - id, - JobConfig, - soloRun, - allowParallelRun + id, + JobConfig, + soloRun, + allowParallelRun ); req.resultPipe = 'ok'; return next(); } catch (err) { if (err instanceof Error) { return next( - new ErrorDTO( - ErrorCodes.JOB_ERROR, - 'Job error: ' + err.toString(), - err - ) + new ErrorDTO( + ErrorCodes.JOB_ERROR, + 'Job error: ' + err.toString(), + err + ) ); } return next( - new ErrorDTO( - ErrorCodes.JOB_ERROR, - 'Job error: ' + JSON.stringify(err, null, ' '), - err - ) + new ErrorDTO( + ErrorCodes.JOB_ERROR, + 'Job error: ' + JSON.stringify(err, null, ' '), + err + ) ); } } @@ -120,56 +120,56 @@ export class AdminMWs { } catch (err) { if (err instanceof Error) { return next( - new ErrorDTO( - ErrorCodes.JOB_ERROR, - 'Job error: ' + err.toString(), - err - ) + new ErrorDTO( + ErrorCodes.JOB_ERROR, + 'Job error: ' + err.toString(), + err + ) ); } return next( - new ErrorDTO( - ErrorCodes.JOB_ERROR, - 'Job error: ' + JSON.stringify(err, null, ' '), - err - ) + new ErrorDTO( + ErrorCodes.JOB_ERROR, + 'Job error: ' + JSON.stringify(err, null, ' '), + err + ) ); } } public static getAvailableJobs( - req: Request, - res: Response, - next: NextFunction + req: Request, + res: Response, + next: NextFunction ): void { try { req.resultPipe = - ObjectManagers.getInstance().JobManager.getAvailableJobs(); + ObjectManagers.getInstance().JobManager.getAvailableJobs(); return next(); } catch (err) { if (err instanceof Error) { return next( - new ErrorDTO( - ErrorCodes.JOB_ERROR, - 'Job error: ' + err.toString(), - err - ) + new ErrorDTO( + ErrorCodes.JOB_ERROR, + 'Job error: ' + err.toString(), + err + ) ); } return next( - new ErrorDTO( - ErrorCodes.JOB_ERROR, - 'Job error: ' + JSON.stringify(err, null, ' '), - err - ) + new ErrorDTO( + ErrorCodes.JOB_ERROR, + 'Job error: ' + JSON.stringify(err, null, ' '), + err + ) ); } } public static getJobProgresses( - req: Request, - res: Response, - next: NextFunction + req: Request, + res: Response, + next: NextFunction ): void { try { req.resultPipe = ObjectManagers.getInstance().JobManager.getProgresses(); @@ -177,19 +177,19 @@ export class AdminMWs { } catch (err) { if (err instanceof Error) { return next( - new ErrorDTO( - ErrorCodes.JOB_ERROR, - 'Job error: ' + err.toString(), - err - ) + new ErrorDTO( + ErrorCodes.JOB_ERROR, + 'Job error: ' + err.toString(), + err + ) ); } return next( - new ErrorDTO( - ErrorCodes.JOB_ERROR, - 'Job error: ' + JSON.stringify(err, null, ' '), - err - ) + new ErrorDTO( + ErrorCodes.JOB_ERROR, + 'Job error: ' + JSON.stringify(err, null, ' '), + err + ) ); } } diff --git a/src/backend/middlewares/admin/SettingsMWs.ts b/src/backend/middlewares/admin/SettingsMWs.ts index a099f022..efc364a0 100644 --- a/src/backend/middlewares/admin/SettingsMWs.ts +++ b/src/backend/middlewares/admin/SettingsMWs.ts @@ -19,8 +19,8 @@ export class SettingsMWs { */ public static async updateSettings(req: Request, res: Response, next: NextFunction): Promise { if ((typeof req.body === 'undefined') - || (typeof req.body.settings === 'undefined') - || (typeof req.body.settingsPath !== 'string')) { + || (typeof req.body.settings === 'undefined') + || (typeof req.body.settingsPath !== 'string')) { return next(new ErrorDTO(ErrorCodes.INPUT_ERROR, 'settings is needed')); } diff --git a/src/backend/middlewares/thumbnail/PhotoConverterMWs.ts b/src/backend/middlewares/thumbnail/PhotoConverterMWs.ts index 9d33c1cc..3b450f75 100644 --- a/src/backend/middlewares/thumbnail/PhotoConverterMWs.ts +++ b/src/backend/middlewares/thumbnail/PhotoConverterMWs.ts @@ -1,14 +1,14 @@ -import { NextFunction, Request, Response } from 'express'; +import {NextFunction, Request, Response} from 'express'; import * as fs from 'fs'; -import { PhotoProcessing } from '../../model/fileprocessing/PhotoProcessing'; -import { Config } from '../../../common/config/private/Config'; +import {PhotoProcessing} from '../../model/fileprocessing/PhotoProcessing'; +import {Config} from '../../../common/config/private/Config'; import {ErrorCodes, ErrorDTO} from '../../../common/entities/Error'; export class PhotoConverterMWs { public static async convertPhoto( - req: Request, - res: Response, - next: NextFunction + req: Request, + res: Response, + next: NextFunction ): Promise { if (!req.resultPipe) { return next(); @@ -20,8 +20,8 @@ export class PhotoConverterMWs { const fullMediaPath = req.resultPipe as string; const convertedVideo = PhotoProcessing.generateConvertedPath( - fullMediaPath, - Config.Media.Photo.Converting.resolution + fullMediaPath, + Config.Media.Photo.Converting.resolution ); // check if converted photo exist @@ -33,7 +33,7 @@ export class PhotoConverterMWs { if (Config.Media.Photo.Converting.onTheFly === true) { try { req.resultPipe = await PhotoProcessing.convertPhoto(fullMediaPath); - }catch (err){ + } catch (err) { return next(new ErrorDTO(ErrorCodes.PHOTO_GENERATION_ERROR, err.message)); } return next(); diff --git a/src/backend/middlewares/thumbnail/ThumbnailGeneratorMWs.ts b/src/backend/middlewares/thumbnail/ThumbnailGeneratorMWs.ts index 9be12f69..a06b8c46 100644 --- a/src/backend/middlewares/thumbnail/ThumbnailGeneratorMWs.ts +++ b/src/backend/middlewares/thumbnail/ThumbnailGeneratorMWs.ts @@ -14,13 +14,13 @@ import {PersonEntry} from '../../model/database/enitites/PersonEntry'; export class ThumbnailGeneratorMWs { private static ThumbnailMapEntries = - Config.Media.Thumbnail.generateThumbnailMapEntries(); + Config.Media.Thumbnail.generateThumbnailMapEntries(); @ServerTime('2.th', 'Thumbnail decoration') public static async addThumbnailInformation( - req: Request, - res: Response, - next: NextFunction + req: Request, + res: Response, + next: NextFunction ): Promise { if (!req.resultPipe) { return next(); @@ -34,7 +34,7 @@ export class ThumbnailGeneratorMWs { // regenerate in case the list change since startup ThumbnailGeneratorMWs.ThumbnailMapEntries = - Config.Media.Thumbnail.generateThumbnailMapEntries(); + Config.Media.Thumbnail.generateThumbnailMapEntries(); if (cw.directory) { ThumbnailGeneratorMWs.addThInfoTODir(cw.directory); } @@ -44,11 +44,11 @@ export class ThumbnailGeneratorMWs { } catch (error) { console.error(error); return next( - new ErrorDTO( - ErrorCodes.SERVER_ERROR, - 'error during postprocessing result (adding thumbnail info)', - error.toString() - ) + new ErrorDTO( + ErrorCodes.SERVER_ERROR, + 'error during postprocessing result (adding thumbnail info)', + error.toString() + ) ); } @@ -57,9 +57,9 @@ export class ThumbnailGeneratorMWs { // eslint-disable-next-line @typescript-eslint/typedef, @typescript-eslint/explicit-function-return-type, @typescript-eslint/explicit-module-boundary-types public static addThumbnailInfoForPersons( - req: Request, - res: Response, - next: NextFunction + req: Request, + res: Response, + next: NextFunction ): void { if (!req.resultPipe) { return next(); @@ -79,28 +79,28 @@ export class ThumbnailGeneratorMWs { } // load parameters const mediaPath = path.join( - ProjectPath.ImageFolder, - item.sampleRegion.media.directory.path, - item.sampleRegion.media.directory.name, - item.sampleRegion.media.name + ProjectPath.ImageFolder, + item.sampleRegion.media.directory.path, + item.sampleRegion.media.directory.name, + item.sampleRegion.media.name ); // generate thumbnail path const thPath = PhotoProcessing.generatePersonThumbnailPath( - mediaPath, - item.sampleRegion.media.metadata.faces.find(f => f.name === item.name), - size + mediaPath, + item.sampleRegion.media.metadata.faces.find(f => f.name === item.name), + size ); item.missingThumbnail = !fs.existsSync(thPath); } } catch (error) { return next( - new ErrorDTO( - ErrorCodes.SERVER_ERROR, - `Error during postprocessing result: adding thumbnail info for persons. Failed on: person ${erroredItem?.name}, at ${erroredItem?.sampleRegion?.media?.name} `, - error.toString() - ) + new ErrorDTO( + ErrorCodes.SERVER_ERROR, + `Error during postprocessing result: adding thumbnail info for persons. Failed on: person ${erroredItem?.name}, at ${erroredItem?.sampleRegion?.media?.name} `, + error.toString() + ) ); } @@ -108,9 +108,9 @@ export class ThumbnailGeneratorMWs { } public static async generatePersonThumbnail( - req: Request, - res: Response, - next: NextFunction + req: Request, + res: Response, + next: NextFunction ): Promise { if (!req.resultPipe) { return next(); @@ -122,22 +122,22 @@ export class ThumbnailGeneratorMWs { } catch (error) { console.error(error); return next( - new ErrorDTO( - ErrorCodes.THUMBNAIL_GENERATION_ERROR, - 'Error during generating face thumbnail: ' + person.name, - error.toString() - ) + new ErrorDTO( + ErrorCodes.THUMBNAIL_GENERATION_ERROR, + 'Error during generating face thumbnail: ' + person.name, + error.toString() + ) ); } } public static generateThumbnailFactory( - sourceType: ThumbnailSourceType + sourceType: ThumbnailSourceType ): (req: Request, res: Response, next: NextFunction) => Promise { return async ( - req: Request, - res: Response, - next: NextFunction + req: Request, + res: Response, + next: NextFunction ): Promise => { if (!req.resultPipe) { return next(); @@ -146,8 +146,8 @@ export class ThumbnailGeneratorMWs { // load parameters const mediaPath = req.resultPipe as string; let size: number = - parseInt(req.params.size, 10) || - Config.Media.Thumbnail.thumbnailSizes[0]; + parseInt(req.params.size, 10) || + Config.Media.Thumbnail.thumbnailSizes[0]; // validate size if (Config.Media.Thumbnail.thumbnailSizes.indexOf(size) === -1) { @@ -156,31 +156,31 @@ export class ThumbnailGeneratorMWs { try { req.resultPipe = await PhotoProcessing.generateThumbnail( - mediaPath, - size, - sourceType, - false + mediaPath, + size, + sourceType, + false ); return next(); } catch (error) { return next( - new ErrorDTO( - ErrorCodes.THUMBNAIL_GENERATION_ERROR, - 'Error during generating thumbnail: ' + mediaPath, - error.toString() - ) + new ErrorDTO( + ErrorCodes.THUMBNAIL_GENERATION_ERROR, + 'Error during generating thumbnail: ' + mediaPath, + error.toString() + ) ); } }; } public static generateIconFactory( - sourceType: ThumbnailSourceType + sourceType: ThumbnailSourceType ): (req: Request, res: Response, next: NextFunction) => Promise { return async ( - req: Request, - res: Response, - next: NextFunction + req: Request, + res: Response, + next: NextFunction ): Promise => { if (!req.resultPipe) { return next(); @@ -192,26 +192,26 @@ export class ThumbnailGeneratorMWs { try { req.resultPipe = await PhotoProcessing.generateThumbnail( - mediaPath, - size, - sourceType, - true + mediaPath, + size, + sourceType, + true ); return next(); } catch (error) { return next( - new ErrorDTO( - ErrorCodes.THUMBNAIL_GENERATION_ERROR, - 'Error during generating thumbnail: ' + mediaPath, - error.toString() - ) + new ErrorDTO( + ErrorCodes.THUMBNAIL_GENERATION_ERROR, + 'Error during generating thumbnail: ' + mediaPath, + error.toString() + ) ); } }; } private static addThInfoTODir( - directory: ParentDirectoryDTO | SubDirectoryDTO + directory: ParentDirectoryDTO | SubDirectoryDTO ): void { if (typeof directory.media !== 'undefined') { ThumbnailGeneratorMWs.addThInfoToPhotos(directory.media, directory); @@ -229,16 +229,16 @@ export class ThumbnailGeneratorMWs { private static addThInfoToAPhoto(photo: MediaDTO, directory: DirectoryPathDTO): void { const fullMediaPath = path.join( - ProjectPath.ImageFolder, - directory.path, - directory.name, - photo.name + ProjectPath.ImageFolder, + directory.path, + directory.name, + photo.name ); for (let i = 0; i < ThumbnailGeneratorMWs.ThumbnailMapEntries.length; ++i) { const entry = ThumbnailGeneratorMWs.ThumbnailMapEntries[i]; const thPath = PhotoProcessing.generateConvertedPath( - fullMediaPath, - entry.size + fullMediaPath, + entry.size ); if (fs.existsSync(thPath) !== true) { if (typeof photo.missingThumbnails === 'undefined') { diff --git a/src/backend/middlewares/user/AuthenticationMWs.ts b/src/backend/middlewares/user/AuthenticationMWs.ts index 68bc569c..06061753 100644 --- a/src/backend/middlewares/user/AuthenticationMWs.ts +++ b/src/backend/middlewares/user/AuthenticationMWs.ts @@ -13,9 +13,9 @@ const LOG_TAG = 'AuthenticationMWs'; export class AuthenticationMWs { public static async tryAuthenticate( - req: Request, - res: Response, - next: NextFunction + req: Request, + res: Response, + next: NextFunction ): Promise { if (Config.Users.authenticationRequired === false) { req.session['user'] = { @@ -38,9 +38,9 @@ export class AuthenticationMWs { } public static async authenticate( - req: Request, - res: Response, - next: NextFunction + req: Request, + res: Response, + next: NextFunction ): Promise { if (Config.Users.authenticationRequired === false) { req.session['user'] = { @@ -67,36 +67,36 @@ export class AuthenticationMWs { if (typeof req.session['user'] === 'undefined') { res.status(401); return next( - new ErrorDTO(ErrorCodes.NOT_AUTHENTICATED, 'Not authenticated') + new ErrorDTO(ErrorCodes.NOT_AUTHENTICATED, 'Not authenticated') ); } return next(); } public static normalizePathParam( - paramName: string + paramName: string ): (req: Request, res: Response, next: NextFunction) => void { return function normalizePathParam( - req: Request, - res: Response, - next: NextFunction + req: Request, + res: Response, + next: NextFunction ): void { req.params[paramName] = path - .normalize(req.params[paramName] || path.sep) - // eslint-disable-next-line no-useless-escape - .replace(/^(\.\.[\/\\])+/, ''); + .normalize(req.params[paramName] || path.sep) + // eslint-disable-next-line no-useless-escape + .replace(/^(\.\.[\/\\])+/, ''); return next(); }; } public static authorisePath( - paramName: string, - isDirectory: boolean + paramName: string, + isDirectory: boolean ): (req: Request, res: Response, next: NextFunction) => void { return function authorisePath( - req: Request, - res: Response, - next: NextFunction + req: Request, + res: Response, + next: NextFunction ): Response | void { let p: string = req.params[paramName]; if (!isDirectory) { @@ -104,7 +104,7 @@ export class AuthenticationMWs { } if ( - !UserDTOUtils.isDirectoryPathAvailable(p, req.session['user'].permissions) + !UserDTOUtils.isDirectoryPathAvailable(p, req.session['user'].permissions) ) { return res.sendStatus(403); } @@ -114,12 +114,12 @@ export class AuthenticationMWs { } public static authorise( - role: UserRoles + role: UserRoles ): (req: Request, res: Response, next: NextFunction) => void { return function authorise( - req: Request, - res: Response, - next: NextFunction + req: Request, + res: Response, + next: NextFunction ): void { if (req.session['user'].role < role) { return next(new ErrorDTO(ErrorCodes.NOT_AUTHORISED)); @@ -129,36 +129,36 @@ export class AuthenticationMWs { } public static async shareLogin( - req: Request, - res: Response, - next: NextFunction + req: Request, + res: Response, + next: NextFunction ): Promise { if (Config.Sharing.enabled === false) { return next(); } // not enough parameter if ( - !req.query[QueryParams.gallery.sharingKey_query] && - !req.params[QueryParams.gallery.sharingKey_params] + !req.query[QueryParams.gallery.sharingKey_query] && + !req.params[QueryParams.gallery.sharingKey_params] ) { return next( - new ErrorDTO(ErrorCodes.INPUT_ERROR, 'no sharing key provided') + new ErrorDTO(ErrorCodes.INPUT_ERROR, 'no sharing key provided') ); } try { const password = (req.body ? req.body.password : null) || null; const sharingKey: string = - (req.query[QueryParams.gallery.sharingKey_query] as string) || - (req.params[QueryParams.gallery.sharingKey_params] as string); + (req.query[QueryParams.gallery.sharingKey_query] as string) || + (req.params[QueryParams.gallery.sharingKey_params] as string); const sharing = await ObjectManagers.getInstance().SharingManager.findOne(sharingKey); if ( - !sharing || - sharing.expires < Date.now() || - (Config.Sharing.passwordProtected === true && - sharing.password && - !PasswordHelper.comparePassword(password, sharing.password)) + !sharing || + sharing.expires < Date.now() || + (Config.Sharing.passwordProtected === true && + sharing.password && + !PasswordHelper.comparePassword(password, sharing.password)) ) { Logger.warn(LOG_TAG, 'Failed login with sharing:' + sharing.sharingKey + ', bad password'); res.status(401); @@ -183,9 +183,9 @@ export class AuthenticationMWs { } public static inverseAuthenticate( - req: Request, - res: Response, - next: NextFunction + req: Request, + res: Response, + next: NextFunction ): void { if (typeof req.session['user'] !== 'undefined') { return next(new ErrorDTO(ErrorCodes.ALREADY_AUTHENTICATED)); @@ -194,9 +194,9 @@ export class AuthenticationMWs { } public static async login( - req: Request, - res: Response, - next: NextFunction + req: Request, + res: Response, + next: NextFunction ): Promise { if (Config.Users.authenticationRequired === false) { return res.sendStatus(404); @@ -204,44 +204,44 @@ export class AuthenticationMWs { // not enough parameter if ( - typeof req.body === 'undefined' || - typeof req.body.loginCredential === 'undefined' || - typeof req.body.loginCredential.username === 'undefined' || - typeof req.body.loginCredential.password === 'undefined' + typeof req.body === 'undefined' || + typeof req.body.loginCredential === 'undefined' || + typeof req.body.loginCredential.username === 'undefined' || + typeof req.body.loginCredential.password === 'undefined' ) { Logger.warn(LOG_TAG, 'Failed login no user or password provided'); return next( - new ErrorDTO( - ErrorCodes.INPUT_ERROR, - 'not all parameters are included for loginCredential' - ) + new ErrorDTO( + ErrorCodes.INPUT_ERROR, + 'not all parameters are included for loginCredential' + ) ); } try { // let's find the user const user = Utils.clone( - await ObjectManagers.getInstance().UserManager.findOne({ - name: req.body.loginCredential.username, - password: req.body.loginCredential.password, - }) + await ObjectManagers.getInstance().UserManager.findOne({ + name: req.body.loginCredential.username, + password: req.body.loginCredential.password, + }) ); delete user.password; req.session['user'] = user; if (req.body.loginCredential.rememberMe) { req.sessionOptions.expires = new Date( - Date.now() + Config.Server.sessionTimeout + Date.now() + Config.Server.sessionTimeout ); } return next(); } catch (err) { Logger.warn(LOG_TAG, 'Failed login for user:' + req.body.loginCredential.username - + ', bad password'); + + ', bad password'); return next( - new ErrorDTO( - ErrorCodes.CREDENTIAL_NOT_FOUND, - 'credentials not found during login', - err - ) + new ErrorDTO( + ErrorCodes.CREDENTIAL_NOT_FOUND, + 'credentials not found during login', + err + ) ); } } @@ -253,21 +253,21 @@ export class AuthenticationMWs { private static async getSharingUser(req: Request): Promise { if ( - Config.Sharing.enabled === true && - (!!req.query[QueryParams.gallery.sharingKey_query] || - !!req.params[QueryParams.gallery.sharingKey_params]) + Config.Sharing.enabled === true && + (!!req.query[QueryParams.gallery.sharingKey_query] || + !!req.params[QueryParams.gallery.sharingKey_params]) ) { const sharingKey: string = - (req.query[QueryParams.gallery.sharingKey_query] as string) || - (req.params[QueryParams.gallery.sharingKey_params] as string); + (req.query[QueryParams.gallery.sharingKey_query] as string) || + (req.params[QueryParams.gallery.sharingKey_params] as string); const sharing = await ObjectManagers.getInstance().SharingManager.findOne(sharingKey); if (!sharing || sharing.expires < Date.now()) { return null; } if ( - Config.Sharing.passwordProtected === true && - sharing.password + Config.Sharing.passwordProtected === true && + sharing.password ) { return null; } diff --git a/src/backend/middlewares/user/UserMWs.ts b/src/backend/middlewares/user/UserMWs.ts index 760cc195..1f802a59 100644 --- a/src/backend/middlewares/user/UserMWs.ts +++ b/src/backend/middlewares/user/UserMWs.ts @@ -6,23 +6,23 @@ import {Config} from '../../../common/config/private/Config'; export class UserMWs { public static async createUser( - req: Request, - res: Response, - next: NextFunction + req: Request, + res: Response, + next: NextFunction ): Promise { if (Config.Users.authenticationRequired === false) { return next(new ErrorDTO(ErrorCodes.USER_MANAGEMENT_DISABLED)); } if ( - typeof req.body === 'undefined' || - typeof req.body.newUser === 'undefined' + typeof req.body === 'undefined' || + typeof req.body.newUser === 'undefined' ) { return next(); } try { await ObjectManagers.getInstance().UserManager.createUser( - req.body.newUser + req.body.newUser ); return next(); } catch (err) { @@ -31,23 +31,23 @@ export class UserMWs { } public static async deleteUser( - req: Request, - res: Response, - next: NextFunction + req: Request, + res: Response, + next: NextFunction ): Promise { if (Config.Users.authenticationRequired === false) { return next(new ErrorDTO(ErrorCodes.USER_MANAGEMENT_DISABLED)); } if ( - typeof req.params === 'undefined' || - typeof req.params.id === 'undefined' + typeof req.params === 'undefined' || + typeof req.params.id === 'undefined' ) { return next(); } try { await ObjectManagers.getInstance().UserManager.deleteUser( - parseInt(req.params.id, 10) + parseInt(req.params.id, 10) ); return next(); } catch (err) { @@ -56,26 +56,26 @@ export class UserMWs { } public static async changeRole( - req: Request, - res: Response, - next: NextFunction + req: Request, + res: Response, + next: NextFunction ): Promise { if (Config.Users.authenticationRequired === false) { return next(new ErrorDTO(ErrorCodes.USER_MANAGEMENT_DISABLED)); } if ( - typeof req.params === 'undefined' || - typeof req.params.id === 'undefined' || - typeof req.body === 'undefined' || - typeof req.body.newRole === 'undefined' + typeof req.params === 'undefined' || + typeof req.params.id === 'undefined' || + typeof req.body === 'undefined' || + typeof req.body.newRole === 'undefined' ) { return next(); } try { await ObjectManagers.getInstance().UserManager.changeRole( - parseInt(req.params.id, 10), - req.body.newRole + parseInt(req.params.id, 10), + req.body.newRole ); return next(); } catch (err) { @@ -84,9 +84,9 @@ export class UserMWs { } public static async listUsers( - req: Request, - res: Response, - next: NextFunction + req: Request, + res: Response, + next: NextFunction ): Promise { if (Config.Users.authenticationRequired === false) { return next(new ErrorDTO(ErrorCodes.USER_MANAGEMENT_DISABLED)); diff --git a/src/backend/middlewares/user/UserRequestConstrainsMWs.ts b/src/backend/middlewares/user/UserRequestConstrainsMWs.ts index 4e3a3f87..d8ef4c9d 100644 --- a/src/backend/middlewares/user/UserRequestConstrainsMWs.ts +++ b/src/backend/middlewares/user/UserRequestConstrainsMWs.ts @@ -1,18 +1,18 @@ -import { NextFunction, Request, Response } from 'express'; -import { MoreThanOrEqual } from 'typeorm'; -import { ErrorCodes, ErrorDTO } from '../../../common/entities/Error'; -import { UserRoles } from '../../../common/entities/UserDTO'; -import { ObjectManagers } from '../../model/ObjectManagers'; +import {NextFunction, Request, Response} from 'express'; +import {MoreThanOrEqual} from 'typeorm'; +import {ErrorCodes, ErrorDTO} from '../../../common/entities/Error'; +import {UserRoles} from '../../../common/entities/UserDTO'; +import {ObjectManagers} from '../../model/ObjectManagers'; export class UserRequestConstrainsMWs { public static forceSelfRequest( - req: Request, - res: Response, - next: NextFunction + req: Request, + res: Response, + next: NextFunction ): void { if ( - typeof req.params === 'undefined' || - typeof req.params.id === 'undefined' + typeof req.params === 'undefined' || + typeof req.params.id === 'undefined' ) { return next(); } @@ -24,13 +24,13 @@ export class UserRequestConstrainsMWs { } public static notSelfRequest( - req: Request, - res: Response, - next: NextFunction + req: Request, + res: Response, + next: NextFunction ): void { if ( - typeof req.params === 'undefined' || - typeof req.params.id === 'undefined' + typeof req.params === 'undefined' || + typeof req.params.id === 'undefined' ) { return next(); } @@ -43,13 +43,13 @@ export class UserRequestConstrainsMWs { } public static async notSelfRequestOr2Admins( - req: Request, - res: Response, - next: NextFunction + req: Request, + res: Response, + next: NextFunction ): Promise { if ( - typeof req.params === 'undefined' || - typeof req.params.id === 'undefined' + typeof req.params === 'undefined' || + typeof req.params.id === 'undefined' ) { return next(); } diff --git a/src/backend/model/DiskManger.ts b/src/backend/model/DiskManger.ts index 4e31d89e..6e84b8f0 100644 --- a/src/backend/model/DiskManger.ts +++ b/src/backend/model/DiskManger.ts @@ -1,13 +1,8 @@ -import { - ParentDirectoryDTO, -} from '../../common/entities/DirectoryDTO'; +import {ParentDirectoryDTO,} from '../../common/entities/DirectoryDTO'; import {Logger} from '../Logger'; import {Config} from '../../common/config/private/Config'; import {DiskManagerTH} from './threading/ThreadPool'; -import { - DirectoryScanSettings, - DiskMangerWorker, -} from './threading/DiskMangerWorker'; +import {DirectoryScanSettings, DiskMangerWorker,} from './threading/DiskMangerWorker'; import {FileDTO} from '../../common/entities/FileDTO'; const LOG_TAG = '[DiskManager]'; @@ -25,16 +20,16 @@ export class DiskManager { * List all files in a folder as fast as possible */ public static async scanDirectoryNoMetadata( - relativeDirectoryName: string, - settings: DirectoryScanSettings = {} + relativeDirectoryName: string, + settings: DirectoryScanSettings = {} ): Promise> { settings.noMetadata = true; return this.scanDirectory(relativeDirectoryName, settings); } public static async scanDirectory( - relativeDirectoryName: string, - settings: DirectoryScanSettings = {} + relativeDirectoryName: string, + settings: DirectoryScanSettings = {} ): Promise { Logger.silly(LOG_TAG, 'scanning directory:', relativeDirectoryName); @@ -42,13 +37,13 @@ export class DiskManager { if (Config.Server.Threading.enabled === true) { directory = await DiskManager.threadPool.execute( - relativeDirectoryName, - settings + relativeDirectoryName, + settings ); } else { directory = (await DiskMangerWorker.scanDirectory( - relativeDirectoryName, - settings + relativeDirectoryName, + settings )) as ParentDirectoryDTO; } return directory; diff --git a/src/backend/model/Localizations.ts b/src/backend/model/Localizations.ts index 1cacfc66..cc664ba4 100644 --- a/src/backend/model/Localizations.ts +++ b/src/backend/model/Localizations.ts @@ -8,12 +8,12 @@ export class Localizations { public static init(): void { const notLanguage = ['assets']; const dirCont = fs - .readdirSync(ProjectPath.FrontendFolder) - .filter((f): boolean => - fs.statSync(path.join(ProjectPath.FrontendFolder, f)).isDirectory() - ); + .readdirSync(ProjectPath.FrontendFolder) + .filter((f): boolean => + fs.statSync(path.join(ProjectPath.FrontendFolder, f)).isDirectory() + ); Config.Server.languages = dirCont.filter( - (d): boolean => notLanguage.indexOf(d) === -1 + (d): boolean => notLanguage.indexOf(d) === -1 ); Config.Server.languages.sort(); } diff --git a/src/backend/model/NotifocationManager.ts b/src/backend/model/NotifocationManager.ts index 777443ae..8e13ff4a 100644 --- a/src/backend/model/NotifocationManager.ts +++ b/src/backend/model/NotifocationManager.ts @@ -1,8 +1,5 @@ -import { - NotificationDTO, - NotificationType, -} from '../../common/entities/NotificationDTO'; -import { Request } from 'express'; +import {NotificationDTO, NotificationType,} from '../../common/entities/NotificationDTO'; +import {Request} from 'express'; export class NotificationManager { public static notifications: NotificationDTO[] = []; @@ -10,7 +7,7 @@ export class NotificationManager { { type: NotificationType.info, message: - 'There are unhandled server notification. Login as Administrator to handle them.', + 'There are unhandled server notification. Login as Administrator to handle them.', }, ]; diff --git a/src/backend/model/ObjectManagers.ts b/src/backend/model/ObjectManagers.ts index 14fdc9b1..8733bb39 100644 --- a/src/backend/model/ObjectManagers.ts +++ b/src/backend/model/ObjectManagers.ts @@ -179,8 +179,8 @@ export class ObjectManagers { public static async reset(): Promise { Logger.silly(LOG_TAG, 'Object manager reset begin'); if ( - ObjectManagers.getInstance().IndexingManager && - ObjectManagers.getInstance().IndexingManager.IsSavingInProgress + ObjectManagers.getInstance().IndexingManager && + ObjectManagers.getInstance().IndexingManager.IsSavingInProgress ) { await ObjectManagers.getInstance().IndexingManager.SavingReady; } @@ -214,7 +214,7 @@ export class ObjectManagers { } public async onDataChange( - changedDir: ParentDirectoryDTO = null + changedDir: ParentDirectoryDTO = null ): Promise { await this.VersionManager.onNewDataVersion(); diff --git a/src/backend/model/PasswordHelper.ts b/src/backend/model/PasswordHelper.ts index accc0384..4568a78d 100644 --- a/src/backend/model/PasswordHelper.ts +++ b/src/backend/model/PasswordHelper.ts @@ -7,13 +7,14 @@ export class PasswordHelper { } public static comparePassword( - password: string, - encryptedPassword: string + password: string, + encryptedPassword: string ): boolean { try { return bcrypt.compareSync(password, encryptedPassword); // eslint-disable-next-line no-empty - } catch (e) {} + } catch (e) { + } return false; } } diff --git a/src/backend/model/database/AlbumManager.ts b/src/backend/model/database/AlbumManager.ts index 0412e847..2665bfda 100644 --- a/src/backend/model/database/AlbumManager.ts +++ b/src/backend/model/database/AlbumManager.ts @@ -19,27 +19,27 @@ export class AlbumManager implements IObjectManager { private static async updateAlbum(album: SavedSearchEntity): Promise { const connection = await SQLConnection.getConnection(); const cover = - await ObjectManagers.getInstance().CoverManager.getAlbumCover(album); + await ObjectManagers.getInstance().CoverManager.getAlbumCover(album); const count = await - ObjectManagers.getInstance().SearchManager.getCount((album as SavedSearchDTO).searchQuery); + ObjectManagers.getInstance().SearchManager.getCount((album as SavedSearchDTO).searchQuery); await connection - .createQueryBuilder() - .update(AlbumBaseEntity) - .set({cover: cover, count}) - .where('id = :id', {id: album.id}) - .execute(); + .createQueryBuilder() + .update(AlbumBaseEntity) + .set({cover: cover, count}) + .where('id = :id', {id: album.id}) + .execute(); } public async addIfNotExistSavedSearch( - name: string, - searchQuery: SearchQueryDTO, - lockedAlbum: boolean + name: string, + searchQuery: SearchQueryDTO, + lockedAlbum: boolean ): Promise { const connection = await SQLConnection.getConnection(); const album = await connection - .getRepository(SavedSearchEntity) - .findOneBy({name, searchQuery}); + .getRepository(SavedSearchEntity) + .findOneBy({name, searchQuery}); if (album) { return; } @@ -47,14 +47,14 @@ export class AlbumManager implements IObjectManager { } public async addSavedSearch( - name: string, - searchQuery: SearchQueryDTO, - lockedAlbum?: boolean + name: string, + searchQuery: SearchQueryDTO, + lockedAlbum?: boolean ): Promise { const connection = await SQLConnection.getConnection(); const a = await connection - .getRepository(SavedSearchEntity) - .save({name, searchQuery, locked: lockedAlbum}); + .getRepository(SavedSearchEntity) + .save({name, searchQuery, locked: lockedAlbum}); await AlbumManager.updateAlbum(a); } @@ -62,28 +62,28 @@ export class AlbumManager implements IObjectManager { const connection = await SQLConnection.getConnection(); if ( - (await connection - .getRepository(AlbumBaseEntity) - .countBy({id, locked: false})) !== 1 + (await connection + .getRepository(AlbumBaseEntity) + .countBy({id, locked: false})) !== 1 ) { throw new Error('Could not delete album, id:' + id); } await connection - .getRepository(AlbumBaseEntity) - .delete({id, locked: false}); + .getRepository(AlbumBaseEntity) + .delete({id, locked: false}); } public async getAlbums(): Promise { await this.updateAlbums(); const connection = await SQLConnection.getConnection(); return await connection - .getRepository(AlbumBaseEntity) - .createQueryBuilder('album') - .leftJoin('album.cover', 'cover') - .leftJoin('cover.directory', 'directory') - .select(['album', 'cover.name', 'directory.name', 'directory.path']) - .getMany(); + .getRepository(AlbumBaseEntity) + .createQueryBuilder('album') + .leftJoin('album.cover', 'cover') + .leftJoin('cover.directory', 'directory') + .select(['album', 'cover.name', 'directory.name', 'directory.path']) + .getMany(); } public async onNewDataVersion(): Promise { @@ -114,9 +114,9 @@ export class AlbumManager implements IObjectManager { async deleteAll() { const connection = await SQLConnection.getConnection(); await connection - .getRepository(AlbumBaseEntity) - .createQueryBuilder('album') - .delete() - .execute(); + .getRepository(AlbumBaseEntity) + .createQueryBuilder('album') + .delete() + .execute(); } } diff --git a/src/backend/model/database/CoverManager.ts b/src/backend/model/database/CoverManager.ts index f6c4db13..5d027f09 100644 --- a/src/backend/model/database/CoverManager.ts +++ b/src/backend/model/database/CoverManager.ts @@ -29,21 +29,21 @@ export class CoverManager implements IObjectManager { public async resetCovers(): Promise { const connection = await SQLConnection.getConnection(); await connection - .createQueryBuilder() - .update(DirectoryEntity) - .set({validCover: false}) - .execute(); + .createQueryBuilder() + .update(DirectoryEntity) + .set({validCover: false}) + .execute(); } public async onNewDataVersion(changedDir: ParentDirectoryDTO): Promise { // Invalidating Album cover let fullPath = DiskMangerWorker.normalizeDirPath( - path.join(changedDir.path, changedDir.name) + path.join(changedDir.path, changedDir.name) ); const query = (await SQLConnection.getConnection()) - .createQueryBuilder() - .update(DirectoryEntity) - .set({validCover: false}); + .createQueryBuilder() + .update(DirectoryEntity) + .set({validCover: false}); let i = 0; const root = DiskMangerWorker.pathFromRelativeDirName('.'); @@ -53,25 +53,25 @@ export class CoverManager implements IObjectManager { fullPath = parentPath; ++i; query.orWhere( - new Brackets((q: WhereExpression) => { - const param: { [key: string]: string } = {}; - param['name' + i] = name; - param['path' + i] = parentPath; - q.where(`path = :path${i}`, param); - q.andWhere(`name = :name${i}`, param); - }) + new Brackets((q: WhereExpression) => { + const param: { [key: string]: string } = {}; + param['name' + i] = name; + param['path' + i] = parentPath; + q.where(`path = :path${i}`, param); + q.andWhere(`name = :name${i}`, param); + }) ); } ++i; query.orWhere( - new Brackets((q: WhereExpression) => { - const param: { [key: string]: string } = {}; - param['name' + i] = DiskMangerWorker.dirName('.'); - param['path' + i] = DiskMangerWorker.pathFromRelativeDirName('.'); - q.where(`path = :path${i}`, param); - q.andWhere(`name = :name${i}`, param); - }) + new Brackets((q: WhereExpression) => { + const param: { [key: string]: string } = {}; + param['name' + i] = DiskMangerWorker.dirName('.'); + param['path' + i] = DiskMangerWorker.pathFromRelativeDirName('.'); + q.where(`path = :path${i}`, param); + q.andWhere(`name = :name${i}`, param); + }) ); await query.execute(); @@ -81,34 +81,34 @@ export class CoverManager implements IObjectManager { searchQuery: SearchQueryDTO; }): Promise { const albumQuery: Brackets = await - ObjectManagers.getInstance().SearchManager.prepareAndBuildWhereQuery(album.searchQuery); + ObjectManagers.getInstance().SearchManager.prepareAndBuildWhereQuery(album.searchQuery); const connection = await SQLConnection.getConnection(); const coverQuery = (): SelectQueryBuilder => { const query = connection - .getRepository(MediaEntity) - .createQueryBuilder('media') - .innerJoin('media.directory', 'directory') - .select(['media.name', 'media.id', ...CoverManager.DIRECTORY_SELECT]) - .where(albumQuery); + .getRepository(MediaEntity) + .createQueryBuilder('media') + .innerJoin('media.directory', 'directory') + .select(['media.name', 'media.id', ...CoverManager.DIRECTORY_SELECT]) + .where(albumQuery); SearchManager.setSorting(query, Config.AlbumCover.Sorting); return query; }; let coverMedia = null; if ( - Config.AlbumCover.SearchQuery && - !Utils.equalsFilter(Config.AlbumCover.SearchQuery, { - type: SearchQueryTypes.any_text, - text: '', - } as TextSearch) + Config.AlbumCover.SearchQuery && + !Utils.equalsFilter(Config.AlbumCover.SearchQuery, { + type: SearchQueryTypes.any_text, + text: '', + } as TextSearch) ) { try { const coverFilterQuery = await - ObjectManagers.getInstance().SearchManager.prepareAndBuildWhereQuery(Config.AlbumCover.SearchQuery); + ObjectManagers.getInstance().SearchManager.prepareAndBuildWhereQuery(Config.AlbumCover.SearchQuery); coverMedia = await coverQuery() - .andWhere(coverFilterQuery) - .limit(1) - .getOne(); + .andWhere(coverFilterQuery) + .limit(1) + .getOne(); } catch (e) { Logger.error(LOG_TAG, 'Cant get album cover using:', JSON.stringify(album.searchQuery), JSON.stringify(Config.AlbumCover.SearchQuery)); throw e; @@ -127,15 +127,15 @@ export class CoverManager implements IObjectManager { } public async getPartialDirsWithoutCovers(): Promise< - { id: number; name: string; path: string }[] + { id: number; name: string; path: string }[] > { const connection = await SQLConnection.getConnection(); return await connection - .getRepository(DirectoryEntity) - .createQueryBuilder('directory') - .where('directory.validCover = :validCover', {validCover: 0}) // 0 === false - .select(['name', 'id', 'path']) - .getRawMany(); + .getRepository(DirectoryEntity) + .createQueryBuilder('directory') + .where('directory.validCover = :validCover', {validCover: 0}) // 0 === false + .select(['name', 'id', 'path']) + .getRawMany(); } public async setAndGetCoverForDirectory(dir: { @@ -146,31 +146,31 @@ export class CoverManager implements IObjectManager { const connection = await SQLConnection.getConnection(); const coverQuery = (): SelectQueryBuilder => { const query = connection - .getRepository(MediaEntity) - .createQueryBuilder('media') - .innerJoin('media.directory', 'directory') - .select(['media.name', 'media.id', ...CoverManager.DIRECTORY_SELECT]) - .where( - new Brackets((q: WhereExpression) => { - q.where('media.directory = :dir', { - dir: dir.id, - }); - if (Config.Database.type === DatabaseType.mysql) { - q.orWhere('directory.path like :path || \'%\'', { - path: DiskMangerWorker.pathFromParent(dir), - }); - } else { - q.orWhere('directory.path GLOB :path', { - path: DiskMangerWorker.pathFromParent(dir) + '*', - }); - } - }) - ); + .getRepository(MediaEntity) + .createQueryBuilder('media') + .innerJoin('media.directory', 'directory') + .select(['media.name', 'media.id', ...CoverManager.DIRECTORY_SELECT]) + .where( + new Brackets((q: WhereExpression) => { + q.where('media.directory = :dir', { + dir: dir.id, + }); + if (Config.Database.type === DatabaseType.mysql) { + q.orWhere('directory.path like :path || \'%\'', { + path: DiskMangerWorker.pathFromParent(dir), + }); + } else { + q.orWhere('directory.path GLOB :path', { + path: DiskMangerWorker.pathFromParent(dir) + '*', + }); + } + }) + ); // Select from the directory if any otherwise from any subdirectories. // (There is no priority between subdirectories) query.orderBy( - `CASE WHEN directory.id = ${dir.id} THEN 0 ELSE 1 END`, - 'ASC' + `CASE WHEN directory.id = ${dir.id} THEN 0 ELSE 1 END`, + 'ASC' ); SearchManager.setSorting(query, Config.AlbumCover.Sorting); @@ -179,18 +179,18 @@ export class CoverManager implements IObjectManager { let coverMedia: CoverPhotoDTOWithID = null; if ( - Config.AlbumCover.SearchQuery && - !Utils.equalsFilter(Config.AlbumCover.SearchQuery, { - type: SearchQueryTypes.any_text, - text: '', - } as TextSearch) + Config.AlbumCover.SearchQuery && + !Utils.equalsFilter(Config.AlbumCover.SearchQuery, { + type: SearchQueryTypes.any_text, + text: '', + } as TextSearch) ) { coverMedia = await coverQuery() - .andWhere( - await ObjectManagers.getInstance().SearchManager.prepareAndBuildWhereQuery(Config.AlbumCover.SearchQuery) - ) - .limit(1) - .getOne(); + .andWhere( + await ObjectManagers.getInstance().SearchManager.prepareAndBuildWhereQuery(Config.AlbumCover.SearchQuery) + ) + .limit(1) + .getOne(); } if (!coverMedia) { @@ -199,13 +199,13 @@ export class CoverManager implements IObjectManager { // set validCover bit to true even if there is no cover (to prevent future updates) await connection - .createQueryBuilder() - .update(DirectoryEntity) - .set({cover: coverMedia, validCover: true}) - .where('id = :dir', { - dir: dir.id, - }) - .execute(); + .createQueryBuilder() + .update(DirectoryEntity) + .set({cover: coverMedia, validCover: true}) + .where('id = :dir', { + dir: dir.id, + }) + .execute(); return coverMedia || null; } diff --git a/src/backend/model/database/GalleryManager.ts b/src/backend/model/database/GalleryManager.ts index 839d7cb7..65121615 100644 --- a/src/backend/model/database/GalleryManager.ts +++ b/src/backend/model/database/GalleryManager.ts @@ -23,7 +23,7 @@ export class GalleryManager { parent: string; } { relativeDirectoryName = DiskMangerWorker.normalizeDirPath( - relativeDirectoryName + relativeDirectoryName ); return { name: path.basename(relativeDirectoryName), @@ -32,12 +32,12 @@ export class GalleryManager { } public async listDirectory( - relativeDirectoryName: string, - knownLastModified?: number, - knownLastScanned?: number + relativeDirectoryName: string, + knownLastModified?: number, + knownLastScanned?: number ): Promise { const directoryPath = GalleryManager.parseRelativeDirePath( - relativeDirectoryName + relativeDirectoryName ); const connection = await SQLConnection.getConnection(); @@ -48,35 +48,35 @@ export class GalleryManager { // Return as soon as possible without touching the original data source (hdd) // See https://github.com/bpatrik/pigallery2/issues/613 if ( - Config.Indexing.reIndexingSensitivity === - ReIndexingSensitivity.never + Config.Indexing.reIndexingSensitivity === + ReIndexingSensitivity.never ) { return null; } const stat = fs.statSync( - path.join(ProjectPath.ImageFolder, relativeDirectoryName) + path.join(ProjectPath.ImageFolder, relativeDirectoryName) ); const lastModified = DiskMangerWorker.calcLastModified(stat); // If it seems that the content did not change, do not work on it if ( - knownLastModified && - knownLastScanned && - lastModified === knownLastModified && - dir.lastScanned === knownLastScanned + knownLastModified && + knownLastScanned && + lastModified === knownLastModified && + dir.lastScanned === knownLastScanned ) { if ( - Config.Indexing.reIndexingSensitivity === - ReIndexingSensitivity.low + Config.Indexing.reIndexingSensitivity === + ReIndexingSensitivity.low ) { return null; } if ( - Date.now() - dir.lastScanned <= - Config.Indexing.cachedFolderTimeout && - Config.Indexing.reIndexingSensitivity === - ReIndexingSensitivity.medium + Date.now() - dir.lastScanned <= + Config.Indexing.cachedFolderTimeout && + Config.Indexing.reIndexingSensitivity === + ReIndexingSensitivity.medium ) { return null; } @@ -84,16 +84,16 @@ export class GalleryManager { if (dir.lastModified !== lastModified) { Logger.silly( - LOG_TAG, - 'Reindexing reason: lastModified mismatch: known: ' + - dir.lastModified + - ', current:' + - lastModified + LOG_TAG, + 'Reindexing reason: lastModified mismatch: known: ' + + dir.lastModified + + ', current:' + + lastModified ); const ret = - await ObjectManagers.getInstance().IndexingManager.indexDirectory( - relativeDirectoryName - ); + await ObjectManagers.getInstance().IndexingManager.indexDirectory( + relativeDirectoryName + ); for (const subDir of ret.directories) { if (!subDir.cover) { // if subdirectories do not have photos, so cannot show a cover, try getting one from DB @@ -105,25 +105,25 @@ export class GalleryManager { // not indexed since a while, index it in a lazy manner if ( - (Date.now() - dir.lastScanned > - Config.Indexing.cachedFolderTimeout && + (Date.now() - dir.lastScanned > + Config.Indexing.cachedFolderTimeout && + Config.Indexing.reIndexingSensitivity >= + ReIndexingSensitivity.medium) || Config.Indexing.reIndexingSensitivity >= - ReIndexingSensitivity.medium) || - Config.Indexing.reIndexingSensitivity >= - ReIndexingSensitivity.high + ReIndexingSensitivity.high ) { // on the fly reindexing Logger.silly( - LOG_TAG, - 'lazy reindexing reason: cache timeout: lastScanned: ' + - (Date.now() - dir.lastScanned) + - 'ms ago, cachedFolderTimeout:' + - Config.Indexing.cachedFolderTimeout + LOG_TAG, + 'lazy reindexing reason: cache timeout: lastScanned: ' + + (Date.now() - dir.lastScanned) + + 'ms ago, cachedFolderTimeout:' + + Config.Indexing.cachedFolderTimeout ); ObjectManagers.getInstance() - .IndexingManager.indexDirectory(relativeDirectoryName) - .catch(console.error); + .IndexingManager.indexDirectory(relativeDirectoryName) + .catch(console.error); } return await this.getParentDirFromId(connection, dir.id); } @@ -131,42 +131,42 @@ export class GalleryManager { // never scanned (deep indexed), do it and return with it Logger.silly(LOG_TAG, 'Reindexing reason: never scanned'); return ObjectManagers.getInstance().IndexingManager.indexDirectory( - relativeDirectoryName + relativeDirectoryName ); } async countDirectories(): Promise { const connection = await SQLConnection.getConnection(); return await connection - .getRepository(DirectoryEntity) - .createQueryBuilder('directory') - .getCount(); + .getRepository(DirectoryEntity) + .createQueryBuilder('directory') + .getCount(); } async countMediaSize(): Promise { const connection = await SQLConnection.getConnection(); const {sum} = await connection - .getRepository(MediaEntity) - .createQueryBuilder('media') - .select('SUM(media.metadata.fileSize)', 'sum') - .getRawOne(); + .getRepository(MediaEntity) + .createQueryBuilder('media') + .select('SUM(media.metadata.fileSize)', 'sum') + .getRawOne(); return sum || 0; } async countPhotos(): Promise { const connection = await SQLConnection.getConnection(); return await connection - .getRepository(PhotoEntity) - .createQueryBuilder('directory') - .getCount(); + .getRepository(PhotoEntity) + .createQueryBuilder('directory') + .getCount(); } async countVideos(): Promise { const connection = await SQLConnection.getConnection(); return await connection - .getRepository(VideoEntity) - .createQueryBuilder('directory') - .getCount(); + .getRepository(VideoEntity) + .createQueryBuilder('directory') + .getCount(); } public async getPossibleDuplicates(): Promise { @@ -174,31 +174,31 @@ export class GalleryManager { const mediaRepository = connection.getRepository(MediaEntity); let duplicates = await mediaRepository - .createQueryBuilder('media') - .innerJoin( - (query) => - query - .from(MediaEntity, 'innerMedia') - .select([ - 'innerMedia.name as name', - 'innerMedia.metadata.fileSize as fileSize', - 'count(*)', - ]) - .groupBy('innerMedia.name, innerMedia.metadata.fileSize') - .having('count(*)>1'), - 'innerMedia', - 'media.name=innerMedia.name AND media.metadata.fileSize = innerMedia.fileSize' - ) - .innerJoinAndSelect('media.directory', 'directory') - .orderBy('media.name, media.metadata.fileSize') - .limit(Config.Duplicates.listingLimit) - .getMany(); + .createQueryBuilder('media') + .innerJoin( + (query) => + query + .from(MediaEntity, 'innerMedia') + .select([ + 'innerMedia.name as name', + 'innerMedia.metadata.fileSize as fileSize', + 'count(*)', + ]) + .groupBy('innerMedia.name, innerMedia.metadata.fileSize') + .having('count(*)>1'), + 'innerMedia', + 'media.name=innerMedia.name AND media.metadata.fileSize = innerMedia.fileSize' + ) + .innerJoinAndSelect('media.directory', 'directory') + .orderBy('media.name, media.metadata.fileSize') + .limit(Config.Duplicates.listingLimit) + .getMany(); const duplicateParis: DuplicatesDTO[] = []; const processDuplicates = ( - duplicateList: MediaEntity[], - equalFn: (a: MediaEntity, b: MediaEntity) => boolean, - checkDuplicates = false + duplicateList: MediaEntity[], + equalFn: (a: MediaEntity, b: MediaEntity) => boolean, + checkDuplicates = false ): void => { let i = duplicateList.length - 1; while (i >= 0) { @@ -216,15 +216,15 @@ export class GalleryManager { if (checkDuplicates) { // ad to group if one already existed const foundDuplicates = duplicateParis.find( - (dp): boolean => - !!dp.media.find( - (m): boolean => !!list.find((lm): boolean => lm.id === m.id) - ) + (dp): boolean => + !!dp.media.find( + (m): boolean => !!list.find((lm): boolean => lm.id === m.id) + ) ); if (foundDuplicates) { list.forEach((lm): void => { if ( - foundDuplicates.media.find((m): boolean => m.id === lm.id) + foundDuplicates.media.find((m): boolean => m.id === lm.id) ) { return; } @@ -239,40 +239,40 @@ export class GalleryManager { }; processDuplicates( - duplicates, - (a, b): boolean => - a.name === b.name && a.metadata.fileSize === b.metadata.fileSize + duplicates, + (a, b): boolean => + a.name === b.name && a.metadata.fileSize === b.metadata.fileSize ); duplicates = await mediaRepository - .createQueryBuilder('media') - .innerJoin( - (query) => - query - .from(MediaEntity, 'innerMedia') - .select([ - 'innerMedia.metadata.creationDate as creationDate', - 'innerMedia.metadata.fileSize as fileSize', - 'count(*)', - ]) - .groupBy( - 'innerMedia.metadata.creationDate, innerMedia.metadata.fileSize' - ) - .having('count(*)>1'), - 'innerMedia', - 'media.metadata.creationDate=innerMedia.creationDate AND media.metadata.fileSize = innerMedia.fileSize' - ) - .innerJoinAndSelect('media.directory', 'directory') - .orderBy('media.metadata.creationDate, media.metadata.fileSize') - .limit(Config.Duplicates.listingLimit) - .getMany(); + .createQueryBuilder('media') + .innerJoin( + (query) => + query + .from(MediaEntity, 'innerMedia') + .select([ + 'innerMedia.metadata.creationDate as creationDate', + 'innerMedia.metadata.fileSize as fileSize', + 'count(*)', + ]) + .groupBy( + 'innerMedia.metadata.creationDate, innerMedia.metadata.fileSize' + ) + .having('count(*)>1'), + 'innerMedia', + 'media.metadata.creationDate=innerMedia.creationDate AND media.metadata.fileSize = innerMedia.fileSize' + ) + .innerJoinAndSelect('media.directory', 'directory') + .orderBy('media.metadata.creationDate, media.metadata.fileSize') + .limit(Config.Duplicates.listingLimit) + .getMany(); processDuplicates( - duplicates, - (a, b): boolean => - a.metadata.creationDate === b.metadata.creationDate && - a.metadata.fileSize === b.metadata.fileSize, - true + duplicates, + (a, b): boolean => + a.metadata.creationDate === b.metadata.creationDate && + a.metadata.fileSize === b.metadata.fileSize, + true ); return duplicateParis; @@ -282,20 +282,20 @@ export class GalleryManager { * Returns with the directories only, does not include media or metafiles */ public async selectDirStructure( - relativeDirectoryName: string + relativeDirectoryName: string ): Promise { const directoryPath = GalleryManager.parseRelativeDirePath( - relativeDirectoryName + relativeDirectoryName ); const connection = await SQLConnection.getConnection(); const query = connection - .getRepository(DirectoryEntity) - .createQueryBuilder('directory') - .where('directory.name = :name AND directory.path = :path', { - name: directoryPath.name, - path: directoryPath.parent, - }) - .leftJoinAndSelect('directory.directories', 'directories'); + .getRepository(DirectoryEntity) + .createQueryBuilder('directory') + .where('directory.name = :name AND directory.path = :path', { + name: directoryPath.name, + path: directoryPath.parent, + }) + .leftJoinAndSelect('directory.directories', 'directories'); return await query.getOne(); } @@ -304,14 +304,14 @@ export class GalleryManager { * Sets cover for the directory and caches it in the DB */ public async fillCoverForSubDir( - connection: Connection, - dir: SubDirectoryDTO + connection: Connection, + dir: SubDirectoryDTO ): Promise { if (!dir.validCover) { dir.cover = - await ObjectManagers.getInstance().CoverManager.setAndGetCoverForDirectory( - dir - ); + await ObjectManagers.getInstance().CoverManager.setAndGetCoverForDirectory( + dir + ); } dir.media = []; @@ -324,48 +324,48 @@ export class GalleryManager { lastModified: number }> { return await connection - .getRepository(DirectoryEntity) - .createQueryBuilder('directory') - .where('directory.name = :name AND directory.path = :path', { - name: name, - path: path, - }) - .select([ - 'directory.id', - 'directory.lastScanned', - 'directory.lastModified', - ]).getOne(); + .getRepository(DirectoryEntity) + .createQueryBuilder('directory') + .where('directory.name = :name AND directory.path = :path', { + name: name, + path: path, + }) + .select([ + 'directory.id', + 'directory.lastScanned', + 'directory.lastModified', + ]).getOne(); } protected async getParentDirFromId( - connection: Connection, - partialDirId: number + connection: Connection, + partialDirId: number ): Promise { const query = connection - .getRepository(DirectoryEntity) - .createQueryBuilder('directory') - .where('directory.id = :id', { - id: partialDirId - }) - .leftJoinAndSelect('directory.directories', 'directories') - .leftJoinAndSelect('directory.media', 'media') - .leftJoinAndSelect('directories.cover', 'cover') - .leftJoinAndSelect('cover.directory', 'coverDirectory') - .select([ - 'directory', - 'directories', - 'media', - 'cover.name', - 'coverDirectory.name', - 'coverDirectory.path', - ]); + .getRepository(DirectoryEntity) + .createQueryBuilder('directory') + .where('directory.id = :id', { + id: partialDirId + }) + .leftJoinAndSelect('directory.directories', 'directories') + .leftJoinAndSelect('directory.media', 'media') + .leftJoinAndSelect('directories.cover', 'cover') + .leftJoinAndSelect('cover.directory', 'coverDirectory') + .select([ + 'directory', + 'directories', + 'media', + 'cover.name', + 'coverDirectory.name', + 'coverDirectory.path', + ]); // TODO: do better filtering // NOTE: it should not cause an issue as it also do not save to the DB if ( - Config.MetaFile.gpx === true || - Config.MetaFile.pg2conf === true || - Config.MetaFile.markdown === true + Config.MetaFile.gpx === true || + Config.MetaFile.pg2conf === true || + Config.MetaFile.markdown === true ) { query.leftJoinAndSelect('directory.metaFile', 'metaFile'); } diff --git a/src/backend/model/database/IObjectManager.ts b/src/backend/model/database/IObjectManager.ts index 362203e9..939c42e7 100644 --- a/src/backend/model/database/IObjectManager.ts +++ b/src/backend/model/database/IObjectManager.ts @@ -1,4 +1,4 @@ -import { ParentDirectoryDTO } from '../../../common/entities/DirectoryDTO'; +import {ParentDirectoryDTO} from '../../../common/entities/DirectoryDTO'; export interface IObjectManager { onNewDataVersion?: (changedDir?: ParentDirectoryDTO) => Promise; diff --git a/src/backend/model/database/IndexingManager.ts b/src/backend/model/database/IndexingManager.ts index a32d3f91..b64fb641 100644 --- a/src/backend/model/database/IndexingManager.ts +++ b/src/backend/model/database/IndexingManager.ts @@ -5,7 +5,7 @@ import {DiskManager} from '../DiskManger'; import {PhotoEntity, PhotoMetadataEntity} from './enitites/PhotoEntity'; import {Utils} from '../../../common/Utils'; import {PhotoMetadata,} from '../../../common/entities/PhotoDTO'; -import {Connection, Repository} from 'typeorm'; +import {Connection, ObjectLiteral, Repository} from 'typeorm'; import {MediaEntity} from './enitites/MediaEntity'; import {MediaDTO, MediaDTOUtils} from '../../../common/entities/MediaDTO'; import {VideoEntity} from './enitites/VideoEntity'; @@ -38,30 +38,30 @@ export class IndexingManager { } private static async processServerSidePG2Conf( - parent: DirectoryPathDTO, - files: FileDTO[] + parent: DirectoryPathDTO, + files: FileDTO[] ): Promise { for (const f of files) { if (ServerPG2ConfMap[f.name] === ServerSidePG2ConfAction.SAVED_SEARCH) { const fullMediaPath = path.join( - ProjectPath.ImageFolder, - parent.path, - parent.name, - f.name + ProjectPath.ImageFolder, + parent.path, + parent.name, + f.name ); Logger.silly( - LOG_TAG, - 'Saving saved-searches to DB from:', - fullMediaPath + LOG_TAG, + 'Saving saved-searches to DB from:', + fullMediaPath ); const savedSearches: { name: string; searchQuery: SearchQueryDTO }[] = - JSON.parse(await fs.promises.readFile(fullMediaPath, 'utf8')); + JSON.parse(await fs.promises.readFile(fullMediaPath, 'utf8')); for (const s of savedSearches) { await ObjectManagers.getInstance().AlbumManager.addIfNotExistSavedSearch( - s.name, - s.searchQuery, - true + s.name, + s.searchQuery, + true ); } } @@ -73,7 +73,7 @@ export class IndexingManager { * does not wait for the DB to be saved */ public indexDirectory( - relativeDirectoryName: string + relativeDirectoryName: string ): Promise { // eslint-disable-next-line no-async-promise-executor return new Promise(async (resolve, reject): Promise => { @@ -87,14 +87,14 @@ export class IndexingManager { } const scannedDirectory = await DiskManager.scanDirectory( - relativeDirectoryName + relativeDirectoryName ); const dirClone = Utils.clone(scannedDirectory); // filter server side only config from returning dirClone.metaFile = dirClone.metaFile.filter( - (m) => !ServerPG2ConfMap[m.name] + (m) => !ServerPG2ConfMap[m.name] ); DirectoryDTOUtils.addReferences(dirClone); @@ -104,8 +104,8 @@ export class IndexingManager { this.queueForSave(scannedDirectory).catch(console.error); } catch (error) { NotificationManager.warning( - 'Unknown indexing error for: ' + relativeDirectoryName, - error.toString() + 'Unknown indexing error for: ' + relativeDirectoryName, + error.toString() ); console.error(error); return reject(error); @@ -117,10 +117,10 @@ export class IndexingManager { Logger.info(LOG_TAG, 'Resetting DB'); const connection = await SQLConnection.getConnection(); await connection - .getRepository(DirectoryEntity) - .createQueryBuilder('directory') - .delete() - .execute(); + .getRepository(DirectoryEntity) + .createQueryBuilder('directory') + .delete() + .execute(); } public async saveToDB(scannedDirectory: ParentDirectoryDTO): Promise { @@ -128,14 +128,14 @@ export class IndexingManager { try { const connection = await SQLConnection.getConnection(); const serverSideConfigs = scannedDirectory.metaFile.filter( - (m) => !!ServerPG2ConfMap[m.name] + (m) => !!ServerPG2ConfMap[m.name] ); scannedDirectory.metaFile = scannedDirectory.metaFile.filter( - (m) => !ServerPG2ConfMap[m.name] + (m) => !ServerPG2ConfMap[m.name] ); const currentDirId: number = await this.saveParentDir( - connection, - scannedDirectory + connection, + scannedDirectory ); await this.saveChildDirs(connection, currentDirId, scannedDirectory); await this.saveMedia(connection, currentDirId, scannedDirectory.media); @@ -152,21 +152,21 @@ export class IndexingManager { * Queues up a directory to save to the DB. */ protected async queueForSave( - scannedDirectory: ParentDirectoryDTO + scannedDirectory: ParentDirectoryDTO ): Promise { // Is this dir already queued for saving? if ( - this.savingQueue.findIndex( - (dir): boolean => - dir.name === scannedDirectory.name && - dir.path === scannedDirectory.path && - dir.lastModified === scannedDirectory.lastModified && - dir.lastScanned === scannedDirectory.lastScanned && - (dir.media || dir.media.length) === - (scannedDirectory.media || scannedDirectory.media.length) && - (dir.metaFile || dir.metaFile.length) === - (scannedDirectory.metaFile || scannedDirectory.metaFile.length) - ) !== -1 + this.savingQueue.findIndex( + (dir): boolean => + dir.name === scannedDirectory.name && + dir.path === scannedDirectory.path && + dir.lastModified === scannedDirectory.lastModified && + dir.lastScanned === scannedDirectory.lastScanned && + (dir.media || dir.media.length) === + (scannedDirectory.media || scannedDirectory.media.length) && + (dir.metaFile || dir.metaFile.length) === + (scannedDirectory.metaFile || scannedDirectory.metaFile.length) + ) !== -1 ) { return; } @@ -193,18 +193,18 @@ export class IndexingManager { } protected async saveParentDir( - connection: Connection, - scannedDirectory: ParentDirectoryDTO + connection: Connection, + scannedDirectory: ParentDirectoryDTO ): Promise { const directoryRepository = connection.getRepository(DirectoryEntity); const currentDir: DirectoryEntity = await directoryRepository - .createQueryBuilder('directory') - .where('directory.name = :name AND directory.path = :path', { - name: scannedDirectory.name, - path: scannedDirectory.path, - }) - .getOne(); + .createQueryBuilder('directory') + .where('directory.name = :name AND directory.path = :path', { + name: scannedDirectory.name, + path: scannedDirectory.path, + }) + .getOne(); if (currentDir) { // Updated parent dir (if it was in the DB previously) currentDir.lastModified = scannedDirectory.lastModified; @@ -216,51 +216,51 @@ export class IndexingManager { return currentDir.id; } else { return ( - await directoryRepository.insert({ - mediaCount: scannedDirectory.mediaCount, - lastModified: scannedDirectory.lastModified, - lastScanned: scannedDirectory.lastScanned, - youngestMedia: scannedDirectory.youngestMedia, - oldestMedia: scannedDirectory.oldestMedia, - name: scannedDirectory.name, - path: scannedDirectory.path, - } as DirectoryEntity) + await directoryRepository.insert({ + mediaCount: scannedDirectory.mediaCount, + lastModified: scannedDirectory.lastModified, + lastScanned: scannedDirectory.lastScanned, + youngestMedia: scannedDirectory.youngestMedia, + oldestMedia: scannedDirectory.oldestMedia, + name: scannedDirectory.name, + path: scannedDirectory.path, + } as DirectoryEntity) ).identifiers[0]['id']; } } protected async saveChildDirs( - connection: Connection, - currentDirId: number, - scannedDirectory: ParentDirectoryDTO + connection: Connection, + currentDirId: number, + scannedDirectory: ParentDirectoryDTO ): Promise { const directoryRepository = connection.getRepository(DirectoryEntity); // update subdirectories that does not have a parent await directoryRepository - .createQueryBuilder() - .update(DirectoryEntity) - .set({parent: currentDirId as any}) - .where('path = :path', { - path: DiskMangerWorker.pathFromParent(scannedDirectory), - }) - .andWhere('name NOT LIKE :root', {root: DiskMangerWorker.dirName('.')}) - .andWhere('parent IS NULL') - .execute(); + .createQueryBuilder() + .update(DirectoryEntity) + .set({parent: currentDirId as unknown}) + .where('path = :path', { + path: DiskMangerWorker.pathFromParent(scannedDirectory), + }) + .andWhere('name NOT LIKE :root', {root: DiskMangerWorker.dirName('.')}) + .andWhere('parent IS NULL') + .execute(); // save subdirectories const childDirectories = await directoryRepository - .createQueryBuilder('directory') - .leftJoinAndSelect('directory.parent', 'parent') - .where('directory.parent = :dir', { - dir: currentDirId, - }) - .getMany(); + .createQueryBuilder('directory') + .leftJoinAndSelect('directory.parent', 'parent') + .where('directory.parent = :dir', { + dir: currentDirId, + }) + .getMany(); for (const directory of scannedDirectory.directories) { // Was this child Dir already indexed before? const dirIndex = childDirectories.findIndex( - (d): boolean => d.name === directory.name + (d): boolean => d.name === directory.name ); if (dirIndex !== -1) { @@ -271,13 +271,13 @@ export class IndexingManager { directory.parent = {id: currentDirId} as ParentDirectoryDTO; (directory as DirectoryEntity).lastScanned = null; // new child dir, not fully scanned yet const d = await directoryRepository.insert( - directory as DirectoryEntity + directory as DirectoryEntity ); await this.saveMedia( - connection, - d.identifiers[0]['id'], - directory.media + connection, + d.identifiers[0]['id'], + directory.media ); } } @@ -289,19 +289,19 @@ export class IndexingManager { } protected async saveMetaFiles( - connection: Connection, - currentDirID: number, - scannedDirectory: ParentDirectoryDTO + connection: Connection, + currentDirID: number, + scannedDirectory: ParentDirectoryDTO ): Promise { const fileRepository = connection.getRepository(FileEntity); const MDfileRepository = connection.getRepository(MDFileEntity); // save files const indexedMetaFiles = await fileRepository - .createQueryBuilder('file') - .where('file.directory = :dir', { - dir: currentDirID, - }) - .getMany(); + .createQueryBuilder('file') + .where('file.directory = :dir', { + dir: currentDirID, + }) + .getMany(); const metaFilesToSave = []; for (const item of scannedDirectory.metaFile) { @@ -337,20 +337,20 @@ export class IndexingManager { } protected async saveMedia( - connection: Connection, - parentDirId: number, - media: MediaDTO[] + connection: Connection, + parentDirId: number, + media: MediaDTO[] ): Promise { const mediaRepository = connection.getRepository(MediaEntity); const photoRepository = connection.getRepository(PhotoEntity); const videoRepository = connection.getRepository(VideoEntity); // save media let indexedMedia = await mediaRepository - .createQueryBuilder('media') - .where('media.directory = :dir', { - dir: parentDirId, - }) - .getMany(); + .createQueryBuilder('media') + .where('media.directory = :dir', { + dir: parentDirId, + }) + .getMany(); const mediaChange = { saveP: [] as MediaDTO[], // save/update photo @@ -376,7 +376,7 @@ export class IndexingManager { // make the list distinct (some photos may contain the same person multiple times) (media[i].metadata as PhotoMetadataEntity).persons = [ ...new Set( - (media[i].metadata as PhotoMetadata).faces.map((f) => f.name) + (media[i].metadata as PhotoMetadata).faces.map((f) => f.name) ), ]; } @@ -389,8 +389,8 @@ export class IndexingManager { mediaItem = Utils.clone(media[i]); mediaItem.directory = {id: parentDirId} as DirectoryBaseDTO; (MediaDTOUtils.isPhoto(mediaItem) - ? mediaChange.insertP - : mediaChange.insertV + ? mediaChange.insertP + : mediaChange.insertV ).push(mediaItem); } else { // Media already in the DB, only needs to be updated @@ -398,8 +398,8 @@ export class IndexingManager { if (!Utils.equalsFilter(mediaItem.metadata, media[i].metadata)) { mediaItem.metadata = media[i].metadata; (MediaDTOUtils.isPhoto(mediaItem) - ? mediaChange.saveP - : mediaChange.saveV + ? mediaChange.saveP + : mediaChange.saveV ).push(mediaItem); } } @@ -416,20 +416,20 @@ export class IndexingManager { await this.saveChunk(videoRepository, mediaChange.insertV, 100); indexedMedia = await mediaRepository - .createQueryBuilder('media') - .where('media.directory = :dir', { - dir: parentDirId, - }) - .select(['media.name', 'media.id']) - .getMany(); + .createQueryBuilder('media') + .where('media.directory = :dir', { + dir: parentDirId, + }) + .select(['media.name', 'media.id']) + .getMany(); const persons: { name: string; mediaId: number }[] = []; personsPerPhoto.forEach((group): void => { const mIndex = indexedMedia.findIndex( - (m): boolean => m.name === group.mediaName + (m): boolean => m.name === group.mediaName ); group.faces.forEach((sf) => - (sf.mediaId = indexedMedia[mIndex].id) + (sf.mediaId = indexedMedia[mIndex].id) ); persons.push(...group.faces as { name: string; mediaId: number }[]); @@ -441,9 +441,9 @@ export class IndexingManager { } protected async savePersonsToMedia( - connection: Connection, - parentDirId: number, - scannedFaces: { name: string; mediaId: number }[] + connection: Connection, + parentDirId: number, + scannedFaces: { name: string; mediaId: number }[] ): Promise { const personJunctionTable = connection.getRepository(PersonJunctionTable); const personRepository = connection.getRepository(PersonEntry); @@ -461,13 +461,13 @@ export class IndexingManager { const savedPersons = await personRepository.find(); const indexedFaces = await personJunctionTable - .createQueryBuilder('face') - .leftJoin('face.media', 'media') - .where('media.directory = :directory', { - directory: parentDirId, - }) - .leftJoinAndSelect('face.person', 'person') - .getMany(); + .createQueryBuilder('face') + .leftJoin('face.media', 'media') + .where('media.directory = :directory', { + directory: parentDirId, + }) + .leftJoinAndSelect('face.person', 'person') + .getMany(); const faceToInsert: { person: { id: number }, media: { id: number } }[] = []; // eslint-disable-next-line @typescript-eslint/prefer-for-of @@ -485,7 +485,7 @@ export class IndexingManager { if (face == null) { faceToInsert.push({ person: savedPersons.find( - (p) => p.name === scannedFaces[i].name + (p) => p.name === scannedFaces[i].name ), media: {id: scannedFaces[i].mediaId} }); @@ -499,10 +499,10 @@ export class IndexingManager { }); } - private async saveChunk( - repository: Repository, - entities: T[], - size: number + private async saveChunk( + repository: Repository, + entities: T[], + size: number ): Promise { if (entities.length === 0) { return []; @@ -513,31 +513,31 @@ export class IndexingManager { let list: T[] = []; for (let i = 0; i < entities.length / size; i++) { list = list.concat( - await repository.save(entities.slice(i * size, (i + 1) * size)) + await repository.save(entities.slice(i * size, (i + 1) * size)) ); } return list; } - private async insertChunk( - repository: Repository, - entities: T[], - size: number + private async insertChunk( + repository: Repository, + entities: T[], + size: number ): Promise { if (entities.length === 0) { return []; } if (entities.length < size) { return (await repository.insert(entities)).identifiers.map( - (i: any) => i.id + (i: { id: number }) => i.id ); } let list: number[] = []; for (let i = 0; i < entities.length / size; i++) { list = list.concat( - ( - await repository.insert(entities.slice(i * size, (i + 1) * size)) - ).identifiers.map((ids) => ids['id']) + ( + await repository.insert(entities.slice(i * size, (i + 1) * size)) + ).identifiers.map((ids) => ids['id']) ); } return list; diff --git a/src/backend/model/database/LocationManager.ts b/src/backend/model/database/LocationManager.ts index 0dff1917..e6e3e28a 100644 --- a/src/backend/model/database/LocationManager.ts +++ b/src/backend/model/database/LocationManager.ts @@ -1,9 +1,9 @@ -import { GPSMetadata } from '../../../common/entities/PhotoDTO'; +import {GPSMetadata} from '../../../common/entities/PhotoDTO'; import * as NodeGeocoder from 'node-geocoder'; -import { LocationLookupException } from '../../exceptions/LocationLookupException'; -import { LRU } from '../../../common/Utils'; -import { IObjectManager } from './IObjectManager'; -import { ParentDirectoryDTO } from '../../../common/entities/DirectoryDTO'; +import {LocationLookupException} from '../../exceptions/LocationLookupException'; +import {LRU} from '../../../common/Utils'; +import {IObjectManager} from './IObjectManager'; +import {ParentDirectoryDTO} from '../../../common/entities/DirectoryDTO'; export class LocationManager implements IObjectManager { // onNewDataVersion only need for TypeScript, otherwise the interface is not implemented. @@ -12,7 +12,7 @@ export class LocationManager implements IObjectManager { cache = new LRU(100); constructor() { - this.geocoder = NodeGeocoder({ provider: 'openstreetmap' }); + this.geocoder = NodeGeocoder({provider: 'openstreetmap'}); } async getGPSData(text: string): Promise { diff --git a/src/backend/model/database/PersonManager.ts b/src/backend/model/database/PersonManager.ts index 28cb1684..fe3f05ec 100644 --- a/src/backend/model/database/PersonManager.ts +++ b/src/backend/model/database/PersonManager.ts @@ -8,7 +8,7 @@ import {IObjectManager} from './IObjectManager'; const LOG_TAG = '[PersonManager]'; -export class PersonManager implements IObjectManager{ +export class PersonManager implements IObjectManager { persons: PersonEntry[] = null; /** * Person table contains denormalized data that needs to update when isDBValid = false @@ -18,44 +18,44 @@ export class PersonManager implements IObjectManager{ private static async updateCounts(): Promise { const connection = await SQLConnection.getConnection(); await connection.query( - 'UPDATE person_entry SET count = ' + - ' (SELECT COUNT(1) FROM person_junction_table WHERE person_junction_table.personId = person_entry.id)' + 'UPDATE person_entry SET count = ' + + ' (SELECT COUNT(1) FROM person_junction_table WHERE person_junction_table.personId = person_entry.id)' ); // remove persons without photo await connection - .createQueryBuilder() - .delete() - .from(PersonEntry) - .where('count = 0') - .execute(); + .createQueryBuilder() + .delete() + .from(PersonEntry) + .where('count = 0') + .execute(); } private static async updateSamplePhotos(): Promise { const connection = await SQLConnection.getConnection(); await connection.query( - 'update person_entry set sampleRegionId = ' + - '(Select person_junction_table.id from media_entity ' + - 'left join person_junction_table on media_entity.id = person_junction_table.mediaId ' + - 'where person_junction_table.personId=person_entry.id ' + + 'update person_entry set sampleRegionId = ' + + '(Select person_junction_table.id from media_entity ' + + 'left join person_junction_table on media_entity.id = person_junction_table.mediaId ' + + 'where person_junction_table.personId=person_entry.id ' + 'order by media_entity.metadataRating desc, ' + 'media_entity.metadataCreationdate desc ' + - 'limit 1)' + 'limit 1)' ); } async updatePerson( - name: string, - partialPerson: PersonDTO + name: string, + partialPerson: PersonDTO ): Promise { this.isDBValid = false; const connection = await SQLConnection.getConnection(); const repository = connection.getRepository(PersonEntry); const person = await repository - .createQueryBuilder('person') - .limit(1) - .where('person.name LIKE :name COLLATE ' + SQL_COLLATE, {name}) - .getOne(); + .createQueryBuilder('person') + .limit(1) + .where('person.name LIKE :name COLLATE ' + SQL_COLLATE, {name}) + .getOne(); if (typeof partialPerson.name !== 'undefined') { person.name = partialPerson.name; @@ -83,9 +83,9 @@ export class PersonManager implements IObjectManager{ public async countFaces(): Promise { const connection = await SQLConnection.getConnection(); return await connection - .getRepository(PersonJunctionTable) - .createQueryBuilder('personJunction') - .getCount(); + .getRepository(PersonJunctionTable) + .createQueryBuilder('personJunction') + .getCount(); } public async get(name: string): Promise { @@ -96,7 +96,7 @@ export class PersonManager implements IObjectManager{ } public async saveAll( - persons: { name: string; mediaId: number }[] + persons: { name: string; mediaId: number }[] ): Promise { const toSave: { name: string; mediaId: number }[] = []; const connection = await SQLConnection.getConnection(); @@ -107,7 +107,7 @@ export class PersonManager implements IObjectManager{ // filter already existing persons for (const personToSave of persons) { const person = savedPersons.find( - (p): boolean => p.name === personToSave.name + (p): boolean => p.name === personToSave.name ); if (!person) { toSave.push(personToSave); @@ -119,7 +119,7 @@ export class PersonManager implements IObjectManager{ const saving = toSave.slice(i * 200, (i + 1) * 200); // saving person const inserted = await personRepository.insert( - saving.map((p) => ({name: p.name})) + saving.map((p) => ({name: p.name})) ); // saving junction table const junctionTable = inserted.identifiers.map((idObj, j) => ({person: idObj, media: {id: saving[j].mediaId}})); diff --git a/src/backend/model/database/SQLConnection.ts b/src/backend/model/database/SQLConnection.ts index 84300d57..80a26d4b 100644 --- a/src/backend/model/database/SQLConnection.ts +++ b/src/backend/model/database/SQLConnection.ts @@ -1,5 +1,5 @@ import 'reflect-metadata'; -import {Connection, createConnection, DataSourceOptions, getConnection,} from 'typeorm'; +import {Connection, createConnection, DataSourceOptions, getConnection, LoggerOptions,} from 'typeorm'; import {UserEntity} from './enitites/UserEntity'; import {UserRoles} from '../../../common/entities/UserDTO'; import {PhotoEntity} from './enitites/PhotoEntity'; @@ -26,38 +26,21 @@ import {MDFileEntity} from './enitites/MDFileEntity'; const LOG_TAG = '[SQLConnection]'; +type Writeable = { -readonly [P in keyof T]: T[P] }; + export class SQLConnection { private static connection: Connection = null; public static async getConnection(): Promise { if (this.connection == null) { - const options: any = this.getDriver(Config.Database); - // options.name = 'main'; - options.entities = [ - UserEntity, - FileEntity, - MDFileEntity, - PersonJunctionTable, - PersonEntry, - MediaEntity, - PhotoEntity, - VideoEntity, - DirectoryEntity, - SharingEntity, - AlbumBaseEntity, - SavedSearchEntity, - VersionEntity, - ]; - options.synchronize = false; - if (Config.Server.Log.sqlLevel !== SQLLogLevel.none) { - options.logging = SQLLogLevel[Config.Server.Log.sqlLevel]; - } + const options = this.getDriver(Config.Database); + Logger.debug( - LOG_TAG, - 'Creating connection: ' + DatabaseType[Config.Database.type], - ', with driver:', - options.type + LOG_TAG, + 'Creating connection: ' + DatabaseType[Config.Database.type], + ', with driver:', + options.type ); this.connection = await this.createConnection(options); await SQLConnection.schemeSync(this.connection); @@ -66,34 +49,15 @@ export class SQLConnection { } public static async tryConnection( - config: ServerDataBaseConfig + config: ServerDataBaseConfig ): Promise { try { await getConnection('test').close(); // eslint-disable-next-line no-empty } catch (err) { } - const options: any = this.getDriver(config); + const options = this.getDriver(config); options.name = 'test'; - options.entities = [ - UserEntity, - FileEntity, - MDFileEntity, - PersonJunctionTable, - PersonEntry, - MediaEntity, - PhotoEntity, - VideoEntity, - DirectoryEntity, - SharingEntity, - AlbumBaseEntity, - SavedSearchEntity, - VersionEntity, - ]; - options.synchronize = false; - if (Config.Server.Log.sqlLevel !== SQLLogLevel.none) { - options.logging = SQLLogLevel[Config.Server.Log.sqlLevel]; - } const conn = await this.createConnection(options); await SQLConnection.schemeSync(conn); await conn.close(); @@ -109,8 +73,8 @@ export class SQLConnection { // Adding enforced users to the db const userRepository = connection.getRepository(UserEntity); if ( - Array.isArray(Config.Users.enforcedUsers) && - Config.Users.enforcedUsers.length > 0 + Array.isArray(Config.Users.enforcedUsers) && + Config.Users.enforcedUsers.length > 0 ) { for (let i = 0; i < Config.Users.enforcedUsers.length; ++i) { const uc = Config.Users.enforcedUsers[i]; @@ -142,12 +106,12 @@ export class SQLConnection { role: UserRoles.Admin, }); if ( - defAdmin && - PasswordHelper.comparePassword('admin', defAdmin.password) + defAdmin && + PasswordHelper.comparePassword('admin', defAdmin.password) ) { NotificationManager.error( - 'Using default admin user!', - 'You are using the default admin/admin user/password, please change or remove it.' + 'Using default admin user!', + 'You are using the default admin/admin user/password, please change or remove it.' ); } } @@ -164,12 +128,12 @@ export class SQLConnection { } } - public static getSQLiteDB(config: ServerDataBaseConfig): any { + public static getSQLiteDB(config: ServerDataBaseConfig): string { return path.join(ProjectPath.getAbsolutePath(config.dbFolder), 'sqlite.db'); } private static async createConnection( - options: DataSourceOptions + options: DataSourceOptions ): Promise { if (options.type === 'sqlite' || options.type === 'better-sqlite3') { return await createConnection(options); @@ -185,7 +149,7 @@ export class SQLConnection { delete tmpOption.database; const tmpConn = await createConnection(tmpOption); await tmpConn.query( - 'CREATE DATABASE IF NOT EXISTS ' + options.database + 'CREATE DATABASE IF NOT EXISTS ' + options.database ); await tmpConn.close(); return await createConnection(options); @@ -213,9 +177,9 @@ export class SQLConnection { let users: UserEntity[] = []; try { users = await connection - .getRepository(UserEntity) - .createQueryBuilder('user') - .getMany(); + .getRepository(UserEntity) + .createQueryBuilder('user') + .getMany(); // eslint-disable-next-line no-empty } catch (ex) { } @@ -229,15 +193,16 @@ export class SQLConnection { await connection.synchronize(); await connection.getRepository(VersionEntity).save(version); Logger.warn( - LOG_TAG, - 'Could not move users to the new db scheme, deleting them. Details:' + - e.toString() + LOG_TAG, + 'Could not move users to the new db scheme, deleting them. Details:' + + e.toString() ); } } - private static getDriver(config: ServerDataBaseConfig): DataSourceOptions { - let driver: DataSourceOptions = null; + + private static getDriver(config: ServerDataBaseConfig): Writeable { + let driver: Writeable; if (config.type === DatabaseType.mysql) { driver = { type: 'mysql', @@ -252,11 +217,30 @@ export class SQLConnection { driver = { type: 'better-sqlite3', database: path.join( - ProjectPath.getAbsolutePath(config.dbFolder), - config.sqlite.DBFileName + ProjectPath.getAbsolutePath(config.dbFolder), + config.sqlite.DBFileName ), }; } + driver.entities = [ + UserEntity, + FileEntity, + MDFileEntity, + PersonJunctionTable, + PersonEntry, + MediaEntity, + PhotoEntity, + VideoEntity, + DirectoryEntity, + SharingEntity, + AlbumBaseEntity, + SavedSearchEntity, + VersionEntity, + ]; + driver.synchronize = false; + if (Config.Server.Log.sqlLevel !== SQLLogLevel.none) { + driver.logging = SQLLogLevel[Config.Server.Log.sqlLevel] as LoggerOptions; + } return driver; } } diff --git a/src/backend/model/database/SearchManager.ts b/src/backend/model/database/SearchManager.ts index 00bd35ed..a67a18b3 100644 --- a/src/backend/model/database/SearchManager.ts +++ b/src/backend/model/database/SearchManager.ts @@ -48,7 +48,7 @@ export class SearchManager { private queryIdBase = 0; private static autoCompleteItemsUnique( - array: Array + array: Array ): Array { const a = array.concat(); for (let i = 0; i < a.length; ++i) { @@ -63,8 +63,8 @@ export class SearchManager { } async autocomplete( - text: string, - type: SearchQueryTypes + text: string, + type: SearchQueryTypes ): Promise { const connection = await SQLConnection.getConnection(); @@ -76,184 +76,184 @@ export class SearchManager { const partialResult: AutoCompleteItem[][] = []; if ( - type === SearchQueryTypes.any_text || - type === SearchQueryTypes.keyword + type === SearchQueryTypes.any_text || + type === SearchQueryTypes.keyword ) { const acList: AutoCompleteItem[] = []; ( - await photoRepository - .createQueryBuilder('photo') - .select('DISTINCT(photo.metadata.keywords)') - .where('photo.metadata.keywords LIKE :text COLLATE ' + SQL_COLLATE, { - text: '%' + text + '%', - }) - .limit(Config.Search.AutoComplete.ItemsPerCategory.keyword) - .getRawMany() + await photoRepository + .createQueryBuilder('photo') + .select('DISTINCT(photo.metadata.keywords)') + .where('photo.metadata.keywords LIKE :text COLLATE ' + SQL_COLLATE, { + text: '%' + text + '%', + }) + .limit(Config.Search.AutoComplete.ItemsPerCategory.keyword) + .getRawMany() ) - .map( - (r): Array => - (r.metadataKeywords as string).split(',') as Array - ) - .forEach((keywords): void => { - acList.push( - ...this.encapsulateAutoComplete( - keywords.filter( - (k): boolean => - k.toLowerCase().indexOf(text.toLowerCase()) !== -1 - ), - SearchQueryTypes.keyword - ) - ); - }); + .map( + (r): Array => + (r.metadataKeywords as string).split(',') as Array + ) + .forEach((keywords): void => { + acList.push( + ...this.encapsulateAutoComplete( + keywords.filter( + (k): boolean => + k.toLowerCase().indexOf(text.toLowerCase()) !== -1 + ), + SearchQueryTypes.keyword + ) + ); + }); partialResult.push(acList); } if ( - type === SearchQueryTypes.any_text || - type === SearchQueryTypes.person + type === SearchQueryTypes.any_text || + type === SearchQueryTypes.person ) { partialResult.push( - this.encapsulateAutoComplete( - ( - await personRepository - .createQueryBuilder('person') - .select('DISTINCT(person.name), person.count') - .where('person.name LIKE :text COLLATE ' + SQL_COLLATE, { - text: '%' + text + '%', - }) - .limit( - Config.Search.AutoComplete.ItemsPerCategory.person - ) - .orderBy('person.count', 'DESC') - .getRawMany() - ).map((r) => r.name), - SearchQueryTypes.person - ) + this.encapsulateAutoComplete( + ( + await personRepository + .createQueryBuilder('person') + .select('DISTINCT(person.name), person.count') + .where('person.name LIKE :text COLLATE ' + SQL_COLLATE, { + text: '%' + text + '%', + }) + .limit( + Config.Search.AutoComplete.ItemsPerCategory.person + ) + .orderBy('person.count', 'DESC') + .getRawMany() + ).map((r) => r.name), + SearchQueryTypes.person + ) ); } if ( - type === SearchQueryTypes.any_text || - type === SearchQueryTypes.position || - type === SearchQueryTypes.distance + type === SearchQueryTypes.any_text || + type === SearchQueryTypes.position || + type === SearchQueryTypes.distance ) { const acList: AutoCompleteItem[] = []; ( - await photoRepository - .createQueryBuilder('photo') - .select( - 'photo.metadata.positionData.country as country, ' + - 'photo.metadata.positionData.state as state, photo.metadata.positionData.city as city' - ) - .where( - 'photo.metadata.positionData.country LIKE :text COLLATE ' + - SQL_COLLATE, - {text: '%' + text + '%'} - ) - .orWhere( - 'photo.metadata.positionData.state LIKE :text COLLATE ' + - SQL_COLLATE, - {text: '%' + text + '%'} - ) - .orWhere( - 'photo.metadata.positionData.city LIKE :text COLLATE ' + - SQL_COLLATE, - {text: '%' + text + '%'} - ) - .groupBy( - 'photo.metadata.positionData.country, photo.metadata.positionData.state, photo.metadata.positionData.city' - ) - .limit(Config.Search.AutoComplete.ItemsPerCategory.position) - .getRawMany() - ) - .filter((pm): boolean => !!pm) - .map( - (pm): Array => - [pm.city || '', pm.country || '', pm.state || ''] as Array - ) - .forEach((positions): void => { - acList.push( - ...this.encapsulateAutoComplete( - positions.filter( - (p): boolean => - p.toLowerCase().indexOf(text.toLowerCase()) !== -1 - ), - type === SearchQueryTypes.distance - ? type - : SearchQueryTypes.position - ) - ); - }); - partialResult.push(acList); - } - - if ( - type === SearchQueryTypes.any_text || - type === SearchQueryTypes.file_name - ) { - partialResult.push( - this.encapsulateAutoComplete( - ( - await mediaRepository - .createQueryBuilder('media') - .select('DISTINCT(media.name)') - .where('media.name LIKE :text COLLATE ' + SQL_COLLATE, { - text: '%' + text + '%', - }) - .limit( - Config.Search.AutoComplete.ItemsPerCategory.fileName + await photoRepository + .createQueryBuilder('photo') + .select( + 'photo.metadata.positionData.country as country, ' + + 'photo.metadata.positionData.state as state, photo.metadata.positionData.city as city' ) - .getRawMany() - ).map((r) => r.name), - SearchQueryTypes.file_name - ) - ); - } - - if ( - type === SearchQueryTypes.any_text || - type === SearchQueryTypes.caption - ) { - partialResult.push( - this.encapsulateAutoComplete( - ( - await photoRepository - .createQueryBuilder('media') - .select('DISTINCT(media.metadata.caption) as caption') .where( - 'media.metadata.caption LIKE :text COLLATE ' + SQL_COLLATE, - {text: '%' + text + '%'} + 'photo.metadata.positionData.country LIKE :text COLLATE ' + + SQL_COLLATE, + {text: '%' + text + '%'} ) - .limit( - Config.Search.AutoComplete.ItemsPerCategory.caption + .orWhere( + 'photo.metadata.positionData.state LIKE :text COLLATE ' + + SQL_COLLATE, + {text: '%' + text + '%'} ) + .orWhere( + 'photo.metadata.positionData.city LIKE :text COLLATE ' + + SQL_COLLATE, + {text: '%' + text + '%'} + ) + .groupBy( + 'photo.metadata.positionData.country, photo.metadata.positionData.state, photo.metadata.positionData.city' + ) + .limit(Config.Search.AutoComplete.ItemsPerCategory.position) .getRawMany() - ).map((r) => r.caption), - SearchQueryTypes.caption - ) + ) + .filter((pm): boolean => !!pm) + .map( + (pm): Array => + [pm.city || '', pm.country || '', pm.state || ''] as Array + ) + .forEach((positions): void => { + acList.push( + ...this.encapsulateAutoComplete( + positions.filter( + (p): boolean => + p.toLowerCase().indexOf(text.toLowerCase()) !== -1 + ), + type === SearchQueryTypes.distance + ? type + : SearchQueryTypes.position + ) + ); + }); + partialResult.push(acList); + } + + if ( + type === SearchQueryTypes.any_text || + type === SearchQueryTypes.file_name + ) { + partialResult.push( + this.encapsulateAutoComplete( + ( + await mediaRepository + .createQueryBuilder('media') + .select('DISTINCT(media.name)') + .where('media.name LIKE :text COLLATE ' + SQL_COLLATE, { + text: '%' + text + '%', + }) + .limit( + Config.Search.AutoComplete.ItemsPerCategory.fileName + ) + .getRawMany() + ).map((r) => r.name), + SearchQueryTypes.file_name + ) ); } if ( - type === SearchQueryTypes.any_text || - type === SearchQueryTypes.directory + type === SearchQueryTypes.any_text || + type === SearchQueryTypes.caption ) { partialResult.push( - this.encapsulateAutoComplete( - ( - await directoryRepository - .createQueryBuilder('dir') - .select('DISTINCT(dir.name)') - .where('dir.name LIKE :text COLLATE ' + SQL_COLLATE, { - text: '%' + text + '%', - }) - .limit( - Config.Search.AutoComplete.ItemsPerCategory.directory - ) - .getRawMany() - ).map((r) => r.name), - SearchQueryTypes.directory - ) + this.encapsulateAutoComplete( + ( + await photoRepository + .createQueryBuilder('media') + .select('DISTINCT(media.metadata.caption) as caption') + .where( + 'media.metadata.caption LIKE :text COLLATE ' + SQL_COLLATE, + {text: '%' + text + '%'} + ) + .limit( + Config.Search.AutoComplete.ItemsPerCategory.caption + ) + .getRawMany() + ).map((r) => r.caption), + SearchQueryTypes.caption + ) + ); + } + + if ( + type === SearchQueryTypes.any_text || + type === SearchQueryTypes.directory + ) { + partialResult.push( + this.encapsulateAutoComplete( + ( + await directoryRepository + .createQueryBuilder('dir') + .select('DISTINCT(dir.name)') + .where('dir.name LIKE :text COLLATE ' + SQL_COLLATE, { + text: '%' + text + '%', + }) + .limit( + Config.Search.AutoComplete.ItemsPerCategory.directory + ) + .getRawMany() + ).map((r) => r.name), + SearchQueryTypes.directory + ) ); } @@ -290,13 +290,13 @@ export class SearchManager { }; result.media = await connection - .getRepository(MediaEntity) - .createQueryBuilder('media') - .select(['media', ...this.DIRECTORY_SELECT]) - .where(this.buildWhereQuery(query)) - .leftJoin('media.directory', 'directory') - .limit(Config.Search.maxMediaResult + 1) - .getMany(); + .getRepository(MediaEntity) + .createQueryBuilder('media') + .select(['media', ...this.DIRECTORY_SELECT]) + .where(this.buildWhereQuery(query)) + .leftJoin('media.directory', 'directory') + .limit(Config.Search.maxMediaResult + 1) + .getMany(); if (result.media.length > Config.Search.maxMediaResult) { @@ -307,31 +307,31 @@ export class SearchManager { if (Config.Search.listMetafiles === true) { const dIds = Array.from(new Set(result.media.map(m => (m.directory as unknown as { id: number }).id))); result.metaFile = await connection - .getRepository(FileEntity) - .createQueryBuilder('file') - .select(['file', ...this.DIRECTORY_SELECT]) - .where(`file.directoryId IN(${dIds})`) - .leftJoin('file.directory', 'directory') - .getMany(); + .getRepository(FileEntity) + .createQueryBuilder('file') + .select(['file', ...this.DIRECTORY_SELECT]) + .where(`file.directoryId IN(${dIds})`) + .leftJoin('file.directory', 'directory') + .getMany(); } if (Config.Search.listDirectories === true) { const dirQuery = this.filterDirectoryQuery(query); if (dirQuery !== null) { result.directories = await connection - .getRepository(DirectoryEntity) - .createQueryBuilder('directory') - .where(this.buildWhereQuery(dirQuery, true)) - .leftJoinAndSelect('directory.cover', 'cover') - .leftJoinAndSelect('cover.directory', 'coverDirectory') - .limit(Config.Search.maxDirectoryResult + 1) - .select([ - 'directory', - 'cover.name', - 'coverDirectory.name', - 'coverDirectory.path', - ]) - .getMany(); + .getRepository(DirectoryEntity) + .createQueryBuilder('directory') + .where(this.buildWhereQuery(dirQuery, true)) + .leftJoinAndSelect('directory.cover', 'cover') + .leftJoinAndSelect('cover.directory', 'coverDirectory') + .limit(Config.Search.maxDirectoryResult + 1) + .select([ + 'directory', + 'cover.name', + 'coverDirectory.name', + 'coverDirectory.path', + ]) + .getMany(); // setting covers if (result.directories) { @@ -340,7 +340,7 @@ export class SearchManager { } } if ( - result.directories.length > Config.Search.maxDirectoryResult + result.directories.length > Config.Search.maxDirectoryResult ) { result.resultOverflow = true; } @@ -352,8 +352,8 @@ export class SearchManager { public static setSorting( - query: SelectQueryBuilder, - sortings: SortingMethod[] + query: SelectQueryBuilder, + sortings: SortingMethod[] ): SelectQueryBuilder { if (!sortings || !Array.isArray(sortings)) { return query; @@ -394,11 +394,11 @@ export class SearchManager { public async getNMedia(query: SearchQueryDTO, sortings: SortingMethod[], take: number, photoOnly = false) { const connection = await SQLConnection.getConnection(); const sqlQuery: SelectQueryBuilder = connection - .getRepository(photoOnly ? PhotoEntity : MediaEntity) - .createQueryBuilder('media') - .select(['media', ...this.DIRECTORY_SELECT]) - .innerJoin('media.directory', 'directory') - .where(await this.prepareAndBuildWhereQuery(query)); + .getRepository(photoOnly ? PhotoEntity : MediaEntity) + .createQueryBuilder('media') + .select(['media', ...this.DIRECTORY_SELECT]) + .innerJoin('media.directory', 'directory') + .where(await this.prepareAndBuildWhereQuery(query)); SearchManager.setSorting(sqlQuery, sortings); return sqlQuery.limit(take).getMany(); @@ -409,16 +409,16 @@ export class SearchManager { const connection = await SQLConnection.getConnection(); return await connection - .getRepository(MediaEntity) - .createQueryBuilder('media') - .innerJoin('media.directory', 'directory') - .where(await this.prepareAndBuildWhereQuery(query)) - .getCount(); + .getRepository(MediaEntity) + .createQueryBuilder('media') + .innerJoin('media.directory', 'directory') + .where(await this.prepareAndBuildWhereQuery(query)) + .getCount(); } public async prepareAndBuildWhereQuery( - queryIN: SearchQueryDTO, - directoryOnly = false + queryIN: SearchQueryDTO, + directoryOnly = false ): Promise { const query = await this.prepareQuery(queryIN); return this.buildWhereQuery(query, directoryOnly); @@ -438,24 +438,24 @@ export class SearchManager { * @private */ public buildWhereQuery( - query: SearchQueryDTO, - directoryOnly = false + query: SearchQueryDTO, + directoryOnly = false ): Brackets { const queryId = (query as SearchQueryDTOWithID).queryId; switch (query.type) { case SearchQueryTypes.AND: return new Brackets((q): unknown => { (query as ANDSearchQuery).list.forEach((sq) => { - q.andWhere(this.buildWhereQuery(sq, directoryOnly)); - } + q.andWhere(this.buildWhereQuery(sq, directoryOnly)); + } ); return q; }); case SearchQueryTypes.OR: return new Brackets((q): unknown => { (query as ANDSearchQuery).list.forEach((sq) => { - q.orWhere(this.buildWhereQuery(sq, directoryOnly)); - } + q.orWhere(this.buildWhereQuery(sq, directoryOnly)); + } ); return q; }); @@ -478,30 +478,30 @@ export class SearchManager { }; const minLat = trimRange( - (query as DistanceSearch).from.GPSData.latitude - - (query as DistanceSearch).distance * latDelta, - -90, - 90 + (query as DistanceSearch).from.GPSData.latitude - + (query as DistanceSearch).distance * latDelta, + -90, + 90 ); const maxLat = trimRange( - (query as DistanceSearch).from.GPSData.latitude + - (query as DistanceSearch).distance * latDelta, - -90, - 90 + (query as DistanceSearch).from.GPSData.latitude + + (query as DistanceSearch).distance * latDelta, + -90, + 90 ); const minLon = trimRange( - (query as DistanceSearch).from.GPSData.longitude - - ((query as DistanceSearch).distance * lonDelta) / - Math.cos(minLat * (Math.PI / 180)), - -180, - 180 + (query as DistanceSearch).from.GPSData.longitude - + ((query as DistanceSearch).distance * lonDelta) / + Math.cos(minLat * (Math.PI / 180)), + -180, + 180 ); const maxLon = trimRange( - (query as DistanceSearch).from.GPSData.longitude + - ((query as DistanceSearch).distance * lonDelta) / - Math.cos(maxLat * (Math.PI / 180)), - -180, - 180 + (query as DistanceSearch).from.GPSData.longitude + + ((query as DistanceSearch).distance * lonDelta) / + Math.cos(maxLat * (Math.PI / 180)), + -180, + 180 ); return new Brackets((q): unknown => { @@ -512,37 +512,37 @@ export class SearchManager { textParam['minLon' + queryId] = minLon; if (!(query as DistanceSearch).negate) { q.where( - `media.metadata.positionData.GPSData.latitude < :maxLat${queryId}`, - textParam + `media.metadata.positionData.GPSData.latitude < :maxLat${queryId}`, + textParam ); q.andWhere( - `media.metadata.positionData.GPSData.latitude > :minLat${queryId}`, - textParam + `media.metadata.positionData.GPSData.latitude > :minLat${queryId}`, + textParam ); q.andWhere( - `media.metadata.positionData.GPSData.longitude < :maxLon${queryId}`, - textParam + `media.metadata.positionData.GPSData.longitude < :maxLon${queryId}`, + textParam ); q.andWhere( - `media.metadata.positionData.GPSData.longitude > :minLon${queryId}`, - textParam + `media.metadata.positionData.GPSData.longitude > :minLon${queryId}`, + textParam ); } else { q.where( - `media.metadata.positionData.GPSData.latitude > :maxLat${queryId}`, - textParam + `media.metadata.positionData.GPSData.latitude > :maxLat${queryId}`, + textParam ); q.orWhere( - `media.metadata.positionData.GPSData.latitude < :minLat${queryId}`, - textParam + `media.metadata.positionData.GPSData.latitude < :minLat${queryId}`, + textParam ); q.orWhere( - `media.metadata.positionData.GPSData.longitude > :maxLon${queryId}`, - textParam + `media.metadata.positionData.GPSData.longitude > :maxLon${queryId}`, + textParam ); q.orWhere( - `media.metadata.positionData.GPSData.longitude < :minLon${queryId}`, - textParam + `media.metadata.positionData.GPSData.longitude < :minLon${queryId}`, + textParam ); } return q; @@ -555,7 +555,7 @@ export class SearchManager { return new Brackets((q): unknown => { if (typeof (query as FromDateSearch).value === 'undefined') { throw new Error( - 'Invalid search query: Date Query should contain from value' + 'Invalid search query: Date Query should contain from value' ); } const relation = (query as TextSearch).negate ? '<' : '>='; @@ -563,8 +563,8 @@ export class SearchManager { const textParam: { [key: string]: unknown } = {}; textParam['from' + queryId] = (query as FromDateSearch).value; q.where( - `media.metadata.creationDate ${relation} :from${queryId}`, - textParam + `media.metadata.creationDate ${relation} :from${queryId}`, + textParam ); return q; @@ -577,7 +577,7 @@ export class SearchManager { return new Brackets((q): unknown => { if (typeof (query as ToDateSearch).value === 'undefined') { throw new Error( - 'Invalid search query: Date Query should contain to value' + 'Invalid search query: Date Query should contain to value' ); } const relation = (query as TextSearch).negate ? '>' : '<='; @@ -585,8 +585,8 @@ export class SearchManager { const textParam: { [key: string]: unknown } = {}; textParam['to' + queryId] = (query as ToDateSearch).value; q.where( - `media.metadata.creationDate ${relation} :to${queryId}`, - textParam + `media.metadata.creationDate ${relation} :to${queryId}`, + textParam ); return q; @@ -599,7 +599,7 @@ export class SearchManager { return new Brackets((q): unknown => { if (typeof (query as MinRatingSearch).value === 'undefined') { throw new Error( - 'Invalid search query: Rating Query should contain minvalue' + 'Invalid search query: Rating Query should contain minvalue' ); } @@ -608,8 +608,8 @@ export class SearchManager { const textParam: { [key: string]: unknown } = {}; textParam['min' + queryId] = (query as MinRatingSearch).value; q.where( - `media.metadata.rating ${relation} :min${queryId}`, - textParam + `media.metadata.rating ${relation} :min${queryId}`, + textParam ); return q; @@ -621,7 +621,7 @@ export class SearchManager { return new Brackets((q): unknown => { if (typeof (query as MaxRatingSearch).value === 'undefined') { throw new Error( - 'Invalid search query: Rating Query should contain max value' + 'Invalid search query: Rating Query should contain max value' ); } @@ -631,8 +631,8 @@ export class SearchManager { const textParam: { [key: string]: unknown } = {}; textParam['max' + queryId] = (query as MaxRatingSearch).value; q.where( - `media.metadata.rating ${relation} :max${queryId}`, - textParam + `media.metadata.rating ${relation} :max${queryId}`, + textParam ); } return q; @@ -645,7 +645,7 @@ export class SearchManager { return new Brackets((q): unknown => { if (typeof (query as MinPersonCountSearch).value === 'undefined') { throw new Error( - 'Invalid search query: Person count Query should contain minvalue' + 'Invalid search query: Person count Query should contain minvalue' ); } @@ -654,8 +654,8 @@ export class SearchManager { const textParam: { [key: string]: unknown } = {}; textParam['min' + queryId] = (query as MinPersonCountSearch).value; q.where( - `media.metadata.personsLength ${relation} :min${queryId}`, - textParam + `media.metadata.personsLength ${relation} :min${queryId}`, + textParam ); return q; @@ -667,7 +667,7 @@ export class SearchManager { return new Brackets((q): unknown => { if (typeof (query as MaxPersonCountSearch).value === 'undefined') { throw new Error( - 'Invalid search query: Person count Query should contain max value' + 'Invalid search query: Person count Query should contain max value' ); } @@ -677,8 +677,8 @@ export class SearchManager { const textParam: { [key: string]: unknown } = {}; textParam['max' + queryId] = (query as MaxPersonCountSearch).value; q.where( - `media.metadata.personsLength ${relation} :max${queryId}`, - textParam + `media.metadata.personsLength ${relation} :max${queryId}`, + textParam ); } return q; @@ -691,7 +691,7 @@ export class SearchManager { return new Brackets((q): unknown => { if (typeof (query as MinResolutionSearch).value === 'undefined') { throw new Error( - 'Invalid search query: Resolution Query should contain min value' + 'Invalid search query: Resolution Query should contain min value' ); } @@ -699,10 +699,10 @@ export class SearchManager { const textParam: { [key: string]: unknown } = {}; textParam['min' + queryId] = - (query as MinResolutionSearch).value * 1000 * 1000; + (query as MinResolutionSearch).value * 1000 * 1000; q.where( - `media.metadata.size.width * media.metadata.size.height ${relation} :min${queryId}`, - textParam + `media.metadata.size.width * media.metadata.size.height ${relation} :min${queryId}`, + textParam ); return q; @@ -715,7 +715,7 @@ export class SearchManager { return new Brackets((q): unknown => { if (typeof (query as MaxResolutionSearch).value === 'undefined') { throw new Error( - 'Invalid search query: Rating Query should contain min or max value' + 'Invalid search query: Rating Query should contain min or max value' ); } @@ -723,10 +723,10 @@ export class SearchManager { const textParam: { [key: string]: unknown } = {}; textParam['max' + queryId] = - (query as MaxResolutionSearch).value * 1000 * 1000; + (query as MaxResolutionSearch).value * 1000 * 1000; q.where( - `media.metadata.size.width * media.metadata.size.height ${relation} :max${queryId}`, - textParam + `media.metadata.size.width * media.metadata.size.height ${relation} :max${queryId}`, + textParam ); return q; @@ -754,9 +754,9 @@ export class SearchManager { return new Brackets((q): unknown => { // Fixed frequency if ((tq.frequency === DatePatternFrequency.years_ago || - tq.frequency === DatePatternFrequency.months_ago || - tq.frequency === DatePatternFrequency.weeks_ago || - tq.frequency === DatePatternFrequency.days_ago)) { + tq.frequency === DatePatternFrequency.months_ago || + tq.frequency === DatePatternFrequency.weeks_ago || + tq.frequency === DatePatternFrequency.days_ago)) { if (isNaN(tq.agoNumber)) { throw new Error('ago number is missing on date patter search query with frequency: ' + DatePatternFrequency[tq.frequency] + ', ago number: ' + tq.agoNumber); @@ -790,16 +790,16 @@ export class SearchManager { if (tq.negate) { q.where( - `media.metadata.creationDate >= :to${queryId}`, - textParam + `media.metadata.creationDate >= :to${queryId}`, + textParam ).orWhere(`media.metadata.creationDate < :from${queryId}`, - textParam); + textParam); } else { q.where( - `media.metadata.creationDate < :to${queryId}`, - textParam + `media.metadata.creationDate < :to${queryId}`, + textParam ).andWhere(`media.metadata.creationDate >= :from${queryId}`, - textParam); + textParam); } } else { @@ -815,15 +815,15 @@ export class SearchManager { if (Config.Database.type === DatabaseType.sqlite) { q.where( - `CAST(strftime('${duration}',media.metadataCreationDate/1000, 'unixepoch') AS INTEGER) ${relationTop} CAST(strftime('${duration}','now') AS INTEGER)` + `CAST(strftime('${duration}',media.metadataCreationDate/1000, 'unixepoch') AS INTEGER) ${relationTop} CAST(strftime('${duration}','now') AS INTEGER)` ).andWhere(`CAST(strftime('${duration}',media.metadataCreationDate/1000, 'unixepoch') AS INTEGER) ${relationBottom} CAST(strftime('${duration}','now','-:diff${queryId} day') AS INTEGER)`, - textParam); + textParam); } else { q.where( - `CAST(FROM_UNIXTIME(media.metadataCreationDate/1000, '${duration}') AS SIGNED) ${relationTop} CAST(DATE_FORMAT(CURDATE(),'${duration}') AS SIGNED)` + `CAST(FROM_UNIXTIME(media.metadataCreationDate/1000, '${duration}') AS SIGNED) ${relationTop} CAST(DATE_FORMAT(CURDATE(),'${duration}') AS SIGNED)` ).andWhere(`CAST(FROM_UNIXTIME(media.metadataCreationDate/1000, '${duration}') AS SIGNED) ${relationBottom} CAST(DATE_FORMAT((DATE_ADD(curdate(), INTERVAL -:diff${queryId} DAY)),'${duration}') AS SIGNED)`, - textParam); + textParam); } }; switch (tq.frequency) { @@ -861,8 +861,8 @@ export class SearchManager { return new Brackets((q: WhereExpression) => { const createMatchString = (str: string): string => { if ( - (query as TextSearch).matchType === - TextSearchQueryMatchTypes.exact_match + (query as TextSearch).matchType === + TextSearchQueryMatchTypes.exact_match ) { return str; } @@ -882,148 +882,148 @@ export class SearchManager { const textParam: { [key: string]: unknown } = {}; textParam['text' + queryId] = createMatchString( - (query as TextSearch).text + (query as TextSearch).text ); if ( - query.type === SearchQueryTypes.any_text || - query.type === SearchQueryTypes.directory + query.type === SearchQueryTypes.any_text || + query.type === SearchQueryTypes.directory ) { const dirPathStr = (query as TextSearch).text.replace( - new RegExp('\\\\', 'g'), - '/' + new RegExp('\\\\', 'g'), + '/' ); textParam['fullPath' + queryId] = createMatchString(dirPathStr); q[whereFN]( - `directory.path ${LIKE} :fullPath${queryId} COLLATE ` + SQL_COLLATE, - textParam + `directory.path ${LIKE} :fullPath${queryId} COLLATE ` + SQL_COLLATE, + textParam ); const directoryPath = GalleryManager.parseRelativeDirePath(dirPathStr); q[whereFN]( - new Brackets((dq): unknown => { - textParam['dirName' + queryId] = createMatchString( - directoryPath.name - ); - dq[whereFNRev]( - `directory.name ${LIKE} :dirName${queryId} COLLATE ${SQL_COLLATE}`, - textParam - ); - if (dirPathStr.includes('/')) { - textParam['parentName' + queryId] = createMatchString( - directoryPath.parent + new Brackets((dq): unknown => { + textParam['dirName' + queryId] = createMatchString( + directoryPath.name ); dq[whereFNRev]( - `directory.path ${LIKE} :parentName${queryId} COLLATE ${SQL_COLLATE}`, - textParam + `directory.name ${LIKE} :dirName${queryId} COLLATE ${SQL_COLLATE}`, + textParam ); - } - return dq; - }) + if (dirPathStr.includes('/')) { + textParam['parentName' + queryId] = createMatchString( + directoryPath.parent + ); + dq[whereFNRev]( + `directory.path ${LIKE} :parentName${queryId} COLLATE ${SQL_COLLATE}`, + textParam + ); + } + return dq; + }) ); } if ( - (query.type === SearchQueryTypes.any_text && !directoryOnly) || - query.type === SearchQueryTypes.file_name + (query.type === SearchQueryTypes.any_text && !directoryOnly) || + query.type === SearchQueryTypes.file_name ) { q[whereFN]( - `media.name ${LIKE} :text${queryId} COLLATE ${SQL_COLLATE}`, - textParam + `media.name ${LIKE} :text${queryId} COLLATE ${SQL_COLLATE}`, + textParam ); } if ( - (query.type === SearchQueryTypes.any_text && !directoryOnly) || - query.type === SearchQueryTypes.caption + (query.type === SearchQueryTypes.any_text && !directoryOnly) || + query.type === SearchQueryTypes.caption ) { q[whereFN]( - `media.metadata.caption ${LIKE} :text${queryId} COLLATE ${SQL_COLLATE}`, - textParam + `media.metadata.caption ${LIKE} :text${queryId} COLLATE ${SQL_COLLATE}`, + textParam ); } if ( - (query.type === SearchQueryTypes.any_text && !directoryOnly) || - query.type === SearchQueryTypes.position + (query.type === SearchQueryTypes.any_text && !directoryOnly) || + query.type === SearchQueryTypes.position ) { q[whereFN]( - `media.metadata.positionData.country ${LIKE} :text${queryId} COLLATE ${SQL_COLLATE}`, - textParam + `media.metadata.positionData.country ${LIKE} :text${queryId} COLLATE ${SQL_COLLATE}`, + textParam )[whereFN]( - `media.metadata.positionData.state ${LIKE} :text${queryId} COLLATE ${SQL_COLLATE}`, - textParam + `media.metadata.positionData.state ${LIKE} :text${queryId} COLLATE ${SQL_COLLATE}`, + textParam )[whereFN]( - `media.metadata.positionData.city ${LIKE} :text${queryId} COLLATE ${SQL_COLLATE}`, - textParam + `media.metadata.positionData.city ${LIKE} :text${queryId} COLLATE ${SQL_COLLATE}`, + textParam ); } // Matching for array type fields const matchArrayField = (fieldName: string): void => { q[whereFN]( - new Brackets((qbr): void => { - if ( - (query as TextSearch).matchType !== - TextSearchQueryMatchTypes.exact_match - ) { - qbr[whereFN]( - `${fieldName} ${LIKE} :text${queryId} COLLATE ${SQL_COLLATE}`, - textParam - ); - } else { - qbr[whereFN]( - new Brackets((qb): void => { - textParam['CtextC' + queryId] = `%,${ - (query as TextSearch).text - },%`; - textParam['Ctext' + queryId] = `%,${ - (query as TextSearch).text - }`; - textParam['textC' + queryId] = `${ - (query as TextSearch).text - },%`; - textParam['text_exact' + queryId] = `${ - (query as TextSearch).text - }`; + new Brackets((qbr): void => { + if ( + (query as TextSearch).matchType !== + TextSearchQueryMatchTypes.exact_match + ) { + qbr[whereFN]( + `${fieldName} ${LIKE} :text${queryId} COLLATE ${SQL_COLLATE}`, + textParam + ); + } else { + qbr[whereFN]( + new Brackets((qb): void => { + textParam['CtextC' + queryId] = `%,${ + (query as TextSearch).text + },%`; + textParam['Ctext' + queryId] = `%,${ + (query as TextSearch).text + }`; + textParam['textC' + queryId] = `${ + (query as TextSearch).text + },%`; + textParam['text_exact' + queryId] = `${ + (query as TextSearch).text + }`; - qb[whereFN]( - `${fieldName} ${LIKE} :CtextC${queryId} COLLATE ${SQL_COLLATE}`, - textParam - ); - qb[whereFN]( - `${fieldName} ${LIKE} :Ctext${queryId} COLLATE ${SQL_COLLATE}`, - textParam - ); - qb[whereFN]( - `${fieldName} ${LIKE} :textC${queryId} COLLATE ${SQL_COLLATE}`, - textParam - ); - qb[whereFN]( - `${fieldName} ${LIKE} :text_exact${queryId} COLLATE ${SQL_COLLATE}`, - textParam - ); - }) - ); - } - if ((query as TextSearch).negate) { - qbr.orWhere(`${fieldName} IS NULL`); - } - }) + qb[whereFN]( + `${fieldName} ${LIKE} :CtextC${queryId} COLLATE ${SQL_COLLATE}`, + textParam + ); + qb[whereFN]( + `${fieldName} ${LIKE} :Ctext${queryId} COLLATE ${SQL_COLLATE}`, + textParam + ); + qb[whereFN]( + `${fieldName} ${LIKE} :textC${queryId} COLLATE ${SQL_COLLATE}`, + textParam + ); + qb[whereFN]( + `${fieldName} ${LIKE} :text_exact${queryId} COLLATE ${SQL_COLLATE}`, + textParam + ); + }) + ); + } + if ((query as TextSearch).negate) { + qbr.orWhere(`${fieldName} IS NULL`); + } + }) ); }; if ( - (query.type === SearchQueryTypes.any_text && !directoryOnly) || - query.type === SearchQueryTypes.person + (query.type === SearchQueryTypes.any_text && !directoryOnly) || + query.type === SearchQueryTypes.person ) { matchArrayField('media.metadata.persons'); } if ( - (query.type === SearchQueryTypes.any_text && !directoryOnly) || - query.type === SearchQueryTypes.keyword + (query.type === SearchQueryTypes.any_text && !directoryOnly) || + query.type === SearchQueryTypes.keyword ) { matchArrayField('media.metadata.keywords'); } @@ -1038,7 +1038,7 @@ export class SearchManager { return { type: query.type, list: ((query as SearchListQuery).list || []).map( - (q): SearchQueryDTO => this.flattenSameOfQueries(q) + (q): SearchQueryDTO => this.flattenSameOfQueries(q) ), } as SearchListQuery; case SearchQueryTypes.SOME_OF: @@ -1060,9 +1060,9 @@ export class SearchManager { } const getAllCombinations = ( - num: number, - arr: SearchQueryDTO[], - start = 0 + num: number, + arr: SearchQueryDTO[], + start = 0 ): SearchQueryDTO[] => { if (num <= 0 || num > arr.length || start >= arr.length) { return null; @@ -1112,8 +1112,8 @@ export class SearchManager { return this.flattenSameOfQueries({ type: SearchQueryTypes.OR, list: getAllCombinations( - someOfQ.min, - (query as SearchListQuery).list + someOfQ.min, + (query as SearchListQuery).list ), } as ORSearchQuery); } @@ -1126,8 +1126,8 @@ export class SearchManager { * Witch SOME_OF query the number of WHERE constrains have O(N!) complexity */ private assignQueryIDs( - queryIN: SearchQueryDTO, - id = {value: 1} + queryIN: SearchQueryDTO, + id = {value: 1} ): SearchQueryDTO { // It is possible that one SQL query contains multiple searchQueries // (like: where ( AND ()) @@ -1140,12 +1140,12 @@ export class SearchManager { } if ((queryIN as SearchListQuery).list) { (queryIN as SearchListQuery).list.forEach((q) => - this.assignQueryIDs(q, id) + this.assignQueryIDs(q, id) ); return queryIN; } (queryIN as SearchQueryDTOWithID).queryId = - this.queryIdBase + '_' + id.value; + this.queryIdBase + '_' + id.value; id.value++; return queryIN; } @@ -1159,7 +1159,7 @@ export class SearchManager { const andRet = { type: SearchQueryTypes.AND, list: (query as SearchListQuery).list.map((q) => - this.filterDirectoryQuery(q) + this.filterDirectoryQuery(q) ), } as ANDSearchQuery; // if any of the queries contain non dir query thw whole and query is a non dir query @@ -1172,8 +1172,8 @@ export class SearchManager { const orRet = { type: SearchQueryTypes.OR, list: (query as SearchListQuery).list - .map((q) => this.filterDirectoryQuery(q)) - .filter((q) => q !== null), + .map((q) => this.filterDirectoryQuery(q)) + .filter((q) => q !== null), } as ORSearchQuery; if (orRet.list.length === 0) { return null; @@ -1194,31 +1194,31 @@ export class SearchManager { private async getGPSData(query: SearchQueryDTO): Promise { if ((query as ANDSearchQuery | ORSearchQuery).list) { for ( - let i = 0; - i < (query as ANDSearchQuery | ORSearchQuery).list.length; - ++i + let i = 0; + i < (query as ANDSearchQuery | ORSearchQuery).list.length; + ++i ) { (query as ANDSearchQuery | ORSearchQuery).list[i] = - await this.getGPSData( - (query as ANDSearchQuery | ORSearchQuery).list[i] - ); + await this.getGPSData( + (query as ANDSearchQuery | ORSearchQuery).list[i] + ); } } if ( - query.type === SearchQueryTypes.distance && - (query as DistanceSearch).from.text + query.type === SearchQueryTypes.distance && + (query as DistanceSearch).from.text ) { (query as DistanceSearch).from.GPSData = - await ObjectManagers.getInstance().LocationManager.getGPSData( - (query as DistanceSearch).from.text - ); + await ObjectManagers.getInstance().LocationManager.getGPSData( + (query as DistanceSearch).from.text + ); } return query; } private encapsulateAutoComplete( - values: string[], - type: SearchQueryTypes + values: string[], + type: SearchQueryTypes ): Array { const res: AutoCompleteItem[] = []; values.forEach((value): void => { diff --git a/src/backend/model/database/SharingManager.ts b/src/backend/model/database/SharingManager.ts index 6c3c7fec..8e07b1d9 100644 --- a/src/backend/model/database/SharingManager.ts +++ b/src/backend/model/database/SharingManager.ts @@ -10,18 +10,18 @@ export class SharingManager { private static async removeExpiredLink(): Promise { const connection = await SQLConnection.getConnection(); return await connection - .getRepository(SharingEntity) - .createQueryBuilder('share') - .where('expires < :now', {now: Date.now()}) - .delete() - .execute(); + .getRepository(SharingEntity) + .createQueryBuilder('share') + .where('expires < :now', {now: Date.now()}) + .delete() + .execute(); } async deleteSharing(sharingKey: string): Promise { const connection = await SQLConnection.getConnection(); const sharing = await connection - .getRepository(SharingEntity) - .findOneBy({sharingKey}); + .getRepository(SharingEntity) + .findOneBy({sharingKey}); await connection.getRepository(SharingEntity).remove(sharing); } @@ -29,10 +29,10 @@ export class SharingManager { await SharingManager.removeExpiredLink(); const connection = await SQLConnection.getConnection(); return await connection - .getRepository(SharingEntity) - .createQueryBuilder('share') - .leftJoinAndSelect('share.creator', 'creator') - .getMany(); + .getRepository(SharingEntity) + .createQueryBuilder('share') + .leftJoinAndSelect('share.creator', 'creator') + .getMany(); } @@ -40,10 +40,10 @@ export class SharingManager { await SharingManager.removeExpiredLink(); const connection = await SQLConnection.getConnection(); const q: SelectQueryBuilder = connection - .getRepository(SharingEntity) - .createQueryBuilder('share') - .leftJoinAndSelect('share.creator', 'creator') - .where('path = :dir', {dir}); + .getRepository(SharingEntity) + .createQueryBuilder('share') + .leftJoinAndSelect('share.creator', 'creator') + .where('path = :dir', {dir}); if (user) { q.andWhere('share.creator = :user', {user: user.id}); } @@ -54,10 +54,10 @@ export class SharingManager { await SharingManager.removeExpiredLink(); const connection = await SQLConnection.getConnection(); return await connection.getRepository(SharingEntity) - .createQueryBuilder('share') - .leftJoinAndSelect('share.creator', 'creator') - .where('share.sharingKey = :sharingKey', {sharingKey}) - .getOne(); + .createQueryBuilder('share') + .leftJoinAndSelect('share.creator', 'creator') + .where('share.sharingKey = :sharingKey', {sharingKey}) + .getOne(); } async createSharing(sharing: SharingDTO): Promise { @@ -70,20 +70,20 @@ export class SharingManager { } async updateSharing( - inSharing: SharingDTO, - forceUpdate: boolean + inSharing: SharingDTO, + forceUpdate: boolean ): Promise { const connection = await SQLConnection.getConnection(); const sharing = await connection.getRepository(SharingEntity).findOneBy({ id: inSharing.id, - creator: inSharing.creator.id as any, + creator: inSharing.creator.id as unknown, path: inSharing.path, }); if ( - sharing.timeStamp < Date.now() - Config.Sharing.updateTimeout && - forceUpdate !== true + sharing.timeStamp < Date.now() - Config.Sharing.updateTimeout && + forceUpdate !== true ) { throw new Error('Sharing is locked, can\'t update anymore'); } diff --git a/src/backend/model/database/VersionManager.ts b/src/backend/model/database/VersionManager.ts index ea2637d6..ccf9c521 100644 --- a/src/backend/model/database/VersionManager.ts +++ b/src/backend/model/database/VersionManager.ts @@ -23,30 +23,30 @@ export class VersionManager implements IObjectManager { } const versionString = - DataStructureVersion + - '_' + - this.latestDirectoryStatus.name + - '_' + - this.latestDirectoryStatus.lastModified + - '_' + - this.latestDirectoryStatus.mediaCount + - '_' + - this.allMediaCount; + DataStructureVersion + + '_' + + this.latestDirectoryStatus.name + + '_' + + this.latestDirectoryStatus.lastModified + + '_' + + this.latestDirectoryStatus.mediaCount + + '_' + + this.allMediaCount; return crypto.createHash('md5').update(versionString).digest('hex'); } async onNewDataVersion(): Promise { const connection = await SQLConnection.getConnection(); const dir = await connection - .getRepository(DirectoryEntity) - .createQueryBuilder('directory') - .limit(1) - .orderBy('directory.lastModified') - .getOne(); + .getRepository(DirectoryEntity) + .createQueryBuilder('directory') + .limit(1) + .orderBy('directory.lastModified') + .getOne(); this.allMediaCount = await connection - .getRepository(MediaEntity) - .createQueryBuilder('media') - .getCount(); + .getRepository(MediaEntity) + .createQueryBuilder('media') + .getCount(); if (!dir) { return; diff --git a/src/backend/model/database/enitites/DirectoryEntity.ts b/src/backend/model/database/enitites/DirectoryEntity.ts index 3df67e58..9c48e0f6 100644 --- a/src/backend/model/database/enitites/DirectoryEntity.ts +++ b/src/backend/model/database/enitites/DirectoryEntity.ts @@ -1,28 +1,16 @@ -import { - Column, - Entity, - Index, - ManyToOne, - OneToMany, - PrimaryGeneratedColumn, - Unique, -} from 'typeorm'; -import { - ParentDirectoryDTO, - SubDirectoryDTO, -} from '../../../../common/entities/DirectoryDTO'; -import { MediaEntity } from './MediaEntity'; -import { FileEntity } from './FileEntity'; -import { columnCharsetCS } from './EntityUtils'; -import { MediaDTO } from '../../../../common/entities/MediaDTO'; +import {Column, Entity, Index, ManyToOne, OneToMany, PrimaryGeneratedColumn, Unique,} from 'typeorm'; +import {ParentDirectoryDTO, SubDirectoryDTO,} from '../../../../common/entities/DirectoryDTO'; +import {MediaEntity} from './MediaEntity'; +import {FileEntity} from './FileEntity'; +import {columnCharsetCS} from './EntityUtils'; +import {MediaDTO} from '../../../../common/entities/MediaDTO'; @Entity() @Unique(['name', 'path']) export class DirectoryEntity - implements ParentDirectoryDTO, SubDirectoryDTO -{ + implements ParentDirectoryDTO, SubDirectoryDTO { @Index() - @PrimaryGeneratedColumn({ unsigned: true }) + @PrimaryGeneratedColumn({unsigned: true}) id: number; @Index() @@ -61,7 +49,7 @@ export class DirectoryEntity isPartial?: boolean; - @Column('mediumint', { unsigned: true }) + @Column('mediumint', {unsigned: true}) mediaCount: number; @Column('bigint', { @@ -83,20 +71,20 @@ export class DirectoryEntity youngestMedia: number; @Index() - @ManyToOne((type) => DirectoryEntity, (directory) => directory.directories, { + @ManyToOne(() => DirectoryEntity, (directory) => directory.directories, { onDelete: 'CASCADE', }) public parent: DirectoryEntity; - @OneToMany((type) => DirectoryEntity, (dir) => dir.parent) + @OneToMany(() => DirectoryEntity, (dir) => dir.parent) public directories: DirectoryEntity[]; // not saving to database, it is only assigned when querying the DB - @ManyToOne((type) => MediaEntity, { onDelete: 'SET NULL' }) + @ManyToOne(() => MediaEntity, {onDelete: 'SET NULL'}) public cover: MediaEntity; // On galley change, cover will be invalid - @Column({ type: 'boolean', default: false }) + @Column({type: 'boolean', default: false}) validCover: boolean; @OneToMany((type) => MediaEntity, (media) => media.directory) diff --git a/src/backend/model/database/enitites/EntityUtils.ts b/src/backend/model/database/enitites/EntityUtils.ts index dd7d11a1..2c54edbd 100644 --- a/src/backend/model/database/enitites/EntityUtils.ts +++ b/src/backend/model/database/enitites/EntityUtils.ts @@ -1,18 +1,18 @@ -import { Config } from '../../../../common/config/private/Config'; -import { ColumnOptions } from 'typeorm/decorator/options/ColumnOptions'; -import { DatabaseType } from '../../../../common/config/private/PrivateConfig'; +import {Config} from '../../../../common/config/private/Config'; +import {ColumnOptions} from 'typeorm/decorator/options/ColumnOptions'; +import {DatabaseType} from '../../../../common/config/private/PrivateConfig'; export class ColumnCharsetCS implements ColumnOptions { public get charset(): string { return Config.Database.type === DatabaseType.mysql - ? 'utf8mb4' - : 'utf8'; + ? 'utf8mb4' + : 'utf8'; } public get collation(): string { return Config.Database.type === DatabaseType.mysql - ? 'utf8mb4_bin' - : null; + ? 'utf8mb4_bin' + : null; } } diff --git a/src/backend/model/database/enitites/FileEntity.ts b/src/backend/model/database/enitites/FileEntity.ts index 00fd6082..ec74e08e 100644 --- a/src/backend/model/database/enitites/FileEntity.ts +++ b/src/backend/model/database/enitites/FileEntity.ts @@ -14,7 +14,7 @@ export class FileEntity implements FileDTO { name: string; @Index() - @ManyToOne((type) => DirectoryEntity, (directory) => directory.metaFile, { + @ManyToOne(() => DirectoryEntity, (directory) => directory.metaFile, { onDelete: 'CASCADE', nullable: false, }) diff --git a/src/backend/model/database/enitites/MediaEntity.ts b/src/backend/model/database/enitites/MediaEntity.ts index fb5495e7..3d959198 100644 --- a/src/backend/model/database/enitites/MediaEntity.ts +++ b/src/backend/model/database/enitites/MediaEntity.ts @@ -54,7 +54,7 @@ export class GPSMetadataEntity implements GPSMetadata { } export class PositionMetaDataEntity implements PositionMetaData { - @Column((type) => GPSMetadataEntity) + @Column(() => GPSMetadataEntity) GPSData: GPSMetadataEntity; @Column({ @@ -86,7 +86,7 @@ export class MediaMetadataEntity implements MediaMetadata { @Column('text') caption: string; - @Column((type) => MediaDimensionEntity) + @Column(() => MediaDimensionEntity) size: MediaDimensionEntity; /** @@ -113,17 +113,17 @@ export class MediaMetadataEntity implements MediaMetadata { }) keywords: string[]; - @Column((type) => CameraMetadataEntity) + @Column(() => CameraMetadataEntity) cameraData: CameraMetadataEntity; - @Column((type) => PositionMetaDataEntity) + @Column(() => PositionMetaDataEntity) positionData: PositionMetaDataEntity; @Column('tinyint', {unsigned: true}) @Index() rating: 0 | 1 | 2 | 3 | 4 | 5; - @OneToMany((type) => PersonJunctionTable, (junctionTable) => junctionTable.media) + @OneToMany(() => PersonJunctionTable, (junctionTable) => junctionTable.media) personJunction: PersonJunctionTable[]; @Column({ @@ -178,13 +178,13 @@ export abstract class MediaEntity implements MediaDTO { name: string; @Index() - @ManyToOne((type) => DirectoryEntity, (directory) => directory.media, { + @ManyToOne(() => DirectoryEntity, (directory) => directory.media, { onDelete: 'CASCADE', nullable: false, }) directory: DirectoryEntity; - @Column((type) => MediaMetadataEntity) + @Column(() => MediaMetadataEntity) metadata: MediaMetadataEntity; missingThumbnails: number; diff --git a/src/backend/model/database/enitites/PersonEntry.ts b/src/backend/model/database/enitites/PersonEntry.ts index 3512be15..66f12563 100644 --- a/src/backend/model/database/enitites/PersonEntry.ts +++ b/src/backend/model/database/enitites/PersonEntry.ts @@ -1,15 +1,7 @@ -import { - Column, - Entity, - Index, - ManyToOne, - OneToMany, - PrimaryGeneratedColumn, - Unique, -} from 'typeorm'; +import {Column, Entity, Index, ManyToOne, OneToMany, PrimaryGeneratedColumn, Unique,} from 'typeorm'; import {PersonJunctionTable} from './PersonJunctionTable'; import {columnCharsetCS} from './EntityUtils'; -import { PersonDTO } from '../../../../common/entities/PersonDTO'; +import {PersonDTO} from '../../../../common/entities/PersonDTO'; @Entity() @Unique(['name']) @@ -27,10 +19,10 @@ export class PersonEntry implements PersonDTO { @Column({default: false}) isFavourite: boolean; - @OneToMany((type) => PersonJunctionTable, (junctionTable) => junctionTable.person) + @OneToMany(() => PersonJunctionTable, (junctionTable) => junctionTable.person) public faces: PersonJunctionTable[]; - @ManyToOne((type) => PersonJunctionTable, { + @ManyToOne(() => PersonJunctionTable, { onDelete: 'SET NULL', nullable: true, }) diff --git a/src/backend/model/database/enitites/PersonJunctionTable.ts b/src/backend/model/database/enitites/PersonJunctionTable.ts index b2107ce3..9d76d016 100644 --- a/src/backend/model/database/enitites/PersonJunctionTable.ts +++ b/src/backend/model/database/enitites/PersonJunctionTable.ts @@ -13,14 +13,14 @@ export class PersonJunctionTable { id: number; @Index() - @ManyToOne((type) => MediaEntity, (media) => media.metadata.faces, { + @ManyToOne(() => MediaEntity, (media) => media.metadata.faces, { onDelete: 'CASCADE', nullable: false, }) media: MediaEntity; @Index() - @ManyToOne((type) => PersonEntry, (person) => person.faces, { + @ManyToOne(() => PersonEntry, (person) => person.faces, { onDelete: 'CASCADE', nullable: false, }) diff --git a/src/backend/model/database/enitites/PhotoEntity.ts b/src/backend/model/database/enitites/PhotoEntity.ts index d66d0be0..1f055423 100644 --- a/src/backend/model/database/enitites/PhotoEntity.ts +++ b/src/backend/model/database/enitites/PhotoEntity.ts @@ -1,13 +1,10 @@ -import { ChildEntity, Column } from 'typeorm'; -import { - PhotoDTO, - PhotoMetadata, -} from '../../../../common/entities/PhotoDTO'; -import { MediaEntity, MediaMetadataEntity } from './MediaEntity'; +import {ChildEntity, Column} from 'typeorm'; +import {PhotoDTO, PhotoMetadata,} from '../../../../common/entities/PhotoDTO'; +import {MediaEntity, MediaMetadataEntity} from './MediaEntity'; export class PhotoMetadataEntity - extends MediaMetadataEntity - implements PhotoMetadata { + extends MediaMetadataEntity + implements PhotoMetadata { /* @Column('simple-array') keywords: string[]; @@ -25,6 +22,6 @@ export class PhotoMetadataEntity @ChildEntity() export class PhotoEntity extends MediaEntity implements PhotoDTO { - @Column((type) => PhotoMetadataEntity) + @Column(() => PhotoMetadataEntity) metadata: PhotoMetadataEntity; } diff --git a/src/backend/model/database/enitites/SharingEntity.ts b/src/backend/model/database/enitites/SharingEntity.ts index f39285e3..cde7549f 100644 --- a/src/backend/model/database/enitites/SharingEntity.ts +++ b/src/backend/model/database/enitites/SharingEntity.ts @@ -1,11 +1,11 @@ -import { Column, Entity, ManyToOne, PrimaryGeneratedColumn } from 'typeorm'; -import { SharingDTO } from '../../../../common/entities/SharingDTO'; -import { UserEntity } from './UserEntity'; -import { UserDTO } from '../../../../common/entities/UserDTO'; +import {Column, Entity, ManyToOne, PrimaryGeneratedColumn} from 'typeorm'; +import {SharingDTO} from '../../../../common/entities/SharingDTO'; +import {UserEntity} from './UserEntity'; +import {UserDTO} from '../../../../common/entities/UserDTO'; @Entity() export class SharingEntity implements SharingDTO { - @PrimaryGeneratedColumn({ unsigned: true }) + @PrimaryGeneratedColumn({unsigned: true}) id: number; @Column() @@ -14,7 +14,7 @@ export class SharingEntity implements SharingDTO { @Column() path: string; - @Column({ type: 'text', nullable: true }) + @Column({type: 'text', nullable: true}) password: string; @Column('bigint', { @@ -38,6 +38,6 @@ export class SharingEntity implements SharingDTO { @Column() includeSubfolders: boolean; - @ManyToOne((type) => UserEntity, { onDelete: 'CASCADE', nullable: false }) + @ManyToOne(() => UserEntity, {onDelete: 'CASCADE', nullable: false}) creator: UserDTO; } diff --git a/src/backend/model/database/enitites/VersionEntity.ts b/src/backend/model/database/enitites/VersionEntity.ts index f668fc01..fc700806 100644 --- a/src/backend/model/database/enitites/VersionEntity.ts +++ b/src/backend/model/database/enitites/VersionEntity.ts @@ -1,4 +1,4 @@ -import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm'; +import {Column, Entity, PrimaryGeneratedColumn} from 'typeorm'; @Entity() export class VersionEntity { diff --git a/src/backend/model/database/enitites/VideoEntity.ts b/src/backend/model/database/enitites/VideoEntity.ts index 529311bf..204c9319 100644 --- a/src/backend/model/database/enitites/VideoEntity.ts +++ b/src/backend/model/database/enitites/VideoEntity.ts @@ -1,14 +1,10 @@ -import { ChildEntity, Column } from 'typeorm'; -import { MediaEntity, MediaMetadataEntity } from './MediaEntity'; -import { - VideoDTO, - VideoMetadata, -} from '../../../../common/entities/VideoDTO'; +import {ChildEntity, Column} from 'typeorm'; +import {MediaEntity, MediaMetadataEntity} from './MediaEntity'; +import {VideoDTO, VideoMetadata,} from '../../../../common/entities/VideoDTO'; export class VideoMetadataEntity - extends MediaMetadataEntity - implements VideoMetadata -{ + extends MediaMetadataEntity + implements VideoMetadata { @Column('int') bitRate: number; @@ -28,6 +24,6 @@ export class VideoMetadataEntity @ChildEntity() export class VideoEntity extends MediaEntity implements VideoDTO { - @Column((type) => VideoMetadataEntity) + @Column(() => VideoMetadataEntity) metadata: VideoMetadataEntity; } diff --git a/src/backend/model/database/enitites/album/AlbumBaseEntity.ts b/src/backend/model/database/enitites/album/AlbumBaseEntity.ts index 5afef913..f4312a1d 100644 --- a/src/backend/model/database/enitites/album/AlbumBaseEntity.ts +++ b/src/backend/model/database/enitites/album/AlbumBaseEntity.ts @@ -23,6 +23,6 @@ export class AlbumBaseEntity implements AlbumBaseDTO { @Column('int', {unsigned: true, default: 0}) count: number; - @ManyToOne((type) => MediaEntity, {onDelete: 'SET NULL', nullable: true}) + @ManyToOne(() => MediaEntity, {onDelete: 'SET NULL', nullable: true}) public cover: MediaEntity; } diff --git a/src/backend/model/database/enitites/album/SavedSearchEntity.ts b/src/backend/model/database/enitites/album/SavedSearchEntity.ts index 3762b56e..30ec68ab 100644 --- a/src/backend/model/database/enitites/album/SavedSearchEntity.ts +++ b/src/backend/model/database/enitites/album/SavedSearchEntity.ts @@ -1,13 +1,12 @@ -import { ChildEntity, Column } from 'typeorm'; -import { AlbumBaseEntity } from './AlbumBaseEntity'; -import { SavedSearchDTO } from '../../../../../common/entities/album/SavedSearchDTO'; -import { SearchQueryDTO } from '../../../../../common/entities/SearchQueryDTO'; +import {ChildEntity, Column} from 'typeorm'; +import {AlbumBaseEntity} from './AlbumBaseEntity'; +import {SavedSearchDTO} from '../../../../../common/entities/album/SavedSearchDTO'; +import {SearchQueryDTO} from '../../../../../common/entities/SearchQueryDTO'; @ChildEntity() export class SavedSearchEntity - extends AlbumBaseEntity - implements SavedSearchDTO -{ + extends AlbumBaseEntity + implements SavedSearchDTO { @Column({ type: 'text', nullable: false, diff --git a/src/backend/model/diagnostics/ConfigDiagnostics.ts b/src/backend/model/diagnostics/ConfigDiagnostics.ts index 6d623c61..42c9bdee 100644 --- a/src/backend/model/diagnostics/ConfigDiagnostics.ts +++ b/src/backend/model/diagnostics/ConfigDiagnostics.ts @@ -31,8 +31,10 @@ const LOG_TAG = '[ConfigDiagnostics]'; export class ConfigDiagnostics { static testAlbumsConfig( - albumConfig: ClientAlbumConfig, - original: PrivateConfigClass + // eslint-disable-next-line @typescript-eslint/no-unused-vars + albumConfig: ClientAlbumConfig, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + original: PrivateConfigClass ): void { Logger.debug(LOG_TAG, 'Testing album config'); // nothing to check @@ -51,27 +53,27 @@ export class ConfigDiagnostics { } static async testDatabase( - databaseConfig: ServerDataBaseConfig + databaseConfig: ServerDataBaseConfig ): Promise { Logger.debug(LOG_TAG, 'Testing database config'); await SQLConnection.tryConnection(databaseConfig); if (databaseConfig.type === DatabaseType.sqlite) { try { await this.checkReadWritePermission( - SQLConnection.getSQLiteDB(databaseConfig) + SQLConnection.getSQLiteDB(databaseConfig) ); } catch (e) { throw new Error( - 'Cannot read or write sqlite storage file: ' + - SQLConnection.getSQLiteDB(databaseConfig) + 'Cannot read or write sqlite storage file: ' + + SQLConnection.getSQLiteDB(databaseConfig) ); } } } static async testMetaFileConfig( - metaFileConfig: ClientMetaFileConfig, - config: PrivateConfigClass + metaFileConfig: ClientMetaFileConfig, + config: PrivateConfigClass ): Promise { Logger.debug(LOG_TAG, 'Testing meta file config'); if (metaFileConfig.gpx === true && config.Map.enabled === false) { @@ -96,19 +98,19 @@ export class ConfigDiagnostics { ffmpeg().getAvailableCodecs((err: Error) => { if (err) { return reject( - new Error( - 'Error accessing ffmpeg, cant find executable: ' + - err.toString() - ) + new Error( + 'Error accessing ffmpeg, cant find executable: ' + + err.toString() + ) ); } ffmpeg(__dirname + '/blank.jpg').ffprobe((err2: Error) => { if (err2) { return reject( - new Error( - 'Error accessing ffmpeg-probe, cant find executable: ' + - err2.toString() - ) + new Error( + 'Error accessing ffmpeg-probe, cant find executable: ' + + err2.toString() + ) ); } return resolve(); @@ -156,7 +158,7 @@ export class ConfigDiagnostics { static async testThumbnailConfig( - thumbnailConfig: ServerThumbnailConfig + thumbnailConfig: ServerThumbnailConfig ): Promise { Logger.debug(LOG_TAG, 'Testing thumbnail config'); @@ -167,7 +169,7 @@ export class ConfigDiagnostics { if (isNaN(thumbnailConfig.iconSize) || thumbnailConfig.iconSize <= 0) { throw new Error( - 'IconSize has to be >= 0 integer, got: ' + thumbnailConfig.iconSize + 'IconSize has to be >= 0 integer, got: ' + thumbnailConfig.iconSize ); } @@ -182,16 +184,18 @@ export class ConfigDiagnostics { } static async testTasksConfig( - task: ServerJobConfig, - config: PrivateConfigClass + // eslint-disable-next-line @typescript-eslint/no-unused-vars + task: ServerJobConfig, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + config: PrivateConfigClass ): Promise { Logger.debug(LOG_TAG, 'Testing tasks config'); return; } static async testFacesConfig( - faces: ClientFacesConfig, - config: PrivateConfigClass + faces: ClientFacesConfig, + config: PrivateConfigClass ): Promise { Logger.debug(LOG_TAG, 'Testing faces config'); if (faces.enabled === true) { @@ -202,29 +206,33 @@ export class ConfigDiagnostics { } static async testSearchConfig( - search: ClientSearchConfig, - config: PrivateConfigClass + // eslint-disable-next-line @typescript-eslint/no-unused-vars + search: ClientSearchConfig, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + config: PrivateConfigClass ): Promise { Logger.debug(LOG_TAG, 'Testing search config'); //nothing to check } static async testSharingConfig( - sharing: ClientSharingConfig, - config: PrivateConfigClass + sharing: ClientSharingConfig, + config: PrivateConfigClass ): Promise { Logger.debug(LOG_TAG, 'Testing sharing config'); if ( - sharing.enabled === true && - config.Users.authenticationRequired === false + sharing.enabled === true && + config.Users.authenticationRequired === false ) { throw new Error('In case of no authentication, sharing is not supported'); } } static async testRandomPhotoConfig( - sharing: ClientRandomPhotoConfig, - config: PrivateConfigClass + // eslint-disable-next-line @typescript-eslint/no-unused-vars + sharing: ClientRandomPhotoConfig, + // eslint-disable-next-line @typescript-eslint/no-unused-vars + config: PrivateConfigClass ): Promise { Logger.debug(LOG_TAG, 'Testing random photo config'); //nothing to check @@ -236,14 +244,14 @@ export class ConfigDiagnostics { return; } if ( - map.mapProvider === MapProviders.Mapbox && - (!map.mapboxAccessToken || map.mapboxAccessToken.length === 0) + map.mapProvider === MapProviders.Mapbox && + (!map.mapboxAccessToken || map.mapboxAccessToken.length === 0) ) { throw new Error('Mapbox needs a valid api key.'); } if ( - map.mapProvider === MapProviders.Custom && - (!map.customLayers || map.customLayers.length === 0) + map.mapProvider === MapProviders.Custom && + (!map.customLayers || map.customLayers.length === 0) ) { throw new Error('Custom maps need at least one valid layer'); } @@ -260,10 +268,10 @@ export class ConfigDiagnostics { Logger.debug(LOG_TAG, 'Testing cover config'); const sp = new SearchQueryParser(); if ( - !Utils.equalsFilter( - sp.parse(sp.stringify(settings.SearchQuery)), - settings.SearchQuery - ) + !Utils.equalsFilter( + sp.parse(sp.stringify(settings.SearchQuery)), + settings.SearchQuery + ) ) { throw new Error('SearchQuery is not valid. Got: ' + JSON.stringify(sp.parse(sp.stringify(settings.SearchQuery)))); } @@ -303,8 +311,8 @@ export class ConfigDiagnostics { const err: Error = ex; Logger.warn(LOG_TAG, '[SQL error]', err.toString()); Logger.error( - LOG_TAG, - 'Error during initializing SQL DB, check DB connection and settings' + LOG_TAG, + 'Error during initializing SQL DB, check DB connection and settings' ); process.exit(1); } @@ -315,15 +323,15 @@ export class ConfigDiagnostics { const err: Error = ex; Logger.warn( - LOG_TAG, - '[Thumbnail hardware acceleration] module error: ', - err.toString() + LOG_TAG, + '[Thumbnail hardware acceleration] module error: ', + err.toString() ); Logger.warn( - LOG_TAG, - 'Thumbnail hardware acceleration is not possible.' + - ' \'sharp\' node module is not found.' + - ' Falling back temporally to JS based thumbnail generation' + LOG_TAG, + 'Thumbnail hardware acceleration is not possible.' + + ' \'sharp\' node module is not found.' + + ' Falling back temporally to JS based thumbnail generation' ); process.exit(1); } @@ -341,32 +349,32 @@ export class ConfigDiagnostics { } catch (ex) { const err: Error = ex; NotificationManager.warning( - 'Video support error, switching off..', - err.toString() + 'Video support error, switching off..', + err.toString() ); Logger.warn( - LOG_TAG, - 'Video support error, switching off..', - err.toString() + LOG_TAG, + 'Video support error, switching off..', + err.toString() ); Config.Media.Video.enabled = false; } try { await ConfigDiagnostics.testMetaFileConfig( - Config.MetaFile, - Config + Config.MetaFile, + Config ); } catch (ex) { const err: Error = ex; NotificationManager.warning( - 'Meta file support error, switching off gpx..', - err.toString() + 'Meta file support error, switching off gpx..', + err.toString() ); Logger.warn( - LOG_TAG, - 'Meta file support error, switching off..', - err.toString() + LOG_TAG, + 'Meta file support error, switching off..', + err.toString() ); Config.MetaFile.gpx = false; } @@ -376,13 +384,13 @@ export class ConfigDiagnostics { } catch (ex) { const err: Error = ex; NotificationManager.warning( - 'Albums support error, switching off..', - err.toString() + 'Albums support error, switching off..', + err.toString() ); Logger.warn( - LOG_TAG, - 'Meta file support error, switching off..', - err.toString() + LOG_TAG, + 'Meta file support error, switching off..', + err.toString() ); Config.Album.enabled = false; } @@ -396,7 +404,7 @@ export class ConfigDiagnostics { } try { await ConfigDiagnostics.testThumbnailConfig( - Config.Media.Thumbnail + Config.Media.Thumbnail ); } catch (ex) { const err: Error = ex; @@ -409,14 +417,14 @@ export class ConfigDiagnostics { } catch (ex) { const err: Error = ex; NotificationManager.warning( - 'Search is not supported with these settings. Disabling temporally. ' + - 'Please adjust the config properly.', - err.toString() + 'Search is not supported with these settings. Disabling temporally. ' + + 'Please adjust the config properly.', + err.toString() ); Logger.warn( - LOG_TAG, - 'Search is not supported with these settings, switching off..', - err.toString() + LOG_TAG, + 'Search is not supported with these settings, switching off..', + err.toString() ); Config.Search.enabled = false; } @@ -426,13 +434,13 @@ export class ConfigDiagnostics { } catch (ex) { const err: Error = ex; NotificationManager.warning( - 'Cover settings are not valid, resetting search query', - err.toString() + 'Cover settings are not valid, resetting search query', + err.toString() ); Logger.warn( - LOG_TAG, - 'Cover settings are not valid, resetting search query', - err.toString() + LOG_TAG, + 'Cover settings are not valid, resetting search query', + err.toString() ); Config.AlbumCover.SearchQuery = { type: SearchQueryTypes.any_text, @@ -445,14 +453,14 @@ export class ConfigDiagnostics { } catch (ex) { const err: Error = ex; NotificationManager.warning( - 'Faces are not supported with these settings. Disabling temporally. ' + - 'Please adjust the config properly.', - err.toString() + '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() + LOG_TAG, + 'Faces are not supported with these settings, switching off..', + err.toString() ); Config.Faces.enabled = false; } @@ -462,14 +470,14 @@ export class ConfigDiagnostics { } catch (ex) { const err: Error = ex; NotificationManager.warning( - 'Some Tasks are not supported with these settings. Disabling temporally. ' + - 'Please adjust the config properly.', - err.toString() + 'Some Tasks are not supported with these settings. Disabling temporally. ' + + 'Please adjust the config properly.', + err.toString() ); Logger.warn( - LOG_TAG, - 'Some Tasks not supported with these settings, switching off..', - err.toString() + LOG_TAG, + 'Some Tasks not supported with these settings, switching off..', + err.toString() ); Config.Faces.enabled = false; } @@ -479,34 +487,34 @@ export class ConfigDiagnostics { } catch (ex) { const err: Error = ex; NotificationManager.warning( - 'Sharing is not supported with these settings. Disabling temporally. ' + - 'Please adjust the config properly.', - err.toString() + 'Sharing is not supported with these settings. Disabling temporally. ' + + 'Please adjust the config properly.', + err.toString() ); Logger.warn( - LOG_TAG, - 'Sharing is not supported with these settings, switching off..', - err.toString() + LOG_TAG, + 'Sharing is not supported with these settings, switching off..', + err.toString() ); Config.Sharing.enabled = false; } try { await ConfigDiagnostics.testRandomPhotoConfig( - Config.Sharing, - Config + Config.Sharing, + Config ); } catch (ex) { const err: Error = ex; NotificationManager.warning( - 'Random Media is not supported with these settings. Disabling temporally. ' + - 'Please adjust the config properly.', - err.toString() + 'Random Media is not supported with these settings. Disabling temporally. ' + + 'Please adjust the config properly.', + err.toString() ); Logger.warn( - LOG_TAG, - 'Random Media is not supported with these settings, switching off..', - err.toString() + LOG_TAG, + 'Random Media is not supported with these settings, switching off..', + err.toString() ); Config.Sharing.enabled = false; } @@ -516,15 +524,15 @@ export class ConfigDiagnostics { } catch (ex) { const err: Error = ex; NotificationManager.warning( - 'Maps is not supported with these settings. Using open street maps temporally. ' + - 'Please adjust the config properly.', - err.toString() + 'Maps is not supported with these settings. Using open street maps temporally. ' + + 'Please adjust the config properly.', + err.toString() ); Logger.warn( - LOG_TAG, - 'Maps is not supported with these settings. Using open street maps temporally ' + - 'Please adjust the config properly.', - err.toString() + LOG_TAG, + 'Maps is not supported with these settings. Using open street maps temporally ' + + 'Please adjust the config properly.', + err.toString() ); Config.Map.mapProvider = MapProviders.OpenStreetMap; } diff --git a/src/backend/model/fileprocessing/PhotoProcessing.ts b/src/backend/model/fileprocessing/PhotoProcessing.ts index 1c07f42b..23edb57d 100644 --- a/src/backend/model/fileprocessing/PhotoProcessing.ts +++ b/src/backend/model/fileprocessing/PhotoProcessing.ts @@ -24,11 +24,11 @@ export class PhotoProcessing { if (Config.Server.Threading.enabled === true) { if (Config.Server.Threading.thumbnailThreads > 0) { Config.Media.Thumbnail.concurrentThumbnailGenerations = - Config.Server.Threading.thumbnailThreads; + Config.Server.Threading.thumbnailThreads; } else { Config.Media.Thumbnail.concurrentThumbnailGenerations = Math.max( - 1, - os.cpus().length - 1 + 1, + os.cpus().length - 1 ); } } else { @@ -36,31 +36,31 @@ export class PhotoProcessing { } this.taskQue = new TaskExecuter( - Config.Media.Thumbnail.concurrentThumbnailGenerations, - (input): Promise => PhotoWorker.render(input) + Config.Media.Thumbnail.concurrentThumbnailGenerations, + (input): Promise => PhotoWorker.render(input) ); this.initDone = true; } public static async generatePersonThumbnail( - person: PersonEntry + person: PersonEntry ): Promise { // load parameters const photo: PhotoDTO = person.sampleRegion.media; const mediaPath = path.join( - ProjectPath.ImageFolder, - photo.directory.path, - photo.directory.name, - photo.name + ProjectPath.ImageFolder, + photo.directory.path, + photo.directory.name, + photo.name ); const size: number = Config.Media.Thumbnail.personThumbnailSize; const faceRegion = person.sampleRegion.media.metadata.faces.find(f => f.name === person.name); // generate thumbnail path const thPath = PhotoProcessing.generatePersonThumbnailPath( - mediaPath, - faceRegion, - size + mediaPath, + faceRegion, + size ); // check if thumbnail already exist @@ -73,12 +73,12 @@ export class PhotoProcessing { const margin = { x: Math.round( - faceRegion.box.width * - Config.Media.Thumbnail.personFaceMargin + faceRegion.box.width * + Config.Media.Thumbnail.personFaceMargin ), y: Math.round( - faceRegion.box.height * - Config.Media.Thumbnail.personFaceMargin + faceRegion.box.height * + Config.Media.Thumbnail.personFaceMargin ), }; @@ -91,10 +91,10 @@ export class PhotoProcessing { makeSquare: false, cut: { left: Math.round( - Math.max(0, faceRegion.box.left - margin.x / 2) + Math.max(0, faceRegion.box.left - margin.x / 2) ), top: Math.round( - Math.max(0, faceRegion.box.top - margin.y / 2) + Math.max(0, faceRegion.box.top - margin.y / 2) ), width: faceRegion.box.width + margin.x, height: faceRegion.box.height + margin.y, @@ -104,12 +104,12 @@ export class PhotoProcessing { smartSubsample: Config.Media.Thumbnail.smartSubsample, } as MediaRendererInput; input.cut.width = Math.min( - input.cut.width, - photo.metadata.size.width - input.cut.left + input.cut.width, + photo.metadata.size.width - input.cut.left ); input.cut.height = Math.min( - input.cut.height, - photo.metadata.size.height - input.cut.top + input.cut.height, + photo.metadata.size.height - input.cut.top ); await fsp.mkdir(ProjectPath.FacesFolder, {recursive: true}); @@ -120,34 +120,34 @@ export class PhotoProcessing { public static generateConvertedPath(mediaPath: string, size: number): string { const file = path.basename(mediaPath); return path.join( - ProjectPath.TranscodedFolder, - ProjectPath.getRelativePathToImages(path.dirname(mediaPath)), - file + '_' + size + 'q' + Config.Media.Thumbnail.quality + (Config.Media.Thumbnail.smartSubsample ? 'cs' : '') + PhotoProcessing.CONVERTED_EXTENSION + ProjectPath.TranscodedFolder, + ProjectPath.getRelativePathToImages(path.dirname(mediaPath)), + file + '_' + size + 'q' + Config.Media.Thumbnail.quality + (Config.Media.Thumbnail.smartSubsample ? 'cs' : '') + PhotoProcessing.CONVERTED_EXTENSION ); } public static generatePersonThumbnailPath( - mediaPath: string, - faceRegion: FaceRegion, - size: number + mediaPath: string, + faceRegion: FaceRegion, + size: number ): string { return path.join( - ProjectPath.FacesFolder, - crypto - .createHash('md5') - .update( - mediaPath + - '_' + - faceRegion.name + - '_' + - faceRegion.box.left + - '_' + - faceRegion.box.top - ) - .digest('hex') + - '_' + - size + - PhotoProcessing.CONVERTED_EXTENSION + ProjectPath.FacesFolder, + crypto + .createHash('md5') + .update( + mediaPath + + '_' + + faceRegion.name + + '_' + + faceRegion.box.left + + '_' + + faceRegion.box.top + ) + .digest('hex') + + '_' + + size + + PhotoProcessing.CONVERTED_EXTENSION ); } @@ -156,14 +156,14 @@ export class PhotoProcessing { * @param convertedPath */ public static async isValidConvertedPath( - convertedPath: string + convertedPath: string ): Promise { const origFilePath = path.join( - ProjectPath.ImageFolder, - path.relative( - ProjectPath.TranscodedFolder, - convertedPath.substring(0, convertedPath.lastIndexOf('_')) - ) + ProjectPath.ImageFolder, + path.relative( + ProjectPath.TranscodedFolder, + convertedPath.substring(0, convertedPath.lastIndexOf('_')) + ) ); if (path.extname(convertedPath) !== PhotoProcessing.CONVERTED_EXTENSION) { @@ -171,24 +171,24 @@ export class PhotoProcessing { } const sizeStr = convertedPath.substring( - convertedPath.lastIndexOf('_') + 1, - convertedPath.lastIndexOf('q') + convertedPath.lastIndexOf('_') + 1, + convertedPath.lastIndexOf('q') ); const size = parseInt(sizeStr, 10); if ( - (size + '').length !== sizeStr.length || - (Config.Media.Thumbnail.thumbnailSizes.indexOf(size) === -1 && - Config.Media.Photo.Converting.resolution !== size) + (size + '').length !== sizeStr.length || + (Config.Media.Thumbnail.thumbnailSizes.indexOf(size) === -1 && + Config.Media.Photo.Converting.resolution !== size) ) { return false; } let qualityStr = convertedPath.substring( - convertedPath.lastIndexOf('q') + 1, - convertedPath.length - path.extname(convertedPath).length + convertedPath.lastIndexOf('q') + 1, + convertedPath.length - path.extname(convertedPath).length ); @@ -202,7 +202,7 @@ export class PhotoProcessing { const quality = parseInt(qualityStr, 10); if ((quality + '').length !== qualityStr.length || - quality !== Config.Media.Thumbnail.quality) { + quality !== Config.Media.Thumbnail.quality) { return false; } @@ -217,16 +217,16 @@ export class PhotoProcessing { public static async convertPhoto(mediaPath: string): Promise { return this.generateThumbnail( - mediaPath, - Config.Media.Photo.Converting.resolution, - ThumbnailSourceType.Photo, - false + mediaPath, + Config.Media.Photo.Converting.resolution, + ThumbnailSourceType.Photo, + false ); } static async convertedPhotoExist( - mediaPath: string, - size: number + mediaPath: string, + size: number ): Promise { // generate thumbnail path const outPath = PhotoProcessing.generateConvertedPath(mediaPath, size); @@ -243,10 +243,10 @@ export class PhotoProcessing { public static async generateThumbnail( - mediaPath: string, - size: number, - sourceType: ThumbnailSourceType, - makeSquare: boolean + mediaPath: string, + size: number, + sourceType: ThumbnailSourceType, + makeSquare: boolean ): Promise { // generate thumbnail path const outPath = PhotoProcessing.generateConvertedPath(mediaPath, size); @@ -284,9 +284,9 @@ export class PhotoProcessing { } public static async renderSVG( - svgString: SVGIconConfig, - outPath: string, - color = '#000' + svgString: SVGIconConfig, + outPath: string, + color = '#000' ): Promise { // check if file already exist diff --git a/src/backend/model/fileprocessing/VideoProcessing.ts b/src/backend/model/fileprocessing/VideoProcessing.ts index 46a68cc0..e324ce20 100644 --- a/src/backend/model/fileprocessing/VideoProcessing.ts +++ b/src/backend/model/fileprocessing/VideoProcessing.ts @@ -9,33 +9,33 @@ import {SupportedFormats} from '../../../common/SupportedFormats'; export class VideoProcessing { private static taskQue: ITaskExecuter = - new TaskExecuter( - 1, - (input): Promise => VideoConverterWorker.convert(input) - ); + new TaskExecuter( + 1, + (input): Promise => VideoConverterWorker.convert(input) + ); public static generateConvertedFilePath(videoPath: string): string { return path.join( - ProjectPath.TranscodedFolder, - ProjectPath.getRelativePathToImages(path.dirname(videoPath)), - path.basename(videoPath) + '_' + this.getConvertedFilePostFix() + ProjectPath.TranscodedFolder, + ProjectPath.getRelativePathToImages(path.dirname(videoPath)), + path.basename(videoPath) + '_' + this.getConvertedFilePostFix() ); } public static async isValidConvertedPath( - convertedPath: string + convertedPath: string ): Promise { const origFilePath = path.join( - ProjectPath.ImageFolder, - path.relative( - ProjectPath.TranscodedFolder, - convertedPath.substring(0, convertedPath.lastIndexOf('_')) - ) + ProjectPath.ImageFolder, + path.relative( + ProjectPath.TranscodedFolder, + convertedPath.substring(0, convertedPath.lastIndexOf('_')) + ) ); const postfix = convertedPath.substring( - convertedPath.lastIndexOf('_') + 1, - convertedPath.length + convertedPath.lastIndexOf('_') + 1, + convertedPath.length ); if (postfix !== this.getConvertedFilePostFix()) { @@ -82,8 +82,8 @@ export class VideoProcessing { output: { path: outPath, codec: Config.Media.Video.transcoding.format === 'mp4' ? - Config.Media.Video.transcoding.mp4Codec : - Config.Media.Video.transcoding.webmCodec, + Config.Media.Video.transcoding.mp4Codec : + Config.Media.Video.transcoding.webmCodec, format: Config.Media.Video.transcoding.format, crf: Config.Media.Video.transcoding.crf, preset: Config.Media.Video.transcoding.preset, @@ -93,17 +93,17 @@ export class VideoProcessing { if (metaData.bitRate > Config.Media.Video.transcoding.bitRate) { renderInput.output.bitRate = - Config.Media.Video.transcoding.bitRate; + Config.Media.Video.transcoding.bitRate; } if (metaData.fps > Config.Media.Video.transcoding.fps) { renderInput.output.fps = Config.Media.Video.transcoding.fps; } if ( - Config.Media.Video.transcoding.resolution < metaData.size.height + Config.Media.Video.transcoding.resolution < metaData.size.height ) { renderInput.output.resolution = - Config.Media.Video.transcoding.resolution; + Config.Media.Video.transcoding.resolution; } const outDir = path.dirname(renderInput.output.path); @@ -119,14 +119,14 @@ export class VideoProcessing { protected static getConvertedFilePostFix(): string { return ( - Math.round(Config.Media.Video.transcoding.bitRate / 1024) + - 'k' + - (Config.Media.Video.transcoding.format === 'mp4' ? - Config.Media.Video.transcoding.mp4Codec : - Config.Media.Video.transcoding.webmCodec).toString().toLowerCase() + - Config.Media.Video.transcoding.resolution + - '.' + - Config.Media.Video.transcoding.format.toLowerCase() + Math.round(Config.Media.Video.transcoding.bitRate / 1024) + + 'k' + + (Config.Media.Video.transcoding.format === 'mp4' ? + Config.Media.Video.transcoding.mp4Codec : + Config.Media.Video.transcoding.webmCodec).toString().toLowerCase() + + Config.Media.Video.transcoding.resolution + + '.' + + Config.Media.Video.transcoding.format.toLowerCase() ); } } diff --git a/src/backend/model/jobs/JobManager.ts b/src/backend/model/jobs/JobManager.ts index 3aa88854..6d40ad48 100644 --- a/src/backend/model/jobs/JobManager.ts +++ b/src/backend/model/jobs/JobManager.ts @@ -22,17 +22,17 @@ export class JobManager implements IJobListener { protected get JobRunning(): boolean { return ( - JobRepository.Instance.getAvailableJobs().findIndex( - (j): boolean => j.InProgress === true - ) !== -1 + JobRepository.Instance.getAvailableJobs().findIndex( + (j): boolean => j.InProgress === true + ) !== -1 ); } protected get JobNoParallelRunning(): boolean { return ( - JobRepository.Instance.getAvailableJobs().findIndex( - (j): boolean => j.InProgress === true && j.allowParallelRun - ) !== -1 + JobRepository.Instance.getAvailableJobs().findIndex( + (j): boolean => j.InProgress === true && j.allowParallelRun + ) !== -1 ); } @@ -41,14 +41,14 @@ export class JobManager implements IJobListener { } async run( - jobName: string, - config: T, - soloRun: boolean, - allowParallelRun: boolean + jobName: string, + config: T, + soloRun: boolean, + allowParallelRun: boolean ): Promise { if ( - (allowParallelRun === false && this.JobRunning === true) || - this.JobNoParallelRunning === true + (allowParallelRun === false && this.JobRunning === true) || + this.JobNoParallelRunning === true ) { throw new Error('Can\'t start this job while another is running'); } @@ -76,42 +76,42 @@ export class JobManager implements IJobListener { }; onJobFinished = async ( - job: IJob, - state: JobProgressStates, - soloRun: boolean + job: IJob, + state: JobProgressStates, + soloRun: boolean ): Promise => { // if it was not finished peacefully or was a soloRun, do not start the next one if (state !== JobProgressStates.finished || soloRun === true) { return; } const sch = Config.Jobs.scheduled.find( - (s): boolean => s.jobName === job.Name + (s): boolean => s.jobName === job.Name ); if (sch) { const children = Config.Jobs.scheduled.filter( - (s): boolean => - s.trigger.type === JobTriggerType.after && - (s.trigger as AfterJobTrigger).afterScheduleName === sch.name + (s): boolean => + s.trigger.type === JobTriggerType.after && + (s.trigger as AfterJobTrigger).afterScheduleName === sch.name ); for (const item of children) { try { await this.run( - item.jobName, - item.config, - false, - item.allowParallelRun + item.jobName, + item.config, + false, + item.allowParallelRun ); } catch (e) { NotificationManager.warning( - 'Job running error:' + item.name, - e.toString() + 'Job running error:' + item.name, + e.toString() ); } } } }; - getAvailableJobs(): IJob[] { + getAvailableJobs(): IJob[] { return JobRepository.Instance.getAvailableJobs(); } @@ -129,7 +129,7 @@ export class JobManager implements IJobListener { Config.Jobs.scheduled.forEach((s): void => this.runSchedule(s)); } - protected findJob(jobName: string): IJob { + protected findJob(jobName: string): IJob { return this.getAvailableJobs().find((t): boolean => t.Name === jobName); } @@ -138,25 +138,25 @@ export class JobManager implements IJobListener { */ private runSchedule(schedule: JobScheduleDTO): void { const nextDate = JobScheduleDTOUtils.getNextRunningDate( - new Date(), - schedule + new Date(), + schedule ); if (nextDate && nextDate.getTime() > Date.now()) { Logger.debug( - LOG_TAG, - 'running schedule: ' + - schedule.jobName + - ' at ' + - nextDate.toLocaleString(undefined, {hour12: false}) + LOG_TAG, + 'running schedule: ' + + schedule.jobName + + ' at ' + + nextDate.toLocaleString(undefined, {hour12: false}) ); const timer: NodeJS.Timeout = setTimeout(async (): Promise => { this.timers = this.timers.filter((t): boolean => t.timer !== timer); await this.run( - schedule.jobName, - schedule.config, - false, - schedule.allowParallelRun + schedule.jobName, + schedule.config, + false, + schedule.allowParallelRun ); this.runSchedule(schedule); }, nextDate.getTime() - Date.now()); diff --git a/src/backend/model/jobs/JobProgressManager.ts b/src/backend/model/jobs/JobProgressManager.ts index 45350e70..a1c46426 100644 --- a/src/backend/model/jobs/JobProgressManager.ts +++ b/src/backend/model/jobs/JobProgressManager.ts @@ -1,11 +1,8 @@ -import { promises as fsp } from 'fs'; +import {promises as fsp} from 'fs'; import * as path from 'path'; -import { ProjectPath } from '../../ProjectPath'; -import { Config } from '../../../common/config/private/Config'; -import { - JobProgressDTO, - JobProgressStates, -} from '../../../common/entities/job/JobProgressDTO'; +import {ProjectPath} from '../../ProjectPath'; +import {Config} from '../../../common/config/private/Config'; +import {JobProgressDTO, JobProgressStates,} from '../../../common/entities/job/JobProgressDTO'; export class JobProgressManager { private static readonly VERSION = 3; @@ -31,7 +28,7 @@ export class JobProgressManager { for (const key of Object.keys(this.db.progresses)) { m[key] = this.db.progresses[key].progress; if ( - this.db.progresses[key].progress.state === JobProgressStates.running + this.db.progresses[key].progress.state === JobProgressStates.running ) { m[key].time.end = Date.now(); } @@ -40,7 +37,7 @@ export class JobProgressManager { } onJobProgressUpdate(progress: JobProgressDTO): void { - this.db.progresses[progress.HashName] = { progress, timestamp: Date.now() }; + this.db.progresses[progress.HashName] = {progress, timestamp: Date.now()}; this.delayedSave(); } @@ -58,14 +55,14 @@ export class JobProgressManager { this.db = db; while ( - Object.keys(this.db.progresses).length > - Config.Jobs.maxSavedProgress - ) { + Object.keys(this.db.progresses).length > + Config.Jobs.maxSavedProgress + ) { let min: string = null; for (const key of Object.keys(this.db.progresses)) { if ( - min === null || - this.db.progresses[min].timestamp > this.db.progresses[key].timestamp + min === null || + this.db.progresses[min].timestamp > this.db.progresses[key].timestamp ) { min = key; } @@ -75,8 +72,8 @@ export class JobProgressManager { for (const key of Object.keys(this.db.progresses)) { if ( - this.db.progresses[key].progress.state === JobProgressStates.running || - this.db.progresses[key].progress.state === JobProgressStates.cancelling + this.db.progresses[key].progress.state === JobProgressStates.running || + this.db.progresses[key].progress.state === JobProgressStates.cancelling ) { this.db.progresses[key].progress.state = JobProgressStates.interrupted; } diff --git a/src/backend/model/jobs/JobRepository.ts b/src/backend/model/jobs/JobRepository.ts index 1baaf1b2..f195bf21 100644 --- a/src/backend/model/jobs/JobRepository.ts +++ b/src/backend/model/jobs/JobRepository.ts @@ -14,7 +14,7 @@ import {AlbumCoverRestJob} from './jobs/AlbumCoverResetJob'; export class JobRepository { private static instance: JobRepository = null; - availableJobs: { [key: string]: IJob } = {}; + availableJobs: { [key: string]: IJob } = {}; public static get Instance(): JobRepository { if (JobRepository.instance == null) { @@ -23,11 +23,11 @@ export class JobRepository { return JobRepository.instance; } - getAvailableJobs(): IJob[] { + getAvailableJobs(): IJob[] { return Object.values(this.availableJobs).filter((t) => t.Supported); } - register(job: IJob): void { + register(job: IJob): void { if (typeof this.availableJobs[job.Name] !== 'undefined') { throw new Error('Job already exist:' + job.Name); } diff --git a/src/backend/model/jobs/jobs/AlbumCoverFillingJob.ts b/src/backend/model/jobs/jobs/AlbumCoverFillingJob.ts index 3fa51c47..89ab10f5 100644 --- a/src/backend/model/jobs/jobs/AlbumCoverFillingJob.ts +++ b/src/backend/model/jobs/jobs/AlbumCoverFillingJob.ts @@ -20,7 +20,7 @@ export class AlbumCoverFillingJob extends Job { if (!this.directoryToSetCover) { this.Progress.log('Loading Directories to process'); this.directoryToSetCover = - await ObjectManagers.getInstance().CoverManager.getPartialDirsWithoutCovers(); + await ObjectManagers.getInstance().CoverManager.getPartialDirsWithoutCovers(); this.Progress.Left = this.directoryToSetCover.length + 2; return true; } @@ -57,7 +57,7 @@ export class AlbumCoverFillingJob extends Job { private async stepDirectoryCover(): Promise { if (this.directoryToSetCover.length === 0) { this.directoryToSetCover = - await ObjectManagers.getInstance().CoverManager.getPartialDirsWithoutCovers(); + await ObjectManagers.getInstance().CoverManager.getPartialDirsWithoutCovers(); // double check if there is really no more if (this.directoryToSetCover.length > 0) { return true; // continue @@ -70,7 +70,7 @@ export class AlbumCoverFillingJob extends Job { this.Progress.Left = this.directoryToSetCover.length; await ObjectManagers.getInstance().CoverManager.setAndGetCoverForDirectory( - directory + directory ); this.Progress.Processed++; return true; diff --git a/src/backend/model/jobs/jobs/FileJob.ts b/src/backend/model/jobs/jobs/FileJob.ts index 4c78e238..6e09dc02 100644 --- a/src/backend/model/jobs/jobs/FileJob.ts +++ b/src/backend/model/jobs/jobs/FileJob.ts @@ -69,10 +69,10 @@ export abstract class FileJob { if ( - this.fileQueue.length === 0 && - ((this.directoryQueue.length === 0 && !this.config.indexedOnly) || - (this.config.indexedOnly && - this.DBProcessing.hasMoreMedia === false))) { + this.fileQueue.length === 0 && + ((this.directoryQueue.length === 0 && !this.config.indexedOnly) || + (this.config.indexedOnly && + this.DBProcessing.hasMoreMedia === false))) { return false; } @@ -113,11 +113,11 @@ export abstract class FileJob { if (this.scanFilter.noVideo === true && - this.scanFilter.noPhoto === true && - this.scanFilter.noMetaFile === true) { + this.scanFilter.noPhoto === true && + this.scanFilter.noMetaFile === true) { return; } @@ -190,7 +190,7 @@ export abstract class FileJob 0; this.DBProcessing.mediaLoaded += result.length; @@ -219,25 +219,25 @@ export abstract class FileJob 0; @@ -250,12 +250,12 @@ export abstract class FileJob { if (this.scanFilter.noVideo === true && - this.scanFilter.noPhoto === true && - this.scanFilter.noMetaFile === true) { + this.scanFilter.noPhoto === true && + this.scanFilter.noMetaFile === true) { return; } let count = 0; const connection = await SQLConnection.getConnection(); if (!this.scanFilter.noVideo || - !this.scanFilter.noPhoto) { + !this.scanFilter.noPhoto) { let usedEntity = MediaEntity; @@ -282,16 +282,16 @@ export abstract class FileJob { return !(await GPXProcessing.compressedGPXExist( - fPath + fPath )); } diff --git a/src/backend/model/jobs/jobs/IJob.ts b/src/backend/model/jobs/jobs/IJob.ts index 08986a89..acd84d5a 100644 --- a/src/backend/model/jobs/jobs/IJob.ts +++ b/src/backend/model/jobs/jobs/IJob.ts @@ -1,6 +1,6 @@ -import { JobDTO } from '../../../../common/entities/job/JobDTO'; -import { JobProgress } from './JobProgress'; -import { IJobListener } from './IJobListener'; +import {JobDTO} from '../../../../common/entities/job/JobDTO'; +import {JobProgress} from './JobProgress'; +import {IJobListener} from './IJobListener'; export interface IJob extends JobDTO { Name: string; diff --git a/src/backend/model/jobs/jobs/IJobListener.ts b/src/backend/model/jobs/jobs/IJobListener.ts index 997f2739..bf1f1b1f 100644 --- a/src/backend/model/jobs/jobs/IJobListener.ts +++ b/src/backend/model/jobs/jobs/IJobListener.ts @@ -1,12 +1,12 @@ -import { JobProgress } from './JobProgress'; -import { IJob } from './IJob'; -import { JobProgressStates } from '../../../../common/entities/job/JobProgressDTO'; +import {JobProgress} from './JobProgress'; +import {IJob} from './IJob'; +import {JobProgressStates} from '../../../../common/entities/job/JobProgressDTO'; export interface IJobListener { onJobFinished( - job: IJob, - state: JobProgressStates, - soloRun: boolean + job: IJob, + state: JobProgressStates, + soloRun: boolean ): void; onProgressUpdate(progress: JobProgress): void; diff --git a/src/backend/model/jobs/jobs/IndexingJob.ts b/src/backend/model/jobs/jobs/IndexingJob.ts index 395dec4d..1c13c75e 100644 --- a/src/backend/model/jobs/jobs/IndexingJob.ts +++ b/src/backend/model/jobs/jobs/IndexingJob.ts @@ -14,7 +14,7 @@ import {FileDTO} from '../../../../common/entities/FileDTO'; const LOG_TAG = '[IndexingJob]'; export class IndexingJob< - S extends { indexChangesOnly: boolean } = { indexChangesOnly: boolean } + S extends { indexChangesOnly: boolean } = { indexChangesOnly: boolean } > extends Job { public readonly Name = DefaultsJobs[DefaultsJobs.Indexing]; directoriesToIndex: string[] = []; @@ -66,9 +66,9 @@ export class IndexingJob< scanned = await ObjectManagers.getInstance().GalleryManager.selectDirStructure(directory); // If not modified and it was scanned before, dir is up-to-date if ( - scanned && - scanned.lastModified === lastModified && - scanned.lastScanned != null + scanned && + scanned.lastModified === lastModified && + scanned.lastScanned != null ) { dirChanged = false; } @@ -80,9 +80,9 @@ export class IndexingJob< this.Progress.log('Indexing: ' + directory); this.Progress.Processed++; scanned = - await ObjectManagers.getInstance().IndexingManager.indexDirectory( - directory - ); + await ObjectManagers.getInstance().IndexingManager.indexDirectory( + directory + ); } else { this.Progress.log('Skipping. No change for: ' + directory); this.Progress.Skipped++; diff --git a/src/backend/model/jobs/jobs/Job.ts b/src/backend/model/jobs/jobs/Job.ts index 632fc0bd..36399ff7 100644 --- a/src/backend/model/jobs/jobs/Job.ts +++ b/src/backend/model/jobs/jobs/Job.ts @@ -10,7 +10,7 @@ declare const global: any; const LOG_TAG = '[JOB]'; -export abstract class Job = Record> implements IJob { +export abstract class Job = Record> implements IJob { public allowParallelRun: boolean = null; protected progress: JobProgress = null; protected config: T; @@ -35,36 +35,36 @@ export abstract class Job = Record> i public get InProgress(): boolean { return ( - this.Progress !== null && - (this.Progress.State === JobProgressStates.running || - this.Progress.State === JobProgressStates.cancelling) + this.Progress !== null && + (this.Progress.State === JobProgressStates.running || + this.Progress.State === JobProgressStates.cancelling) ); } public start( - config: T, - soloRun = false, - allowParallelRun = false + config: T, + soloRun = false, + allowParallelRun = false ): Promise { if (this.InProgress === false && this.Supported === true) { Logger.info( - LOG_TAG, - 'Running job ' + (soloRun === true ? 'solo' : '') + ': ' + this.Name + LOG_TAG, + 'Running job ' + (soloRun === true ? 'solo' : '') + ': ' + this.Name ); this.soloRun = soloRun; this.allowParallelRun = allowParallelRun; this.config = {} as T; if (this.ConfigTemplate) { - this.ConfigTemplate.forEach(ct => (this.config as any)[ct.id] = ct.defaultValue); + this.ConfigTemplate.forEach(ct => (this.config as Record)[ct.id] = ct.defaultValue); } if (config) { for (const key of Object.keys(config)) { - (this.config as any)[key] = config[key]; + (this.config as Record)[key] = config[key]; } } this.progress = new JobProgress( - this.Name, - JobDTOUtils.getHashName(this.Name, this.config) + this.Name, + JobDTOUtils.getHashName(this.Name, this.config) ); this.progress.OnChange = this.jobListener.onProgressUpdate; const pr = new Promise((resolve): void => { @@ -79,11 +79,11 @@ export abstract class Job = Record> i return pr; } else { Logger.info( - LOG_TAG, - 'Job already running or not supported: ' + this.Name + LOG_TAG, + 'Job already running or not supported: ' + this.Name ); return Promise.reject( - 'Job already running or not supported: ' + this.Name + 'Job already running or not supported: ' + this.Name ); } } @@ -137,8 +137,8 @@ export abstract class Job = Record> i process.nextTick(async (): Promise => { try { if ( - this.Progress == null || - this.Progress.State !== JobProgressStates.running + this.Progress == null || + this.Progress.State !== JobProgressStates.running ) { this.onFinish(); return; diff --git a/src/backend/model/jobs/jobs/JobProgress.ts b/src/backend/model/jobs/jobs/JobProgress.ts index f156dcd3..f42fce64 100644 --- a/src/backend/model/jobs/jobs/JobProgress.ts +++ b/src/backend/model/jobs/jobs/JobProgress.ts @@ -1,8 +1,4 @@ -import { - JobProgressDTO, - JobProgressLogDTO, - JobProgressStates, -} from '../../../../common/entities/job/JobProgressDTO'; +import {JobProgressDTO, JobProgressLogDTO, JobProgressStates,} from '../../../../common/entities/job/JobProgressDTO'; import {Config} from '../../../../common/config/private/Config'; export class JobProgress { @@ -20,9 +16,10 @@ export class JobProgress { private logs: { id: number; timestamp: string; comment: string }[] = []; constructor( - public readonly jobName: string, - public readonly HashName: string - ) {} + public readonly jobName: string, + public readonly HashName: string + ) { + } set OnChange(val: (progress: JobProgress) => void) { this.onChange = val; diff --git a/src/backend/model/jobs/jobs/PhotoConvertingJob.ts b/src/backend/model/jobs/jobs/PhotoConvertingJob.ts index bc405937..0b52fa2f 100644 --- a/src/backend/model/jobs/jobs/PhotoConvertingJob.ts +++ b/src/backend/model/jobs/jobs/PhotoConvertingJob.ts @@ -1,13 +1,13 @@ -import { Config } from '../../../../common/config/private/Config'; -import { DefaultsJobs } from '../../../../common/entities/job/JobDTO'; -import { FileJob } from './FileJob'; -import { PhotoProcessing } from '../../fileprocessing/PhotoProcessing'; +import {Config} from '../../../../common/config/private/Config'; +import {DefaultsJobs} from '../../../../common/entities/job/JobDTO'; +import {FileJob} from './FileJob'; +import {PhotoProcessing} from '../../fileprocessing/PhotoProcessing'; export class PhotoConvertingJob extends FileJob { public readonly Name = DefaultsJobs[DefaultsJobs['Photo Converting']]; constructor() { - super({ noVideo: true, noMetaFile: true }); + super({noVideo: true, noMetaFile: true}); } public get Supported(): boolean { @@ -16,8 +16,8 @@ export class PhotoConvertingJob extends FileJob { protected async shouldProcess(mPath: string): Promise { return !(await PhotoProcessing.convertedPhotoExist( - mPath, - Config.Media.Photo.Converting.resolution + mPath, + Config.Media.Photo.Converting.resolution )); } diff --git a/src/backend/model/jobs/jobs/TempFolderCleaningJob.ts b/src/backend/model/jobs/jobs/TempFolderCleaningJob.ts index d24f4fb0..227db5c7 100644 --- a/src/backend/model/jobs/jobs/TempFolderCleaningJob.ts +++ b/src/backend/model/jobs/jobs/TempFolderCleaningJob.ts @@ -38,8 +38,8 @@ export class TempFolderCleaningJob extends Job { protected async isValidDirectory(filePath: string): Promise { const originalPath = path.join( - ProjectPath.ImageFolder, - path.relative(ProjectPath.TranscodedFolder, filePath) + ProjectPath.ImageFolder, + path.relative(ProjectPath.TranscodedFolder, filePath) ); try { await fs.promises.access(originalPath); @@ -52,7 +52,7 @@ export class TempFolderCleaningJob extends Job { protected async readDir(dirPath: string): Promise { return (await fs.promises.readdir(dirPath)).map((f) => - path.normalize(path.join(dirPath, f)) + path.normalize(path.join(dirPath, f)) ); } @@ -91,7 +91,7 @@ export class TempFolderCleaningJob extends Job { this.Progress.log('skipping: ' + filePath); this.Progress.Skipped++; this.directoryQueue = this.directoryQueue.concat( - await this.readDir(filePath) + await this.readDir(filePath) ); } } else { diff --git a/src/backend/model/jobs/jobs/ThumbnailGenerationJob.ts b/src/backend/model/jobs/jobs/ThumbnailGenerationJob.ts index e1cd3d48..446b3202 100644 --- a/src/backend/model/jobs/jobs/ThumbnailGenerationJob.ts +++ b/src/backend/model/jobs/jobs/ThumbnailGenerationJob.ts @@ -29,9 +29,9 @@ export class ThumbnailGenerationJob extends FileJob<{ } start( - config: { sizes?: number[]; indexedOnly?: boolean }, - soloRun = false, - allowParallelRun = false + config: { sizes?: number[]; indexedOnly?: boolean }, + soloRun = false, + allowParallelRun = false ): Promise { if (!config || !config.sizes || !Array.isArray(config.sizes) || config.sizes.length === 0) { config = config || {}; @@ -40,9 +40,9 @@ export class ThumbnailGenerationJob extends FileJob<{ for (const item of config.sizes) { if (Config.Media.Thumbnail.thumbnailSizes.indexOf(item) === -1) { throw new Error( - 'unknown thumbnails size: ' + - item + - '. Add it to the possible thumbnail sizes.' + 'unknown thumbnails size: ' + + item + + '. Add it to the possible thumbnail sizes.' ); } } @@ -70,12 +70,12 @@ export class ThumbnailGenerationJob extends FileJob<{ protected async processFile(mPath: string): Promise { for (const item of this.config.sizes) { await PhotoProcessing.generateThumbnail( - mPath, - item, - MediaDTOUtils.isVideoPath(mPath) - ? ThumbnailSourceType.Video - : ThumbnailSourceType.Photo, - false + mPath, + item, + MediaDTOUtils.isVideoPath(mPath) + ? ThumbnailSourceType.Video + : ThumbnailSourceType.Photo, + false ); } } diff --git a/src/backend/model/jobs/jobs/TopPickSendJob.ts b/src/backend/model/jobs/jobs/TopPickSendJob.ts index 47a0d4b1..56c8667c 100644 --- a/src/backend/model/jobs/jobs/TopPickSendJob.ts +++ b/src/backend/model/jobs/jobs/TopPickSendJob.ts @@ -85,15 +85,15 @@ export class TopPickSendJob extends Job<{ this.mediaList = []; for (let i = 0; i < this.config.mediaPick.length; ++i) { const media = await ObjectManagers.getInstance().SearchManager - .getNMedia(this.config.mediaPick[i].searchQuery, this.config.mediaPick[i].sortBy, this.config.mediaPick[i].pick); + .getNMedia(this.config.mediaPick[i].searchQuery, this.config.mediaPick[i].sortBy, this.config.mediaPick[i].pick); this.Progress.log('Find ' + media.length + ' photos and videos from ' + (i + 1) + '. load'); this.mediaList = this.mediaList.concat(media); } // make the list unique this.mediaList = this.mediaList - .filter((value, index, arr) => - arr.findIndex(m => MediaDTOUtils.equals(m, value)) === index); + .filter((value, index, arr) => + arr.findIndex(m => MediaDTOUtils.equals(m, value)) === index); this.Progress.Processed++; // console.log(this.mediaList); diff --git a/src/backend/model/jobs/jobs/VideoConvertingJob.ts b/src/backend/model/jobs/jobs/VideoConvertingJob.ts index 51dc5639..5edc4ad6 100644 --- a/src/backend/model/jobs/jobs/VideoConvertingJob.ts +++ b/src/backend/model/jobs/jobs/VideoConvertingJob.ts @@ -1,7 +1,7 @@ -import { Config } from '../../../../common/config/private/Config'; -import { DefaultsJobs } from '../../../../common/entities/job/JobDTO'; -import { FileJob } from './FileJob'; -import { VideoProcessing } from '../../fileprocessing/VideoProcessing'; +import {Config} from '../../../../common/config/private/Config'; +import {DefaultsJobs} from '../../../../common/entities/job/JobDTO'; +import {FileJob} from './FileJob'; +import {VideoProcessing} from '../../fileprocessing/VideoProcessing'; declare const global: any; @@ -9,7 +9,7 @@ export class VideoConvertingJob extends FileJob { public readonly Name = DefaultsJobs[DefaultsJobs['Video Converting']]; constructor() { - super({ noPhoto: true, noMetaFile: true }); + super({noPhoto: true, noMetaFile: true}); } public get Supported(): boolean { diff --git a/src/backend/model/mediamessengers/EmailMediaMessenger.ts b/src/backend/model/mediamessengers/EmailMediaMessenger.ts index 89e24afa..2da5d34a 100644 --- a/src/backend/model/mediamessengers/EmailMediaMessenger.ts +++ b/src/backend/model/mediamessengers/EmailMediaMessenger.ts @@ -13,24 +13,24 @@ export class EmailMediaMessenger { transporter: Transporter; constructor() { - this.transporter = createTransport({ - host: Config.Messaging.Email.smtp.host, - port: Config.Messaging.Email.smtp.port, - secure: Config.Messaging.Email.smtp.secure, - requireTLS: Config.Messaging.Email.smtp.requireTLS, - auth: { - user: Config.Messaging.Email.smtp.user, - pass: Config.Messaging.Email.smtp.password - } - }); + this.transporter = createTransport({ + host: Config.Messaging.Email.smtp.host, + port: Config.Messaging.Email.smtp.port, + secure: Config.Messaging.Email.smtp.secure, + requireTLS: Config.Messaging.Email.smtp.requireTLS, + auth: { + user: Config.Messaging.Email.smtp.user, + pass: Config.Messaging.Email.smtp.password + } + }); } private async getThumbnail(m: MediaDTO) { return await PhotoProcessing.generateThumbnail( - path.join(ProjectPath.ImageFolder, m.directory.path, m.directory.name, m.name), - Config.Media.Thumbnail.thumbnailSizes[0], - MediaDTOUtils.isPhoto(m) ? ThumbnailSourceType.Photo : ThumbnailSourceType.Video, - false + path.join(ProjectPath.ImageFolder, m.directory.path, m.directory.name, m.name), + Config.Media.Thumbnail.thumbnailSizes[0], + MediaDTOUtils.isPhoto(m) ? ThumbnailSourceType.Photo : ThumbnailSourceType.Video, + false ); } @@ -42,22 +42,22 @@ export class EmailMediaMessenger { const attachments = []; const htmlStart = '

' + Config.Server.applicationTitle + '

\n' + - '

' + mailSettings.text + '

\n' + - '\n' + - ' \n'; + '

' + mailSettings.text + '

\n' + + '
\n' + + ' \n'; const htmlEnd = ' \n' + - ' \n' + - '
'; + ' \n' + + ''; let htmlMiddle = ''; const numberOfColumns = media.length >= 6 ? 3 : 2; for (let i = 0; i < media.length; ++i) { const thPath = await this.getThumbnail(media[i]); const linkUrl = Utils.concatUrls(Config.Server.publicUrl, '/gallery/', encodeURIComponent(path.join(media[i].directory.path, media[i].directory.name))) + - '?' + QueryParams.gallery.photo + '=' + encodeURIComponent(media[i].name); + '?' + QueryParams.gallery.photo + '=' + encodeURIComponent(media[i].name); const location = (media[i].metadata as PhotoMetadata).positionData?.country ? - (media[i].metadata as PhotoMetadata).positionData?.country : - ((media[i].metadata as PhotoMetadata).positionData?.city ? - (media[i].metadata as PhotoMetadata).positionData?.city : ''); + (media[i].metadata as PhotoMetadata).positionData?.country : + ((media[i].metadata as PhotoMetadata).positionData?.city ? + (media[i].metadata as PhotoMetadata).positionData?.city : ''); const caption = (new Date(media[i].metadata.creationDate)).getFullYear() + (location ? ', ' + location : ''); attachments.push({ filename: media[i].name, @@ -68,9 +68,9 @@ export class EmailMediaMessenger { htmlMiddle += ''; } htmlMiddle += '\n' + - ' ' + media[i].name + '\n' + - caption + - ' \n'; + ' ' + media[i].name + '\n' + + caption + + ' \n'; if (i % numberOfColumns == (numberOfColumns - 1) || i === media.length - 1) { htmlMiddle += ''; diff --git a/src/backend/model/threading/DiskMangerWorker.ts b/src/backend/model/threading/DiskMangerWorker.ts index 7959ad90..aa11a100 100644 --- a/src/backend/model/threading/DiskMangerWorker.ts +++ b/src/backend/model/threading/DiskMangerWorker.ts @@ -25,15 +25,15 @@ export class DiskMangerWorker { public static pathFromRelativeDirName(relativeDirectoryName: string): string { return path.join( - path.dirname(this.normalizeDirPath(relativeDirectoryName)), - path.sep + path.dirname(this.normalizeDirPath(relativeDirectoryName)), + path.sep ); } public static pathFromParent(parent: { path: string; name: string }): string { return path.join( - this.normalizeDirPath(path.join(parent.path, parent.name)), - path.sep + this.normalizeDirPath(path.join(parent.path, parent.name)), + path.sep ); } @@ -45,13 +45,13 @@ export class DiskMangerWorker { } public static async excludeDir( - name: string, - relativeDirectoryName: string, - absoluteDirectoryName: string + name: string, + relativeDirectoryName: string, + absoluteDirectoryName: string ): Promise { if ( - Config.Indexing.excludeFolderList.length === 0 && - Config.Indexing.excludeFileList.length === 0 + Config.Indexing.excludeFolderList.length === 0 && + Config.Indexing.excludeFileList.length === 0 ) { return false; } @@ -87,30 +87,30 @@ export class DiskMangerWorker { } public static async scanDirectoryNoMetadata( - relativeDirectoryName: string, - settings: DirectoryScanSettings = {} + relativeDirectoryName: string, + settings: DirectoryScanSettings = {} ): Promise> { settings.noMetadata = true; return (await this.scanDirectory( - relativeDirectoryName, - settings + relativeDirectoryName, + settings )) as ParentDirectoryDTO; } public static async scanDirectory( - relativeDirectoryName: string, - settings: DirectoryScanSettings = {} + relativeDirectoryName: string, + settings: DirectoryScanSettings = {} ): Promise { relativeDirectoryName = this.normalizeDirPath(relativeDirectoryName); const directoryName = DiskMangerWorker.dirName(relativeDirectoryName); const directoryParent = this.pathFromRelativeDirName(relativeDirectoryName); const absoluteDirectoryName = path.join( - ProjectPath.ImageFolder, - relativeDirectoryName + ProjectPath.ImageFolder, + relativeDirectoryName ); const stat = await fsp.stat( - path.join(ProjectPath.ImageFolder, relativeDirectoryName) + path.join(ProjectPath.ImageFolder, relativeDirectoryName) ); const directory: ParentDirectoryDTO = { id: null, @@ -132,36 +132,36 @@ export class DiskMangerWorker { // nothing to scan, we are here for the empty dir if ( - settings.noPhoto === true && - settings.noMetaFile === true && - settings.noVideo === true + settings.noPhoto === true && + settings.noMetaFile === true && + settings.noVideo === true ) { return directory; } const list = await fsp.readdir(absoluteDirectoryName); for (const file of list) { const fullFilePath = path.normalize( - path.join(absoluteDirectoryName, file) + path.join(absoluteDirectoryName, file) ); if ((await fsp.stat(fullFilePath)).isDirectory()) { if ( - settings.noDirectory === true || - settings.coverOnly === true || - (await DiskMangerWorker.excludeDir( - file, - relativeDirectoryName, - absoluteDirectoryName - )) + settings.noDirectory === true || + settings.coverOnly === true || + (await DiskMangerWorker.excludeDir( + file, + relativeDirectoryName, + absoluteDirectoryName + )) ) { continue; } // create cover directory const d = (await DiskMangerWorker.scanDirectory( - path.join(relativeDirectoryName, file), - { - coverOnly: true, - } + path.join(relativeDirectoryName, file), + { + coverOnly: true, + } )) as SubDirectoryDTO; directory.directories.push(d); @@ -174,9 +174,9 @@ export class DiskMangerWorker { name: file, directory: null, metadata: - settings.noMetadata === true - ? null - : await MetadataLoader.loadPhotoMetadata(fullFilePath), + settings.noMetadata === true + ? null + : await MetadataLoader.loadPhotoMetadata(fullFilePath), } as PhotoDTO; if (!directory.cover) { @@ -197,9 +197,9 @@ export class DiskMangerWorker { } } else if (VideoProcessing.isVideo(fullFilePath)) { if ( - Config.Media.Video.enabled === false || - settings.noVideo === true || - settings.coverOnly === true + Config.Media.Video.enabled === false || + settings.noVideo === true || + settings.coverOnly === true ) { continue; } @@ -208,23 +208,23 @@ export class DiskMangerWorker { name: file, directory: null, metadata: - settings.noMetadata === true - ? null - : await MetadataLoader.loadVideoMetadata(fullFilePath), + settings.noMetadata === true + ? null + : await MetadataLoader.loadVideoMetadata(fullFilePath), } as VideoDTO); } catch (e) { Logger.warn( - 'Media loading error, skipping: ' + - file + - ', reason: ' + - e.toString() + 'Media loading error, skipping: ' + + file + + ', reason: ' + + e.toString() ); } } else if (GPXProcessing.isMetaFile(fullFilePath)) { if ( - !DiskMangerWorker.isEnabledMetaFile(fullFilePath) || - settings.noMetaFile === true || - settings.coverOnly === true + !DiskMangerWorker.isEnabledMetaFile(fullFilePath) || + settings.noMetaFile === true || + settings.coverOnly === true ) { continue; } @@ -242,9 +242,9 @@ export class DiskMangerWorker { directory.oldestMedia = Number.MIN_SAFE_INTEGER; directory.media.forEach((m) => { - directory.youngestMedia = Math.min(m.metadata.creationDate, directory.youngestMedia); - directory.oldestMedia = Math.max(m.metadata.creationDate, directory.oldestMedia); - } + directory.youngestMedia = Math.min(m.metadata.creationDate, directory.youngestMedia); + directory.oldestMedia = Math.max(m.metadata.creationDate, directory.oldestMedia); + } ); directory.metaFile.forEach(mf => { diff --git a/src/backend/model/threading/MetadataLoader.ts b/src/backend/model/threading/MetadataLoader.ts index 22b42f63..fa42eec5 100644 --- a/src/backend/model/threading/MetadataLoader.ts +++ b/src/backend/model/threading/MetadataLoader.ts @@ -50,8 +50,8 @@ export class MetadataLoader { metadata.size.height = stream.height; if ( - Utils.isInt32(parseInt('' + stream.rotation, 10)) && - (Math.abs(parseInt('' + stream.rotation, 10)) / 90) % 2 === 1 + Utils.isInt32(parseInt('' + stream.rotation, 10)) && + (Math.abs(parseInt('' + stream.rotation, 10)) / 90) % 2 === 1 ) { // noinspection JSSuspiciousNameCombination metadata.size.width = stream.height; @@ -60,10 +60,10 @@ export class MetadataLoader { } if ( - Utils.isInt32(Math.floor(parseFloat(stream.duration) * 1000)) + Utils.isInt32(Math.floor(parseFloat(stream.duration) * 1000)) ) { metadata.duration = Math.floor( - parseFloat(stream.duration) * 1000 + parseFloat(stream.duration) * 1000 ); } @@ -74,39 +74,39 @@ export class MetadataLoader { metadata.fps = parseInt(stream.avg_frame_rate, 10) || null; } metadata.creationDate = - Date.parse(stream.tags.creation_time) || - metadata.creationDate; + Date.parse(stream.tags.creation_time) || + metadata.creationDate; break; } } // For some filetypes (for instance Matroska), bitrate and duration are stored in // the format section, not in the stream section. - + // Only use duration from container header if necessary (stream duration is usually more accurate) if ( - metadata.duration === 0 && - data.format.duration !== undefined && - Utils.isInt32(Math.floor(data.format.duration * 1000)) + metadata.duration === 0 && + data.format.duration !== undefined && + Utils.isInt32(Math.floor(data.format.duration * 1000)) ) { metadata.duration = Math.floor(data.format.duration * 1000); } - + // Prefer bitrate from container header (includes video and audio) if ( - data.format.bit_rate !== undefined && - Utils.isInt32(data.format.bit_rate) + data.format.bit_rate !== undefined && + Utils.isInt32(data.format.bit_rate) ) { metadata.bitRate = data.format.bit_rate; } if ( - data.format.tags !== undefined && - typeof data.format.tags.creation_time === 'string' + data.format.tags !== undefined && + typeof data.format.tags.creation_time === 'string' ) { metadata.creationDate = - Date.parse(data.format.tags.creation_time) || - metadata.creationDate; + Date.parse(data.format.tags.creation_time) || + metadata.creationDate; } // eslint-disable-next-line no-empty @@ -158,13 +158,13 @@ export class MetadataLoader { try { const exif = ExifParserFactory.create(data).parse(); if ( - exif.tags.ISO || - exif.tags.Model || - exif.tags.Make || - exif.tags.FNumber || - exif.tags.ExposureTime || - exif.tags.FocalLength || - exif.tags.LensModel + exif.tags.ISO || + exif.tags.Model || + exif.tags.Make || + exif.tags.FNumber || + exif.tags.ExposureTime || + exif.tags.FocalLength || + exif.tags.LensModel ) { if (exif.tags.Model && exif.tags.Model !== '') { metadata.cameraData = metadata.cameraData || {}; @@ -185,50 +185,50 @@ export class MetadataLoader { if (Utils.isFloat32(exif.tags.FocalLength)) { metadata.cameraData = metadata.cameraData || {}; metadata.cameraData.focalLength = parseFloat( - '' + exif.tags.FocalLength + '' + exif.tags.FocalLength ); } if (Utils.isFloat32(exif.tags.ExposureTime)) { metadata.cameraData = metadata.cameraData || {}; metadata.cameraData.exposure = parseFloat( - parseFloat('' + exif.tags.ExposureTime).toFixed(6) + parseFloat('' + exif.tags.ExposureTime).toFixed(6) ); } if (Utils.isFloat32(exif.tags.FNumber)) { metadata.cameraData = metadata.cameraData || {}; metadata.cameraData.fStop = parseFloat( - parseFloat('' + exif.tags.FNumber).toFixed(2) + parseFloat('' + exif.tags.FNumber).toFixed(2) ); } } if ( - !isNaN(exif.tags.GPSLatitude) || - exif.tags.GPSLongitude || - exif.tags.GPSAltitude + !isNaN(exif.tags.GPSLatitude) || + exif.tags.GPSLongitude || + exif.tags.GPSAltitude ) { metadata.positionData = metadata.positionData || {}; metadata.positionData.GPSData = {}; if (Utils.isFloat32(exif.tags.GPSLongitude)) { metadata.positionData.GPSData.longitude = parseFloat( - exif.tags.GPSLongitude.toFixed(6) + exif.tags.GPSLongitude.toFixed(6) ); } if (Utils.isFloat32(exif.tags.GPSLatitude)) { metadata.positionData.GPSData.latitude = parseFloat( - exif.tags.GPSLatitude.toFixed(6) + exif.tags.GPSLatitude.toFixed(6) ); } } if ( - exif.tags.CreateDate || - exif.tags.DateTimeOriginal || - exif.tags.ModifyDate + exif.tags.CreateDate || + exif.tags.DateTimeOriginal || + exif.tags.ModifyDate ) { metadata.creationDate = - (exif.tags.DateTimeOriginal || - exif.tags.CreateDate || - exif.tags.ModifyDate) * 1000; + (exif.tags.DateTimeOriginal || + exif.tags.CreateDate || + exif.tags.ModifyDate) * 1000; } if (exif.imageSize) { metadata.size = { @@ -236,16 +236,16 @@ export class MetadataLoader { height: exif.imageSize.height, }; } else if ( - exif.tags.RelatedImageWidth && - exif.tags.RelatedImageHeight + exif.tags.RelatedImageWidth && + exif.tags.RelatedImageHeight ) { metadata.size = { width: exif.tags.RelatedImageWidth, height: exif.tags.RelatedImageHeight, }; } else if ( - exif.tags.ImageWidth && - exif.tags.ImageHeight + exif.tags.ImageWidth && + exif.tags.ImageHeight ) { metadata.size = { width: exif.tags.ImageWidth, @@ -270,21 +270,21 @@ export class MetadataLoader { if (iptcData.country_or_primary_location_name) { metadata.positionData = metadata.positionData || {}; metadata.positionData.country = - iptcData.country_or_primary_location_name - .replace(/\0/g, '') - .trim(); + iptcData.country_or_primary_location_name + .replace(/\0/g, '') + .trim(); } if (iptcData.province_or_state) { metadata.positionData = metadata.positionData || {}; metadata.positionData.state = iptcData.province_or_state - .replace(/\0/g, '') - .trim(); + .replace(/\0/g, '') + .trim(); } if (iptcData.city) { metadata.positionData = metadata.positionData || {}; metadata.positionData.city = iptcData.city - .replace(/\0/g, '') - .trim(); + .replace(/\0/g, '') + .trim(); } if (iptcData.caption) { metadata.caption = iptcData.caption.replace(/\0/g, '').trim(); @@ -316,9 +316,9 @@ export class MetadataLoader { } } if ( - exif.subject && - exif.subject.value && - exif.subject.value.length > 0 + exif.subject && + exif.subject.value && + exif.subject.value.length > 0 ) { if (metadata.keywords === undefined) { metadata.keywords = []; @@ -332,8 +332,8 @@ export class MetadataLoader { let orientation = OrientationTypes.TOP_LEFT; if (exif.Orientation) { orientation = parseInt( - exif.Orientation.value as any, - 10 + exif.Orientation.value as any, + 10 ) as number; } if (OrientationTypes.BOTTOM_LEFT < orientation) { @@ -347,18 +347,18 @@ export class MetadataLoader { if (Config.Faces.enabled) { const faces: FaceRegion[] = []; if ( - ((exif.Regions as any)?.value?.RegionList)?.value + ((exif.Regions as any)?.value?.RegionList)?.value ) { for (const regionRoot of (exif.Regions as any).value.RegionList - .value as any[]) { + .value as any[]) { let type; let name; let box; const createFaceBox = ( - w: string, - h: string, - x: string, - y: string + w: string, + h: string, + x: string, + y: string ) => { if (OrientationTypes.BOTTOM_LEFT < orientation) { [x, y] = [y, x]; @@ -392,10 +392,10 @@ export class MetadataLoader { /* Adobe Lightroom based face region structure */ if ( - regionRoot.value && - regionRoot.value['rdf:Description'] && - regionRoot.value['rdf:Description'].value && - regionRoot.value['rdf:Description'].value['mwg-rs:Area'] + regionRoot.value && + regionRoot.value['rdf:Description'] && + regionRoot.value['rdf:Description'].value && + regionRoot.value['rdf:Description'].value['mwg-rs:Area'] ) { const region = regionRoot.value['rdf:Description']; const regionBox = region.value['mwg-rs:Area'].attributes; @@ -403,25 +403,25 @@ export class MetadataLoader { name = region.attributes['mwg-rs:Name']; type = region.attributes['mwg-rs:Type']; box = createFaceBox( - regionBox['stArea:w'], - regionBox['stArea:h'], - regionBox['stArea:x'], - regionBox['stArea:y'] + regionBox['stArea:w'], + regionBox['stArea:h'], + regionBox['stArea:x'], + regionBox['stArea:y'] ); /* Load exiftool edited face region structure, see github issue #191 */ } else if ( - regionRoot.Area && - regionRoot.Name && - regionRoot.Type + regionRoot.Area && + regionRoot.Name && + regionRoot.Type ) { const regionBox = regionRoot.Area.value; name = regionRoot.Name.value; type = regionRoot.Type.value; box = createFaceBox( - regionBox.w.value, - regionBox.h.value, - regionBox.x.value, - regionBox.y.value + regionBox.w.value, + regionBox.h.value, + regionBox.x.value, + regionBox.y.value ); } diff --git a/src/backend/model/threading/PhotoWorker.ts b/src/backend/model/threading/PhotoWorker.ts index e79377eb..fe34ad5e 100644 --- a/src/backend/model/threading/PhotoWorker.ts +++ b/src/backend/model/threading/PhotoWorker.ts @@ -92,21 +92,21 @@ export class VideoRendererFactory { const folder = path.dirname(input.outPath); let executedCmd = ''; command - .on('start', (cmd): void => { - executedCmd = cmd; - }) - .on('end', (): void => { - resolve(); - }) - .on('error', (e): void => { - reject('[FFmpeg] ' + e.toString() + ' executed: ' + executedCmd); - }) - .outputOptions(['-qscale:v 4']); + .on('start', (cmd): void => { + executedCmd = cmd; + }) + .on('end', (): void => { + resolve(); + }) + .on('error', (e): void => { + reject('[FFmpeg] ' + e.toString() + ' executed: ' + executedCmd); + }) + .outputOptions(['-qscale:v 4']); if (input.makeSquare === false) { const newSize = - width < height - ? Math.min(input.size, width) + 'x?' - : '?x' + Math.min(input.size, height); + width < height + ? Math.min(input.size, width) + 'x?' + : '?x' + Math.min(input.size, height); command.takeScreenshots({ timemarks: ['10%'], size: newSize, @@ -134,22 +134,22 @@ export class ImageRendererFactory { let image: Sharp; if ((input as MediaRendererInput).mediaPath) { Logger.silly( - '[SharpRenderer] rendering photo:' + - (input as MediaRendererInput).mediaPath + - ', size:' + - input.size + '[SharpRenderer] rendering photo:' + + (input as MediaRendererInput).mediaPath + + ', size:' + + input.size ); image = sharp((input as MediaRendererInput).mediaPath, {failOnError: false}); } else { const svg_buffer = Buffer.from((input as SvgRendererInput).svgString); - image = sharp(svg_buffer, { density: 450 }); + image = sharp(svg_buffer, {density: 450}); } image.rotate(); const metadata: Metadata = await image.metadata(); const kernel = - input.useLanczos3 === true - ? sharp.kernel.lanczos3 - : sharp.kernel.nearest; + input.useLanczos3 === true + ? sharp.kernel.lanczos3 + : sharp.kernel.nearest; if (input.cut) { image.extract(input.cut); diff --git a/src/backend/model/threading/TaskExecuter.ts b/src/backend/model/threading/TaskExecuter.ts index 5c30f954..35fb44c5 100644 --- a/src/backend/model/threading/TaskExecuter.ts +++ b/src/backend/model/threading/TaskExecuter.ts @@ -1,4 +1,4 @@ -import { TaskQue } from './TaskQue'; +import {TaskQue} from './TaskQue'; export interface ITaskExecuter { execute(input: I): Promise; @@ -23,7 +23,8 @@ export class TaskExecuter implements ITaskExecuter { process.nextTick(this.run); }; - constructor(private size: number, private worker: (input: I) => Promise) {} + constructor(private size: number, private worker: (input: I) => Promise) { + } execute(input: I): Promise { const promise = this.taskQue.add(input).promise.obj; diff --git a/src/backend/model/threading/TaskQue.ts b/src/backend/model/threading/TaskQue.ts index ef222e27..b0205d0e 100644 --- a/src/backend/model/threading/TaskQue.ts +++ b/src/backend/model/threading/TaskQue.ts @@ -1,4 +1,4 @@ -import { Utils } from '../../../common/Utils'; +import {Utils} from '../../../common/Utils'; export interface TaskQueEntry { data: I; @@ -37,9 +37,9 @@ export class TaskQue { private getSameTask(input: I): TaskQueEntry { return (this.tasks.find((t) => Utils.equalsFilter(t.data, input)) || - this.processing.find((t) => - Utils.equalsFilter(t.data, input) - )) as TaskQueEntry; + this.processing.find((t) => + Utils.equalsFilter(t.data, input) + )) as TaskQueEntry; } private putNewTask(input: I): TaskQueEntry { @@ -53,10 +53,10 @@ export class TaskQue { }; this.tasks.push(taskEntry); taskEntry.promise.obj = new Promise( - (resolve: (ret: O) => void, reject: (err: any) => void) => { - taskEntry.promise.reject = reject; - taskEntry.promise.resolve = resolve; - } + (resolve: (ret: O) => void, reject: (err: any) => void) => { + taskEntry.promise.reject = reject; + taskEntry.promise.resolve = resolve; + } ); return taskEntry; } diff --git a/src/backend/model/threading/ThreadPool.ts b/src/backend/model/threading/ThreadPool.ts index 9d07500f..e0f7ce79 100644 --- a/src/backend/model/threading/ThreadPool.ts +++ b/src/backend/model/threading/ThreadPool.ts @@ -64,23 +64,23 @@ export class ThreadPool { worker.worker.on('online', (): void => { ThreadPool.WorkerCount++; Logger.debug( - LOG_TAG, - 'Worker ' + worker.worker.process.pid + ' is online, worker count:', - ThreadPool.WorkerCount + LOG_TAG, + 'Worker ' + worker.worker.process.pid + ' is online, worker count:', + ThreadPool.WorkerCount ); }); worker.worker.on('exit', (code, signal): void => { ThreadPool.WorkerCount--; Logger.warn( - LOG_TAG, - 'Worker ' + - worker.worker.process.pid + - ' died with code: ' + - code + - ', and signal: ' + - signal + - ', worker count:', - ThreadPool.WorkerCount + LOG_TAG, + 'Worker ' + + worker.worker.process.pid + + ' died with code: ' + + code + + ', and signal: ' + + signal + + ', worker count:', + ThreadPool.WorkerCount ); Logger.debug(LOG_TAG, 'Starting a new worker'); this.startWorker(); @@ -103,11 +103,11 @@ export class ThreadPool { } export class DiskManagerTH - extends ThreadPool - implements ITaskExecuter { + extends ThreadPool + implements ITaskExecuter { execute( - relativeDirectoryName: string, - settings: DirectoryScanSettings = {} + relativeDirectoryName: string, + settings: DirectoryScanSettings = {} ): Promise { return super.executeTask({ type: WorkerTaskTypes.diskManager, diff --git a/src/backend/model/threading/VideoConverterWorker.ts b/src/backend/model/threading/VideoConverterWorker.ts index f67d1658..4ef94d2e 100644 --- a/src/backend/model/threading/VideoConverterWorker.ts +++ b/src/backend/model/threading/VideoConverterWorker.ts @@ -43,20 +43,20 @@ export class VideoConverterWorker { const command: FfmpegCommand = this.ffmpeg(input.videoPath); let executedCmd = ''; command - .on('start', (cmd: string) => { - Logger.silly('[FFmpeg] running:' + cmd); - executedCmd = cmd; - }) - .on('end', () => { - resolve(); - }) - .on('error', (e: any) => { - reject('[FFmpeg] ' + e.toString() + ' executed: ' + executedCmd); - }) - .on('stderr', function (line: string) { - // Although this is under `stderr` event, all of ffmpeg output come here. - Logger.debug('[FFmpeg] ' + line); - }); + .on('start', (cmd: string) => { + Logger.silly('[FFmpeg] running:' + cmd); + executedCmd = cmd; + }) + .on('end', () => { + resolve(); + }) + .on('error', (e: any) => { + reject('[FFmpeg] ' + e.toString() + ' executed: ' + executedCmd); + }) + .on('stderr', function(line: string) { + // Although this is under `stderr` event, all of ffmpeg output come here. + Logger.debug('[FFmpeg] ' + line); + }); // set custom input options if (input.input.customOptions) { @@ -93,9 +93,9 @@ export class VideoConverterWorker { // set output format to force command - .format(input.output.format) - // save to file - .save(input.output.path); + .format(input.output.format) + // save to file + .save(input.output.path); }); } } diff --git a/src/backend/model/threading/Worker.ts b/src/backend/model/threading/Worker.ts index 786413be..ca719efc 100644 --- a/src/backend/model/threading/Worker.ts +++ b/src/backend/model/threading/Worker.ts @@ -17,8 +17,8 @@ export class Worker { switch (task.type) { case WorkerTaskTypes.diskManager: result = await DiskMangerWorker.scanDirectory( - (task as DiskManagerTask).relativeDirectoryName, - (task as DiskManagerTask).settings + (task as DiskManagerTask).relativeDirectoryName, + (task as DiskManagerTask).settings ); if (global.gc) { global.gc(); diff --git a/src/backend/routes/AlbumRouter.ts b/src/backend/routes/AlbumRouter.ts index 5f529cac..4d6a310e 100644 --- a/src/backend/routes/AlbumRouter.ts +++ b/src/backend/routes/AlbumRouter.ts @@ -16,46 +16,46 @@ export class AlbumRouter { private static addListAlbums(app: Express): void { app.get( - [Config.Server.apiPath + '/albums'], - // common part - AuthenticationMWs.authenticate, - AuthenticationMWs.authorise(UserRoles.User), - VersionMWs.injectGalleryVersion, + [Config.Server.apiPath + '/albums'], + // common part + AuthenticationMWs.authenticate, + AuthenticationMWs.authorise(UserRoles.User), + VersionMWs.injectGalleryVersion, - // specific part - AlbumMWs.listAlbums, - ServerTimingMWs.addServerTiming, - RenderingMWs.renderResult + // specific part + AlbumMWs.listAlbums, + ServerTimingMWs.addServerTiming, + RenderingMWs.renderResult ); } private static addDeleteAlbum(app: Express): void { app.delete( - [Config.Server.apiPath + '/albums/:id'], - // common part - AuthenticationMWs.authenticate, - AuthenticationMWs.authorise(UserRoles.Admin), - VersionMWs.injectGalleryVersion, + [Config.Server.apiPath + '/albums/:id'], + // common part + AuthenticationMWs.authenticate, + AuthenticationMWs.authorise(UserRoles.Admin), + VersionMWs.injectGalleryVersion, - // specific part - AlbumMWs.deleteAlbum, - ServerTimingMWs.addServerTiming, - RenderingMWs.renderResult + // specific part + AlbumMWs.deleteAlbum, + ServerTimingMWs.addServerTiming, + RenderingMWs.renderResult ); } private static addAddSavedSearch(app: Express): void { app.put( - [Config.Server.apiPath + '/albums/saved-searches'], - // common part - AuthenticationMWs.authenticate, - AuthenticationMWs.authorise(UserRoles.Admin), - VersionMWs.injectGalleryVersion, + [Config.Server.apiPath + '/albums/saved-searches'], + // common part + AuthenticationMWs.authenticate, + AuthenticationMWs.authorise(UserRoles.Admin), + VersionMWs.injectGalleryVersion, - // specific part - AlbumMWs.createSavedSearch, - ServerTimingMWs.addServerTiming, - RenderingMWs.renderResult + // specific part + AlbumMWs.createSavedSearch, + ServerTimingMWs.addServerTiming, + RenderingMWs.renderResult ); } } diff --git a/src/backend/routes/ErrorRouter.ts b/src/backend/routes/ErrorRouter.ts index a50ee1be..eef3472c 100644 --- a/src/backend/routes/ErrorRouter.ts +++ b/src/backend/routes/ErrorRouter.ts @@ -1,7 +1,7 @@ -import { RenderingMWs } from '../middlewares/RenderingMWs'; -import { ErrorCodes, ErrorDTO } from '../../common/entities/Error'; -import { Logger } from '../Logger'; -import { Express, NextFunction, Request, Response } from 'express'; +import {RenderingMWs} from '../middlewares/RenderingMWs'; +import {ErrorCodes, ErrorDTO} from '../../common/entities/Error'; +import {Logger} from '../Logger'; +import {Express, NextFunction, Request, Response} from 'express'; import {Config} from '../../common/config/private/Config'; export class ErrorRouter { @@ -16,42 +16,42 @@ export class ErrorRouter { private static addGenericHandler(app: Express): void { app.use( - (err: any, req: Request, res: Response, next: NextFunction): any => { - if (err.name === 'UnauthorizedError') { - // jwt authentication error - res.status(401); - return next( - new ErrorDTO(ErrorCodes.NOT_AUTHENTICATED, 'Invalid token') - ); - } - if (err.name === 'ForbiddenError' && err.code === 'EBADCSRFTOKEN') { - // jwt authentication error - res.status(401); - return next( - new ErrorDTO( - ErrorCodes.NOT_AUTHENTICATED, - 'Invalid CSRF token', - err, - req - ) - ); - } + (err: any, req: Request, res: Response, next: NextFunction): any => { + if (err.name === 'UnauthorizedError') { + // jwt authentication error + res.status(401); + return next( + new ErrorDTO(ErrorCodes.NOT_AUTHENTICATED, 'Invalid token') + ); + } + if (err.name === 'ForbiddenError' && err.code === 'EBADCSRFTOKEN') { + // jwt authentication error + res.status(401); + return next( + new ErrorDTO( + ErrorCodes.NOT_AUTHENTICATED, + 'Invalid CSRF token', + err, + req + ) + ); + } - console.log(err); + console.log(err); - // Flush out the stack to the console - Logger.error('Unexpected error:'); - console.error(err); - return next( - new ErrorDTO( - ErrorCodes.SERVER_ERROR, - 'Unknown server side error', - err, - req - ) - ); - }, - RenderingMWs.renderError + // Flush out the stack to the console + Logger.error('Unexpected error:'); + console.error(err); + return next( + new ErrorDTO( + ErrorCodes.SERVER_ERROR, + 'Unknown server side error', + err, + req + ) + ); + }, + RenderingMWs.renderError ); } } diff --git a/src/backend/routes/GalleryRouter.ts b/src/backend/routes/GalleryRouter.ts index be9768b7..4691709b 100644 --- a/src/backend/routes/GalleryRouter.ts +++ b/src/backend/routes/GalleryRouter.ts @@ -34,270 +34,270 @@ export class GalleryRouter { protected static addDirectoryList(app: Express): void { app.get( - [Config.Server.apiPath + '/gallery/content/:directory(*)', Config.Server.apiPath + '/gallery/', Config.Server.apiPath + '/gallery//'], - // common part - AuthenticationMWs.authenticate, - AuthenticationMWs.normalizePathParam('directory'), - AuthenticationMWs.authorisePath('directory', true), - VersionMWs.injectGalleryVersion, + [Config.Server.apiPath + '/gallery/content/:directory(*)', Config.Server.apiPath + '/gallery/', Config.Server.apiPath + '/gallery//'], + // common part + AuthenticationMWs.authenticate, + AuthenticationMWs.normalizePathParam('directory'), + AuthenticationMWs.authorisePath('directory', true), + VersionMWs.injectGalleryVersion, - // specific part - GalleryMWs.listDirectory, - ThumbnailGeneratorMWs.addThumbnailInformation, - GalleryMWs.cleanUpGalleryResults, - ServerTimingMWs.addServerTiming, - RenderingMWs.renderResult + // specific part + GalleryMWs.listDirectory, + ThumbnailGeneratorMWs.addThumbnailInformation, + GalleryMWs.cleanUpGalleryResults, + ServerTimingMWs.addServerTiming, + RenderingMWs.renderResult ); } protected static addDirectoryZip(app: Express): void { app.get( - [Config.Server.apiPath + '/gallery/zip/:directory(*)'], - // common part - AuthenticationMWs.authenticate, - AuthenticationMWs.normalizePathParam('directory'), - AuthenticationMWs.authorisePath('directory', true), + [Config.Server.apiPath + '/gallery/zip/:directory(*)'], + // common part + AuthenticationMWs.authenticate, + AuthenticationMWs.normalizePathParam('directory'), + AuthenticationMWs.authorisePath('directory', true), - // specific part - ServerTimingMWs.addServerTiming, - GalleryMWs.zipDirectory + // specific part + ServerTimingMWs.addServerTiming, + GalleryMWs.zipDirectory ); } protected static addGetImage(app: Express): void { app.get( - [ - Config.Server.apiPath + '/gallery/content/:mediaPath(*.(' + - SupportedFormats.Photos.join('|') + - '))', - ], - // common part - AuthenticationMWs.authenticate, - AuthenticationMWs.normalizePathParam('mediaPath'), - AuthenticationMWs.authorisePath('mediaPath', false), + [ + Config.Server.apiPath + '/gallery/content/:mediaPath(*.(' + + SupportedFormats.Photos.join('|') + + '))', + ], + // common part + AuthenticationMWs.authenticate, + AuthenticationMWs.normalizePathParam('mediaPath'), + AuthenticationMWs.authorisePath('mediaPath', false), - // specific part - GalleryMWs.loadFile, - ServerTimingMWs.addServerTiming, - RenderingMWs.renderFile + // specific part + GalleryMWs.loadFile, + ServerTimingMWs.addServerTiming, + RenderingMWs.renderFile ); } protected static addGetBestFitImage(app: Express): void { app.get( - [ - Config.Server.apiPath + '/gallery/content/:mediaPath(*.(' + - SupportedFormats.Photos.join('|') + - '))/bestFit', - ], - // common part - AuthenticationMWs.authenticate, - AuthenticationMWs.normalizePathParam('mediaPath'), - AuthenticationMWs.authorisePath('mediaPath', false), + [ + Config.Server.apiPath + '/gallery/content/:mediaPath(*.(' + + SupportedFormats.Photos.join('|') + + '))/bestFit', + ], + // common part + AuthenticationMWs.authenticate, + AuthenticationMWs.normalizePathParam('mediaPath'), + AuthenticationMWs.authorisePath('mediaPath', false), - // specific part - GalleryMWs.loadFile, - PhotoConverterMWs.convertPhoto, - ServerTimingMWs.addServerTiming, - RenderingMWs.renderFile + // specific part + GalleryMWs.loadFile, + PhotoConverterMWs.convertPhoto, + ServerTimingMWs.addServerTiming, + RenderingMWs.renderFile ); } protected static addGetVideo(app: Express): void { app.get( - [ - Config.Server.apiPath + '/gallery/content/:mediaPath(*.(' + - SupportedFormats.Videos.join('|') + - '))', - ], - // common part - AuthenticationMWs.authenticate, - AuthenticationMWs.normalizePathParam('mediaPath'), - AuthenticationMWs.authorisePath('mediaPath', false), + [ + Config.Server.apiPath + '/gallery/content/:mediaPath(*.(' + + SupportedFormats.Videos.join('|') + + '))', + ], + // common part + AuthenticationMWs.authenticate, + AuthenticationMWs.normalizePathParam('mediaPath'), + AuthenticationMWs.authorisePath('mediaPath', false), - // specific part - GalleryMWs.loadFile, - ServerTimingMWs.addServerTiming, - RenderingMWs.renderFile + // specific part + GalleryMWs.loadFile, + ServerTimingMWs.addServerTiming, + RenderingMWs.renderFile ); } protected static addGetBestFitVideo(app: Express): void { app.get( - [ - Config.Server.apiPath + '/gallery/content/:mediaPath(*.(' + - SupportedFormats.Videos.join('|') + - '))/bestFit', - ], - // common part - AuthenticationMWs.authenticate, - AuthenticationMWs.normalizePathParam('mediaPath'), - AuthenticationMWs.authorisePath('mediaPath', false), + [ + Config.Server.apiPath + '/gallery/content/:mediaPath(*.(' + + SupportedFormats.Videos.join('|') + + '))/bestFit', + ], + // common part + AuthenticationMWs.authenticate, + AuthenticationMWs.normalizePathParam('mediaPath'), + AuthenticationMWs.authorisePath('mediaPath', false), - // specific part - GalleryMWs.loadFile, - GalleryMWs.loadBestFitVideo, - ServerTimingMWs.addServerTiming, - RenderingMWs.renderFile + // specific part + GalleryMWs.loadFile, + GalleryMWs.loadBestFitVideo, + ServerTimingMWs.addServerTiming, + RenderingMWs.renderFile ); } protected static addGetMetaFile(app: Express): void { app.get( - [ - Config.Server.apiPath + '/gallery/content/:mediaPath(*.(' + - SupportedFormats.MetaFiles.join('|') + - '))', - ], - // common part - AuthenticationMWs.authenticate, - AuthenticationMWs.normalizePathParam('mediaPath'), - AuthenticationMWs.authorisePath('mediaPath', false), + [ + Config.Server.apiPath + '/gallery/content/:mediaPath(*.(' + + SupportedFormats.MetaFiles.join('|') + + '))', + ], + // common part + AuthenticationMWs.authenticate, + AuthenticationMWs.normalizePathParam('mediaPath'), + AuthenticationMWs.authorisePath('mediaPath', false), - // specific part - GalleryMWs.loadFile, - ServerTimingMWs.addServerTiming, - RenderingMWs.renderFile + // specific part + GalleryMWs.loadFile, + ServerTimingMWs.addServerTiming, + RenderingMWs.renderFile ); } protected static addGetBestFitMetaFile(app: Express): void { app.get( - [ - Config.Server.apiPath + '/gallery/content/:mediaPath(*.(' + - SupportedFormats.MetaFiles.join('|') + - '))/bestFit', - ], - // common part - AuthenticationMWs.authenticate, - AuthenticationMWs.normalizePathParam('mediaPath'), - AuthenticationMWs.authorisePath('mediaPath', false), + [ + Config.Server.apiPath + '/gallery/content/:mediaPath(*.(' + + SupportedFormats.MetaFiles.join('|') + + '))/bestFit', + ], + // common part + AuthenticationMWs.authenticate, + AuthenticationMWs.normalizePathParam('mediaPath'), + AuthenticationMWs.authorisePath('mediaPath', false), - // specific part - GalleryMWs.loadFile, - MetaFileMWs.compressGPX, - ServerTimingMWs.addServerTiming, - RenderingMWs.renderFile + // specific part + GalleryMWs.loadFile, + MetaFileMWs.compressGPX, + ServerTimingMWs.addServerTiming, + RenderingMWs.renderFile ); } protected static addRandom(app: Express): void { app.get( - [Config.Server.apiPath + '/gallery/random/:searchQueryDTO'], - // common part - AuthenticationMWs.authenticate, - AuthenticationMWs.authorise(UserRoles.Guest), - VersionMWs.injectGalleryVersion, + [Config.Server.apiPath + '/gallery/random/:searchQueryDTO'], + // common part + AuthenticationMWs.authenticate, + AuthenticationMWs.authorise(UserRoles.Guest), + VersionMWs.injectGalleryVersion, - // specific part - GalleryMWs.getRandomImage, - GalleryMWs.loadFile, - ServerTimingMWs.addServerTiming, - RenderingMWs.renderFile + // specific part + GalleryMWs.getRandomImage, + GalleryMWs.loadFile, + ServerTimingMWs.addServerTiming, + RenderingMWs.renderFile ); } protected static addGetPhotoThumbnail(app: Express): void { app.get( - Config.Server.apiPath + '/gallery/content/:mediaPath(*.(' + - SupportedFormats.Photos.join('|') + - '))/thumbnail/:size?', - // common part - AuthenticationMWs.authenticate, - AuthenticationMWs.normalizePathParam('mediaPath'), - AuthenticationMWs.authorisePath('mediaPath', false), + Config.Server.apiPath + '/gallery/content/:mediaPath(*.(' + + SupportedFormats.Photos.join('|') + + '))/thumbnail/:size?', + // common part + AuthenticationMWs.authenticate, + AuthenticationMWs.normalizePathParam('mediaPath'), + AuthenticationMWs.authorisePath('mediaPath', false), - // specific part - GalleryMWs.loadFile, - ThumbnailGeneratorMWs.generateThumbnailFactory(ThumbnailSourceType.Photo), - ServerTimingMWs.addServerTiming, - RenderingMWs.renderFile + // specific part + GalleryMWs.loadFile, + ThumbnailGeneratorMWs.generateThumbnailFactory(ThumbnailSourceType.Photo), + ServerTimingMWs.addServerTiming, + RenderingMWs.renderFile ); } protected static addGetVideoThumbnail(app: Express): void { app.get( - Config.Server.apiPath + '/gallery/content/:mediaPath(*.(' + - SupportedFormats.Videos.join('|') + - '))/thumbnail/:size?', - // common part - AuthenticationMWs.authenticate, - AuthenticationMWs.normalizePathParam('mediaPath'), - AuthenticationMWs.authorisePath('mediaPath', false), + Config.Server.apiPath + '/gallery/content/:mediaPath(*.(' + + SupportedFormats.Videos.join('|') + + '))/thumbnail/:size?', + // common part + AuthenticationMWs.authenticate, + AuthenticationMWs.normalizePathParam('mediaPath'), + AuthenticationMWs.authorisePath('mediaPath', false), - // specific part - GalleryMWs.loadFile, - ThumbnailGeneratorMWs.generateThumbnailFactory(ThumbnailSourceType.Video), - ServerTimingMWs.addServerTiming, - RenderingMWs.renderFile + // specific part + GalleryMWs.loadFile, + ThumbnailGeneratorMWs.generateThumbnailFactory(ThumbnailSourceType.Video), + ServerTimingMWs.addServerTiming, + RenderingMWs.renderFile ); } protected static addGetVideoIcon(app: Express): void { app.get( - Config.Server.apiPath + '/gallery/content/:mediaPath(*.(' + - SupportedFormats.Videos.join('|') + - '))/icon', - // common part - AuthenticationMWs.authenticate, - AuthenticationMWs.normalizePathParam('mediaPath'), - AuthenticationMWs.authorisePath('mediaPath', false), + Config.Server.apiPath + '/gallery/content/:mediaPath(*.(' + + SupportedFormats.Videos.join('|') + + '))/icon', + // common part + AuthenticationMWs.authenticate, + AuthenticationMWs.normalizePathParam('mediaPath'), + AuthenticationMWs.authorisePath('mediaPath', false), - // specific part - GalleryMWs.loadFile, - ThumbnailGeneratorMWs.generateIconFactory(ThumbnailSourceType.Video), - ServerTimingMWs.addServerTiming, - RenderingMWs.renderFile + // specific part + GalleryMWs.loadFile, + ThumbnailGeneratorMWs.generateIconFactory(ThumbnailSourceType.Video), + ServerTimingMWs.addServerTiming, + RenderingMWs.renderFile ); } protected static addGetImageIcon(app: Express): void { app.get( - Config.Server.apiPath + '/gallery/content/:mediaPath(*.(' + - SupportedFormats.Photos.join('|') + - '))/icon', - // common part - AuthenticationMWs.authenticate, - AuthenticationMWs.normalizePathParam('mediaPath'), - AuthenticationMWs.authorisePath('mediaPath', false), + Config.Server.apiPath + '/gallery/content/:mediaPath(*.(' + + SupportedFormats.Photos.join('|') + + '))/icon', + // common part + AuthenticationMWs.authenticate, + AuthenticationMWs.normalizePathParam('mediaPath'), + AuthenticationMWs.authorisePath('mediaPath', false), - // specific part - GalleryMWs.loadFile, - ThumbnailGeneratorMWs.generateIconFactory(ThumbnailSourceType.Photo), - ServerTimingMWs.addServerTiming, - RenderingMWs.renderFile + // specific part + GalleryMWs.loadFile, + ThumbnailGeneratorMWs.generateIconFactory(ThumbnailSourceType.Photo), + ServerTimingMWs.addServerTiming, + RenderingMWs.renderFile ); } protected static addSearch(app: Express): void { app.get( - Config.Server.apiPath + '/search/:searchQueryDTO(*)', - // common part - AuthenticationMWs.authenticate, - AuthenticationMWs.authorise(UserRoles.Guest), - VersionMWs.injectGalleryVersion, + Config.Server.apiPath + '/search/:searchQueryDTO(*)', + // common part + AuthenticationMWs.authenticate, + AuthenticationMWs.authorise(UserRoles.Guest), + VersionMWs.injectGalleryVersion, - // specific part - GalleryMWs.search, - ThumbnailGeneratorMWs.addThumbnailInformation, - GalleryMWs.cleanUpGalleryResults, - ServerTimingMWs.addServerTiming, - RenderingMWs.renderResult + // specific part + GalleryMWs.search, + ThumbnailGeneratorMWs.addThumbnailInformation, + GalleryMWs.cleanUpGalleryResults, + ServerTimingMWs.addServerTiming, + RenderingMWs.renderResult ); } protected static addAutoComplete(app: Express): void { app.get( - Config.Server.apiPath + '/autocomplete/:text(*)', - // common part - AuthenticationMWs.authenticate, - AuthenticationMWs.authorise(UserRoles.Guest), - VersionMWs.injectGalleryVersion, + Config.Server.apiPath + '/autocomplete/:text(*)', + // common part + AuthenticationMWs.authenticate, + AuthenticationMWs.authorise(UserRoles.Guest), + VersionMWs.injectGalleryVersion, - // specific part - GalleryMWs.autocomplete, - ServerTimingMWs.addServerTiming, - RenderingMWs.renderResult + // specific part + GalleryMWs.autocomplete, + ServerTimingMWs.addServerTiming, + RenderingMWs.renderResult ); } } diff --git a/src/backend/routes/LoggerRouter.ts b/src/backend/routes/LoggerRouter.ts index 730bf653..896d9422 100644 --- a/src/backend/routes/LoggerRouter.ts +++ b/src/backend/routes/LoggerRouter.ts @@ -1,5 +1,5 @@ -import { Express, NextFunction, Request, Response } from 'express'; -import { logFN, Logger } from '../Logger'; +import {Express, NextFunction, Request, Response} from 'express'; +import {logFN, Logger} from '../Logger'; import {Config} from '../../common/config/private/Config'; declare global { @@ -26,10 +26,10 @@ export class LoggerRouter { res.end = end; res.end(a, b, c); loggerFn( - req.method, - req.url, - res.statusCode, - Date.now() - req._startTime + 'ms' + req.method, + req.url, + res.statusCode, + Date.now() - req._startTime + 'ms' ); return res; }; @@ -48,11 +48,11 @@ export class LoggerRouter { }); app.get( - '/node_modules*', - (req: Request, res: Response, next: NextFunction): any => { - LoggerRouter.log(Logger.silly, req, res); - return next(); - } + '/node_modules*', + (req: Request, res: Response, next: NextFunction): any => { + LoggerRouter.log(Logger.silly, req, res); + return next(); + } ); app.use((req: Request, res: Response, next: NextFunction): any => { diff --git a/src/backend/routes/NotificationRouter.ts b/src/backend/routes/NotificationRouter.ts index 9708c506..bd94e47e 100644 --- a/src/backend/routes/NotificationRouter.ts +++ b/src/backend/routes/NotificationRouter.ts @@ -1,10 +1,10 @@ -import { UserRoles } from '../../common/entities/UserDTO'; -import { AuthenticationMWs } from '../middlewares/user/AuthenticationMWs'; -import { RenderingMWs } from '../middlewares/RenderingMWs'; -import { NotificationMWs } from '../middlewares/NotificationMWs'; -import { Express } from 'express'; -import { VersionMWs } from '../middlewares/VersionMWs'; -import { ServerTimingMWs } from '../middlewares/ServerTimingMWs'; +import {UserRoles} from '../../common/entities/UserDTO'; +import {AuthenticationMWs} from '../middlewares/user/AuthenticationMWs'; +import {RenderingMWs} from '../middlewares/RenderingMWs'; +import {NotificationMWs} from '../middlewares/NotificationMWs'; +import {Express} from 'express'; +import {VersionMWs} from '../middlewares/VersionMWs'; +import {ServerTimingMWs} from '../middlewares/ServerTimingMWs'; import {Config} from '../../common/config/private/Config'; export class NotificationRouter { @@ -14,13 +14,13 @@ export class NotificationRouter { private static addGetNotifications(app: Express): void { app.get( - Config.Server.apiPath + '/notifications', - AuthenticationMWs.authenticate, - AuthenticationMWs.authorise(UserRoles.Guest), - VersionMWs.injectGalleryVersion, - NotificationMWs.list, - ServerTimingMWs.addServerTiming, - RenderingMWs.renderResult + Config.Server.apiPath + '/notifications', + AuthenticationMWs.authenticate, + AuthenticationMWs.authorise(UserRoles.Guest), + VersionMWs.injectGalleryVersion, + NotificationMWs.list, + ServerTimingMWs.addServerTiming, + RenderingMWs.renderResult ); } } diff --git a/src/backend/routes/PersonRouter.ts b/src/backend/routes/PersonRouter.ts index e7d17cce..30cb9cb7 100644 --- a/src/backend/routes/PersonRouter.ts +++ b/src/backend/routes/PersonRouter.ts @@ -1,12 +1,12 @@ -import { AuthenticationMWs } from '../middlewares/user/AuthenticationMWs'; -import { Express } from 'express'; -import { RenderingMWs } from '../middlewares/RenderingMWs'; -import { UserRoles } from '../../common/entities/UserDTO'; -import { PersonMWs } from '../middlewares/PersonMWs'; -import { ThumbnailGeneratorMWs } from '../middlewares/thumbnail/ThumbnailGeneratorMWs'; -import { VersionMWs } from '../middlewares/VersionMWs'; -import { Config } from '../../common/config/private/Config'; -import { ServerTimingMWs } from '../middlewares/ServerTimingMWs'; +import {AuthenticationMWs} from '../middlewares/user/AuthenticationMWs'; +import {Express} from 'express'; +import {RenderingMWs} from '../middlewares/RenderingMWs'; +import {UserRoles} from '../../common/entities/UserDTO'; +import {PersonMWs} from '../middlewares/PersonMWs'; +import {ThumbnailGeneratorMWs} from '../middlewares/thumbnail/ThumbnailGeneratorMWs'; +import {VersionMWs} from '../middlewares/VersionMWs'; +import {Config} from '../../common/config/private/Config'; +import {ServerTimingMWs} from '../middlewares/ServerTimingMWs'; export class PersonRouter { public static route(app: Express): void { @@ -17,50 +17,50 @@ export class PersonRouter { protected static updatePerson(app: Express): void { app.post( - [Config.Server.apiPath + '/person/:name'], - // common part - AuthenticationMWs.authenticate, - AuthenticationMWs.authorise(Config.Faces.writeAccessMinRole), - VersionMWs.injectGalleryVersion, + [Config.Server.apiPath + '/person/:name'], + // common part + AuthenticationMWs.authenticate, + AuthenticationMWs.authorise(Config.Faces.writeAccessMinRole), + VersionMWs.injectGalleryVersion, - // specific part - PersonMWs.updatePerson, - ServerTimingMWs.addServerTiming, - RenderingMWs.renderResult + // specific part + PersonMWs.updatePerson, + ServerTimingMWs.addServerTiming, + RenderingMWs.renderResult ); } protected static addGetPersons(app: Express): void { app.get( - [Config.Server.apiPath + '/person'], - // common part - AuthenticationMWs.authenticate, - AuthenticationMWs.authorise(Config.Faces.readAccessMinRole), - VersionMWs.injectGalleryVersion, + [Config.Server.apiPath + '/person'], + // common part + AuthenticationMWs.authenticate, + AuthenticationMWs.authorise(Config.Faces.readAccessMinRole), + VersionMWs.injectGalleryVersion, - // specific part - PersonMWs.listPersons, - // PersonMWs.addSamplePhotoForAll, - ThumbnailGeneratorMWs.addThumbnailInfoForPersons, - PersonMWs.cleanUpPersonResults, - ServerTimingMWs.addServerTiming, - RenderingMWs.renderResult + // specific part + PersonMWs.listPersons, + // PersonMWs.addSamplePhotoForAll, + ThumbnailGeneratorMWs.addThumbnailInfoForPersons, + PersonMWs.cleanUpPersonResults, + ServerTimingMWs.addServerTiming, + RenderingMWs.renderResult ); } protected static getPersonThumbnail(app: Express): void { app.get( - [Config.Server.apiPath + '/person/:name/thumbnail'], - // common part - AuthenticationMWs.authenticate, - AuthenticationMWs.authorise(UserRoles.User), - VersionMWs.injectGalleryVersion, + [Config.Server.apiPath + '/person/:name/thumbnail'], + // common part + AuthenticationMWs.authenticate, + AuthenticationMWs.authorise(UserRoles.User), + VersionMWs.injectGalleryVersion, - // specific part - PersonMWs.getPerson, - ThumbnailGeneratorMWs.generatePersonThumbnail, - ServerTimingMWs.addServerTiming, - RenderingMWs.renderFile + // specific part + PersonMWs.getPerson, + ThumbnailGeneratorMWs.generatePersonThumbnail, + ServerTimingMWs.addServerTiming, + RenderingMWs.renderFile ); } } diff --git a/src/backend/routes/PublicRouter.ts b/src/backend/routes/PublicRouter.ts index 023f1442..fcbe5248 100644 --- a/src/backend/routes/PublicRouter.ts +++ b/src/backend/routes/PublicRouter.ts @@ -35,7 +35,7 @@ export class PublicRouter { let selectedLocale = req.locale; if (req.cookies && req.cookies[CookieNames.lang]) { if ( - Config.Server.languages.indexOf(req.cookies[CookieNames.lang]) !== -1 + Config.Server.languages.indexOf(req.cookies[CookieNames.lang]) !== -1 ) { selectedLocale = req.cookies[CookieNames.lang]; } @@ -48,14 +48,14 @@ export class PublicRouter { // index.html should not be cached as it contains template that can change const renderIndex = (req: Request, res: Response, next: NextFunction) => { ejs.renderFile( - path.join(ProjectPath.FrontendFolder, req.localePath, 'index.html'), - res.tpl, - (err, str) => { - if (err) { - return next(new ErrorDTO(ErrorCodes.GENERAL_ERROR, err.message)); + path.join(ProjectPath.FrontendFolder, req.localePath, 'index.html'), + res.tpl, + (err, str) => { + if (err) { + return next(new ErrorDTO(ErrorCodes.GENERAL_ERROR, err.message)); + } + res.send(str); } - res.send(str); - } ); }; @@ -94,12 +94,12 @@ export class PublicRouter { }) as unknown as ClientConfig; // Escaping html tags, like confCopy.Server.customHTMLHead = - confCopy.Server.customHTMLHead - .replace(/&/g, '&') - .replace(//g, '>') - .replace(/"/g, '"') - .replace(/'/g, '''); + confCopy.Server.customHTMLHead + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, '''); res.tpl.Config = confCopy; res.tpl.customHTMLHead = Config.Server.customHTMLHead; const selectedTheme = Config.Gallery.Themes.availableThemes.find(th => th.name === Config.Gallery.Themes.selectedTheme)?.theme || ''; @@ -140,7 +140,7 @@ export class PublicRouter { 'photo' ], start_url: - Config.Server.publicUrl === '' ? '.' : Config.Server.publicUrl, + Config.Server.publicUrl === '' ? '.' : Config.Server.publicUrl, background_color: '#000000', theme_color: '#000000', }); @@ -185,40 +185,40 @@ export class PublicRouter { y: vBs[1] }; return '' + - (theme === 'auto' ? ('') : - (theme != null ? - ('') - : '')) + - `` + - Config.Server.svgIcon.items + ''; + ' xmlns="http://www.w3.org/2000/svg"' + + ' viewBox="' + vBs.join(' ') + '">' + + (theme === 'auto' ? ('') : + (theme != null ? + ('') + : '')) + + `` + + Config.Server.svgIcon.items + ''; }; app.get('/icon.svg', (req: Request, res: Response) => { @@ -276,44 +276,44 @@ export class PublicRouter { }); app.get( - [ - '/', - '/login', - '/gallery*', - '/share/:' + QueryParams.gallery.sharingKey_params, - '/shareLogin', - '/admin', - '/duplicates', - '/faces', - '/albums', - '/search*', - ], - AuthenticationMWs.tryAuthenticate, - addTPl, // add template after authentication was successful - setLocale, - renderIndex + [ + '/', + '/login', + '/gallery*', + '/share/:' + QueryParams.gallery.sharingKey_params, + '/shareLogin', + '/admin', + '/duplicates', + '/faces', + '/albums', + '/search*', + ], + AuthenticationMWs.tryAuthenticate, + addTPl, // add template after authentication was successful + setLocale, + renderIndex ); Config.Server.languages.forEach((l) => { app.get( - [ - '/' + l + '/', - '/' + l + '/login', - '/' + l + '/gallery*', - '/' + l + '/share*', - '/' + l + '/admin', - '/' + l + '/search*', - ], - redirectToBase(l) + [ + '/' + l + '/', + '/' + l + '/login', + '/' + l + '/gallery*', + '/' + l + '/share*', + '/' + l + '/admin', + '/' + l + '/search*', + ], + redirectToBase(l) ); }); const renderFile = (subDir = '') => { return (req: Request, res: Response) => { const file = path.join( - ProjectPath.FrontendFolder, - req.localePath, - subDir, - req.params.file + ProjectPath.FrontendFolder, + req.localePath, + subDir, + req.params.file ); if (!fs.existsSync(file)) { return res.sendStatus(404); @@ -326,16 +326,16 @@ export class PublicRouter { }; app.get( - '/assets/:file(*)', - setLocale, - AuthenticationMWs.normalizePathParam('file'), - renderFile('assets') + '/assets/:file(*)', + setLocale, + AuthenticationMWs.normalizePathParam('file'), + renderFile('assets') ); app.get( - '/:file', - setLocale, - AuthenticationMWs.normalizePathParam('file'), - renderFile() + '/:file', + setLocale, + AuthenticationMWs.normalizePathParam('file'), + renderFile() ); } } diff --git a/src/backend/routes/Router.ts b/src/backend/routes/Router.ts index 261e0363..a6fdfd8c 100644 --- a/src/backend/routes/Router.ts +++ b/src/backend/routes/Router.ts @@ -1,14 +1,14 @@ -import { Express } from 'express'; -import { PublicRouter } from './PublicRouter'; -import { UserRouter } from './UserRouter'; -import { GalleryRouter } from './GalleryRouter'; -import { PersonRouter } from './PersonRouter'; -import { SharingRouter } from './SharingRouter'; -import { AdminRouter } from './admin/AdminRouter'; -import { SettingsRouter } from './admin/SettingsRouter'; -import { NotificationRouter } from './NotificationRouter'; -import { ErrorRouter } from './ErrorRouter'; -import { AlbumRouter } from './AlbumRouter'; +import {Express} from 'express'; +import {PublicRouter} from './PublicRouter'; +import {UserRouter} from './UserRouter'; +import {GalleryRouter} from './GalleryRouter'; +import {PersonRouter} from './PersonRouter'; +import {SharingRouter} from './SharingRouter'; +import {AdminRouter} from './admin/AdminRouter'; +import {SettingsRouter} from './admin/SettingsRouter'; +import {NotificationRouter} from './NotificationRouter'; +import {ErrorRouter} from './ErrorRouter'; +import {AlbumRouter} from './AlbumRouter'; export class Router { public static route(app: Express): void { diff --git a/src/backend/routes/SharingRouter.ts b/src/backend/routes/SharingRouter.ts index 771977ed..42b62744 100644 --- a/src/backend/routes/SharingRouter.ts +++ b/src/backend/routes/SharingRouter.ts @@ -20,79 +20,79 @@ export class SharingRouter { private static addShareLogin(app: express.Express): void { app.post( - Config.Server.apiPath + '/share/login', - AuthenticationMWs.inverseAuthenticate, - AuthenticationMWs.shareLogin, - ServerTimingMWs.addServerTiming, - RenderingMWs.renderSessionUser + Config.Server.apiPath + '/share/login', + AuthenticationMWs.inverseAuthenticate, + AuthenticationMWs.shareLogin, + ServerTimingMWs.addServerTiming, + RenderingMWs.renderSessionUser ); } private static addGetSharing(app: express.Express): void { app.get( - Config.Server.apiPath + '/share/:' + QueryParams.gallery.sharingKey_params, - AuthenticationMWs.authenticate, - AuthenticationMWs.authorise(UserRoles.LimitedGuest), - SharingMWs.getSharing, - ServerTimingMWs.addServerTiming, - RenderingMWs.renderSharing + Config.Server.apiPath + '/share/:' + QueryParams.gallery.sharingKey_params, + AuthenticationMWs.authenticate, + AuthenticationMWs.authorise(UserRoles.LimitedGuest), + SharingMWs.getSharing, + ServerTimingMWs.addServerTiming, + RenderingMWs.renderSharing ); } private static addCreateSharing(app: express.Express): void { app.post( - [Config.Server.apiPath + '/share/:directory(*)', Config.Server.apiPath + '/share/', Config.Server.apiPath + '/share//'], - AuthenticationMWs.authenticate, - AuthenticationMWs.authorise(UserRoles.User), - SharingMWs.createSharing, - ServerTimingMWs.addServerTiming, - RenderingMWs.renderSharing + [Config.Server.apiPath + '/share/:directory(*)', Config.Server.apiPath + '/share/', Config.Server.apiPath + '/share//'], + AuthenticationMWs.authenticate, + AuthenticationMWs.authorise(UserRoles.User), + SharingMWs.createSharing, + ServerTimingMWs.addServerTiming, + RenderingMWs.renderSharing ); } private static addUpdateSharing(app: express.Express): void { app.put( - [Config.Server.apiPath + '/share/:directory(*)', Config.Server.apiPath + '/share/', Config.Server.apiPath + '/share//'], - AuthenticationMWs.authenticate, - AuthenticationMWs.authorise(UserRoles.User), - SharingMWs.updateSharing, - ServerTimingMWs.addServerTiming, - RenderingMWs.renderSharing + [Config.Server.apiPath + '/share/:directory(*)', Config.Server.apiPath + '/share/', Config.Server.apiPath + '/share//'], + AuthenticationMWs.authenticate, + AuthenticationMWs.authorise(UserRoles.User), + SharingMWs.updateSharing, + ServerTimingMWs.addServerTiming, + RenderingMWs.renderSharing ); } private static addDeleteSharing(app: express.Express): void { app.delete( - [Config.Server.apiPath + '/share/:' + QueryParams.gallery.sharingKey_params], - AuthenticationMWs.authenticate, - AuthenticationMWs.authorise(UserRoles.User), - SharingMWs.deleteSharing, - ServerTimingMWs.addServerTiming, - RenderingMWs.renderResult + [Config.Server.apiPath + '/share/:' + QueryParams.gallery.sharingKey_params], + AuthenticationMWs.authenticate, + AuthenticationMWs.authorise(UserRoles.User), + SharingMWs.deleteSharing, + ServerTimingMWs.addServerTiming, + RenderingMWs.renderResult ); } private static addListSharing(app: express.Express): void { app.get( - [Config.Server.apiPath + '/share/listAll'], - AuthenticationMWs.authenticate, - AuthenticationMWs.authorise(UserRoles.Admin), - SharingMWs.listSharing, - ServerTimingMWs.addServerTiming, - RenderingMWs.renderSharingList + [Config.Server.apiPath + '/share/listAll'], + AuthenticationMWs.authenticate, + AuthenticationMWs.authorise(UserRoles.Admin), + SharingMWs.listSharing, + ServerTimingMWs.addServerTiming, + RenderingMWs.renderSharingList ); } private static addListSharingForDir(app: express.Express): void { app.get( - [Config.Server.apiPath + '/share/list/:directory(*)', - Config.Server.apiPath + '/share/list//', - Config.Server.apiPath + '/share/list'], - AuthenticationMWs.authenticate, - AuthenticationMWs.authorise(UserRoles.User), - SharingMWs.listSharingForDir, - ServerTimingMWs.addServerTiming, - RenderingMWs.renderSharingList + [Config.Server.apiPath + '/share/list/:directory(*)', + Config.Server.apiPath + '/share/list//', + Config.Server.apiPath + '/share/list'], + AuthenticationMWs.authenticate, + AuthenticationMWs.authorise(UserRoles.User), + SharingMWs.listSharingForDir, + ServerTimingMWs.addServerTiming, + RenderingMWs.renderSharingList ); } } diff --git a/src/backend/routes/UserRouter.ts b/src/backend/routes/UserRouter.ts index 8d06ed1b..9c186e2f 100644 --- a/src/backend/routes/UserRouter.ts +++ b/src/backend/routes/UserRouter.ts @@ -1,11 +1,11 @@ -import { UserMWs } from '../middlewares/user/UserMWs'; -import { Express } from 'express'; -import { UserRoles } from '../../common/entities/UserDTO'; -import { AuthenticationMWs } from '../middlewares/user/AuthenticationMWs'; -import { UserRequestConstrainsMWs } from '../middlewares/user/UserRequestConstrainsMWs'; -import { RenderingMWs } from '../middlewares/RenderingMWs'; -import { ServerTimingMWs } from '../middlewares/ServerTimingMWs'; -import { Config } from '../../common/config/private/Config'; +import {UserMWs} from '../middlewares/user/UserMWs'; +import {Express} from 'express'; +import {UserRoles} from '../../common/entities/UserDTO'; +import {AuthenticationMWs} from '../middlewares/user/AuthenticationMWs'; +import {UserRequestConstrainsMWs} from '../middlewares/user/UserRequestConstrainsMWs'; +import {RenderingMWs} from '../middlewares/RenderingMWs'; +import {ServerTimingMWs} from '../middlewares/ServerTimingMWs'; +import {Config} from '../../common/config/private/Config'; export class UserRouter { public static route(app: Express): void { @@ -21,75 +21,75 @@ export class UserRouter { private static addLogin(app: Express): void { app.post( - Config.Server.apiPath + '/user/login', - AuthenticationMWs.inverseAuthenticate, - AuthenticationMWs.login, - ServerTimingMWs.addServerTiming, - RenderingMWs.renderSessionUser + Config.Server.apiPath + '/user/login', + AuthenticationMWs.inverseAuthenticate, + AuthenticationMWs.login, + ServerTimingMWs.addServerTiming, + RenderingMWs.renderSessionUser ); } private static addLogout(app: Express): void { app.post( - Config.Server.apiPath + '/user/logout', - AuthenticationMWs.logout, - ServerTimingMWs.addServerTiming, - RenderingMWs.renderOK + Config.Server.apiPath + '/user/logout', + AuthenticationMWs.logout, + ServerTimingMWs.addServerTiming, + RenderingMWs.renderOK ); } private static addGetSessionUser(app: Express): void { app.get( - Config.Server.apiPath + '/user/me', - AuthenticationMWs.authenticate, - ServerTimingMWs.addServerTiming, - RenderingMWs.renderSessionUser + Config.Server.apiPath + '/user/me', + AuthenticationMWs.authenticate, + ServerTimingMWs.addServerTiming, + RenderingMWs.renderSessionUser ); } private static addCreateUser(app: Express): void { app.put( - Config.Server.apiPath + '/user', - AuthenticationMWs.authenticate, - AuthenticationMWs.authorise(UserRoles.Admin), - UserMWs.createUser, - ServerTimingMWs.addServerTiming, - RenderingMWs.renderOK + Config.Server.apiPath + '/user', + AuthenticationMWs.authenticate, + AuthenticationMWs.authorise(UserRoles.Admin), + UserMWs.createUser, + ServerTimingMWs.addServerTiming, + RenderingMWs.renderOK ); } private static addDeleteUser(app: Express): void { app.delete( - Config.Server.apiPath + '/user/:id', - AuthenticationMWs.authenticate, - AuthenticationMWs.authorise(UserRoles.Admin), - UserRequestConstrainsMWs.notSelfRequest, - UserMWs.deleteUser, - ServerTimingMWs.addServerTiming, - RenderingMWs.renderOK + Config.Server.apiPath + '/user/:id', + AuthenticationMWs.authenticate, + AuthenticationMWs.authorise(UserRoles.Admin), + UserRequestConstrainsMWs.notSelfRequest, + UserMWs.deleteUser, + ServerTimingMWs.addServerTiming, + RenderingMWs.renderOK ); } private static addListUsers(app: Express): void { app.get( - Config.Server.apiPath + '/user/list', - AuthenticationMWs.authenticate, - AuthenticationMWs.authorise(UserRoles.Admin), - UserMWs.listUsers, - ServerTimingMWs.addServerTiming, - RenderingMWs.renderResult + Config.Server.apiPath + '/user/list', + AuthenticationMWs.authenticate, + AuthenticationMWs.authorise(UserRoles.Admin), + UserMWs.listUsers, + ServerTimingMWs.addServerTiming, + RenderingMWs.renderResult ); } private static addChangeRole(app: Express): void { app.post( - Config.Server.apiPath + '/user/:id/role', - AuthenticationMWs.authenticate, - AuthenticationMWs.authorise(UserRoles.Admin), - UserRequestConstrainsMWs.notSelfRequestOr2Admins, - UserMWs.changeRole, - ServerTimingMWs.addServerTiming, - RenderingMWs.renderOK + Config.Server.apiPath + '/user/:id/role', + AuthenticationMWs.authenticate, + AuthenticationMWs.authorise(UserRoles.Admin), + UserRequestConstrainsMWs.notSelfRequestOr2Admins, + UserMWs.changeRole, + ServerTimingMWs.addServerTiming, + RenderingMWs.renderOK ); } } diff --git a/src/backend/routes/admin/AdminRouter.ts b/src/backend/routes/admin/AdminRouter.ts index f8d768d1..26a1f949 100644 --- a/src/backend/routes/admin/AdminRouter.ts +++ b/src/backend/routes/admin/AdminRouter.ts @@ -1,9 +1,9 @@ -import { AuthenticationMWs } from '../../middlewares/user/AuthenticationMWs'; -import { UserRoles } from '../../../common/entities/UserDTO'; -import { RenderingMWs } from '../../middlewares/RenderingMWs'; -import { AdminMWs } from '../../middlewares/admin/AdminMWs'; -import { Express } from 'express'; -import { Config } from '../../../common/config/private/Config'; +import {AuthenticationMWs} from '../../middlewares/user/AuthenticationMWs'; +import {UserRoles} from '../../../common/entities/UserDTO'; +import {RenderingMWs} from '../../middlewares/RenderingMWs'; +import {AdminMWs} from '../../middlewares/admin/AdminMWs'; +import {Express} from 'express'; +import {Config} from '../../../common/config/private/Config'; export class AdminRouter { public static route(app: Express): void { @@ -14,52 +14,52 @@ export class AdminRouter { private static addGetStatistic(app: Express): void { app.get( - Config.Server.apiPath + '/admin/statistic', - AuthenticationMWs.authenticate, - AuthenticationMWs.authorise(UserRoles.Admin), - AdminMWs.loadStatistic, - RenderingMWs.renderResult + Config.Server.apiPath + '/admin/statistic', + AuthenticationMWs.authenticate, + AuthenticationMWs.authorise(UserRoles.Admin), + AdminMWs.loadStatistic, + RenderingMWs.renderResult ); } private static addGetDuplicates(app: Express): void { app.get( - Config.Server.apiPath + '/admin/duplicates', - AuthenticationMWs.authenticate, - AuthenticationMWs.authorise(UserRoles.Admin), - AdminMWs.getDuplicates, - RenderingMWs.renderResult + Config.Server.apiPath + '/admin/duplicates', + AuthenticationMWs.authenticate, + AuthenticationMWs.authorise(UserRoles.Admin), + AdminMWs.getDuplicates, + RenderingMWs.renderResult ); } private static addJobs(app: Express): void { app.get( - Config.Server.apiPath + '/admin/jobs/available', - AuthenticationMWs.authenticate, - AuthenticationMWs.authorise(UserRoles.Admin), - AdminMWs.getAvailableJobs, - RenderingMWs.renderResult + Config.Server.apiPath + '/admin/jobs/available', + AuthenticationMWs.authenticate, + AuthenticationMWs.authorise(UserRoles.Admin), + AdminMWs.getAvailableJobs, + RenderingMWs.renderResult ); app.get( - Config.Server.apiPath + '/admin/jobs/scheduled/progress', - AuthenticationMWs.authenticate, - AuthenticationMWs.authorise(UserRoles.Admin), - AdminMWs.getJobProgresses, - RenderingMWs.renderResult + Config.Server.apiPath + '/admin/jobs/scheduled/progress', + AuthenticationMWs.authenticate, + AuthenticationMWs.authorise(UserRoles.Admin), + AdminMWs.getJobProgresses, + RenderingMWs.renderResult ); app.post( - Config.Server.apiPath + '/admin/jobs/scheduled/:id/start', - AuthenticationMWs.authenticate, - AuthenticationMWs.authorise(UserRoles.Admin), - AdminMWs.startJob, - RenderingMWs.renderResult + Config.Server.apiPath + '/admin/jobs/scheduled/:id/start', + AuthenticationMWs.authenticate, + AuthenticationMWs.authorise(UserRoles.Admin), + AdminMWs.startJob, + RenderingMWs.renderResult ); app.post( - Config.Server.apiPath + '/admin/jobs/scheduled/:id/stop', - AuthenticationMWs.authenticate, - AuthenticationMWs.authorise(UserRoles.Admin), - AdminMWs.stopJob, - RenderingMWs.renderResult + Config.Server.apiPath + '/admin/jobs/scheduled/:id/stop', + AuthenticationMWs.authenticate, + AuthenticationMWs.authorise(UserRoles.Admin), + AdminMWs.stopJob, + RenderingMWs.renderResult ); } } diff --git a/src/backend/routes/admin/SettingsRouter.ts b/src/backend/routes/admin/SettingsRouter.ts index a540531d..aa8cc250 100644 --- a/src/backend/routes/admin/SettingsRouter.ts +++ b/src/backend/routes/admin/SettingsRouter.ts @@ -1,9 +1,9 @@ -import { AuthenticationMWs } from '../../middlewares/user/AuthenticationMWs'; -import { UserRoles } from '../../../common/entities/UserDTO'; -import { RenderingMWs } from '../../middlewares/RenderingMWs'; -import { Express } from 'express'; -import { SettingsMWs } from '../../middlewares/admin/SettingsMWs'; -import { Config } from '../../../common/config/private/Config'; +import {AuthenticationMWs} from '../../middlewares/user/AuthenticationMWs'; +import {UserRoles} from '../../../common/entities/UserDTO'; +import {RenderingMWs} from '../../middlewares/RenderingMWs'; +import {Express} from 'express'; +import {SettingsMWs} from '../../middlewares/admin/SettingsMWs'; +import {Config} from '../../../common/config/private/Config'; export class SettingsRouter { public static route(app: Express): void { @@ -12,18 +12,18 @@ export class SettingsRouter { private static addSettings(app: Express): void { app.get( - Config.Server.apiPath + '/settings', - AuthenticationMWs.authenticate, - AuthenticationMWs.authorise(UserRoles.Admin), - RenderingMWs.renderConfig + Config.Server.apiPath + '/settings', + AuthenticationMWs.authenticate, + AuthenticationMWs.authorise(UserRoles.Admin), + RenderingMWs.renderConfig ); app.put( - Config.Server.apiPath + '/settings', - AuthenticationMWs.authenticate, - AuthenticationMWs.authorise(UserRoles.Admin), - SettingsMWs.updateSettings, - RenderingMWs.renderOK + Config.Server.apiPath + '/settings', + AuthenticationMWs.authenticate, + AuthenticationMWs.authorise(UserRoles.Admin), + SettingsMWs.updateSettings, + RenderingMWs.renderOK ); } diff --git a/src/backend/server.ts b/src/backend/server.ts index 93597a18..69643cf2 100644 --- a/src/backend/server.ts +++ b/src/backend/server.ts @@ -21,7 +21,7 @@ import {Event} from '../common/event/Event'; import {QueryParams} from '../common/QueryParams'; import {ConfigClassBuilder} from 'typeconfig/node'; import {ConfigClassOptions} from 'typeconfig/src/decorators/class/IConfigClass'; -import {DatabaseType, ServerConfig} from '../common/config/private/PrivateConfig'; +import {ServerConfig} from '../common/config/private/PrivateConfig'; import {unless} from 'express-unless'; // eslint-disable-next-line @typescript-eslint/no-var-requires @@ -39,8 +39,8 @@ export class Server { constructor() { if (!(process.env.NODE_ENV === 'production')) { Logger.info( - LOG_TAG, - 'Running in DEBUG mode, set env variable NODE_ENV=production to disable ' + LOG_TAG, + 'Running in DEBUG mode, set env variable NODE_ENV=production to disable ' ); } this.init().catch(console.error); @@ -54,13 +54,13 @@ export class Server { Logger.info(LOG_TAG, 'running diagnostics...'); await ConfigDiagnostics.runDiagnostics(); Logger.verbose( - LOG_TAG, - 'using config from ' + - ( - ConfigClassBuilder.attachPrivateInterface(Config) - .__options as ConfigClassOptions - ).configPath + - ':' + LOG_TAG, + 'using config from ' + + ( + ConfigClassBuilder.attachPrivateInterface(Config) + .__options as ConfigClassOptions + ).configPath + + ':' ); Logger.verbose(LOG_TAG, JSON.stringify(Config.toJSON({attachDescription: false}), null, '\t')); @@ -75,10 +75,10 @@ export class Server { */ this.app.use( - session({ - name: CookieNames.session, - keys: Config.Server.sessionSecret, - }) + session({ + name: CookieNames.session, + keys: Config.Server.sessionSecret, + }) ); /** @@ -90,26 +90,26 @@ export class Server { const csuf: any = _csrf(); csuf.unless = unless; this.app.use( - csuf.unless((req: Request) => { - return ( - Config.Users.authenticationRequired === false || - [Config.Server.apiPath + '/user/login', Config.Server.apiPath + '/user/logout', Config.Server.apiPath + '/share/login'].indexOf( - req.originalUrl - ) !== -1 || - (Config.Sharing.enabled === true && - !!req.query[QueryParams.gallery.sharingKey_query]) - ); - }) + csuf.unless((req: Request) => { + return ( + Config.Users.authenticationRequired === false || + [Config.Server.apiPath + '/user/login', Config.Server.apiPath + '/user/logout', Config.Server.apiPath + '/share/login'].indexOf( + req.originalUrl + ) !== -1 || + (Config.Sharing.enabled === true && + !!req.query[QueryParams.gallery.sharingKey_query]) + ); + }) ); // enable token generation but do not check it this.app.post( - [Config.Server.apiPath + '/user/login', Config.Server.apiPath + '/share/login'], - _csrf({ignoreMethods: ['POST']}) + [Config.Server.apiPath + '/user/login', Config.Server.apiPath + '/share/login'], + _csrf({ignoreMethods: ['POST']}) ); this.app.get( - [Config.Server.apiPath + '/user/me', Config.Server.apiPath + '/share/:' + QueryParams.gallery.sharingKey_params], - _csrf({ignoreMethods: ['GET']}) + [Config.Server.apiPath + '/user/me', Config.Server.apiPath + '/share/:' + QueryParams.gallery.sharingKey_params], + _csrf({ignoreMethods: ['GET']}) ); DiskManager.init(); @@ -176,7 +176,7 @@ export class Server { private onListening = () => { const addr = this.server.address(); const bind = - typeof addr === 'string' ? 'pipe ' + addr : 'port ' + addr.port; + typeof addr === 'string' ? 'pipe ' + addr : 'port ' + addr.port; Logger.info(LOG_TAG, 'Listening on ' + bind); }; diff --git a/src/common/SearchQueryParser.ts b/src/common/SearchQueryParser.ts index e6aaed02..80354e36 100644 --- a/src/common/SearchQueryParser.ts +++ b/src/common/SearchQueryParser.ts @@ -100,8 +100,8 @@ export class SearchQueryParser { } public static stringifyText( - text: string, - matchType = TextSearchQueryMatchTypes.like + text: string, + matchType = TextSearchQueryMatchTypes.like ): string { if (matchType === TextSearchQueryMatchTypes.exact_match) { return '"' + text + '"'; @@ -127,8 +127,8 @@ export class SearchQueryParser { text = text.substring(1); } if ( - text.charAt(text.length - 1) === '"' || - text.charAt(text.length - 1) === ')' + text.charAt(text.length - 1) === '"' || + text.charAt(text.length - 1) === ')' ) { text = text.substring(0, text.length - 1); } @@ -167,9 +167,9 @@ export class SearchQueryParser { public parse(str: string, implicitAND = true): SearchQueryDTO { str = str - .replace(/\s\s+/g, ' ') // remove double spaces - .replace(/:\s+/g, ':') - .trim(); + .replace(/\s\s+/g, ' ') // remove double spaces + .replace(/:\s+/g, ':') + .trim(); const intFromRegexp = (str: string) => { @@ -200,9 +200,9 @@ export class SearchQueryParser { } if ( - quotationMark === false && - bracketIn.length === 0 && - str.charAt(i) === ' ' + quotationMark === false && + bracketIn.length === 0 && + str.charAt(i) === ' ' ) { return i; } @@ -216,38 +216,38 @@ export class SearchQueryParser { if (tokenEnd !== str.length - 1) { if (str.startsWith(' ' + this.keywords.and, tokenEnd)) { const rest = this.parse( - str.slice(tokenEnd + (' ' + this.keywords.and).length), - implicitAND + str.slice(tokenEnd + (' ' + this.keywords.and).length), + implicitAND ); return { type: SearchQueryTypes.AND, list: [ this.parse(str.slice(0, tokenEnd), implicitAND), // trim brackets ...(rest.type === SearchQueryTypes.AND - ? (rest as SearchListQuery).list - : [rest]), + ? (rest as SearchListQuery).list + : [rest]), ], } as ANDSearchQuery; } else if (str.startsWith(' ' + this.keywords.or, tokenEnd)) { const rest = this.parse( - str.slice(tokenEnd + (' ' + this.keywords.or).length), - implicitAND + str.slice(tokenEnd + (' ' + this.keywords.or).length), + implicitAND ); return { type: SearchQueryTypes.OR, list: [ this.parse(str.slice(0, tokenEnd), implicitAND), // trim brackets ...(rest.type === SearchQueryTypes.OR - ? (rest as SearchListQuery).list - : [rest]), + ? (rest as SearchListQuery).list + : [rest]), ], } as ORSearchQuery; } else { // Relation cannot be detected const t = - implicitAND === true - ? SearchQueryTypes.AND - : SearchQueryTypes.UNKNOWN_RELATION; + implicitAND === true + ? SearchQueryTypes.AND + : SearchQueryTypes.UNKNOWN_RELATION; const rest = this.parse(str.slice(tokenEnd), implicitAND); return { type: t, @@ -259,12 +259,12 @@ export class SearchQueryParser { } } if ( - str.startsWith(this.keywords.someOf + ':') || - new RegExp('^\\d*-' + this.keywords.NSomeOf + ':').test(str) + str.startsWith(this.keywords.someOf + ':') || + new RegExp('^\\d*-' + this.keywords.NSomeOf + ':').test(str) ) { const prefix = str.startsWith(this.keywords.someOf + ':') - ? this.keywords.someOf + ':' - : new RegExp('^\\d*-' + this.keywords.NSomeOf + ':').exec(str)[0]; + ? this.keywords.someOf + ':' + : new RegExp('^\\d*-' + this.keywords.NSomeOf + ':').exec(str)[0]; let tmpList: SearchQueryDTO | SearchQueryDTO[] = this.parse(str.slice(prefix.length + 1, -1), false); // trim brackets const unfoldList = (q: SearchListQuery): SearchQueryDTO[] => { @@ -318,11 +318,11 @@ export class SearchQueryParser { }; const range = addValueRangeParser(this.keywords.minRating, SearchQueryTypes.min_rating) || - addValueRangeParser(this.keywords.maxRating, SearchQueryTypes.max_rating) || - addValueRangeParser(this.keywords.minResolution, SearchQueryTypes.min_resolution) || - addValueRangeParser(this.keywords.maxResolution, SearchQueryTypes.max_resolution) || - addValueRangeParser(this.keywords.minPersonCount, SearchQueryTypes.min_person_count) || - addValueRangeParser(this.keywords.maxPersonCount, SearchQueryTypes.max_person_count); + addValueRangeParser(this.keywords.maxRating, SearchQueryTypes.max_rating) || + addValueRangeParser(this.keywords.minResolution, SearchQueryTypes.min_resolution) || + addValueRangeParser(this.keywords.maxResolution, SearchQueryTypes.max_resolution) || + addValueRangeParser(this.keywords.minPersonCount, SearchQueryTypes.min_person_count) || + addValueRangeParser(this.keywords.maxPersonCount, SearchQueryTypes.max_person_count); if (range) { return range; @@ -331,11 +331,11 @@ export class SearchQueryParser { if (new RegExp('^\\d*-' + this.keywords.kmFrom + '!?:').test(str)) { let from = str.slice( - new RegExp('^\\d*-' + this.keywords.kmFrom + '!?:').exec(str)[0].length + new RegExp('^\\d*-' + this.keywords.kmFrom + '!?:').exec(str)[0].length ); if ( - (from.charAt(0) === '(' && from.charAt(from.length - 1) === ')') || - (from.charAt(0) === '"' && from.charAt(from.length - 1) === '"') + (from.charAt(0) === '(' && from.charAt(from.length - 1) === ')') || + (from.charAt(0) === '"' && from.charAt(from.length - 1) === '"') ) { from = from.slice(1, from.length - 1); } @@ -353,14 +353,14 @@ export class SearchQueryParser { return { type: SearchQueryTypes.orientation, landscape: - str.slice((this.keywords.orientation + ':').length) === - this.keywords.landscape, + str.slice((this.keywords.orientation + ':').length) === + this.keywords.landscape, } as OrientationSearch; } if (kwStartsWith(str, this.keywords.sameDay) || - new RegExp('^' + SearchQueryParser.humanToRegexpStr(this.keywords.lastNDays) + '!?:').test(str)) { + new RegExp('^' + SearchQueryParser.humanToRegexpStr(this.keywords.lastNDays) + '!?:').test(str)) { const freqStr = str.indexOf('!:') === -1 ? str.slice(str.indexOf(':') + 1) : str.slice(str.indexOf('!:') + 2); let freq: DatePatternFrequency = null; @@ -391,7 +391,7 @@ export class SearchQueryParser { daysLength: kwStartsWith(str, this.keywords.sameDay) ? 0 : intFromRegexp(str), frequency: freq, ...((new RegExp('^' + SearchQueryParser.humanToRegexpStr(this.keywords.lastNDays) + '!:').test(str) || - str.startsWith(this.keywords.sameDay + '!:')) && { + str.startsWith(this.keywords.sameDay + '!:')) && { negate: true }), ...(!isNaN(ago) && {agoNumber: ago}) @@ -404,25 +404,25 @@ export class SearchQueryParser { key: (this.keywords as any)[SearchQueryTypes[type]] + ':', queryTemplate: {type, text: ''} as TextSearch, })).concat( - TextSearchQueryTypes.map((type) => ({ - key: (this.keywords as any)[SearchQueryTypes[type]] + '!:', - queryTemplate: {type, text: '', negate: true} as TextSearch, - })) + TextSearchQueryTypes.map((type) => ({ + key: (this.keywords as any)[SearchQueryTypes[type]] + '!:', + queryTemplate: {type, text: '', negate: true} as TextSearch, + })) ); for (const typeTmp of tmp) { if (str.startsWith(typeTmp.key)) { const ret: TextSearch = Utils.clone(typeTmp.queryTemplate); // exact match if ( - str.charAt(typeTmp.key.length) === '"' && - str.charAt(str.length - 1) === '"' + str.charAt(typeTmp.key.length) === '"' && + str.charAt(str.length - 1) === '"' ) { ret.text = str.slice(typeTmp.key.length + 1, str.length - 1); ret.matchType = TextSearchQueryMatchTypes.exact_match; // like match } else if ( - str.charAt(typeTmp.key.length) === '(' && - str.charAt(str.length - 1) === ')' + str.charAt(typeTmp.key.length) === '(' && + str.charAt(str.length - 1) === ')' ) { ret.text = str.slice(typeTmp.key.length + 1, str.length - 1); } else { @@ -451,42 +451,42 @@ export class SearchQueryParser { switch (query.type) { case SearchQueryTypes.AND: return ( - '(' + - (query as SearchListQuery).list - .map((q) => this.stringifyOnEntry(q)) - .join(' ' + this.keywords.and + ' ') + - ')' + '(' + + (query as SearchListQuery).list + .map((q) => this.stringifyOnEntry(q)) + .join(' ' + this.keywords.and + ' ') + + ')' ); case SearchQueryTypes.OR: return ( - '(' + - (query as SearchListQuery).list - .map((q) => this.stringifyOnEntry(q)) - .join(' ' + this.keywords.or + ' ') + - ')' + '(' + + (query as SearchListQuery).list + .map((q) => this.stringifyOnEntry(q)) + .join(' ' + this.keywords.or + ' ') + + ')' ); case SearchQueryTypes.SOME_OF: if ((query as SomeOfSearchQuery).min) { return ( - (query as SomeOfSearchQuery).min + - '-' + - this.keywords.NSomeOf + - ':(' + - (query as SearchListQuery).list - .map((q) => this.stringifyOnEntry(q)) - .join(' ') + - ')' + (query as SomeOfSearchQuery).min + + '-' + + this.keywords.NSomeOf + + ':(' + + (query as SearchListQuery).list + .map((q) => this.stringifyOnEntry(q)) + .join(' ') + + ')' ); } return ( - this.keywords.someOf + - ':(' + - (query as SearchListQuery).list - .map((q) => this.stringifyOnEntry(q)) - .join(' ') + - ')' + this.keywords.someOf + + ':(' + + (query as SearchListQuery).list + .map((q) => this.stringifyOnEntry(q)) + .join(' ') + + ')' ); @@ -495,93 +495,93 @@ export class SearchQueryParser { return ''; } return ( - this.keywords.from + - colon + - SearchQueryParser.stringifyDate((query as FromDateSearch).value) + this.keywords.from + + colon + + SearchQueryParser.stringifyDate((query as FromDateSearch).value) ); case SearchQueryTypes.to_date: if (!(query as ToDateSearch).value) { return ''; } return ( - this.keywords.to + - colon + - SearchQueryParser.stringifyDate((query as ToDateSearch).value) + this.keywords.to + + colon + + SearchQueryParser.stringifyDate((query as ToDateSearch).value) ); case SearchQueryTypes.min_rating: return ( - this.keywords.minRating + - colon + - (isNaN((query as RangeSearch).value) - ? '' - : (query as RangeSearch).value) + this.keywords.minRating + + colon + + (isNaN((query as RangeSearch).value) + ? '' + : (query as RangeSearch).value) ); case SearchQueryTypes.max_rating: return ( - this.keywords.maxRating + - colon + - (isNaN((query as RangeSearch).value) - ? '' - : (query as RangeSearch).value) + this.keywords.maxRating + + colon + + (isNaN((query as RangeSearch).value) + ? '' + : (query as RangeSearch).value) ); case SearchQueryTypes.min_person_count: return ( - this.keywords.minPersonCount + - colon + - (isNaN((query as RangeSearch).value) - ? '' - : (query as RangeSearch).value) + this.keywords.minPersonCount + + colon + + (isNaN((query as RangeSearch).value) + ? '' + : (query as RangeSearch).value) ); case SearchQueryTypes.max_person_count: return ( - this.keywords.maxPersonCount + - colon + - (isNaN((query as RangeSearch).value) - ? '' - : (query as RangeSearch).value) + this.keywords.maxPersonCount + + colon + + (isNaN((query as RangeSearch).value) + ? '' + : (query as RangeSearch).value) ); case SearchQueryTypes.min_resolution: return ( - this.keywords.minResolution + - colon + - (isNaN((query as RangeSearch).value) - ? '' - : (query as RangeSearch).value) + this.keywords.minResolution + + colon + + (isNaN((query as RangeSearch).value) + ? '' + : (query as RangeSearch).value) ); case SearchQueryTypes.max_resolution: return ( - this.keywords.maxResolution + - colon + - (isNaN((query as RangeSearch).value) - ? '' - : (query as RangeSearch).value) + this.keywords.maxResolution + + colon + + (isNaN((query as RangeSearch).value) + ? '' + : (query as RangeSearch).value) ); case SearchQueryTypes.distance: if ((query as DistanceSearch).from.text.indexOf(' ') !== -1) { return ( + (query as DistanceSearch).distance + + '-' + + this.keywords.kmFrom + + colon + + '(' + + (query as DistanceSearch).from.text + + ')' + ); + } + return ( (query as DistanceSearch).distance + '-' + this.keywords.kmFrom + colon + - '(' + - (query as DistanceSearch).from.text + - ')' - ); - } - return ( - (query as DistanceSearch).distance + - '-' + - this.keywords.kmFrom + - colon + - (query as DistanceSearch).from.text + (query as DistanceSearch).from.text ); case SearchQueryTypes.orientation: return ( - this.keywords.orientation + - ':' + - ((query as OrientationSearch).landscape - ? this.keywords.landscape - : this.keywords.portrait) + this.keywords.orientation + + ':' + + ((query as OrientationSearch).landscape + ? this.keywords.landscape + : this.keywords.portrait) ); case SearchQueryTypes.date_pattern: { const q = (query as DatePatternSearch); @@ -624,17 +624,17 @@ export class SearchQueryParser { case SearchQueryTypes.any_text: if (!(query as TextSearch).negate) { return SearchQueryParser.stringifyText( - (query as TextSearch).text, - (query as TextSearch).matchType + (query as TextSearch).text, + (query as TextSearch).matchType ); } else { return ( - (this.keywords as any)[SearchQueryTypes[query.type]] + - colon + - SearchQueryParser.stringifyText( - (query as TextSearch).text, - (query as TextSearch).matchType - ) + (this.keywords as any)[SearchQueryTypes[query.type]] + + colon + + SearchQueryParser.stringifyText( + (query as TextSearch).text, + (query as TextSearch).matchType + ) ); } @@ -648,12 +648,12 @@ export class SearchQueryParser { return ''; } return ( - (this.keywords as any)[SearchQueryTypes[query.type]] + - colon + - SearchQueryParser.stringifyText( - (query as TextSearch).text, - (query as TextSearch).matchType - ) + (this.keywords as any)[SearchQueryTypes[query.type]] + + colon + + SearchQueryParser.stringifyText( + (query as TextSearch).text, + (query as TextSearch).matchType + ) ); default: diff --git a/src/common/SupportedFormats.ts b/src/common/SupportedFormats.ts index 0716ff73..f28a9876 100644 --- a/src/common/SupportedFormats.ts +++ b/src/common/SupportedFormats.ts @@ -36,18 +36,18 @@ export const SupportedFormats = { }; SupportedFormats.Photos = SupportedFormats.Photos.concat( - SupportedFormats.TranscodeNeed.Photos + SupportedFormats.TranscodeNeed.Photos ); SupportedFormats.Videos = SupportedFormats.Videos.concat( - SupportedFormats.TranscodeNeed.Videos + SupportedFormats.TranscodeNeed.Videos ); SupportedFormats.WithDots.Photos = SupportedFormats.Photos.map((f) => '.' + f); SupportedFormats.WithDots.Videos = SupportedFormats.Videos.map((f) => '.' + f); SupportedFormats.WithDots.MetaFiles = SupportedFormats.MetaFiles.map( - (f) => '.' + f + (f) => '.' + f ); SupportedFormats.WithDots.TranscodeNeed.Photos = - SupportedFormats.TranscodeNeed.Photos.map((f) => '.' + f); + SupportedFormats.TranscodeNeed.Photos.map((f) => '.' + f); SupportedFormats.WithDots.TranscodeNeed.Videos = - SupportedFormats.TranscodeNeed.Videos.map((f) => '.' + f); + SupportedFormats.TranscodeNeed.Videos.map((f) => '.' + f); diff --git a/src/common/Utils.ts b/src/common/Utils.ts index ceef8811..296e9a78 100644 --- a/src/common/Utils.ts +++ b/src/common/Utils.ts @@ -1,9 +1,9 @@ export class Utils { static GUID(): string { const s4 = (): string => - Math.floor((1 + Math.random()) * 0x10000) - .toString(16) - .substring(1); + Math.floor((1 + Math.random()) * 0x10000) + .toString(16) + .substring(1); return s4() + s4() + '-' + s4() + s4(); } @@ -135,8 +135,8 @@ export class Utils { public static canonizePath(path: string): string { return path - .replace(new RegExp('\\\\', 'g'), '/') - .replace(new RegExp('/+', 'g'), '/'); + .replace(new RegExp('\\\\', 'g'), '/') + .replace(new RegExp('/+', 'g'), '/'); } static concatUrls(...args: string[]): string { @@ -262,9 +262,9 @@ export class Utils { const E = Math.pow(10, 38); const nE = Math.pow(10, -38); return ( - !isNaN(value) && - ((value >= -3.402823466 * E && value <= -1.175494351 * nE) || - (value <= 3.402823466 * E && value >= 1.175494351 * nE)) + !isNaN(value) && + ((value >= -3.402823466 * E && value <= -1.175494351 * nE) || + (value <= 3.402823466 * E && value >= 1.175494351 * nE)) ); } diff --git a/src/common/config/private/Config.ts b/src/common/config/private/Config.ts index afbb7cb4..2cd38a1b 100644 --- a/src/common/config/private/Config.ts +++ b/src/common/config/private/Config.ts @@ -13,7 +13,7 @@ const upTime = new Date().toISOString(); // TODO: Refactor Config to be injectable globally. // This is a bad habit to let the Config know if its in a testing env. const isTesting = process.env['NODE_ENV'] == true || ['afterEach', 'after', 'beforeEach', 'before', 'describe', 'it'] - .every((fn) => (global as any)[fn] instanceof Function); + .every((fn) => (global as any)[fn] instanceof Function); @ConfigClass & ServerConfig>({ configPath: path.join(__dirname, !isTesting ? './../../../../config.json' : './../../../../test/backend/tmp/config.json'), @@ -76,11 +76,11 @@ export class PrivateConfigClass extends ServerConfig { } this.Environment.appVersion = - require('../../../../package.json').version; + require('../../../../package.json').version; this.Environment.buildTime = - require('../../../../package.json').buildTime; + require('../../../../package.json').buildTime; this.Environment.buildCommitHash = - require('../../../../package.json').buildCommitHash; + require('../../../../package.json').buildCommitHash; this.Environment.upTime = upTime; this.Environment.isDocker = !!process.env.PI_DOCKER; } @@ -89,7 +89,7 @@ export class PrivateConfigClass extends ServerConfig { const pc = ConfigClassBuilder.attachPrivateInterface(new PrivateConfigClass()); try { await pc.load(); - }catch (e){ + } catch (e) { console.error('Error during loading original config. Reverting to defaults.'); console.error(e); } @@ -99,7 +99,7 @@ export class PrivateConfigClass extends ServerConfig { } export const Config = ConfigClassBuilder.attachInterface( - new PrivateConfigClass() + new PrivateConfigClass() ); try { Config.loadSync(); diff --git a/src/common/config/private/MessagingConfig.ts b/src/common/config/private/MessagingConfig.ts index 36dcdc9f..1a01c5c3 100644 --- a/src/common/config/private/MessagingConfig.ts +++ b/src/common/config/private/MessagingConfig.ts @@ -2,7 +2,6 @@ import {SubConfigClass} from '../../../../node_modules/typeconfig/src/decorators/class/SubConfigClass'; import {ConfigPriority, TAGS} from '../public/ClientConfig'; import {ConfigProperty} from '../../../../node_modules/typeconfig/src/decorators/property/ConfigPropoerty'; -import {ServerConfig} from './PrivateConfig'; declare let $localize: (s: TemplateStringsArray) => string; @@ -80,19 +79,19 @@ export class EmailMessagingConfig { @ConfigProperty({ tags: - { - name: $localize`Sender email`, - priority: ConfigPriority.advanced, - } as TAGS, + { + name: $localize`Sender email`, + priority: ConfigPriority.advanced, + } as TAGS, description: $localize`Some services do not allow sending from random e-mail addresses. Set this accordingly.` }) emailFrom: string = 'noreply@pigallery2.com'; @ConfigProperty({ tags: - { - name: $localize`SMTP`, - } + { + name: $localize`SMTP`, + } }) smtp?: EmailSMTPMessagingConfig = new EmailSMTPMessagingConfig(); @@ -102,9 +101,9 @@ export class EmailMessagingConfig { export class MessagingConfig { @ConfigProperty({ tags: - { - name: $localize`Email`, - }, + { + name: $localize`Email`, + }, description: $localize`The app uses Nodemailer in the background for sending e-mails. Refer to https://nodemailer.com/usage/ if some options are not clear.` }) Email: EmailMessagingConfig = new EmailMessagingConfig(); diff --git a/src/common/config/private/PrivateConfig.ts b/src/common/config/private/PrivateConfig.ts index 9cd3d269..638a6621 100644 --- a/src/common/config/private/PrivateConfig.ts +++ b/src/common/config/private/PrivateConfig.ts @@ -87,14 +87,14 @@ export enum FFmpegPresets { export type videoCodecType = 'libvpx-vp9' | 'libx264' | 'libvpx' | 'libx265'; export type videoResolutionType = - | 240 - | 360 - | 480 - | 720 - | 1080 - | 1440 - | 2160 - | 4320; + | 240 + | 360 + | 480 + | 720 + | 1080 + | 1440 + | 2160 + | 4320; export type videoFormatType = 'mp4' | 'webm'; @SubConfigClass({softReadonly: true}) @@ -102,51 +102,51 @@ export class MySQLConfig { @ConfigProperty({ envAlias: 'MYSQL_HOST', tags: - { - name: $localize`Host`, - uiResetNeeded: {server: true}, - priority: ConfigPriority.advanced - }, + { + name: $localize`Host`, + uiResetNeeded: {server: true}, + priority: ConfigPriority.advanced + }, }) host: string = 'localhost'; @ConfigProperty({ envAlias: 'MYSQL_PORT', min: 0, max: 65535, tags: - { - name: $localize`Port`, - uiResetNeeded: {server: true}, - priority: ConfigPriority.advanced - }, + { + name: $localize`Port`, + uiResetNeeded: {server: true}, + priority: ConfigPriority.advanced + }, }) port: number = 3306; @ConfigProperty({ envAlias: 'MYSQL_DATABASE', tags: - { - name: $localize`Database`, - uiResetNeeded: {server: true}, - priority: ConfigPriority.advanced - }, + { + name: $localize`Database`, + uiResetNeeded: {server: true}, + priority: ConfigPriority.advanced + }, }) database: string = 'pigallery2'; @ConfigProperty({ envAlias: 'MYSQL_USERNAME', tags: - { - name: $localize`Username`, - uiResetNeeded: {server: true}, - priority: ConfigPriority.advanced - }, + { + name: $localize`Username`, + uiResetNeeded: {server: true}, + priority: ConfigPriority.advanced + }, }) username: string = ''; @ConfigProperty({ envAlias: 'MYSQL_PASSWORD', type: 'password', tags: - { - name: $localize`Password`, - uiResetNeeded: {server: true}, - priority: ConfigPriority.advanced - } + { + name: $localize`Password`, + uiResetNeeded: {server: true}, + priority: ConfigPriority.advanced + } }) password: string = ''; } @@ -155,11 +155,11 @@ export class MySQLConfig { export class SQLiteConfig { @ConfigProperty({ tags: - { - name: $localize`Sqlite db filename`, - uiResetNeeded: {server: true}, - priority: ConfigPriority.underTheHood - }, + { + name: $localize`Sqlite db filename`, + uiResetNeeded: {server: true}, + priority: ConfigPriority.underTheHood + }, description: $localize`Sqlite will save the db with this filename.`, }) DBFileName: string = 'sqlite.db'; @@ -169,51 +169,51 @@ export class SQLiteConfig { export class UserConfig { @ConfigProperty({ tags: - { - name: $localize`Name`, - priority: ConfigPriority.underTheHood - } + { + name: $localize`Name`, + priority: ConfigPriority.underTheHood + } }) name: string; @ConfigProperty({ type: UserRoles, tags: - { - name: $localize`Role`, - priority: ConfigPriority.underTheHood - }, + { + name: $localize`Role`, + priority: ConfigPriority.underTheHood + }, }) role: UserRoles = UserRoles.User; @ConfigProperty({ type: 'string', tags: - { - name: $localize`Password`, - priority: ConfigPriority.underTheHood, - relevant: (c: UserConfig) => !c.encrypted - }, + { + name: $localize`Password`, + priority: ConfigPriority.underTheHood, + relevant: (c: UserConfig) => !c.encrypted + }, description: $localize`Unencrypted, temporary password. App will encrypt it and delete this.` }) password: string; @ConfigProperty({ tags: - { - name: $localize`Encrypted password`, - priority: ConfigPriority.underTheHood, - secret: true - }, + { + name: $localize`Encrypted password`, + priority: ConfigPriority.underTheHood, + secret: true + }, }) encryptedPassword: string | undefined; @ConfigProperty({ tags: - { - priority: ConfigPriority.underTheHood, - relevant: () => false // never render this on UI. Only used to indicate that encryption is done. - } as TAGS, + { + priority: ConfigPriority.underTheHood, + relevant: () => false // never render this on UI. Only used to indicate that encryption is done. + } as TAGS, }) encrypted: boolean; @@ -235,44 +235,44 @@ export class ServerDataBaseConfig { @ConfigProperty({ type: DatabaseType, tags: - { - name: $localize`Type`, - priority: ConfigPriority.advanced, - uiResetNeeded: {db: true}, - githubIssue: 573 - } as TAGS, + { + name: $localize`Type`, + priority: ConfigPriority.advanced, + uiResetNeeded: {db: true}, + githubIssue: 573 + } as TAGS, description: $localize`SQLite is recommended.` }) type: DatabaseType = DatabaseType.sqlite; @ConfigProperty({ tags: - { - name: $localize`Database folder`, - uiResetNeeded: {server: true}, - priority: ConfigPriority.advanced - }, + { + name: $localize`Database folder`, + uiResetNeeded: {server: true}, + priority: ConfigPriority.advanced + }, description: $localize`All file-based data will be stored here (sqlite database, job history data).`, }) dbFolder: string = 'db'; @ConfigProperty({ tags: - { - name: $localize`SQLite`, - uiResetNeeded: {db: true}, - relevant: (c: any) => c.type === DatabaseType.sqlite, - } + { + name: $localize`SQLite`, + uiResetNeeded: {db: true}, + relevant: (c: any) => c.type === DatabaseType.sqlite, + } }) sqlite?: SQLiteConfig = new SQLiteConfig(); @ConfigProperty({ tags: - { - name: $localize`MySQL`, - uiResetNeeded: {db: true}, - relevant: (c: any) => c.type === DatabaseType.mysql, - } + { + name: $localize`MySQL`, + uiResetNeeded: {db: true}, + relevant: (c: any) => c.type === DatabaseType.mysql, + } }) mysql?: MySQLConfig = new MySQLConfig(); @@ -285,13 +285,13 @@ export class ServerUserConfig extends ClientUserConfig { @ConfigProperty({ arrayType: UserConfig, tags: - { - name: $localize`Enforced users`, - priority: ConfigPriority.underTheHood, - uiResetNeeded: {server: true}, - uiOptional: true, - githubIssue: 575 - } as TAGS, + { + name: $localize`Enforced users`, + priority: ConfigPriority.underTheHood, + uiResetNeeded: {server: true}, + uiOptional: true, + githubIssue: 575 + } as TAGS, description: $localize`Creates these users in the DB during startup if they do not exist. If a user with this name exist, it won't be overwritten, even if the role is different.`, }) enforcedUsers: UserConfig[] = []; @@ -302,40 +302,40 @@ export class ServerUserConfig extends ClientUserConfig { export class ServerThumbnailConfig extends ClientThumbnailConfig { @ConfigProperty({ tags: - { - name: $localize`Enforced users`, - priority: ConfigPriority.underTheHood - }, + { + name: $localize`Enforced users`, + priority: ConfigPriority.underTheHood + }, description: $localize`if true, 'lanczos3' will used to scale photos, otherwise faster but lower quality 'nearest'.` }) useLanczos3: boolean = true; @ConfigProperty({ max: 100, min: 1, type: 'unsignedInt', tags: - { - name: $localize`Converted photo and thumbnail quality`, - priority: ConfigPriority.underTheHood - }, + { + name: $localize`Converted photo and thumbnail quality`, + priority: ConfigPriority.underTheHood + }, description: $localize`Between 0-100.` }) quality = 80; @ConfigProperty({ type: 'boolean', tags: - { - name: $localize`Use chroma subsampling`, - priority: ConfigPriority.underTheHood - }, + { + name: $localize`Use chroma subsampling`, + priority: ConfigPriority.underTheHood + }, description: $localize`Use high quality chroma subsampling in webp. See: https://sharp.pixelplumbing.com/api-output#webp.` }) smartSubsample = true; @ConfigProperty({ type: 'ratio', tags: - { - name: $localize`Person face margin`, - priority: ConfigPriority.underTheHood - }, + { + name: $localize`Person face margin`, + priority: ConfigPriority.underTheHood + }, description: $localize`Person face size ratio on the face thumbnail.` }) personFaceMargin: number = 0.6; // in ration [0-1] @@ -345,47 +345,47 @@ export class ServerThumbnailConfig extends ClientThumbnailConfig { export class ServerGPXCompressingConfig extends ClientGPXCompressingConfig { @ConfigProperty({ tags: - { - name: $localize`OnTheFly *.gpx compression`, - priority: ConfigPriority.advanced, - uiDisabled: (sc: ServerGPXCompressingConfig, c: ServerConfig) => !c.Map.enabled || !sc.enabled || !c.MetaFile.gpx - }, + { + name: $localize`OnTheFly *.gpx compression`, + priority: ConfigPriority.advanced, + uiDisabled: (sc: ServerGPXCompressingConfig, c: ServerConfig) => !c.Map.enabled || !sc.enabled || !c.MetaFile.gpx + }, description: $localize`Enables on the fly *.gpx compression.`, }) onTheFly: boolean = true; @ConfigProperty({ type: 'unsignedInt', tags: - { - name: $localize`Min distance`, - priority: ConfigPriority.underTheHood, - unit: 'm', - uiDisabled: (sc: ServerGPXCompressingConfig, c: ServerConfig) => !c.Map.enabled || !sc.enabled || !c.MetaFile.gpx - } as TAGS, + { + name: $localize`Min distance`, + priority: ConfigPriority.underTheHood, + unit: 'm', + uiDisabled: (sc: ServerGPXCompressingConfig, c: ServerConfig) => !c.Map.enabled || !sc.enabled || !c.MetaFile.gpx + } as TAGS, description: $localize`Filters out entry that are closer than this to each other in meters.` }) minDistance: number = 5; @ConfigProperty({ type: 'unsignedInt', tags: - { - name: $localize`Max middle point deviance`, - priority: ConfigPriority.underTheHood, - unit: 'm', - uiDisabled: (sc: ServerGPXCompressingConfig, c: ServerConfig) => !c.Map.enabled || !sc.enabled || !c.MetaFile.gpx - } as TAGS, + { + name: $localize`Max middle point deviance`, + priority: ConfigPriority.underTheHood, + unit: 'm', + uiDisabled: (sc: ServerGPXCompressingConfig, c: ServerConfig) => !c.Map.enabled || !sc.enabled || !c.MetaFile.gpx + } as TAGS, description: $localize`Filters out entry that would fall on the line if we would just connect the previous and the next points. This setting sets the sensitivity for that (higher number, more points are filtered).` }) maxMiddleDeviance: number = 5; @ConfigProperty({ type: 'unsignedInt', tags: - { - name: $localize`Min time delta`, - priority: ConfigPriority.underTheHood, - unit: 'ms', - uiDisabled: (sc: ServerGPXCompressingConfig, c: ServerConfig) => !c.Map.enabled || !sc.enabled || !c.MetaFile.gpx - } as TAGS, + { + name: $localize`Min time delta`, + priority: ConfigPriority.underTheHood, + unit: 'ms', + uiDisabled: (sc: ServerGPXCompressingConfig, c: ServerConfig) => !c.Map.enabled || !sc.enabled || !c.MetaFile.gpx + } as TAGS, description: $localize`Filters out entry that are closer than this in time in milliseconds.` }) minTimeDistance: number = 5000; @@ -395,17 +395,17 @@ export class ServerGPXCompressingConfig extends ClientGPXCompressingConfig { export class ServerMetaFileConfig extends ClientMetaFileConfig { @ConfigProperty({ tags: - { - name: $localize`GPX compression`, - priority: ConfigPriority.advanced, - uiJob: [{ - job: DefaultsJobs[DefaultsJobs['GPX Compression']], - relevant: (c) => c.MetaFile.GPXCompressing.enabled - }, { - job: DefaultsJobs[DefaultsJobs['Delete Compressed GPX']], - relevant: (c) => c.MetaFile.GPXCompressing.enabled - }] - } as TAGS + { + name: $localize`GPX compression`, + priority: ConfigPriority.advanced, + uiJob: [{ + job: DefaultsJobs[DefaultsJobs['GPX Compression']], + relevant: (c) => c.MetaFile.GPXCompressing.enabled + }, { + job: DefaultsJobs[DefaultsJobs['Delete Compressed GPX']], + relevant: (c) => c.MetaFile.GPXCompressing.enabled + }] + } as TAGS }) GPXCompressing: ServerGPXCompressingConfig = new ServerGPXCompressingConfig(); } @@ -416,11 +416,11 @@ export class ServerSharingConfig extends ClientSharingConfig { @ConfigProperty({ type: 'unsignedInt', tags: - { - name: $localize`Update timeout`, - priority: ConfigPriority.underTheHood, - unit: 'ms' - } as TAGS, + { + name: $localize`Update timeout`, + priority: ConfigPriority.underTheHood, + unit: 'ms' + } as TAGS, description: $localize`After creating a sharing link, it can be updated for this long.` }) updateTimeout: number = 1000 * 60 * 5; @@ -431,47 +431,47 @@ export class ServerIndexingConfig { @ConfigProperty({ type: 'unsignedInt', tags: - { - name: $localize`Index cache timeout`, - priority: ConfigPriority.underTheHood, - unit: 'ms' - } as TAGS, + { + name: $localize`Index cache timeout`, + priority: ConfigPriority.underTheHood, + unit: 'ms' + } as TAGS, description: $localize`If there was no indexing in this time, it reindexes. (skipped if indexes are in DB and sensitivity is low).` }) cachedFolderTimeout: number = 1000 * 60 * 60; // Do not rescans the folder if seems ok @ConfigProperty({ type: ReIndexingSensitivity, tags: - { - name: $localize`Folder reindexing sensitivity`, - priority: ConfigPriority.advanced - }, + { + name: $localize`Folder reindexing sensitivity`, + priority: ConfigPriority.advanced + }, description: $localize`Set the reindexing sensitivity. High value check the folders for change more often. Setting to never only indexes if never indexed or explicit running the Indexing Job.` }) reIndexingSensitivity: ReIndexingSensitivity = ReIndexingSensitivity.low; @ConfigProperty({ arrayType: 'string', tags: - { - name: $localize`Exclude Folder List`, - priority: ConfigPriority.advanced, - uiResetNeeded: {server: true, db: true}, - uiOptional: true, - uiAllowSpaces: true - } as TAGS, + { + name: $localize`Exclude Folder List`, + priority: ConfigPriority.advanced, + uiResetNeeded: {server: true, db: true}, + uiOptional: true, + uiAllowSpaces: true + } as TAGS, description: $localize`Folders to exclude from indexing. If an entry starts with '/' it is treated as an absolute path. If it doesn't start with '/' but contains a '/', the path is relative to the image directory. If it doesn't contain a '/', any folder with this name will be excluded.`, }) excludeFolderList: string[] = ['.Trash-1000', '.dtrash', '$RECYCLE.BIN']; @ConfigProperty({ arrayType: 'string', tags: - { - name: $localize`Exclude File List`, - priority: ConfigPriority.advanced, - uiResetNeeded: {server: true, db: true}, - uiOptional: true, - hint: $localize`.ignore;.pg2ignore` - } as TAGS, + { + name: $localize`Exclude File List`, + priority: ConfigPriority.advanced, + uiResetNeeded: {server: true, db: true}, + uiOptional: true, + hint: $localize`.ignore;.pg2ignore` + } as TAGS, description: $localize`Files that mark a folder to be excluded from indexing. Any folder that contains a file with this name will be excluded from indexing.`, }) excludeFileList: string[] = []; @@ -481,21 +481,21 @@ export class ServerIndexingConfig { export class ServerThreadingConfig { @ConfigProperty({ tags: - { - name: $localize`Threading`, - uiResetNeeded: {server: true}, - priority: ConfigPriority.underTheHood, - } as TAGS, + { + name: $localize`Threading`, + uiResetNeeded: {server: true}, + priority: ConfigPriority.underTheHood, + } as TAGS, description: $localize`[Deprecated, will be removed in the next release] Runs directory scanning and thumbnail generation in a different thread.` }) enabled: boolean = false; @ConfigProperty({ tags: - { - name: $localize`Thumbnail threads`, - uiResetNeeded: {server: true}, - priority: ConfigPriority.underTheHood - }, + { + name: $localize`Thumbnail threads`, + uiResetNeeded: {server: true}, + priority: ConfigPriority.underTheHood + }, description: $localize`Number of threads that are used to generate thumbnails. If 0, number of 'CPU cores -1' threads will be used.`, }) thumbnailThreads: number = 0; // if zero-> CPU count -1 @@ -506,10 +506,10 @@ export class ServerDuplicatesConfig { @ConfigProperty({ type: 'unsignedInt', tags: - { - name: $localize`Max duplicates`, - priority: ConfigPriority.underTheHood - }, + { + name: $localize`Max duplicates`, + priority: ConfigPriority.underTheHood + }, description: $localize`Maximum number of duplicates to list.` }) listingLimit: number = 1000; @@ -610,21 +610,21 @@ export class JobScheduleConfig implements JobScheduleDTO { }, }) trigger: - | AfterJobTriggerConfig - | NeverJobTriggerConfig - | PeriodicJobTriggerConfig - | ScheduledJobTriggerConfig; - - constructor( - name: string, - jobName: string, - trigger: | AfterJobTriggerConfig | NeverJobTriggerConfig | PeriodicJobTriggerConfig - | ScheduledJobTriggerConfig, - config: any = {}, - allowParallelRun: boolean = false + | ScheduledJobTriggerConfig; + + constructor( + name: string, + jobName: string, + trigger: + | AfterJobTriggerConfig + | NeverJobTriggerConfig + | PeriodicJobTriggerConfig + | ScheduledJobTriggerConfig, + config: any = {}, + allowParallelRun: boolean = false ) { this.name = name; this.jobName = jobName; @@ -639,20 +639,20 @@ export class ServerJobConfig { @ConfigProperty({ type: 'unsignedInt', tags: - { - name: $localize`Max saved progress`, - priority: ConfigPriority.underTheHood - }, + { + name: $localize`Max saved progress`, + priority: ConfigPriority.underTheHood + }, description: $localize`Job history size.` }) maxSavedProgress: number = 20; @ConfigProperty({ type: 'unsignedInt', tags: - { - name: $localize`Processing batch size`, - priority: ConfigPriority.underTheHood - }, + { + name: $localize`Processing batch size`, + priority: ConfigPriority.underTheHood + }, description: $localize`Jobs load this many photos or videos form the DB for processing at once.` }) mediaProcessingBatchSize: number = 1000; @@ -665,46 +665,46 @@ export class ServerJobConfig { }) scheduled: JobScheduleConfig[] = [ new JobScheduleConfig( - DefaultsJobs[DefaultsJobs.Indexing], - DefaultsJobs[DefaultsJobs.Indexing], - new NeverJobTriggerConfig(), - {indexChangesOnly: true} // set config explicitly, so it is not undefined on the UI + DefaultsJobs[DefaultsJobs.Indexing], + DefaultsJobs[DefaultsJobs.Indexing], + new NeverJobTriggerConfig(), + {indexChangesOnly: true} // set config explicitly, so it is not undefined on the UI ), new JobScheduleConfig( - DefaultsJobs[DefaultsJobs['Album Cover Filling']], - DefaultsJobs[DefaultsJobs['Album Cover Filling']], - new AfterJobTriggerConfig(DefaultsJobs[DefaultsJobs['Indexing']]), - {} + DefaultsJobs[DefaultsJobs['Album Cover Filling']], + DefaultsJobs[DefaultsJobs['Album Cover Filling']], + new AfterJobTriggerConfig(DefaultsJobs[DefaultsJobs['Indexing']]), + {} ), new JobScheduleConfig( - DefaultsJobs[DefaultsJobs['Thumbnail Generation']], - DefaultsJobs[DefaultsJobs['Thumbnail Generation']], - new AfterJobTriggerConfig(DefaultsJobs[DefaultsJobs['Album Cover Filling']]), - {sizes: [240], indexedOnly: true} + DefaultsJobs[DefaultsJobs['Thumbnail Generation']], + DefaultsJobs[DefaultsJobs['Thumbnail Generation']], + new AfterJobTriggerConfig(DefaultsJobs[DefaultsJobs['Album Cover Filling']]), + {sizes: [240], indexedOnly: true} ), new JobScheduleConfig( - DefaultsJobs[DefaultsJobs['Photo Converting']], - DefaultsJobs[DefaultsJobs['Photo Converting']], - new AfterJobTriggerConfig(DefaultsJobs[DefaultsJobs['Thumbnail Generation']]), - {indexedOnly: true} + DefaultsJobs[DefaultsJobs['Photo Converting']], + DefaultsJobs[DefaultsJobs['Photo Converting']], + new AfterJobTriggerConfig(DefaultsJobs[DefaultsJobs['Thumbnail Generation']]), + {indexedOnly: true} ), new JobScheduleConfig( - DefaultsJobs[DefaultsJobs['Video Converting']], - DefaultsJobs[DefaultsJobs['Video Converting']], - new AfterJobTriggerConfig(DefaultsJobs[DefaultsJobs['Photo Converting']]), - {indexedOnly: true} + DefaultsJobs[DefaultsJobs['Video Converting']], + DefaultsJobs[DefaultsJobs['Video Converting']], + new AfterJobTriggerConfig(DefaultsJobs[DefaultsJobs['Photo Converting']]), + {indexedOnly: true} ), new JobScheduleConfig( - DefaultsJobs[DefaultsJobs['GPX Compression']], - DefaultsJobs[DefaultsJobs['GPX Compression']], - new AfterJobTriggerConfig(DefaultsJobs[DefaultsJobs['Video Converting']]), - {indexedOnly: true} + DefaultsJobs[DefaultsJobs['GPX Compression']], + DefaultsJobs[DefaultsJobs['GPX Compression']], + new AfterJobTriggerConfig(DefaultsJobs[DefaultsJobs['Video Converting']]), + {indexedOnly: true} ), new JobScheduleConfig( - DefaultsJobs[DefaultsJobs['Temp Folder Cleaning']], - DefaultsJobs[DefaultsJobs['Temp Folder Cleaning']], - new AfterJobTriggerConfig(DefaultsJobs[DefaultsJobs['GPX Compression']]), - {indexedOnly: true} + DefaultsJobs[DefaultsJobs['Temp Folder Cleaning']], + DefaultsJobs[DefaultsJobs['Temp Folder Cleaning']], + new AfterJobTriggerConfig(DefaultsJobs[DefaultsJobs['GPX Compression']]), + {indexedOnly: true} ), ]; } @@ -714,73 +714,73 @@ export class VideoTranscodingConfig { @ConfigProperty({ type: 'unsignedInt', tags: - { - name: $localize`Bit rate`, - priority: ConfigPriority.advanced, - unit: 'bps' - }, + { + name: $localize`Bit rate`, + priority: ConfigPriority.advanced, + unit: 'bps' + }, description: $localize`Target bit rate of the output video will be scaled down this this. This should be less than the upload rate of your home server.` }) bitRate: number = 5 * 1024 * 1024; @ConfigProperty({ type: 'unsignedInt', tags: - { - name: $localize`Resolution`, - priority: ConfigPriority.advanced, - uiOptions: [720, 1080, 1440, 2160, 4320], - unit: 'px' - }, + { + name: $localize`Resolution`, + priority: ConfigPriority.advanced, + uiOptions: [720, 1080, 1440, 2160, 4320], + unit: 'px' + }, description: $localize`The height of the output video will be scaled down to this, while keeping the aspect ratio.` }) resolution: videoResolutionType = 720; @ConfigProperty({ type: 'positiveFloat', tags: - { - name: $localize`FPS`, - priority: ConfigPriority.underTheHood, - uiOptions: [24, 25, 30, 48, 50, 60] - }, + { + name: $localize`FPS`, + priority: ConfigPriority.underTheHood, + uiOptions: [24, 25, 30, 48, 50, 60] + }, description: $localize`Target frame per second (fps) of the output video will be scaled down this this.` }) fps: number = 25; @ConfigProperty({ tags: - { - name: $localize`Format`, - priority: ConfigPriority.advanced, - uiOptions: ['mp4', 'webm'] - } + { + name: $localize`Format`, + priority: ConfigPriority.advanced, + uiOptions: ['mp4', 'webm'] + } }) format: videoFormatType = 'mp4'; @ConfigProperty({ tags: - { - name: $localize`MP4 codec`, - priority: ConfigPriority.underTheHood, - uiOptions: ['libx264', 'libx265'], - relevant: (c: any) => c.format === 'mp4' - } + { + name: $localize`MP4 codec`, + priority: ConfigPriority.underTheHood, + uiOptions: ['libx264', 'libx265'], + relevant: (c: any) => c.format === 'mp4' + } }) mp4Codec: videoCodecType = 'libx264'; @ConfigProperty({ tags: - { - name: $localize`Webm Codec`, - priority: ConfigPriority.underTheHood, - uiOptions: ['libvpx', 'libvpx-vp9'], - relevant: (c: any) => c.format === 'webm' - } + { + name: $localize`Webm Codec`, + priority: ConfigPriority.underTheHood, + uiOptions: ['libvpx', 'libvpx-vp9'], + relevant: (c: any) => c.format === 'webm' + } }) webmCodec: videoCodecType = 'libvpx'; @ConfigProperty({ type: 'unsignedInt', max: 51, tags: - { - name: $localize`CRF`, - priority: ConfigPriority.underTheHood, - }, + { + name: $localize`CRF`, + priority: ConfigPriority.underTheHood, + }, description: $localize`The range of the Constant Rate Factor (CRF) scale is 0–51, where 0 is lossless, 23 is the default, and 51 is worst quality possible.`, }) @@ -788,10 +788,10 @@ export class VideoTranscodingConfig { @ConfigProperty({ type: FFmpegPresets, tags: - { - name: $localize`Preset`, - priority: ConfigPriority.advanced, - }, + { + name: $localize`Preset`, + priority: ConfigPriority.advanced, + }, description: $localize`A preset is a collection of options that will provide a certain encoding speed to compression ratio. A slower preset will provide better compression (compression is quality per filesize).`, }) preset: FFmpegPresets = FFmpegPresets.medium; @@ -843,7 +843,7 @@ export class PhotoConvertingConfig extends ClientPhotoConvertingConfig { name: $localize`On the fly converting`, priority: ConfigPriority.underTheHood, uiDisabled: (sc: PhotoConvertingConfig) => - !sc.enabled + !sc.enabled }, description: $localize`Converts photos on the fly, when they are requested.`, @@ -857,7 +857,7 @@ export class PhotoConvertingConfig extends ClientPhotoConvertingConfig { uiOptions: [720, 1080, 1440, 2160, 4320], unit: 'px', uiDisabled: (sc: PhotoConvertingConfig) => - !sc.enabled + !sc.enabled }, description: $localize`The shorter edge of the converted photo will be scaled down to this, while keeping the aspect ratio.`, }) diff --git a/src/common/config/public/Config.ts b/src/common/config/public/Config.ts index 77126544..6f8269c9 100644 --- a/src/common/config/public/Config.ts +++ b/src/common/config/public/Config.ts @@ -17,11 +17,11 @@ declare namespace ServerInject { } export const Config: IWebConfigClass & ClientClass = - WebConfigClassBuilder.attachInterface(new ClientClass()); + WebConfigClassBuilder.attachInterface(new ClientClass()); if ( - typeof ServerInject !== 'undefined' && - typeof ServerInject.ConfigInject !== 'undefined' + typeof ServerInject !== 'undefined' && + typeof ServerInject.ConfigInject !== 'undefined' ) { Config.load(ServerInject.ConfigInject); } diff --git a/src/common/entities/AutoCompleteItem.ts b/src/common/entities/AutoCompleteItem.ts index f76e4264..07eef1b4 100644 --- a/src/common/entities/AutoCompleteItem.ts +++ b/src/common/entities/AutoCompleteItem.ts @@ -1,4 +1,4 @@ -import { SearchQueryTypes } from './SearchQueryDTO'; +import {SearchQueryTypes} from './SearchQueryDTO'; export interface IAutoCompleteItem { text: string; @@ -6,7 +6,8 @@ export interface IAutoCompleteItem { } export class AutoCompleteItem implements IAutoCompleteItem { - constructor(public text: string, public type: SearchQueryTypes = null) {} + constructor(public text: string, public type: SearchQueryTypes = null) { + } equals(other: AutoCompleteItem): boolean { return this.text === other.text && this.type === other.type; diff --git a/src/common/entities/ConentWrapper.ts b/src/common/entities/ConentWrapper.ts index cde723d1..bc3435e3 100644 --- a/src/common/entities/ConentWrapper.ts +++ b/src/common/entities/ConentWrapper.ts @@ -28,9 +28,9 @@ export class ContentWrapper { public notModified?: boolean; constructor( - directory: ParentDirectoryDTO = null, - searchResult: SearchResultDTO = null, - notModified?: boolean + directory: ParentDirectoryDTO = null, + searchResult: SearchResultDTO = null, + notModified?: boolean ) { if (directory) { this.directory = directory; @@ -138,15 +138,15 @@ export class ContentWrapper { if ((media as PhotoDTO).metadata.cameraData) { if ((media as PhotoDTO).metadata.cameraData.lens) { mapifyOne(cw.map.lens, cw.reverseMap.lens, - (media as PhotoDTO).metadata.cameraData, 'lens', 'l'); + (media as PhotoDTO).metadata.cameraData, 'lens', 'l'); } if ((media as PhotoDTO).metadata.cameraData.make) { mapifyOne(cw.map.camera, cw.reverseMap.camera, - (media as PhotoDTO).metadata.cameraData, 'make', 'm'); + (media as PhotoDTO).metadata.cameraData, 'make', 'm'); } if ((media as PhotoDTO).metadata.cameraData.model) { mapifyOne(cw.map.camera, cw.reverseMap.camera, - (media as PhotoDTO).metadata.cameraData, 'model', 'o'); + (media as PhotoDTO).metadata.cameraData, 'model', 'o'); } if ((media as PhotoDTO).metadata.cameraData.ISO) { @@ -177,15 +177,15 @@ export class ContentWrapper { if ((media as PhotoDTO).metadata.positionData) { if ((media as PhotoDTO).metadata.positionData.country) { mapifyOne(cw.map.keywords, cw.reverseMap.keywords, - (media as PhotoDTO).metadata.positionData, 'country', 'c'); + (media as PhotoDTO).metadata.positionData, 'country', 'c'); } if ((media as PhotoDTO).metadata.positionData.city) { mapifyOne(cw.map.keywords, cw.reverseMap.keywords, - (media as PhotoDTO).metadata.positionData, 'city', 'cy'); + (media as PhotoDTO).metadata.positionData, 'city', 'cy'); } if ((media as PhotoDTO).metadata.positionData.state) { mapifyOne(cw.map.keywords, cw.reverseMap.keywords, - (media as PhotoDTO).metadata.positionData, 'state', 's'); + (media as PhotoDTO).metadata.positionData, 'state', 's'); } if ((media as PhotoDTO).metadata.positionData.GPSData) { @@ -412,17 +412,17 @@ export class ContentWrapper { // @ts-ignore if (typeof (media as PhotoDTO).metadata.cameraData.l !== 'undefined') { deMapifyOne(cw.map.lens, - (media as PhotoDTO).metadata.cameraData, 'lens', 'l'); + (media as PhotoDTO).metadata.cameraData, 'lens', 'l'); } // @ts-ignore if (typeof (media as PhotoDTO).metadata.cameraData.m !== 'undefined') { deMapifyOne(cw.map.camera, - (media as PhotoDTO).metadata.cameraData, 'make', 'm'); + (media as PhotoDTO).metadata.cameraData, 'make', 'm'); } // @ts-ignore if (typeof (media as PhotoDTO).metadata.cameraData['o'] !== 'undefined') { deMapifyOne(cw.map.camera, - (media as PhotoDTO).metadata.cameraData, 'model', 'o'); + (media as PhotoDTO).metadata.cameraData, 'model', 'o'); } // @ts-ignore @@ -464,28 +464,28 @@ export class ContentWrapper { // @ts-ignore if (typeof (media as PhotoDTO).metadata.positionData.c !== 'undefined') { deMapifyOne(cw.map.keywords, - (media as PhotoDTO).metadata.positionData, 'country', 'c'); + (media as PhotoDTO).metadata.positionData, 'country', 'c'); } // @ts-ignore if (typeof (media as PhotoDTO).metadata.positionData.cy !== 'undefined') { deMapifyOne(cw.map.keywords, - (media as PhotoDTO).metadata.positionData, 'city', 'cy'); + (media as PhotoDTO).metadata.positionData, 'city', 'cy'); } // @ts-ignore if (typeof (media as PhotoDTO).metadata.positionData.s !== 'undefined') { deMapifyOne(cw.map.keywords, - (media as PhotoDTO).metadata.positionData, 'state', 's'); + (media as PhotoDTO).metadata.positionData, 'state', 's'); } // @ts-ignore if ((media as PhotoDTO).metadata.positionData['g']) { (media as PhotoDTO).metadata.positionData.GPSData = - { - // @ts-ignore - latitude: (media as PhotoDTO).metadata.positionData['g'][0], - // @ts-ignore - longitude: (media as PhotoDTO).metadata.positionData['g'][1] - }; + { + // @ts-ignore + latitude: (media as PhotoDTO).metadata.positionData['g'][0], + // @ts-ignore + longitude: (media as PhotoDTO).metadata.positionData['g'][1] + }; // @ts-ignore delete (media as PhotoDTO).metadata.positionData['g']; } diff --git a/src/common/entities/DirectoryDTO.ts b/src/common/entities/DirectoryDTO.ts index 164126d9..abd5c71b 100644 --- a/src/common/entities/DirectoryDTO.ts +++ b/src/common/entities/DirectoryDTO.ts @@ -1,7 +1,7 @@ -import { MediaDTO, MediaDTOUtils } from './MediaDTO'; -import { FileDTO } from './FileDTO'; -import { PhotoDTO, CoverPhotoDTO } from './PhotoDTO'; -import { Utils } from '../Utils'; +import {MediaDTO} from './MediaDTO'; +import {FileDTO} from './FileDTO'; +import {CoverPhotoDTO} from './PhotoDTO'; +import {Utils} from '../Utils'; export interface DirectoryPathDTO { name: string; @@ -9,9 +9,8 @@ export interface DirectoryPathDTO { } - export interface DirectoryBaseDTO - extends DirectoryPathDTO { + extends DirectoryPathDTO { id: number; name: string; path: string; @@ -30,7 +29,7 @@ export interface DirectoryBaseDTO } export interface ParentDirectoryDTO - extends DirectoryBaseDTO { + extends DirectoryBaseDTO { id: number; name: string; path: string; @@ -47,7 +46,7 @@ export interface ParentDirectoryDTO } export interface SubDirectoryDTO - extends DirectoryBaseDTO { + extends DirectoryBaseDTO { id: number; name: string; path: string; diff --git a/src/common/entities/DuplicatesDTO.ts b/src/common/entities/DuplicatesDTO.ts index 25a381f3..66dd7695 100644 --- a/src/common/entities/DuplicatesDTO.ts +++ b/src/common/entities/DuplicatesDTO.ts @@ -1,4 +1,4 @@ -import { MediaDTO } from './MediaDTO'; +import {MediaDTO} from './MediaDTO'; export interface DuplicatesDTO { media: MediaDTO[]; diff --git a/src/common/entities/Error.ts b/src/common/entities/Error.ts index c8b9b00a..c3a6315f 100644 --- a/src/common/entities/Error.ts +++ b/src/common/entities/Error.ts @@ -1,4 +1,4 @@ -import { Request } from 'express'; +import {Request} from 'express'; export enum ErrorCodes { NOT_AUTHENTICATED = 1, @@ -33,16 +33,16 @@ export class ErrorDTO { public request: { method: string; url: string; - } = { method: '', url: '' }; + } = {method: '', url: ''}; constructor( - public code: ErrorCodes, - public message?: string, - public details?: any, - req?: Request + public code: ErrorCodes, + public message?: string, + public details?: any, + req?: Request ) { this.detailsStr = - (this.details ? this.details.toString() : '') || ErrorCodes[code]; + (this.details ? this.details.toString() : '') || ErrorCodes[code]; if (req) { this.request = { method: req.method, diff --git a/src/common/entities/LoginCredential.ts b/src/common/entities/LoginCredential.ts index 2bd0732c..ff81cf85 100644 --- a/src/common/entities/LoginCredential.ts +++ b/src/common/entities/LoginCredential.ts @@ -1,7 +1,8 @@ export class LoginCredential { constructor( - public username: string = '', - public password: string = '', - public rememberMe: boolean = true - ) {} + public username: string = '', + public password: string = '', + public rememberMe: boolean = true + ) { + } } diff --git a/src/common/entities/MediaDTO.ts b/src/common/entities/MediaDTO.ts index 2b6dbc21..0a1a3e79 100644 --- a/src/common/entities/MediaDTO.ts +++ b/src/common/entities/MediaDTO.ts @@ -25,15 +25,15 @@ export interface MediaDimension { export const MediaDTOUtils = { hasPositionData: (media: MediaDTO): boolean => { return ( - !!(media as PhotoDTO).metadata.positionData && - !!( - (media as PhotoDTO).metadata.positionData.city || - (media as PhotoDTO).metadata.positionData.state || - (media as PhotoDTO).metadata.positionData.country || - ((media as PhotoDTO).metadata.positionData.GPSData && - (media as PhotoDTO).metadata.positionData.GPSData.latitude && - (media as PhotoDTO).metadata.positionData.GPSData.longitude) - ) + !!(media as PhotoDTO).metadata.positionData && + !!( + (media as PhotoDTO).metadata.positionData.city || + (media as PhotoDTO).metadata.positionData.state || + (media as PhotoDTO).metadata.positionData.country || + ((media as PhotoDTO).metadata.positionData.GPSData && + (media as PhotoDTO).metadata.positionData.GPSData.latitude && + (media as PhotoDTO).metadata.positionData.GPSData.longitude) + ) ); }, isPhoto: (media: FileDTO): boolean => { @@ -76,7 +76,7 @@ export const MediaDTOUtils = { equals: (a: MediaDTO, b: MediaDTO): boolean => { return a.directory.path === b.directory.path && - a.directory.name === b.directory.name && - a.name === b.name; + a.directory.name === b.directory.name && + a.name === b.name; } }; diff --git a/src/common/entities/Message.ts b/src/common/entities/Message.ts index c9478d42..2418b345 100644 --- a/src/common/entities/Message.ts +++ b/src/common/entities/Message.ts @@ -1,4 +1,4 @@ -import { ErrorDTO } from './Error'; +import {ErrorDTO} from './Error'; export class Message { public error: ErrorDTO = null; diff --git a/src/common/entities/PasswordChangeRequest.ts b/src/common/entities/PasswordChangeRequest.ts index 1e769ea1..cc8e7cff 100644 --- a/src/common/entities/PasswordChangeRequest.ts +++ b/src/common/entities/PasswordChangeRequest.ts @@ -1,10 +1,10 @@ -import { UserModificationRequest } from './UserModificationRequest'; +import {UserModificationRequest} from './UserModificationRequest'; export class PasswordChangeRequest extends UserModificationRequest { constructor( - id: number, - public oldPassword: string, - public newPassword: string + id: number, + public oldPassword: string, + public newPassword: string ) { super(id); } diff --git a/src/common/entities/PhotoDTO.ts b/src/common/entities/PhotoDTO.ts index 14cc5818..f95a10e8 100644 --- a/src/common/entities/PhotoDTO.ts +++ b/src/common/entities/PhotoDTO.ts @@ -1,5 +1,5 @@ -import { DirectoryPathDTO } from './DirectoryDTO'; -import { MediaDimension, MediaDTO, MediaMetadata } from './MediaDTO'; +import {DirectoryPathDTO} from './DirectoryDTO'; +import {MediaDimension, MediaDTO, MediaMetadata} from './MediaDTO'; export interface CoverPhotoDTO extends MediaDTO { name: string; diff --git a/src/common/entities/SearchQueryDTO.ts b/src/common/entities/SearchQueryDTO.ts index 18a61f15..148f9b55 100644 --- a/src/common/entities/SearchQueryDTO.ts +++ b/src/common/entities/SearchQueryDTO.ts @@ -61,21 +61,21 @@ export const MaxRangeSearchQueryTypes = [ ]; export const RangeSearchQueryTypes = MinRangeSearchQueryTypes.concat( - MaxRangeSearchQueryTypes + MaxRangeSearchQueryTypes ); export const MetadataSearchQueryTypes = [ SearchQueryTypes.distance, SearchQueryTypes.orientation, ] - .concat(RangeSearchQueryTypes) - .concat(TextSearchQueryTypes); + .concat(RangeSearchQueryTypes) + .concat(TextSearchQueryTypes); export const rangedTypePairs: any = {}; rangedTypePairs[SearchQueryTypes.from_date] = SearchQueryTypes.to_date; rangedTypePairs[SearchQueryTypes.min_rating] = SearchQueryTypes.max_rating; rangedTypePairs[SearchQueryTypes.min_resolution] = - SearchQueryTypes.max_resolution; + SearchQueryTypes.max_resolution; // add the other direction too for (const key of Object.keys(rangedTypePairs)) { rangedTypePairs[rangedTypePairs[key]] = key; @@ -98,19 +98,19 @@ export const SearchQueryDTOUtils = { case SearchQueryTypes.AND: query.type = SearchQueryTypes.OR; (query as SearchListQuery).list = (query as SearchListQuery).list.map( - (q) => SearchQueryDTOUtils.negate(q) + (q) => SearchQueryDTOUtils.negate(q) ); return query; case SearchQueryTypes.OR: query.type = SearchQueryTypes.AND; (query as SearchListQuery).list = (query as SearchListQuery).list.map( - (q) => SearchQueryDTOUtils.negate(q) + (q) => SearchQueryDTOUtils.negate(q) ); return query; case SearchQueryTypes.orientation: (query as OrientationSearch).landscape = !(query as OrientationSearch) - .landscape; + .landscape; return query; case SearchQueryTypes.from_date: @@ -128,7 +128,7 @@ export const SearchQueryDTOUtils = { case SearchQueryTypes.file_name: case SearchQueryTypes.directory: (query as NegatableSearchQuery).negate = !( - query as NegatableSearchQuery + query as NegatableSearchQuery ).negate; return query; @@ -171,13 +171,13 @@ export interface SomeOfSearchQuery extends SearchQueryDTO, SearchListQuery { export interface TextSearch extends NegatableSearchQuery { type: - | SearchQueryTypes.any_text - | SearchQueryTypes.person - | SearchQueryTypes.keyword - | SearchQueryTypes.position - | SearchQueryTypes.caption - | SearchQueryTypes.file_name - | SearchQueryTypes.directory; + | SearchQueryTypes.any_text + | SearchQueryTypes.person + | SearchQueryTypes.keyword + | SearchQueryTypes.position + | SearchQueryTypes.caption + | SearchQueryTypes.file_name + | SearchQueryTypes.directory; matchType?: TextSearchQueryMatchTypes; text: string; } diff --git a/src/common/entities/SearchResultDTO.ts b/src/common/entities/SearchResultDTO.ts index d0eede9e..28fba8cc 100644 --- a/src/common/entities/SearchResultDTO.ts +++ b/src/common/entities/SearchResultDTO.ts @@ -1,7 +1,7 @@ -import { SubDirectoryDTO } from './DirectoryDTO'; -import { FileDTO } from './FileDTO'; -import { MediaDTO } from './MediaDTO'; -import { SearchQueryDTO } from './SearchQueryDTO'; +import {SubDirectoryDTO} from './DirectoryDTO'; +import {FileDTO} from './FileDTO'; +import {MediaDTO} from './MediaDTO'; +import {SearchQueryDTO} from './SearchQueryDTO'; export interface SearchResultDTO { searchQuery: SearchQueryDTO; diff --git a/src/common/entities/SharingDTO.ts b/src/common/entities/SharingDTO.ts index 80f9750c..154cc09a 100644 --- a/src/common/entities/SharingDTO.ts +++ b/src/common/entities/SharingDTO.ts @@ -1,4 +1,4 @@ -import { UserDTO } from './UserDTO'; +import {UserDTO} from './UserDTO'; export interface SharingDTO { id: number; diff --git a/src/common/entities/UserDTO.ts b/src/common/entities/UserDTO.ts index 7c0cd7b5..790a9243 100644 --- a/src/common/entities/UserDTO.ts +++ b/src/common/entities/UserDTO.ts @@ -1,5 +1,5 @@ -import { DirectoryPathDTO } from './DirectoryDTO'; -import { Utils } from '../Utils'; +import {DirectoryPathDTO} from './DirectoryDTO'; +import {Utils} from '../Utils'; export enum UserRoles { LimitedGuest = 1, @@ -36,8 +36,8 @@ export const UserDTOUtils = { if (permission[permission.length - 1] === '*') { permission = permission.slice(0, -1); if ( - path.startsWith(permission) && - (!path[permission.length] || path[permission.length] === '/') + path.startsWith(permission) && + (!path[permission.length] || path[permission.length] === '/') ) { return true; } @@ -51,12 +51,12 @@ export const UserDTOUtils = { }, isDirectoryAvailable: ( - directory: DirectoryPathDTO, - permissions: string[] + directory: DirectoryPathDTO, + permissions: string[] ): boolean => { return UserDTOUtils.isDirectoryPathAvailable( - Utils.concatUrls(directory.path, directory.name), - permissions + Utils.concatUrls(directory.path, directory.name), + permissions ); }, }; diff --git a/src/common/entities/UserModificationRequest.ts b/src/common/entities/UserModificationRequest.ts index 8f25d123..3148c2f4 100644 --- a/src/common/entities/UserModificationRequest.ts +++ b/src/common/entities/UserModificationRequest.ts @@ -1,3 +1,4 @@ export class UserModificationRequest { - constructor(public id: number) {} + constructor(public id: number) { + } } diff --git a/src/common/entities/VideoDTO.ts b/src/common/entities/VideoDTO.ts index a74ff937..d9cefefc 100644 --- a/src/common/entities/VideoDTO.ts +++ b/src/common/entities/VideoDTO.ts @@ -1,5 +1,5 @@ -import { DirectoryPathDTO } from './DirectoryDTO'; -import { MediaDimension, MediaDTO, MediaMetadata } from './MediaDTO'; +import {DirectoryPathDTO} from './DirectoryDTO'; +import {MediaDimension, MediaDTO, MediaMetadata} from './MediaDTO'; export interface VideoDTO extends MediaDTO { id: number; diff --git a/src/common/entities/album/AlbumBaseDTO.ts b/src/common/entities/album/AlbumBaseDTO.ts index a51da555..a3263af2 100644 --- a/src/common/entities/album/AlbumBaseDTO.ts +++ b/src/common/entities/album/AlbumBaseDTO.ts @@ -1,4 +1,4 @@ -import { CoverPhotoDTO } from '../PhotoDTO'; +import {CoverPhotoDTO} from '../PhotoDTO'; export interface AlbumBaseDTO { id: number; diff --git a/src/common/entities/album/SavedSearchDTO.ts b/src/common/entities/album/SavedSearchDTO.ts index 6f835b7f..ed2d6de4 100644 --- a/src/common/entities/album/SavedSearchDTO.ts +++ b/src/common/entities/album/SavedSearchDTO.ts @@ -1,6 +1,6 @@ -import { AlbumBaseDTO } from './AlbumBaseDTO'; -import { CoverPhotoDTO } from '../PhotoDTO'; -import { SearchQueryDTO } from '../SearchQueryDTO'; +import {AlbumBaseDTO} from './AlbumBaseDTO'; +import {CoverPhotoDTO} from '../PhotoDTO'; +import {SearchQueryDTO} from '../SearchQueryDTO'; export interface SavedSearchDTO extends AlbumBaseDTO { id: number; diff --git a/src/common/entities/job/JobScheduleDTO.ts b/src/common/entities/job/JobScheduleDTO.ts index 6026d587..047f6d77 100644 --- a/src/common/entities/job/JobScheduleDTO.ts +++ b/src/common/entities/job/JobScheduleDTO.ts @@ -38,17 +38,17 @@ export interface JobScheduleDTO { config: Record; allowParallelRun: boolean; trigger: - | NeverJobTrigger - | ScheduledJobTrigger - | PeriodicJobTrigger - | AfterJobTrigger; + | NeverJobTrigger + | ScheduledJobTrigger + | PeriodicJobTrigger + | AfterJobTrigger; } export const JobScheduleDTOUtils = { getNextDayOfTheWeek: (refDate: Date, dayOfWeek: number): Date => { const date = new Date(refDate); date.setDate( - refDate.getDate() + ((dayOfWeek + 1 + 7 - refDate.getDay()) % 7) + refDate.getDate() + ((dayOfWeek + 1 + 7 - refDate.getDay()) % 7) ); if (date.getDay() === refDate.getDay()) { return new Date(refDate); @@ -61,8 +61,8 @@ export const JobScheduleDTOUtils = { date.setUTCSeconds(0); date.setUTCMilliseconds(0); if ( - date.getUTCHours() < h || - (date.getUTCHours() === h && date.getUTCMinutes() < m) + date.getUTCHours() < h || + (date.getUTCHours() === h && date.getUTCMinutes() < m) ) { date.setUTCHours(h); date.setUTCMinutes(m); @@ -86,23 +86,23 @@ export const JobScheduleDTOUtils = { if (schedule.trigger.periodicity <= 6) { // Between Monday and Sunday const nextRunDate = JobScheduleDTOUtils.getNextDayOfTheWeek( - refDate, - schedule.trigger.periodicity + refDate, + schedule.trigger.periodicity ); return JobScheduleDTOUtils.nextValidDate( - nextRunDate, - hour, - minute, - 7 * 24 * 60 * 60 * 1000 + nextRunDate, + hour, + minute, + 7 * 24 * 60 * 60 * 1000 ); } // every day return JobScheduleDTOUtils.nextValidDate( - new Date(refDate), - hour, - minute, - 24 * 60 * 60 * 1000 + new Date(refDate), + hour, + minute, + 24 * 60 * 60 * 1000 ); } return null; diff --git a/src/common/event/EventLimit.ts b/src/common/event/EventLimit.ts index 54ce3b2a..81adde11 100644 --- a/src/common/event/EventLimit.ts +++ b/src/common/event/EventLimit.ts @@ -19,7 +19,7 @@ export class EventLimit { public off(limit: T, handler: (data?: T) => void): void { this.handlers = this.handlers.filter( - (h) => h.handler !== handler && h.limit !== limit + (h) => h.handler !== handler && h.limit !== limit ); } @@ -31,8 +31,8 @@ export class EventLimit { if (this.handlers) { this.handlers.slice(0).forEach((h) => { if ( - h.limit <= data && - (h.lastTriggerValue < h.limit || h.lastTriggerValue == null) + h.limit <= data && + (h.lastTriggerValue < h.limit || h.lastTriggerValue == null) ) { h.fire(data); } @@ -47,7 +47,8 @@ export class EventLimit { class EventLimitHandler { public lastTriggerValue: T = null; - constructor(public limit: T, public handler: (data?: T) => void) {} + constructor(public limit: T, public handler: (data?: T) => void) { + } public fire(data?: T): void { this.handler(data); diff --git a/src/frontend/app/model/backendtext.service.spec.ts b/src/frontend/app/model/backendtext.service.spec.ts index c95c1fae..8006e735 100644 --- a/src/frontend/app/model/backendtext.service.spec.ts +++ b/src/frontend/app/model/backendtext.service.spec.ts @@ -10,18 +10,18 @@ describe('BackendTextService', () => { }); it('should have valid text for all keys', inject( - [BackendtextService], - (backendTextService: BackendtextService) => { - const getTexts = (obj: any) => { - for (const key of Object.keys(obj)) { - if (typeof obj[key] === 'object') { - getTexts(obj[key]); - continue; + [BackendtextService], + (backendTextService: BackendtextService) => { + const getTexts = (obj: any) => { + for (const key of Object.keys(obj)) { + if (typeof obj[key] === 'object') { + getTexts(obj[key]); + continue; + } + expect(backendTextService.get(obj[key])).not.toEqual(null, 'Error for key: ' + obj[key] + ', ' + key); } - expect(backendTextService.get(obj[key])).not.toEqual(null, 'Error for key: ' + obj[key] +', ' + key); - } - }; - getTexts(backendTexts); - } + }; + getTexts(backendTexts); + } )); }); diff --git a/src/frontend/app/model/backendtext.service.ts b/src/frontend/app/model/backendtext.service.ts index 363aa723..46a2fadf 100644 --- a/src/frontend/app/model/backendtext.service.ts +++ b/src/frontend/app/model/backendtext.service.ts @@ -1,6 +1,6 @@ -import { Injectable } from '@angular/core'; -import { backendText, backendTexts } from '../../../common/BackendTexts'; -import { DefaultsJobs } from '../../../common/entities/job/JobDTO'; +import {Injectable} from '@angular/core'; +import {backendText, backendTexts} from '../../../common/BackendTexts'; +import {DefaultsJobs} from '../../../common/entities/job/JobDTO'; @Injectable() export class BackendtextService { diff --git a/src/frontend/app/model/navigation.service.ts b/src/frontend/app/model/navigation.service.ts index 390ae60b..e1ef2e6b 100644 --- a/src/frontend/app/model/navigation.service.ts +++ b/src/frontend/app/model/navigation.service.ts @@ -12,10 +12,10 @@ export class NavigationService { public isLoginPage(): boolean { return ( - this.router.isActive('login', - {paths: 'exact', queryParams: 'exact', fragment: 'ignored', matrixParams: 'ignored'} as IsActiveMatchOptions) || - this.router.isActive('shareLogin', - {paths: 'exact', queryParams: 'ignored', fragment: 'ignored', matrixParams: 'ignored'} as IsActiveMatchOptions) + this.router.isActive('login', + {paths: 'exact', queryParams: 'exact', fragment: 'ignored', matrixParams: 'ignored'} as IsActiveMatchOptions) || + this.router.isActive('shareLogin', + {paths: 'exact', queryParams: 'ignored', fragment: 'ignored', matrixParams: 'ignored'} as IsActiveMatchOptions) ); } diff --git a/src/frontend/app/model/network/autehentication.service.spec.ts b/src/frontend/app/model/network/autehentication.service.spec.ts index 702e7bc8..9f45d73b 100644 --- a/src/frontend/app/model/network/autehentication.service.spec.ts +++ b/src/frontend/app/model/network/autehentication.service.spec.ts @@ -1,16 +1,16 @@ -import { inject, TestBed } from '@angular/core/testing'; -import { UserService } from './user.service'; -import { UserDTO } from '../../../../common/entities/UserDTO'; -import { LoginCredential } from '../../../../common/entities/LoginCredential'; -import { AuthenticationService } from './authentication.service'; -import { NetworkService } from './network.service'; -import { ErrorDTO } from '../../../../common/entities/Error'; -import { VersionService } from '../version.service'; -import { ShareService } from '../../ui/gallery/share.service'; +import {inject, TestBed} from '@angular/core/testing'; +import {UserService} from './user.service'; +import {UserDTO} from '../../../../common/entities/UserDTO'; +import {LoginCredential} from '../../../../common/entities/LoginCredential'; +import {AuthenticationService} from './authentication.service'; +import {NetworkService} from './network.service'; +import {ErrorDTO} from '../../../../common/entities/Error'; +import {VersionService} from '../version.service'; +import {ShareService} from '../../ui/gallery/share.service'; class MockUserService { public login(credential: LoginCredential): Promise { - return Promise.resolve({ name: 'testUserName' } as UserDTO); + return Promise.resolve({name: 'testUserName'} as UserDTO); } public async getSessionUser(): Promise { @@ -27,7 +27,7 @@ class MockNetworkService { class MockShareService { onNewUser(user: any): void { // mock fn - } + } } describe('AuthenticationService', () => { @@ -36,45 +36,45 @@ describe('AuthenticationService', () => { TestBed.configureTestingModule({ providers: [ VersionService, - { provide: NetworkService, useClass: MockNetworkService }, - { provide: UserService, useClass: MockUserService }, - { provide: ShareService, useClass: MockShareService }, + {provide: NetworkService, useClass: MockNetworkService}, + {provide: UserService, useClass: MockUserService}, + {provide: ShareService, useClass: MockShareService}, AuthenticationService, ], }); }); it('should call UserDTO service login', inject( - [AuthenticationService, UserService], - async (authService: AuthenticationService, userService: UserService) => { - spyOn(userService, 'login').and.callThrough(); + [AuthenticationService, UserService], + async (authService: AuthenticationService, userService: UserService) => { + spyOn(userService, 'login').and.callThrough(); - expect(userService.login).not.toHaveBeenCalled(); - await authService.login(null); - expect(userService.login).toHaveBeenCalled(); - } + expect(userService.login).not.toHaveBeenCalled(); + await authService.login(null); + expect(userService.login).toHaveBeenCalled(); + } )); it('should have NO Authenticated use', inject( - [AuthenticationService], - (authService: AuthenticationService) => { - expect(authService.user.value).toBe(null); - expect(authService.isAuthenticated()).toBe(false); - } + [AuthenticationService], + (authService: AuthenticationService) => { + expect(authService.user.value).toBe(null); + expect(authService.isAuthenticated()).toBe(false); + } )); it('should have Authenticated use', (done) => - inject([AuthenticationService], (authService: AuthenticationService) => { - spyOn(authService.user, 'next').and.callThrough(); - authService.user.subscribe((user) => { - if (user == null) { - return; - } - expect(authService.user.next).toHaveBeenCalled(); - expect(authService.user.value).not.toBe(null); - expect(authService.isAuthenticated()).toBe(true); - done(); - }); - authService.login({} as any); - })()); + inject([AuthenticationService], (authService: AuthenticationService) => { + spyOn(authService.user, 'next').and.callThrough(); + authService.user.subscribe((user) => { + if (user == null) { + return; + } + expect(authService.user.next).toHaveBeenCalled(); + expect(authService.user.value).not.toBe(null); + expect(authService.isAuthenticated()).toBe(true); + done(); + }); + authService.login({} as any); + })()); }); diff --git a/src/frontend/app/model/network/authentication.service.ts b/src/frontend/app/model/network/authentication.service.ts index 08f76c99..e45953e2 100644 --- a/src/frontend/app/model/network/authentication.service.ts +++ b/src/frontend/app/model/network/authentication.service.ts @@ -16,26 +16,26 @@ declare module ServerInject { export let user: UserDTO; } -@Injectable({ providedIn: 'root' }) +@Injectable({providedIn: 'root'}) export class AuthenticationService { public readonly user: BehaviorSubject; constructor( - private userService: UserService, - private networkService: NetworkService, - private shareService: ShareService, - private cookieService: CookieService + private userService: UserService, + private networkService: NetworkService, + private shareService: ShareService, + private cookieService: CookieService ) { this.user = new BehaviorSubject(null); // picking up session.. if ( - this.isAuthenticated() === false && - this.cookieService.get(CookieNames.session) != null + this.isAuthenticated() === false && + this.cookieService.get(CookieNames.session) != null ) { if ( - typeof ServerInject !== 'undefined' && - typeof ServerInject.user !== 'undefined' + typeof ServerInject !== 'undefined' && + typeof ServerInject.user !== 'undefined' ) { this.user.next(ServerInject.user); } diff --git a/src/frontend/app/model/network/helper/auth.guard.ts b/src/frontend/app/model/network/helper/auth.guard.ts index 99c9ad37..c8d5e0e7 100644 --- a/src/frontend/app/model/network/helper/auth.guard.ts +++ b/src/frontend/app/model/network/helper/auth.guard.ts @@ -1,22 +1,19 @@ -import { Injectable } from '@angular/core'; -import { - ActivatedRouteSnapshot, - CanActivate, - RouterStateSnapshot, -} from '@angular/router'; -import { AuthenticationService } from '../authentication.service'; -import { NavigationService } from '../../navigation.service'; +import {Injectable} from '@angular/core'; +import {ActivatedRouteSnapshot, CanActivate, RouterStateSnapshot,} from '@angular/router'; +import {AuthenticationService} from '../authentication.service'; +import {NavigationService} from '../../navigation.service'; -@Injectable({ providedIn: 'root' }) +@Injectable({providedIn: 'root'}) export class AuthGuard implements CanActivate { constructor( - private authenticationService: AuthenticationService, - private navigationService: NavigationService - ) {} + private authenticationService: AuthenticationService, + private navigationService: NavigationService + ) { + } canActivate( - route: ActivatedRouteSnapshot, - state: RouterStateSnapshot + route: ActivatedRouteSnapshot, + state: RouterStateSnapshot ): boolean { if (this.authenticationService.isAuthenticated() === true) { return true; diff --git a/src/frontend/app/model/network/helper/csrf.interceptor.ts b/src/frontend/app/model/network/helper/csrf.interceptor.ts index 3fe9b28b..a678fbf5 100644 --- a/src/frontend/app/model/network/helper/csrf.interceptor.ts +++ b/src/frontend/app/model/network/helper/csrf.interceptor.ts @@ -1,20 +1,16 @@ -import { Injectable } from '@angular/core'; -import { - HttpEvent, - HttpHandler, - HttpInterceptor, - HttpRequest, -} from '@angular/common/http'; -import { Observable } from 'rxjs'; -import { AuthenticationService } from '../authentication.service'; +import {Injectable} from '@angular/core'; +import {HttpEvent, HttpHandler, HttpInterceptor, HttpRequest,} from '@angular/common/http'; +import {Observable} from 'rxjs'; +import {AuthenticationService} from '../authentication.service'; @Injectable() export class CSRFInterceptor implements HttpInterceptor { - constructor(private authenticationService: AuthenticationService) {} + constructor(private authenticationService: AuthenticationService) { + } intercept( - request: HttpRequest, - next: HttpHandler + request: HttpRequest, + next: HttpHandler ): Observable> { // add authorization header with jwt token if available const currentUser = this.authenticationService.user.value; diff --git a/src/frontend/app/model/network/helper/error.interceptor.ts b/src/frontend/app/model/network/helper/error.interceptor.ts index beec1a85..fcd7ccb5 100644 --- a/src/frontend/app/model/network/helper/error.interceptor.ts +++ b/src/frontend/app/model/network/helper/error.interceptor.ts @@ -1,32 +1,28 @@ -import { Injectable } from '@angular/core'; -import { - HttpEvent, - HttpHandler, - HttpInterceptor, - HttpRequest, -} from '@angular/common/http'; -import { Observable, throwError } from 'rxjs'; -import { catchError } from 'rxjs/operators'; -import { AuthenticationService } from '../authentication.service'; +import {Injectable} from '@angular/core'; +import {HttpEvent, HttpHandler, HttpInterceptor, HttpRequest,} from '@angular/common/http'; +import {Observable, throwError} from 'rxjs'; +import {catchError} from 'rxjs/operators'; +import {AuthenticationService} from '../authentication.service'; @Injectable() export class ErrorInterceptor implements HttpInterceptor { - constructor(private authenticationService: AuthenticationService) {} + constructor(private authenticationService: AuthenticationService) { + } intercept( - request: HttpRequest, - next: HttpHandler + request: HttpRequest, + next: HttpHandler ): Observable> { return next.handle(request).pipe( - catchError((err) => { - if (err.status === 401) { - // auto logout if 401 response returned from api - this.authenticationService.logout(); - } + catchError((err) => { + if (err.status === 401) { + // auto logout if 401 response returned from api + this.authenticationService.logout(); + } - const error = err.error.message || err.statusText; - return throwError(error); - }) + const error = err.error.message || err.statusText; + return throwError(error); + }) ); } } diff --git a/src/frontend/app/model/network/network.service.spec.ts b/src/frontend/app/model/network/network.service.spec.ts index 0986ccfb..9635d9d1 100644 --- a/src/frontend/app/model/network/network.service.spec.ts +++ b/src/frontend/app/model/network/network.service.spec.ts @@ -1,8 +1,5 @@ import {getTestBed, inject, TestBed} from '@angular/core/testing'; -import { - HttpClientTestingModule, - HttpTestingController, -} from '@angular/common/http/testing'; +import {HttpClientTestingModule, HttpTestingController,} from '@angular/common/http/testing'; import {NetworkService} from './network.service'; import {Message} from '../../../../common/entities/Message'; import {LoadingBarService} from '@ngx-loading-bar/core'; @@ -31,99 +28,99 @@ describe('NetworkService Success tests', () => { }); it('should call GET', inject( - [NetworkService], - (networkService: NetworkService) => { - networkService - .getJson(testUrl) - .then((res: string) => { - expect(res).toBe(testResponse); - }) - .catch((err) => { - console.error(err); - expect(err).toBeUndefined(); - }); + [NetworkService], + (networkService: NetworkService) => { + networkService + .getJson(testUrl) + .then((res: string) => { + expect(res).toBe(testResponse); + }) + .catch((err) => { + console.error(err); + expect(err).toBeUndefined(); + }); - const mockReq = httpMock.expectOne({method: 'GET'}); - expect(mockReq.cancelled).toBeFalsy(); - expect(mockReq.request.responseType).toEqual('json'); - mockReq.flush(testResponseMessage); - } + const mockReq = httpMock.expectOne({method: 'GET'}); + expect(mockReq.cancelled).toBeFalsy(); + expect(mockReq.request.responseType).toEqual('json'); + mockReq.flush(testResponseMessage); + } )); it('should call POST', inject( - [NetworkService], - (networkService: NetworkService) => { - networkService - .postJson(testUrl, testData) - .then((res: string) => { - expect(res).toBe(testResponse); - }) - .catch((err) => { - console.error(err); - expect(err).toBeUndefined(); - }); + [NetworkService], + (networkService: NetworkService) => { + networkService + .postJson(testUrl, testData) + .then((res: string) => { + expect(res).toBe(testResponse); + }) + .catch((err) => { + console.error(err); + expect(err).toBeUndefined(); + }); - let mockReq = httpMock.expectOne(Config.Server.apiPath + testUrl); - expect(mockReq.cancelled).toBeFalsy(); - expect(mockReq.request.responseType).toEqual('json'); - mockReq.flush(testResponseMessage); - expect(mockReq.request.body).toBe(testData); + let mockReq = httpMock.expectOne(Config.Server.apiPath + testUrl); + expect(mockReq.cancelled).toBeFalsy(); + expect(mockReq.request.responseType).toEqual('json'); + mockReq.flush(testResponseMessage); + expect(mockReq.request.body).toBe(testData); - networkService - .postJson(testUrl) - .then((res: string) => { - expect(res).toBe(testResponse); - }) - .catch((err) => { - console.error(err); - expect(err).toBeUndefined(); - }); + networkService + .postJson(testUrl) + .then((res: string) => { + expect(res).toBe(testResponse); + }) + .catch((err) => { + console.error(err); + expect(err).toBeUndefined(); + }); - mockReq = httpMock.expectOne(Config.Server.apiPath + testUrl); - expect(mockReq.cancelled).toBeFalsy(); - expect(mockReq.request.responseType).toEqual('json'); - expect(mockReq.request.body).toEqual({}); - mockReq.flush(testResponseMessage); - } + mockReq = httpMock.expectOne(Config.Server.apiPath + testUrl); + expect(mockReq.cancelled).toBeFalsy(); + expect(mockReq.request.responseType).toEqual('json'); + expect(mockReq.request.body).toEqual({}); + mockReq.flush(testResponseMessage); + } )); it('should call DELETE', inject( - [NetworkService], - (networkService: NetworkService) => { - networkService.deleteJson(testUrl).then((res: any) => { - expect(res).toBe(testResponse); - }); + [NetworkService], + (networkService: NetworkService) => { + networkService.deleteJson(testUrl).then((res: any) => { + expect(res).toBe(testResponse); + }); - const mockReq = httpMock.expectOne({method: 'DELETE'}); - expect(mockReq.cancelled).toBeFalsy(); - expect(mockReq.request.responseType).toEqual('json'); - mockReq.flush(testResponseMessage); - } + const mockReq = httpMock.expectOne({method: 'DELETE'}); + expect(mockReq.cancelled).toBeFalsy(); + expect(mockReq.request.responseType).toEqual('json'); + mockReq.flush(testResponseMessage); + } )); it('should call PUT', inject( - [NetworkService], - (networkService: NetworkService) => { - networkService.putJson(testUrl, testData).then((res: any) => { - expect(res).toBe(testResponse); - }); + [NetworkService], + (networkService: NetworkService) => { + networkService.putJson(testUrl, testData).then((res: any) => { + expect(res).toBe(testResponse); + }); - let mockReq = httpMock.expectOne({}); - expect(mockReq.cancelled).toBeFalsy(); - expect(mockReq.request.responseType).toEqual('json'); - expect(mockReq.request.body).toEqual(testData); - mockReq.flush(testResponseMessage); + let mockReq = httpMock.expectOne({}); + expect(mockReq.cancelled).toBeFalsy(); + expect(mockReq.request.responseType).toEqual('json'); + expect(mockReq.request.body).toEqual(testData); + mockReq.flush(testResponseMessage); - networkService.putJson(testUrl).then((res: any) => { - expect(res).toBe(testResponse); - }); + networkService.putJson(testUrl).then((res: any) => { + expect(res).toBe(testResponse); + }); - mockReq = httpMock.expectOne({}); - expect(mockReq.cancelled).toBeFalsy(); - expect(mockReq.request.responseType).toEqual('json'); - expect(mockReq.request.body).toEqual({}); - mockReq.flush(testResponseMessage); - } + mockReq = httpMock.expectOne({}); + expect(mockReq.cancelled).toBeFalsy(); + expect(mockReq.request.responseType).toEqual('json'); + expect(mockReq.request.body).toEqual({}); + mockReq.flush(testResponseMessage); + } )); }); @@ -148,88 +145,88 @@ describe('NetworkService Fail tests', () => { }); it('should call GET with error', inject( - [NetworkService], - (networkService: NetworkService) => { - networkService - .getJson(testUrl) - .then((res: any) => { - expect(res).toBe(null); - }) - .catch((err) => { - expect(err).toBe( - `Http failure response for ${Config.Server.apiPath}/test/url: 0 ` + testError - ); - }); + [NetworkService], + (networkService: NetworkService) => { + networkService + .getJson(testUrl) + .then((res: any) => { + expect(res).toBe(null); + }) + .catch((err) => { + expect(err).toBe( + `Http failure response for ${Config.Server.apiPath}/test/url: 0 ` + testError + ); + }); - const mockReq = httpMock.expectOne({method: 'GET'}); - expect(mockReq.cancelled).toBeFalsy(); - expect(mockReq.request.responseType).toEqual('json'); - mockReq.error(null, {statusText: testError}); - } + const mockReq = httpMock.expectOne({method: 'GET'}); + expect(mockReq.cancelled).toBeFalsy(); + expect(mockReq.request.responseType).toEqual('json'); + mockReq.error(null, {statusText: testError}); + } )); it('should call POST with error', inject( - [NetworkService], - (networkService: NetworkService) => { - networkService - .postJson(testUrl, testData) - .then((res: any) => { - expect(res).toBe(null); - }) - .catch((err) => { - expect(err).toBe( - `Http failure response for ${Config.Server.apiPath}/test/url: 0 ` + testError - ); - }); + [NetworkService], + (networkService: NetworkService) => { + networkService + .postJson(testUrl, testData) + .then((res: any) => { + expect(res).toBe(null); + }) + .catch((err) => { + expect(err).toBe( + `Http failure response for ${Config.Server.apiPath}/test/url: 0 ` + testError + ); + }); - const mockReq = httpMock.expectOne({method: 'POST'}); - expect(mockReq.cancelled).toBeFalsy(); - expect(mockReq.request.responseType).toEqual('json'); - expect(mockReq.request.body).toEqual(testData); - mockReq.error(null, {statusText: testError}); - } + const mockReq = httpMock.expectOne({method: 'POST'}); + expect(mockReq.cancelled).toBeFalsy(); + expect(mockReq.request.responseType).toEqual('json'); + expect(mockReq.request.body).toEqual(testData); + mockReq.error(null, {statusText: testError}); + } )); it('should call PUT with error', inject( - [NetworkService], - (networkService: NetworkService) => { - networkService - .putJson(testUrl, testData) - .then((res: any) => { - expect(res).toBe(null); - }) - .catch((err) => { - expect(err).toBe( - `Http failure response for ${Config.Server.apiPath}/test/url: 0 ` + testError - ); - }); + [NetworkService], + (networkService: NetworkService) => { + networkService + .putJson(testUrl, testData) + .then((res: any) => { + expect(res).toBe(null); + }) + .catch((err) => { + expect(err).toBe( + `Http failure response for ${Config.Server.apiPath}/test/url: 0 ` + testError + ); + }); - const mockReq = httpMock.expectOne({method: 'PUT'}); - expect(mockReq.cancelled).toBeFalsy(); - expect(mockReq.request.responseType).toEqual('json'); - expect(mockReq.request.body).toEqual(testData); - mockReq.error(null, {statusText: testError}); - } + const mockReq = httpMock.expectOne({method: 'PUT'}); + expect(mockReq.cancelled).toBeFalsy(); + expect(mockReq.request.responseType).toEqual('json'); + expect(mockReq.request.body).toEqual(testData); + mockReq.error(null, {statusText: testError}); + } )); it('should call DELETE with error', inject( - [NetworkService], - (networkService: NetworkService) => { - networkService - .deleteJson(testUrl) - .then((res: any) => { - expect(res).toBe(null); - }) - .catch((err) => { - expect(err).toBe( - `Http failure response for ${Config.Server.apiPath}/test/url: 0 ` + testError - ); - }); + [NetworkService], + (networkService: NetworkService) => { + networkService + .deleteJson(testUrl) + .then((res: any) => { + expect(res).toBe(null); + }) + .catch((err) => { + expect(err).toBe( + `Http failure response for ${Config.Server.apiPath}/test/url: 0 ` + testError + ); + }); - const mockReq = httpMock.expectOne({method: 'DELETE'}); - expect(mockReq.cancelled).toBeFalsy(); - expect(mockReq.request.responseType).toEqual('json'); - mockReq.error(null, {statusText: testError}); - } + const mockReq = httpMock.expectOne({method: 'DELETE'}); + expect(mockReq.cancelled).toBeFalsy(); + expect(mockReq.request.responseType).toEqual('json'); + mockReq.error(null, {statusText: testError}); + } )); }); diff --git a/src/frontend/app/model/network/network.service.ts b/src/frontend/app/model/network/network.service.ts index 8b9fc6b1..5eeb6e55 100644 --- a/src/frontend/app/model/network/network.service.ts +++ b/src/frontend/app/model/network/network.service.ts @@ -14,9 +14,9 @@ export class NetworkService { private globalErrorHandlers: Array<(error: ErrorDTO) => boolean> = []; constructor( - private http: HttpClient, - private loadingBarService: LoadingBarService, - private versionService: VersionService + private http: HttpClient, + private loadingBarService: LoadingBarService, + private versionService: VersionService ) { } @@ -51,10 +51,10 @@ export class NetworkService { }; return this.http - .get(this.apiBaseUrl + url, {responseType: 'text'}) - .toPromise() - .then(process) - .catch(err); + .get(this.apiBaseUrl + url, {responseType: 'text'}) + .toPromise() + .then(process) + .catch(err); } public getText(url: string): Promise { @@ -71,10 +71,10 @@ export class NetworkService { }; return this.http - .get(this.apiBaseUrl + url, {responseType: 'text'}) - .toPromise() - .then(process) - .catch(err); + .get(this.apiBaseUrl + url, {responseType: 'text'}) + .toPromise() + .then(process) + .catch(err); } public postJson(url: string, data = {}): Promise { @@ -98,9 +98,9 @@ export class NetworkService { } private callJson( - method: 'get' | 'post' | 'delete' | 'put', - url: string, - data = {} + method: 'get' | 'post' | 'delete' | 'put', + url: string, + data = {} ): Promise { const body = data; @@ -111,7 +111,7 @@ export class NetworkService { const msg = res.body; if (res.headers.has(CustomHeaders.dataVersion)) { this.versionService.onNewVersion( - res.headers.get(CustomHeaders.dataVersion) + res.headers.get(CustomHeaders.dataVersion) ); } if (msg.error) { @@ -131,30 +131,30 @@ export class NetworkService { switch (method) { case 'get': return this.http - .get>(this.apiBaseUrl + url, {observe: 'response'}) - .toPromise() - .then(process) - .catch(err); + .get>(this.apiBaseUrl + url, {observe: 'response'}) + .toPromise() + .then(process) + .catch(err); case 'delete': return this.http - .delete>(this.apiBaseUrl + url, {observe: 'response'}) - .toPromise() - .then(process) - .catch(err); + .delete>(this.apiBaseUrl + url, {observe: 'response'}) + .toPromise() + .then(process) + .catch(err); case 'post': return this.http - .post>(this.apiBaseUrl + url, body, { - observe: 'response', - }) - .toPromise() - .then(process) - .catch(err); + .post>(this.apiBaseUrl + url, body, { + observe: 'response', + }) + .toPromise() + .then(process) + .catch(err); case 'put': return this.http - .put>(this.apiBaseUrl + url, body, {observe: 'response'}) - .toPromise() - .then(process) - .catch(err); + .put>(this.apiBaseUrl + url, body, {observe: 'response'}) + .toPromise() + .then(process) + .catch(err); default: throw new Error('Unknown method'); } diff --git a/src/frontend/app/model/network/user.service.spec.ts b/src/frontend/app/model/network/user.service.spec.ts index 5e218c5f..1aa53594 100644 --- a/src/frontend/app/model/network/user.service.spec.ts +++ b/src/frontend/app/model/network/user.service.spec.ts @@ -32,35 +32,35 @@ describe('UserService', (): void => { }); it('should call postJson at login', inject( - [UserService, NetworkService], - async ( - userService: UserService, - networkService: NetworkService - ): Promise => { - spyOn(networkService, 'postJson'); - const credential = new LoginCredential('name', 'pass'); - await userService.login(credential); - expect(networkService.postJson).toHaveBeenCalled(); - expect((networkService.postJson as any).calls.argsFor(0)).toEqual([ - '/user/login', - {loginCredential: credential}, - ]); - } + [UserService, NetworkService], + async ( + userService: UserService, + networkService: NetworkService + ): Promise => { + spyOn(networkService, 'postJson'); + const credential = new LoginCredential('name', 'pass'); + await userService.login(credential); + expect(networkService.postJson).toHaveBeenCalled(); + expect((networkService.postJson as any).calls.argsFor(0)).toEqual([ + '/user/login', + {loginCredential: credential}, + ]); + } )); it('should call getJson at getSessionUser', inject( - [UserService, NetworkService], - async ( - userService: UserService, - networkService: NetworkService - ): Promise => { - spyOn(networkService, 'getJson'); - await userService.getSessionUser(); - expect(networkService.getJson).toHaveBeenCalled(); - expect((networkService.getJson as any).calls.argsFor(0)).toEqual([ - '/user/me', - ]); - } + [UserService, NetworkService], + async ( + userService: UserService, + networkService: NetworkService + ): Promise => { + spyOn(networkService, 'getJson'); + await userService.getSessionUser(); + expect(networkService.getJson).toHaveBeenCalled(); + expect((networkService.getJson as any).calls.argsFor(0)).toEqual([ + '/user/me', + ]); + } )); }); diff --git a/src/frontend/app/model/network/user.service.ts b/src/frontend/app/model/network/user.service.ts index 0cdc2149..6f3b92cd 100644 --- a/src/frontend/app/model/network/user.service.ts +++ b/src/frontend/app/model/network/user.service.ts @@ -9,8 +9,8 @@ import {QueryParams} from '../../../../common/QueryParams'; @Injectable() export class UserService { constructor( - private networkService: NetworkService, - private shareService: ShareService + private networkService: NetworkService, + private shareService: ShareService ) { } @@ -26,11 +26,11 @@ export class UserService { public async shareLogin(password: string): Promise { return this.networkService.postJson( - '/share/login?' + - QueryParams.gallery.sharingKey_query + - '=' + - this.shareService.getSharingKey(), - {password} + '/share/login?' + + QueryParams.gallery.sharingKey_query + + '=' + + this.shareService.getSharingKey(), + {password} ); } @@ -40,7 +40,7 @@ export class UserService { if (this.shareService.isSharing()) { const query: any = {}; query[QueryParams.gallery.sharingKey_query] = - this.shareService.getSharingKey(); + this.shareService.getSharingKey(); return this.networkService.getJson('/user/me', query); } } diff --git a/src/frontend/app/model/notification.service.ts b/src/frontend/app/model/notification.service.ts index 31015333..11dbe67d 100644 --- a/src/frontend/app/model/notification.service.ts +++ b/src/frontend/app/model/notification.service.ts @@ -1,12 +1,9 @@ -import { Injectable } from '@angular/core'; -import { ToastrService } from 'ngx-toastr'; -import { NetworkService } from './network/network.service'; -import { AuthenticationService } from './network/authentication.service'; -import { - NotificationDTO, - NotificationType, -} from '../../../common/entities/NotificationDTO'; -import { UserDTO, UserRoles } from '../../../common/entities/UserDTO'; +import {Injectable} from '@angular/core'; +import {ToastrService} from 'ngx-toastr'; +import {NetworkService} from './network/network.service'; +import {AuthenticationService} from './network/authentication.service'; +import {NotificationDTO, NotificationType,} from '../../../common/entities/NotificationDTO'; +import {UserDTO, UserRoles} from '../../../common/entities/UserDTO'; export interface CountedNotificationDTO extends NotificationDTO { count: number; @@ -23,16 +20,16 @@ export class NotificationService { lastUser: UserDTO = null; constructor( - private toastr: ToastrService, - private networkService: NetworkService, - private authService: AuthenticationService + private toastr: ToastrService, + private networkService: NetworkService, + private authService: AuthenticationService ) { this.authService.user.subscribe(() => { if ( - this.authService.isAuthenticated() && - (!this.lastUser || - this.lastUser.id !== this.authService.user.value.id) && - this.authService.user.value.role >= UserRoles.Guest + this.authService.isAuthenticated() && + (!this.lastUser || + this.lastUser.id !== this.authService.user.value.id) && + this.authService.user.value.role >= UserRoles.Guest ) { this.getServerNotifications(); } @@ -53,16 +50,16 @@ export class NotificationService { if (n.details) { key += JSON.stringify(n.details); } - groups[key] = groups[key] || { notification: n, count: 0 }; + groups[key] = groups[key] || {notification: n, count: 0}; groups[key].count++; }); this.numberOfNotifications = notifications.length; this.countedNotifications = []; for (const key of Object.keys(groups)) { (groups[key].notification as CountedNotificationDTO).count = - groups[key].count; + groups[key].count; this.countedNotifications.push( - groups[key].notification as CountedNotificationDTO + groups[key].notification as CountedNotificationDTO ); } } @@ -70,9 +67,9 @@ export class NotificationService { async getServerNotifications(): Promise { try { this.groupNotifications( - (await this.networkService.getJson( - '/notifications' - )) || [] + (await this.networkService.getJson( + '/notifications' + )) || [] ); this.countedNotifications.forEach((noti) => { let msg = '(' + noti.count + ') ' + noti.message; diff --git a/src/frontend/app/model/page.helper.ts b/src/frontend/app/model/page.helper.ts index 6fd55005..ffd42a3c 100644 --- a/src/frontend/app/model/page.helper.ts +++ b/src/frontend/app/model/page.helper.ts @@ -1,16 +1,16 @@ export class PageHelper { private static readonly supportPageOffset = window.pageXOffset !== undefined; private static readonly isCSS1Compat = - (document.compatMode || '') === 'CSS1Compat'; + (document.compatMode || '') === 'CSS1Compat'; private static readonly body = document.getElementsByTagName('body')[0]; public static get ScrollY(): number { return this.supportPageOffset - ? window.pageYOffset - : this.isCSS1Compat - ? document.documentElement.scrollTop - : document.body.scrollTop; + ? window.pageYOffset + : this.isCSS1Compat + ? document.documentElement.scrollTop + : document.body.scrollTop; } public static set ScrollY(value: number) { @@ -19,22 +19,22 @@ export class PageHelper { public static get MaxScrollY(): number { return ( - Math.max( - document.body.scrollHeight, - document.body.offsetHeight, - document.documentElement.clientHeight, - document.documentElement.scrollHeight, - document.documentElement.offsetHeight - ) - window.innerHeight + Math.max( + document.body.scrollHeight, + document.body.offsetHeight, + document.documentElement.clientHeight, + document.documentElement.scrollHeight, + document.documentElement.offsetHeight + ) - window.innerHeight ); } public static get ScrollX(): number { return this.supportPageOffset - ? window.pageXOffset - : this.isCSS1Compat - ? document.documentElement.scrollLeft - : document.body.scrollLeft; + ? window.pageXOffset + : this.isCSS1Compat + ? document.documentElement.scrollLeft + : document.body.scrollLeft; } public static showScrollY(): void { @@ -43,7 +43,7 @@ export class PageHelper { public static isScrollYVisible(): boolean { return PageHelper.body.style.overflowY === 'scroll' || - (!PageHelper.body.style.overflowY && document.documentElement.scrollHeight > document.documentElement.clientHeight); + (!PageHelper.body.style.overflowY && document.documentElement.scrollHeight > document.documentElement.clientHeight); } public static hideScrollY(): void { diff --git a/src/frontend/app/model/pi-title.service.ts b/src/frontend/app/model/pi-title.service.ts index 345c3604..65dbb978 100644 --- a/src/frontend/app/model/pi-title.service.ts +++ b/src/frontend/app/model/pi-title.service.ts @@ -13,8 +13,8 @@ export class PiTitleService { private lastNonMedia: string = null; constructor( - private titleService: Title, - private searchQueryParserService: SearchQueryParserService) { + private titleService: Title, + private searchQueryParserService: SearchQueryParserService) { } setTitle(title: string) { diff --git a/src/frontend/app/model/query.service.ts b/src/frontend/app/model/query.service.ts index 53aaf199..9a71f1e8 100644 --- a/src/frontend/app/model/query.service.ts +++ b/src/frontend/app/model/query.service.ts @@ -10,17 +10,17 @@ import {ContentLoaderService} from '../ui/gallery/contentLoader.service'; @Injectable() export class QueryService { constructor( - private shareService: ShareService, - private galleryService: ContentLoaderService + private shareService: ShareService, + private galleryService: ContentLoaderService ) { } getMediaStringId(media: MediaDTO): string { if (this.galleryService.isSearchResult()) { return Utils.concatUrls( - media.directory.path, - media.directory.name, - media.name + media.directory.path, + media.directory.name, + media.name ); } else { return media.name; @@ -35,7 +35,7 @@ export class QueryService { if (Config.Sharing.enabled === true) { if (this.shareService.isSharing()) { query[QueryParams.gallery.sharingKey_query] = - this.shareService.getSharingKey(); + this.shareService.getSharingKey(); } } return query; @@ -48,14 +48,14 @@ export class QueryService { if (Config.Sharing.enabled === true) { if (this.shareService.isSharing()) { params[QueryParams.gallery.sharingKey_query] = - this.shareService.getSharingKey(); + this.shareService.getSharingKey(); } } if ( - directory && - directory.lastModified && - directory.lastScanned && - !directory.isPartial + directory && + directory.lastModified && + directory.lastScanned && + !directory.isPartial ) { params[QueryParams.gallery.knownLastModified] = directory.lastModified; params[QueryParams.gallery.knownLastScanned] = directory.lastScanned; diff --git a/src/frontend/app/model/seededRandom.service.ts b/src/frontend/app/model/seededRandom.service.ts index 678ba226..b6b96ca0 100644 --- a/src/frontend/app/model/seededRandom.service.ts +++ b/src/frontend/app/model/seededRandom.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import {Injectable} from '@angular/core'; @Injectable() export class SeededRandomService { diff --git a/src/frontend/app/model/theme.service.ts b/src/frontend/app/model/theme.service.ts index 51742eb5..bb2909c6 100644 --- a/src/frontend/app/model/theme.service.ts +++ b/src/frontend/app/model/theme.service.ts @@ -24,8 +24,8 @@ export class ThemeService { this.setMode(Config.Gallery.Themes.defaultMode); } this.darkMode.subscribe((darkMode: boolean) => { - this.applyMode(darkMode); - } + this.applyMode(darkMode); + } ); } diff --git a/src/frontend/app/model/version.service.ts b/src/frontend/app/model/version.service.ts index 223990b4..1a831b2b 100644 --- a/src/frontend/app/model/version.service.ts +++ b/src/frontend/app/model/version.service.ts @@ -1,5 +1,5 @@ -import { Injectable } from '@angular/core'; -import { BehaviorSubject } from 'rxjs'; +import {Injectable} from '@angular/core'; +import {BehaviorSubject} from 'rxjs'; @Injectable() export class VersionService { diff --git a/src/frontend/app/pipes/DurationPipe.ts b/src/frontend/app/pipes/DurationPipe.ts index 2099782e..2e026154 100644 --- a/src/frontend/app/pipes/DurationPipe.ts +++ b/src/frontend/app/pipes/DurationPipe.ts @@ -1,6 +1,6 @@ -import { Pipe, PipeTransform } from '@angular/core'; +import {Pipe, PipeTransform} from '@angular/core'; -@Pipe({ name: 'duration' }) +@Pipe({name: 'duration'}) export class DurationPipe implements PipeTransform { transform(time: number, separator: ':' | 'string' = 'string'): string { @@ -12,7 +12,7 @@ export class DurationPipe implements PipeTransform { if (separator === ':') { const leftPad = (x: any): string => - String(x).length >= 2 ? x : leftPad(`0${x}`); + String(x).length >= 2 ? x : leftPad(`0${x}`); return [h || 0, m || 0, s || 0].map(leftPad).join(':'); } let str = ''; diff --git a/src/frontend/app/pipes/FileDTOToPathPipe.ts b/src/frontend/app/pipes/FileDTOToPathPipe.ts index 857a84b7..fa49438c 100644 --- a/src/frontend/app/pipes/FileDTOToPathPipe.ts +++ b/src/frontend/app/pipes/FileDTOToPathPipe.ts @@ -1,18 +1,18 @@ -import { Pipe, PipeTransform } from '@angular/core'; -import { FileDTO } from '../../../common/entities/FileDTO'; -import { Utils } from '../../../common/Utils'; +import {Pipe, PipeTransform} from '@angular/core'; +import {FileDTO} from '../../../common/entities/FileDTO'; +import {Utils} from '../../../common/Utils'; -@Pipe({ name: 'toPath' }) +@Pipe({name: 'toPath'}) export class FileDTOToPathPipe implements PipeTransform { transform(metaFile: FileDTO): string | null { if (!metaFile) { return null; } return Utils.concatUrls( - 'api/gallery/content/', - metaFile.directory.path, - metaFile.directory.name, - metaFile.name + 'api/gallery/content/', + metaFile.directory.path, + metaFile.directory.name, + metaFile.name ); } } diff --git a/src/frontend/app/pipes/FileDTOToRelativePathPipe.ts b/src/frontend/app/pipes/FileDTOToRelativePathPipe.ts index 1298b6ec..1ff6a83b 100644 --- a/src/frontend/app/pipes/FileDTOToRelativePathPipe.ts +++ b/src/frontend/app/pipes/FileDTOToRelativePathPipe.ts @@ -1,17 +1,17 @@ -import { Pipe, PipeTransform } from '@angular/core'; -import { FileDTO } from '../../../common/entities/FileDTO'; -import { Utils } from '../../../common/Utils'; +import {Pipe, PipeTransform} from '@angular/core'; +import {FileDTO} from '../../../common/entities/FileDTO'; +import {Utils} from '../../../common/Utils'; -@Pipe({ name: 'toRelativePath' }) +@Pipe({name: 'toRelativePath'}) export class FileDTOToRelativePathPipe implements PipeTransform { transform(metaFile: FileDTO): string | null { if (!metaFile) { return null; } return Utils.concatUrls( - metaFile.directory.path, - metaFile.directory.name, - metaFile.name + metaFile.directory.path, + metaFile.directory.name, + metaFile.name ); } } diff --git a/src/frontend/app/pipes/FileSizePipe.ts b/src/frontend/app/pipes/FileSizePipe.ts index 5ed0c104..6c304b03 100644 --- a/src/frontend/app/pipes/FileSizePipe.ts +++ b/src/frontend/app/pipes/FileSizePipe.ts @@ -1,6 +1,6 @@ -import { Pipe, PipeTransform } from '@angular/core'; +import {Pipe, PipeTransform} from '@angular/core'; -@Pipe({ name: 'fileSize' }) +@Pipe({name: 'fileSize'}) export class FileSizePipe implements PipeTransform { transform(size: number): string { const postFixes = ['B', 'KB', 'MB', 'GB', 'TB']; diff --git a/src/frontend/app/pipes/GPXFilesFilterPipe.ts b/src/frontend/app/pipes/GPXFilesFilterPipe.ts index 4e6cdee0..b10a2264 100644 --- a/src/frontend/app/pipes/GPXFilesFilterPipe.ts +++ b/src/frontend/app/pipes/GPXFilesFilterPipe.ts @@ -1,8 +1,8 @@ -import { Pipe, PipeTransform } from '@angular/core'; -import { FileDTO } from '../../../common/entities/FileDTO'; -import { Config } from '../../../common/config/public/Config'; +import {Pipe, PipeTransform} from '@angular/core'; +import {FileDTO} from '../../../common/entities/FileDTO'; +import {Config} from '../../../common/config/public/Config'; -@Pipe({ name: 'gpxFiles' }) +@Pipe({name: 'gpxFiles'}) export class GPXFilesFilterPipe implements PipeTransform { transform(metaFiles: FileDTO[]): FileDTO[] | null { if (!Config.MetaFile.gpx) { @@ -12,7 +12,7 @@ export class GPXFilesFilterPipe implements PipeTransform { return null; } return metaFiles.filter((f: FileDTO): boolean => - f.name.toLocaleLowerCase().endsWith('.gpx') + f.name.toLocaleLowerCase().endsWith('.gpx') ); } } diff --git a/src/frontend/app/pipes/MDFilesFilterPipe.ts b/src/frontend/app/pipes/MDFilesFilterPipe.ts index c0698134..17afc00b 100644 --- a/src/frontend/app/pipes/MDFilesFilterPipe.ts +++ b/src/frontend/app/pipes/MDFilesFilterPipe.ts @@ -1,15 +1,15 @@ -import { Pipe, PipeTransform } from '@angular/core'; -import { FileDTO } from '../../../common/entities/FileDTO'; -import { MDFileDTO } from '../../../common/entities/MDFileDTO'; +import {Pipe, PipeTransform} from '@angular/core'; +import {FileDTO} from '../../../common/entities/FileDTO'; +import {MDFileDTO} from '../../../common/entities/MDFileDTO'; -@Pipe({ name: 'mdFiles' }) +@Pipe({name: 'mdFiles'}) export class MDFilesFilterPipe implements PipeTransform { transform(metaFiles: FileDTO[]): MDFileDTO[] | null { if (!metaFiles) { return null; } return metaFiles.filter((f: FileDTO): boolean => - f.name.toLocaleLowerCase().endsWith('.md') + f.name.toLocaleLowerCase().endsWith('.md') ) as MDFileDTO[]; } } diff --git a/src/frontend/app/pipes/PhotoFilterPipe.ts b/src/frontend/app/pipes/PhotoFilterPipe.ts index 6d5426e1..a0827695 100644 --- a/src/frontend/app/pipes/PhotoFilterPipe.ts +++ b/src/frontend/app/pipes/PhotoFilterPipe.ts @@ -1,19 +1,19 @@ -import { Pipe, PipeTransform } from '@angular/core'; -import { MediaDTO, MediaDTOUtils } from '../../../common/entities/MediaDTO'; -import { PhotoDTO } from '../../../common/entities/PhotoDTO'; +import {Pipe, PipeTransform} from '@angular/core'; +import {MediaDTO, MediaDTOUtils} from '../../../common/entities/MediaDTO'; +import {PhotoDTO} from '../../../common/entities/PhotoDTO'; import {MediaGroup} from '../ui/gallery/navigator/sorting.service'; -@Pipe({ name: 'photosOnly' }) +@Pipe({name: 'photosOnly'}) export class PhotoFilterPipe implements PipeTransform { transform(mediaGroups: MediaGroup[]): PhotoDTO[] | null { if (!mediaGroups) { return null; } const ret = []; - for(let i = 0; i < mediaGroups.length; ++i){ + for (let i = 0; i < mediaGroups.length; ++i) { ret.push(...mediaGroups[i].media.filter((m: MediaDTO): boolean => - MediaDTOUtils.isPhoto(m) - ) as PhotoDTO[]) + MediaDTOUtils.isPhoto(m) + ) as PhotoDTO[]); } return ret; } diff --git a/src/frontend/app/pipes/SafeHTMLPipe.ts b/src/frontend/app/pipes/SafeHTMLPipe.ts index fb05b8b3..88f360f6 100644 --- a/src/frontend/app/pipes/SafeHTMLPipe.ts +++ b/src/frontend/app/pipes/SafeHTMLPipe.ts @@ -1,4 +1,4 @@ -import {Pipe, PipeTransform, SecurityContext} from '@angular/core'; +import {Pipe, PipeTransform} from '@angular/core'; import {DomSanitizer} from '@angular/platform-browser'; @Pipe({name: 'safeHtml'}) diff --git a/src/frontend/app/pipes/StringifyRolePipe.ts b/src/frontend/app/pipes/StringifyRolePipe.ts index 647b6026..24a9c659 100644 --- a/src/frontend/app/pipes/StringifyRolePipe.ts +++ b/src/frontend/app/pipes/StringifyRolePipe.ts @@ -1,7 +1,7 @@ -import { Pipe, PipeTransform } from '@angular/core'; -import { UserRoles } from '../../../common/entities/UserDTO'; +import {Pipe, PipeTransform} from '@angular/core'; +import {UserRoles} from '../../../common/entities/UserDTO'; -@Pipe({ name: 'stringifyRole' }) +@Pipe({name: 'stringifyRole'}) export class StringifyRole implements PipeTransform { transform(role: number): string { return UserRoles[role]; diff --git a/src/frontend/app/pipes/StringifySearchQuery.ts b/src/frontend/app/pipes/StringifySearchQuery.ts index f8ae80c8..0c9f0a92 100644 --- a/src/frontend/app/pipes/StringifySearchQuery.ts +++ b/src/frontend/app/pipes/StringifySearchQuery.ts @@ -1,10 +1,11 @@ -import { Pipe, PipeTransform } from '@angular/core'; -import { SearchQueryDTO } from '../../../common/entities/SearchQueryDTO'; -import { SearchQueryParserService } from '../ui/gallery/search/search-query-parser.service'; +import {Pipe, PipeTransform} from '@angular/core'; +import {SearchQueryDTO} from '../../../common/entities/SearchQueryDTO'; +import {SearchQueryParserService} from '../ui/gallery/search/search-query-parser.service'; -@Pipe({ name: 'searchQuery' }) +@Pipe({name: 'searchQuery'}) export class StringifySearchQuery implements PipeTransform { - constructor(private searchQueryParserService: SearchQueryParserService) {} + constructor(private searchQueryParserService: SearchQueryParserService) { + } transform(query: SearchQueryDTO): string { return this.searchQueryParserService.stringify(query); diff --git a/src/frontend/app/pipes/StringifySearchType.ts b/src/frontend/app/pipes/StringifySearchType.ts index 20db18ac..1196eef9 100644 --- a/src/frontend/app/pipes/StringifySearchType.ts +++ b/src/frontend/app/pipes/StringifySearchType.ts @@ -1,8 +1,8 @@ -import { Pipe, PipeTransform } from '@angular/core'; +import {Pipe, PipeTransform} from '@angular/core'; import {EnumTranslations} from '../ui/EnumTranslations'; import {SearchQueryTypes} from '../../../common/entities/SearchQueryDTO'; -@Pipe({ name: 'stringifySearchType' }) +@Pipe({name: 'stringifySearchType'}) export class StringifySearchType implements PipeTransform { transform(type: SearchQueryTypes): string { diff --git a/src/frontend/app/ui/EnumTranslations.ts b/src/frontend/app/ui/EnumTranslations.ts index 11f5d0d0..03a68dbe 100644 --- a/src/frontend/app/ui/EnumTranslations.ts +++ b/src/frontend/app/ui/EnumTranslations.ts @@ -3,7 +3,7 @@ import {ConfigPriority, MapProviders, NavigationLinkTypes, ScrollUpModes} from ' import {ReIndexingSensitivity} from '../../../common/config/private/PrivateConfig'; import {SearchQueryTypes} from '../../../common/entities/SearchQueryDTO'; import {ConfigStyle} from './settings/settings.service'; -import {SortByTypes,GroupByTypes} from '../../../common/entities/SortingMethods'; +import {GroupByTypes, SortByTypes} from '../../../common/entities/SortingMethods'; import {GridSizes} from '../../../common/entities/GridSizes'; export const EnumTranslations: Record = {}; diff --git a/src/frontend/app/ui/admin/admin.component.ts b/src/frontend/app/ui/admin/admin.component.ts index c1a85b27..64f929c7 100644 --- a/src/frontend/app/ui/admin/admin.component.ts +++ b/src/frontend/app/ui/admin/admin.component.ts @@ -30,18 +30,18 @@ export class AdminComponent implements OnInit, AfterViewInit { public readonly configPaths: string[] = []; constructor( - private authService: AuthenticationService, - private navigation: NavigationService, - public viewportScroller: ViewportScroller, - public notificationService: NotificationService, - public settingsService: SettingsService, - private piTitleService: PiTitleService + private authService: AuthenticationService, + private navigation: NavigationService, + public viewportScroller: ViewportScroller, + public notificationService: NotificationService, + public settingsService: SettingsService, + private piTitleService: PiTitleService ) { this.configPriorities = enumToTranslatedArray(ConfigPriority); this.configStyles = enumToTranslatedArray(ConfigStyle); const wc = WebConfigClassBuilder.attachPrivateInterface(new WebConfig()); this.configPaths = Object.keys(wc.State) - .filter(s => !wc.__state[s].volatile); + .filter(s => !wc.__state[s].volatile); } ngAfterViewInit(): void { @@ -50,8 +50,8 @@ export class AdminComponent implements OnInit, AfterViewInit { ngOnInit(): void { if ( - !this.authService.isAuthenticated() || - this.authService.user.value.role < UserRoles.Admin + !this.authService.isAuthenticated() || + this.authService.user.value.role < UserRoles.Admin ) { this.navigation.toLogin(); return; diff --git a/src/frontend/app/ui/albums/album/album.component.ts b/src/frontend/app/ui/albums/album/album.component.ts index e7791197..2b7abd33 100644 --- a/src/frontend/app/ui/albums/album/album.component.ts +++ b/src/frontend/app/ui/albums/album/album.component.ts @@ -1,16 +1,13 @@ -import { Component, Input, OnDestroy, OnInit } from '@angular/core'; -import { RouterLink } from '@angular/router'; -import { DomSanitizer, SafeStyle } from '@angular/platform-browser'; -import { - Thumbnail, - ThumbnailManagerService, -} from '../../gallery/thumbnailManager.service'; -import { AuthenticationService } from '../../../model/network/authentication.service'; -import { AlbumsService } from '../albums.service'; -import { AlbumBaseDTO } from '../../../../../common/entities/album/AlbumBaseDTO'; -import { Media } from '../../gallery/Media'; -import { SavedSearchDTO } from '../../../../../common/entities/album/SavedSearchDTO'; -import { UserRoles } from '../../../../../common/entities/UserDTO'; +import {Component, Input, OnDestroy, OnInit} from '@angular/core'; +import {RouterLink} from '@angular/router'; +import {DomSanitizer, SafeStyle} from '@angular/platform-browser'; +import {Thumbnail, ThumbnailManagerService,} from '../../gallery/thumbnailManager.service'; +import {AuthenticationService} from '../../../model/network/authentication.service'; +import {AlbumsService} from '../albums.service'; +import {AlbumBaseDTO} from '../../../../../common/entities/album/AlbumBaseDTO'; +import {Media} from '../../gallery/Media'; +import {SavedSearchDTO} from '../../../../../common/entities/album/SavedSearchDTO'; +import {UserRoles} from '../../../../../common/entities/UserDTO'; import {Config} from '../../../../../common/config/public/Config'; @Component({ @@ -27,11 +24,12 @@ export class AlbumComponent implements OnInit, OnDestroy { public thumbnail: Thumbnail = null; constructor( - private thumbnailService: ThumbnailManagerService, - private sanitizer: DomSanitizer, - private albumService: AlbumsService, - public authenticationService: AuthenticationService - ) {} + private thumbnailService: ThumbnailManagerService, + private sanitizer: DomSanitizer, + private albumService: AlbumsService, + public authenticationService: AuthenticationService + ) { + } get IsSavedSearch(): boolean { return this.album && !!this.AsSavedSearch.searchQuery; @@ -56,17 +54,17 @@ export class AlbumComponent implements OnInit, OnDestroy { ngOnInit(): void { if (this.album.cover) { this.thumbnail = this.thumbnailService.getThumbnail( - new Media(this.album.cover, this.size, this.size) + new Media(this.album.cover, this.size, this.size) ); } } getSanitizedThUrl(): SafeStyle { return this.sanitizer.bypassSecurityTrustStyle( - 'url(' + + 'url(' + this.thumbnail.Src.replace(/\(/g, '%28') - .replace(/'/g, '%27') - .replace(/\)/g, '%29') + + .replace(/'/g, '%27') + .replace(/\)/g, '%29') + ')' ); } diff --git a/src/frontend/app/ui/albums/albums.component.ts b/src/frontend/app/ui/albums/albums.component.ts index 6847a807..f3e9cb63 100644 --- a/src/frontend/app/ui/albums/albums.component.ts +++ b/src/frontend/app/ui/albums/albums.component.ts @@ -22,10 +22,10 @@ export class AlbumsComponent implements OnInit { private modalRef: BsModalRef; constructor( - public albumsService: AlbumsService, - private modalService: BsModalService, - public authenticationService: AuthenticationService, - private piTitleService: PiTitleService + public albumsService: AlbumsService, + private modalService: BsModalService, + public authenticationService: AuthenticationService, + private piTitleService: PiTitleService ) { this.albumsService.getAlbums().catch(console.error); } @@ -51,8 +51,8 @@ export class AlbumsComponent implements OnInit { async saveSearch(): Promise { await this.albumsService.addSavedSearch( - this.savedSearch.name, - this.savedSearch.searchQuery + this.savedSearch.name, + this.savedSearch.searchQuery ); this.hideModal(); } diff --git a/src/frontend/app/ui/albums/albums.service.ts b/src/frontend/app/ui/albums/albums.service.ts index 5d303610..bb46a541 100644 --- a/src/frontend/app/ui/albums/albums.service.ts +++ b/src/frontend/app/ui/albums/albums.service.ts @@ -14,9 +14,9 @@ export class AlbumsService { public async getAlbums(): Promise { this.albums.next( - (await this.networkService.getJson('/albums')).sort( - (a, b): number => a.name.localeCompare(b.name) - ) + (await this.networkService.getJson('/albums')).sort( + (a, b): number => a.name.localeCompare(b.name) + ) ); } @@ -26,8 +26,8 @@ export class AlbumsService { } async addSavedSearch( - name: string, - searchQuery: SearchQueryDTO + name: string, + searchQuery: SearchQueryDTO ): Promise { await this.networkService.putJson('/albums/saved-searches', { name, diff --git a/src/frontend/app/ui/albums/saved-search-popup/saved-search-popup.component.ts b/src/frontend/app/ui/albums/saved-search-popup/saved-search-popup.component.ts index 9cdab1f4..828826df 100644 --- a/src/frontend/app/ui/albums/saved-search-popup/saved-search-popup.component.ts +++ b/src/frontend/app/ui/albums/saved-search-popup/saved-search-popup.component.ts @@ -1,7 +1,7 @@ -import { Component, Input, TemplateRef } from '@angular/core'; -import { BsModalService } from 'ngx-bootstrap/modal'; -import { BsModalRef } from 'ngx-bootstrap/modal/bs-modal-ref.service'; -import { SearchQueryDTO } from '../../../../../common/entities/SearchQueryDTO'; +import {Component, Input, TemplateRef} from '@angular/core'; +import {BsModalService} from 'ngx-bootstrap/modal'; +import {BsModalRef} from 'ngx-bootstrap/modal/bs-modal-ref.service'; +import {SearchQueryDTO} from '../../../../../common/entities/SearchQueryDTO'; @Component({ selector: 'app-saved-search-popup-btn', @@ -13,10 +13,11 @@ export class SavedSearchPopupComponent { @Input() savedSearchDTO: { name: string; searchQuery: SearchQueryDTO }; private modalRef: BsModalRef; - constructor(private modalService: BsModalService) {} + constructor(private modalService: BsModalService) { + } public async openModal(template: TemplateRef): Promise { - this.modalRef = this.modalService.show(template, { class: 'modal-lg' }); + this.modalRef = this.modalService.show(template, {class: 'modal-lg'}); document.body.style.paddingRight = '0px'; } diff --git a/src/frontend/app/ui/duplicates/duplicates.component.ts b/src/frontend/app/ui/duplicates/duplicates.component.ts index 89ef1b54..225db261 100644 --- a/src/frontend/app/ui/duplicates/duplicates.component.ts +++ b/src/frontend/app/ui/duplicates/duplicates.component.ts @@ -35,83 +35,83 @@ export class DuplicateComponent implements OnDestroy, OnInit { }; constructor( - public duplicateService: DuplicateService, - public queryService: QueryService, - private piTitleService: PiTitleService + public duplicateService: DuplicateService, + public queryService: QueryService, + private piTitleService: PiTitleService ) { this.duplicateService.getDuplicates().catch(console.error); this.subscription = this.duplicateService.duplicates.subscribe( - (duplicates: DuplicatesDTO[]): void => { - this.directoryGroups = []; - this.renderedIndex = {group: -1, pairs: 0}; - this.renderedDirGroups = []; - this.duplicateCount = { - pairs: 0, - photos: 0, - }; - if (duplicates === null) { - return; - } - this.duplicateCount.photos = duplicates.reduce( - (prev: number, curr): number => prev + curr.media.length, - 0 - ); - this.duplicateCount.pairs = duplicates.length; - - const getMostFrequentDir = ( - dupls: DuplicatesDTO[] - ): DirectoryPathDTO | null => { - if (dupls.length === 0) { - return null; - } - const dirFrequency: { - [key: string]: { count: number; dir: DirectoryPathDTO }; - } = {}; - dupls.forEach((d): void => - d.media.forEach((m): void => { - const k = Utils.concatUrls(m.directory.path, m.directory.name); - dirFrequency[k] = dirFrequency[k] || { - dir: m.directory, - count: 0, - }; - dirFrequency[k].count++; - }) - ); - let max: { count: number; dir: DirectoryPathDTO } = { - count: -1, - dir: null, + (duplicates: DuplicatesDTO[]): void => { + this.directoryGroups = []; + this.renderedIndex = {group: -1, pairs: 0}; + this.renderedDirGroups = []; + this.duplicateCount = { + pairs: 0, + photos: 0, }; - for (const freq of Object.values(dirFrequency)) { - if (max.count <= freq.count) { - max = freq; - } + if (duplicates === null) { + return; } - return max.dir; - }; + this.duplicateCount.photos = duplicates.reduce( + (prev: number, curr): number => prev + curr.media.length, + 0 + ); + this.duplicateCount.pairs = duplicates.length; - while (duplicates.length > 0) { - const dir = getMostFrequentDir(duplicates); - const group = duplicates.filter( - (d): MediaDTO => - d.media.find( - (m): boolean => - m.directory.name === dir.name && m.directory.path === dir.path - ) - ); - duplicates = duplicates.filter( - (d): boolean => - !d.media.find( - (m): boolean => - m.directory.name === dir.name && m.directory.path === dir.path - ) - ); - this.directoryGroups.push({ - name: this.getDirectoryPath(dir) + ' (' + group.length + ')', - duplicates: group, - }); + const getMostFrequentDir = ( + dupls: DuplicatesDTO[] + ): DirectoryPathDTO | null => { + if (dupls.length === 0) { + return null; + } + const dirFrequency: { + [key: string]: { count: number; dir: DirectoryPathDTO }; + } = {}; + dupls.forEach((d): void => + d.media.forEach((m): void => { + const k = Utils.concatUrls(m.directory.path, m.directory.name); + dirFrequency[k] = dirFrequency[k] || { + dir: m.directory, + count: 0, + }; + dirFrequency[k].count++; + }) + ); + let max: { count: number; dir: DirectoryPathDTO } = { + count: -1, + dir: null, + }; + for (const freq of Object.values(dirFrequency)) { + if (max.count <= freq.count) { + max = freq; + } + } + return max.dir; + }; + + while (duplicates.length > 0) { + const dir = getMostFrequentDir(duplicates); + const group = duplicates.filter( + (d): MediaDTO => + d.media.find( + (m): boolean => + m.directory.name === dir.name && m.directory.path === dir.path + ) + ); + duplicates = duplicates.filter( + (d): boolean => + !d.media.find( + (m): boolean => + m.directory.name === dir.name && m.directory.path === dir.path + ) + ); + this.directoryGroups.push({ + name: this.getDirectoryPath(dir) + ' (' + group.length + ')', + duplicates: group, + }); + } + this.renderMore(); } - this.renderMore(); - } ); } @@ -141,17 +141,17 @@ export class DuplicateComponent implements OnDestroy, OnInit { } if ( - this.renderedIndex.group === this.directoryGroups.length - 1 && - this.renderedIndex.pairs >= - this.directoryGroups[this.renderedIndex.group].duplicates.length + this.renderedIndex.group === this.directoryGroups.length - 1 && + this.renderedIndex.pairs >= + this.directoryGroups[this.renderedIndex.group].duplicates.length ) { return; } if (this.shouldRenderMore()) { if ( - this.renderedDirGroups.length === 0 || - this.renderedIndex.pairs >= - this.directoryGroups[this.renderedIndex.group].duplicates.length + this.renderedDirGroups.length === 0 || + this.renderedIndex.pairs >= + this.directoryGroups[this.renderedIndex.group].duplicates.length ) { this.renderedDirGroups.push({ name: this.directoryGroups[++this.renderedIndex.group].name, @@ -160,9 +160,9 @@ export class DuplicateComponent implements OnDestroy, OnInit { this.renderedIndex.pairs = 0; } this.renderedDirGroups[this.renderedDirGroups.length - 1].duplicates.push( - this.directoryGroups[this.renderedIndex.group].duplicates[ - this.renderedIndex.pairs++ - ] + this.directoryGroups[this.renderedIndex.group].duplicates[ + this.renderedIndex.pairs++ + ] ); this.renderTimer = window.setTimeout(this.renderMore, 0); @@ -176,9 +176,9 @@ export class DuplicateComponent implements OnDestroy, OnInit { private shouldRenderMore(): boolean { return ( - Config.Gallery.enableOnScrollRendering === false || - PageHelper.ScrollY >= PageHelper.MaxScrollY * 0.7 || - document.body.clientHeight * 0.85 < window.innerHeight + Config.Gallery.enableOnScrollRendering === false || + PageHelper.ScrollY >= PageHelper.MaxScrollY * 0.7 || + document.body.clientHeight * 0.85 < window.innerHeight ); } } diff --git a/src/frontend/app/ui/duplicates/duplicates.service.ts b/src/frontend/app/ui/duplicates/duplicates.service.ts index d7400db0..ebae2281 100644 --- a/src/frontend/app/ui/duplicates/duplicates.service.ts +++ b/src/frontend/app/ui/duplicates/duplicates.service.ts @@ -1,7 +1,7 @@ -import { Injectable } from '@angular/core'; -import { NetworkService } from '../../model/network/network.service'; -import { DuplicatesDTO } from '../../../../common/entities/DuplicatesDTO'; -import { BehaviorSubject } from 'rxjs'; +import {Injectable} from '@angular/core'; +import {NetworkService} from '../../model/network/network.service'; +import {DuplicatesDTO} from '../../../../common/entities/DuplicatesDTO'; +import {BehaviorSubject} from 'rxjs'; @Injectable() export class DuplicateService { @@ -13,7 +13,7 @@ export class DuplicateService { public async getDuplicates(): Promise { this.duplicates.next( - await this.networkService.getJson('/admin/duplicates') + await this.networkService.getJson('/admin/duplicates') ); } } diff --git a/src/frontend/app/ui/duplicates/photo/photo.duplicates.component.ts b/src/frontend/app/ui/duplicates/photo/photo.duplicates.component.ts index a7d87357..142114c2 100644 --- a/src/frontend/app/ui/duplicates/photo/photo.duplicates.component.ts +++ b/src/frontend/app/ui/duplicates/photo/photo.duplicates.component.ts @@ -1,10 +1,7 @@ -import { Component, Input, OnDestroy, OnInit } from '@angular/core'; -import { MediaDTO } from '../../../../../common/entities/MediaDTO'; -import { - IconThumbnail, - ThumbnailManagerService, -} from '../../gallery/thumbnailManager.service'; -import { MediaIcon } from '../../gallery/MediaIcon'; +import {Component, Input, OnDestroy, OnInit} from '@angular/core'; +import {MediaDTO} from '../../../../../common/entities/MediaDTO'; +import {IconThumbnail, ThumbnailManagerService,} from '../../gallery/thumbnailManager.service'; +import {MediaIcon} from '../../gallery/MediaIcon'; @Component({ selector: 'app-duplicates-photo', @@ -16,7 +13,8 @@ export class DuplicatesPhotoComponent implements OnInit, OnDestroy { thumbnail: IconThumbnail; - constructor(private thumbnailService: ThumbnailManagerService) {} + constructor(private thumbnailService: ThumbnailManagerService) { + } ngOnInit(): void { this.thumbnail = this.thumbnailService.getIcon(new MediaIcon(this.media)); diff --git a/src/frontend/app/ui/faces/Person.ts b/src/frontend/app/ui/faces/Person.ts index 3e1a0abc..3e7d80de 100644 --- a/src/frontend/app/ui/faces/Person.ts +++ b/src/frontend/app/ui/faces/Person.ts @@ -1,6 +1,6 @@ -import { PersonDTO } from '../../../../common/entities/PersonDTO'; -import { Config } from '../../../../common/config/public/Config'; -import { Utils } from '../../../../common/Utils'; +import {PersonDTO} from '../../../../common/entities/PersonDTO'; +import {Config} from '../../../../common/config/public/Config'; +import {Utils} from '../../../../common/Utils'; export class Person implements PersonDTO { isFavourite: boolean; @@ -11,10 +11,10 @@ export class Person implements PersonDTO { public static getThumbnailUrl(that: PersonDTO): string { return Utils.concatUrls( - Config.Server.urlBase, - Config.Server.apiPath + '/person/', - encodeURIComponent(that.name), - '/thumbnail' + Config.Server.urlBase, + Config.Server.apiPath + '/person/', + encodeURIComponent(that.name), + '/thumbnail' ); } } diff --git a/src/frontend/app/ui/faces/face/face.component.ts b/src/frontend/app/ui/faces/face/face.component.ts index 970a67de..5a637368 100644 --- a/src/frontend/app/ui/faces/face/face.component.ts +++ b/src/frontend/app/ui/faces/face/face.component.ts @@ -1,19 +1,12 @@ -import { Component, Input, OnDestroy, OnInit } from '@angular/core'; -import { RouterLink } from '@angular/router'; -import { PersonDTO } from '../../../../../common/entities/PersonDTO'; -import { DomSanitizer, SafeStyle } from '@angular/platform-browser'; -import { - PersonThumbnail, - ThumbnailManagerService, -} from '../../gallery/thumbnailManager.service'; -import { FacesService } from '../faces.service'; -import { AuthenticationService } from '../../../model/network/authentication.service'; -import { Config } from '../../../../../common/config/public/Config'; -import { - SearchQueryTypes, - TextSearch, - TextSearchQueryMatchTypes, -} from '../../../../../common/entities/SearchQueryDTO'; +import {Component, Input, OnDestroy, OnInit} from '@angular/core'; +import {RouterLink} from '@angular/router'; +import {PersonDTO} from '../../../../../common/entities/PersonDTO'; +import {DomSanitizer, SafeStyle} from '@angular/platform-browser'; +import {PersonThumbnail, ThumbnailManagerService,} from '../../gallery/thumbnailManager.service'; +import {FacesService} from '../faces.service'; +import {AuthenticationService} from '../../../model/network/authentication.service'; +import {Config} from '../../../../../common/config/public/Config'; +import {SearchQueryTypes, TextSearch, TextSearchQueryMatchTypes,} from '../../../../../common/entities/SearchQueryDTO'; @Component({ selector: 'app-face', @@ -29,16 +22,17 @@ export class FaceComponent implements OnInit, OnDestroy { public searchQueryDTOstr: string; constructor( - private thumbnailService: ThumbnailManagerService, - private sanitizer: DomSanitizer, - private faceService: FacesService, - public authenticationService: AuthenticationService - ) {} + private thumbnailService: ThumbnailManagerService, + private sanitizer: DomSanitizer, + private faceService: FacesService, + public authenticationService: AuthenticationService + ) { + } get CanUpdate(): boolean { return ( - this.authenticationService.user.getValue().role >= - Config.Faces.writeAccessMinRole + this.authenticationService.user.getValue().role >= + Config.Faces.writeAccessMinRole ); } @@ -53,10 +47,10 @@ export class FaceComponent implements OnInit, OnDestroy { getSanitizedThUrl(): SafeStyle { return this.sanitizer.bypassSecurityTrustStyle( - 'url(' + + 'url(' + this.thumbnail.Src.replace(/\(/g, '%28') - .replace(/'/g, '%27') - .replace(/\)/g, '%29') + + .replace(/'/g, '%27') + .replace(/\)/g, '%29') + ')' ); } @@ -71,8 +65,8 @@ export class FaceComponent implements OnInit, OnDestroy { $event.preventDefault(); $event.stopPropagation(); await this.faceService - .setFavourite(this.person, !this.person.isFavourite) - .catch(console.error); + .setFavourite(this.person, !this.person.isFavourite) + .catch(console.error); } } diff --git a/src/frontend/app/ui/faces/faces.component.ts b/src/frontend/app/ui/faces/faces.component.ts index 5e86014a..c37c1cdc 100644 --- a/src/frontend/app/ui/faces/faces.component.ts +++ b/src/frontend/app/ui/faces/faces.component.ts @@ -1,9 +1,9 @@ -import { Component, ElementRef, OnInit, ViewChild } from '@angular/core'; -import { FacesService } from './faces.service'; -import { QueryService } from '../../model/query.service'; -import { map } from 'rxjs/operators'; -import { PersonDTO } from '../../../../common/entities/PersonDTO'; -import { Observable } from 'rxjs'; +import {Component, ElementRef, OnInit, ViewChild} from '@angular/core'; +import {FacesService} from './faces.service'; +import {QueryService} from '../../model/query.service'; +import {map} from 'rxjs/operators'; +import {PersonDTO} from '../../../../common/entities/PersonDTO'; +import {Observable} from 'rxjs'; import {PiTitleService} from '../../model/pi-title.service'; @Component({ @@ -12,25 +12,25 @@ import {PiTitleService} from '../../model/pi-title.service'; styleUrls: ['./faces.component.css'], }) export class FacesComponent implements OnInit { - @ViewChild('container', { static: true }) container: ElementRef; + @ViewChild('container', {static: true}) container: ElementRef; public size: number; favourites: Observable; nonFavourites: Observable; constructor( - public facesService: FacesService, - public queryService: QueryService, - private piTitleService: PiTitleService + public facesService: FacesService, + public queryService: QueryService, + private piTitleService: PiTitleService ) { this.facesService.getPersons().catch(console.error); const personCmp = (p1: PersonDTO, p2: PersonDTO) => { return p1.name.localeCompare(p2.name); }; this.favourites = this.facesService.persons.pipe( - map((value) => value.filter((p) => p.isFavourite).sort(personCmp)) + map((value) => value.filter((p) => p.isFavourite).sort(personCmp)) ); this.nonFavourites = this.facesService.persons.pipe( - map((value) => value.filter((p) => !p.isFavourite).sort(personCmp)) + map((value) => value.filter((p) => !p.isFavourite).sort(personCmp)) ); } diff --git a/src/frontend/app/ui/faces/faces.service.ts b/src/frontend/app/ui/faces/faces.service.ts index 9b4dfbdb..c197d48b 100644 --- a/src/frontend/app/ui/faces/faces.service.ts +++ b/src/frontend/app/ui/faces/faces.service.ts @@ -1,7 +1,7 @@ -import { Injectable } from '@angular/core'; -import { NetworkService } from '../../model/network/network.service'; -import { BehaviorSubject } from 'rxjs'; -import { PersonDTO } from '../../../../common/entities/PersonDTO'; +import {Injectable} from '@angular/core'; +import {NetworkService} from '../../model/network/network.service'; +import {BehaviorSubject} from 'rxjs'; +import {PersonDTO} from '../../../../common/entities/PersonDTO'; @Injectable() export class FacesService { @@ -12,12 +12,12 @@ export class FacesService { } public async setFavourite( - person: PersonDTO, - isFavourite: boolean + person: PersonDTO, + isFavourite: boolean ): Promise { const updated = await this.networkService.postJson( - '/person/' + person.name, - { isFavourite } + '/person/' + person.name, + {isFavourite} ); const updatesList = this.persons.getValue(); for (let i = 0; i < updatesList.length; i++) { @@ -31,9 +31,9 @@ export class FacesService { public async getPersons(): Promise { this.persons.next( - (await this.networkService.getJson('/person')).sort( - (a, b): number => a.name.localeCompare(b.name) - ) + (await this.networkService.getJson('/person')).sort( + (a, b): number => a.name.localeCompare(b.name) + ) ); } } diff --git a/src/frontend/app/ui/frame/frame.component.ts b/src/frontend/app/ui/frame/frame.component.ts index 396c9596..4388c537 100644 --- a/src/frontend/app/ui/frame/frame.component.ts +++ b/src/frontend/app/ui/frame/frame.component.ts @@ -53,12 +53,12 @@ export class FrameComponent { public readonly enableScrollUpButton: boolean; constructor( - private authService: AuthenticationService, - public notificationService: NotificationService, - public queryService: QueryService, - private router: Router, - public themeService: ThemeService, - private deviceService: DeviceDetectorService + private authService: AuthenticationService, + public notificationService: NotificationService, + public queryService: QueryService, + private router: Router, + public themeService: ThemeService, + private deviceService: DeviceDetectorService ) { this.enableScrollUpButton = Config.Gallery.NavBar.showScrollUpButton === ScrollUpModes.always || (Config.Gallery.NavBar.showScrollUpButton === ScrollUpModes.mobileOnly && !this.deviceService.isDesktop()); this.user = this.authService.user; @@ -70,9 +70,9 @@ export class FrameComponent { isFacesAvailable(): boolean { return ( - Config.Faces.enabled && - this.user.value && - this.user.value.role >= Config.Faces.readAccessMinRole + Config.Faces.enabled && + this.user.value && + this.user.value.role >= Config.Faces.readAccessMinRole ); } diff --git a/src/frontend/app/ui/gallery/Media.ts b/src/frontend/app/ui/gallery/Media.ts index 38531702..5a2ab610 100644 --- a/src/frontend/app/ui/gallery/Media.ts +++ b/src/frontend/app/ui/gallery/Media.ts @@ -5,12 +5,12 @@ import {MediaDTO, MediaDTOUtils} from '../../../../common/entities/MediaDTO'; export class Media extends MediaIcon { static readonly sortedThumbnailSizes = - Config.Media.Thumbnail.thumbnailSizes.sort((a, b): number => a - b); + Config.Media.Thumbnail.thumbnailSizes.sort((a, b): number => a - b); constructor( - media: MediaDTO, - public renderWidth: number, - public renderHeight: number + media: MediaDTO, + public renderWidth: number, + public renderHeight: number ) { super(media); } @@ -19,7 +19,7 @@ export class Media extends MediaIcon { if (!this.isThumbnailAvailable()) { this.media.missingThumbnails = this.media.missingThumbnails || 0; this.media.missingThumbnails -= - MediaIcon.ThumbnailMap[this.getThumbnailSize()]; + MediaIcon.ThumbnailMap[this.getThumbnailSize()]; if (this.media.missingThumbnails < 0) { throw new Error('missingThumbnails got below 0'); } @@ -40,9 +40,9 @@ export class Media extends MediaIcon { for (const thSize of Config.Media.Thumbnail.thumbnailSizes) { // eslint-disable-next-line no-bitwise if ( - (this.media.missingThumbnails & MediaIcon.ThumbnailMap[thSize]) === - 0 && - thSize < size + (this.media.missingThumbnails & MediaIcon.ThumbnailMap[thSize]) === + 0 && + thSize < size ) { this.replacementSizeCache = thSize; break; @@ -60,21 +60,21 @@ export class Media extends MediaIcon { isThumbnailAvailable(): boolean { // eslint-disable-next-line no-bitwise return ( - (this.media.missingThumbnails & - MediaIcon.ThumbnailMap[this.getThumbnailSize()]) === - 0 + (this.media.missingThumbnails & + MediaIcon.ThumbnailMap[this.getThumbnailSize()]) === + 0 ); } getReplacementThumbnailPath(): string { const size = this.getReplacementThumbnailSize(); return Utils.concatUrls( - Config.Server.urlBase, - Config.Server.apiPath, - '/gallery/content/', - this.getRelativePath(), - 'thumbnail', - size.toString() + Config.Server.urlBase, + Config.Server.apiPath, + '/gallery/content/', + this.getRelativePath(), + 'thumbnail', + size.toString() ); } @@ -85,12 +85,12 @@ export class Media extends MediaIcon { getThumbnailPath(): string { const size = this.getThumbnailSize(); return Utils.concatUrls( - Config.Server.urlBase, - Config.Server.apiPath, - '/gallery/content/', - this.getRelativePath(), - 'thumbnail', - size.toString() + Config.Server.urlBase, + Config.Server.apiPath, + '/gallery/content/', + this.getRelativePath(), + 'thumbnail', + size.toString() ); } } diff --git a/src/frontend/app/ui/gallery/MediaIcon.ts b/src/frontend/app/ui/gallery/MediaIcon.ts index a99ea0d9..20acc081 100644 --- a/src/frontend/app/ui/gallery/MediaIcon.ts +++ b/src/frontend/app/ui/gallery/MediaIcon.ts @@ -4,7 +4,7 @@ import {MediaDTO} from '../../../../common/entities/MediaDTO'; export class MediaIcon { protected static readonly ThumbnailMap = - Config.Media.Thumbnail.generateThumbnailMap(); + Config.Media.Thumbnail.generateThumbnailMap(); protected replacementSizeCache: number | boolean = false; @@ -17,56 +17,56 @@ export class MediaIcon { iconLoaded(): void { this.media.missingThumbnails -= - MediaIcon.ThumbnailMap[Config.Media.Thumbnail.iconSize]; + MediaIcon.ThumbnailMap[Config.Media.Thumbnail.iconSize]; } isIconAvailable(): boolean { // eslint-disable-next-line no-bitwise return ( - (this.media.missingThumbnails & - MediaIcon.ThumbnailMap[Config.Media.Thumbnail.iconSize]) === - 0 + (this.media.missingThumbnails & + MediaIcon.ThumbnailMap[Config.Media.Thumbnail.iconSize]) === + 0 ); } getReadableRelativePath(): string { return Utils.concatUrls( - this.media.directory.path, - this.media.directory.name, - this.media.name + this.media.directory.path, + this.media.directory.name, + this.media.name ); } getRelativePath(): string { return ( - encodeURI( - this.getReadableRelativePath() - ) - // do not escape all urls with encodeURIComponent because that make the URL ugly and not needed - // do not escape before concatUrls as that would make prevent optimizations - // .replace(new RegExp('%', 'g'), '%25') // order important - .replace(new RegExp('#', 'g'), '%23') - .replace(new RegExp('\\$', 'g'), '%24') - .replace(new RegExp('\\?', 'g'), '%3F') + encodeURI( + this.getReadableRelativePath() + ) + // do not escape all urls with encodeURIComponent because that make the URL ugly and not needed + // do not escape before concatUrls as that would make prevent optimizations + // .replace(new RegExp('%', 'g'), '%25') // order important + .replace(new RegExp('#', 'g'), '%23') + .replace(new RegExp('\\$', 'g'), '%24') + .replace(new RegExp('\\?', 'g'), '%3F') ); } getIconPath(): string { return Utils.concatUrls( - Config.Server.urlBase, - Config.Server.apiPath, - '/gallery/content/', - this.getRelativePath(), - 'icon' + Config.Server.urlBase, + Config.Server.apiPath, + '/gallery/content/', + this.getRelativePath(), + 'icon' ); } getMediaPath(): string { return Utils.concatUrls( - Config.Server.urlBase, - Config.Server.apiPath, - '/gallery/content/', - this.getRelativePath() + Config.Server.urlBase, + Config.Server.apiPath, + '/gallery/content/', + this.getRelativePath() ); } @@ -78,18 +78,18 @@ export class MediaIcon { // is gridphoto if (other instanceof MediaIcon) { return ( - this.media.directory.path === other.media.directory.path && - this.media.directory.name === other.media.directory.name && - this.media.name === other.media.name + this.media.directory.path === other.media.directory.path && + this.media.directory.name === other.media.directory.name && + this.media.name === other.media.name ); } // is media if (other.directory) { return ( - this.media.directory.path === other.directory.path && - this.media.directory.name === other.directory.name && - this.media.name === other.name + this.media.directory.path === other.directory.path && + this.media.directory.name === other.directory.name && + this.media.name === other.name ); } diff --git a/src/frontend/app/ui/gallery/blog/blog.gallery.component.ts b/src/frontend/app/ui/gallery/blog/blog.gallery.component.ts index d8804935..ea8adbea 100644 --- a/src/frontend/app/ui/gallery/blog/blog.gallery.component.ts +++ b/src/frontend/app/ui/gallery/blog/blog.gallery.component.ts @@ -1,7 +1,6 @@ import {Component, EventEmitter, Input, Output} from '@angular/core'; import {BlogService, GroupedMarkdown} from './blog.service'; import {OnChanges} from '../../../../../../node_modules/@angular/core'; -import {Utils} from '../../../../../common/Utils'; import {map, Observable} from 'rxjs'; @Component({ diff --git a/src/frontend/app/ui/gallery/blog/blog.service.ts b/src/frontend/app/ui/gallery/blog/blog.service.ts index 2ec864cb..c1695b7f 100644 --- a/src/frontend/app/ui/gallery/blog/blog.service.ts +++ b/src/frontend/app/ui/gallery/blog/blog.service.ts @@ -17,21 +17,21 @@ export class BlogService { private mdFilesFilterPipe: MDFilesFilterPipe) { this.groupedMarkdowns = this.galleryService.sortedFilteredContent.pipe( - mergeMap(async content => { - if (!content) { - return []; - } - const dates = content.mediaGroups.map(g => g.date) - .filter(d => !!d).map(d => d.getTime()); + mergeMap(async content => { + if (!content) { + return []; + } + const dates = content.mediaGroups.map(g => g.date) + .filter(d => !!d).map(d => d.getTime()); - const firstMedia = content.mediaGroups[0].media.reduce((p, m) => - Math.min(m.metadata.creationDate, p), Number.MAX_SAFE_INTEGER); + const firstMedia = content.mediaGroups[0].media.reduce((p, m) => + Math.min(m.metadata.creationDate, p), Number.MAX_SAFE_INTEGER); - const files = this.mdFilesFilterPipe.transform(content.metaFile) - .map(f => this.splitMarkDown(f, dates, firstMedia)); + const files = this.mdFilesFilterPipe.transform(content.metaFile) + .map(f => this.splitMarkDown(f, dates, firstMedia)); - return (await Promise.all(files)).flat(); - }), shareReplay(1)); + return (await Promise.all(files)).flat(); + }), shareReplay(1)); } private async splitMarkDown(file: MDFileDTO, dates: number[], firstMedia: number): Promise { @@ -126,13 +126,13 @@ export class BlogService { public getMarkDown(file: FileDTO): Promise { const filePath = Utils.concatUrls( - file.directory.path, - file.directory.name, - file.name + file.directory.path, + file.directory.name, + file.name ); if (!this.cache[filePath]) { this.cache[filePath] = this.networkService.getText( - '/gallery/content/' + filePath + '/gallery/content/' + filePath ); (this.cache[filePath] as Promise).then((val: string) => { this.cache[filePath] = val; diff --git a/src/frontend/app/ui/gallery/content.service.ts b/src/frontend/app/ui/gallery/content.service.ts index ed1944ee..31cda467 100644 --- a/src/frontend/app/ui/gallery/content.service.ts +++ b/src/frontend/app/ui/gallery/content.service.ts @@ -9,14 +9,14 @@ export class ContentService { public sortedFilteredContent: Observable; constructor( - private contentLoaderService: ContentLoaderService, - private sortingService: GallerySortingService, - private filterService: FilterService + private contentLoaderService: ContentLoaderService, + private sortingService: GallerySortingService, + private filterService: FilterService ) { this.sortedFilteredContent = this.sortingService - .applySorting( - this.filterService.applyFilters(this.contentLoaderService.originalContent) - ).pipe(shareReplay(1)); + .applySorting( + this.filterService.applyFilters(this.contentLoaderService.originalContent) + ).pipe(shareReplay(1)); } diff --git a/src/frontend/app/ui/gallery/contentLoader.service.ts b/src/frontend/app/ui/gallery/contentLoader.service.ts index 80367ea2..1fce09d2 100644 --- a/src/frontend/app/ui/gallery/contentLoader.service.ts +++ b/src/frontend/app/ui/gallery/contentLoader.service.ts @@ -24,16 +24,16 @@ export class ContentLoaderService { private ongoingSearch: string = null; constructor( - private networkService: NetworkService, - private galleryCacheService: GalleryCacheService, - private shareService: ShareService, - private navigationService: NavigationService, + private networkService: NetworkService, + private galleryCacheService: GalleryCacheService, + private shareService: ShareService, + private navigationService: NavigationService, ) { this.content = new BehaviorSubject( - new ContentWrapperWithError() + new ContentWrapperWithError() ); this.originalContent = this.content.pipe( - map((c) => (c.directory ? c.directory : c.searchResult)) + map((c) => (c.directory ? c.directory : c.searchResult)) ); } @@ -56,26 +56,26 @@ export class ContentLoaderService { if (Config.Sharing.enabled === true) { if (this.shareService.isSharing()) { params[QueryParams.gallery.sharingKey_query] = - this.shareService.getSharingKey(); + this.shareService.getSharingKey(); } } if ( - cw.directory && - cw.directory.lastModified && - cw.directory.lastScanned && - !cw.directory.isPartial + cw.directory && + cw.directory.lastModified && + cw.directory.lastScanned && + !cw.directory.isPartial ) { params[QueryParams.gallery.knownLastModified] = - cw.directory.lastModified; + cw.directory.lastModified; params[QueryParams.gallery.knownLastScanned] = - cw.directory.lastScanned; + cw.directory.lastScanned; } try { const cw = await this.networkService.getJson( - '/gallery/content/' + encodeURIComponent(directoryName), - params + '/gallery/content/' + encodeURIComponent(directoryName), + params ); if (!cw || cw.notModified === true) { diff --git a/src/frontend/app/ui/gallery/directories/directories.component.ts b/src/frontend/app/ui/gallery/directories/directories.component.ts index 4771a2bc..ff16d87c 100644 --- a/src/frontend/app/ui/gallery/directories/directories.component.ts +++ b/src/frontend/app/ui/gallery/directories/directories.component.ts @@ -13,8 +13,8 @@ export class DirectoriesComponent implements OnChanges { isDesktop: boolean; constructor( - private container: ElementRef, - private deviceService: DeviceDetectorService + private container: ElementRef, + private deviceService: DeviceDetectorService ) { this.isDesktop = this.deviceService.isDesktop(); } @@ -34,7 +34,7 @@ export class DirectoriesComponent implements OnChanges { } const directoryMargin = 2; // 2px margin on both sides const containerWidth = - this.container.nativeElement.clientWidth - 1; // the browser sometimes makes some rounding error. Sacrifice 1px to make that error up. + this.container.nativeElement.clientWidth - 1; // the browser sometimes makes some rounding error. Sacrifice 1px to make that error up. if (!this.isDesktop && window.innerWidth < window.innerHeight) { // On portrait mode, show 2 directories side by side with some padding diff --git a/src/frontend/app/ui/gallery/directories/directory/directory.gallery.component.ts b/src/frontend/app/ui/gallery/directories/directory/directory.gallery.component.ts index 4b4e73a9..04566a05 100644 --- a/src/frontend/app/ui/gallery/directories/directory/directory.gallery.component.ts +++ b/src/frontend/app/ui/gallery/directories/directory/directory.gallery.component.ts @@ -7,7 +7,6 @@ import {Media} from '../../Media'; import {Thumbnail, ThumbnailManagerService,} from '../../thumbnailManager.service'; import {QueryService} from '../../../../model/query.service'; import {CoverPhotoDTO} from '../../../../../../common/entities/PhotoDTO'; -import {Config} from '../../../../../../common/config/public/Config'; @Component({ selector: 'app-gallery-directory', @@ -21,9 +20,9 @@ export class GalleryDirectoryComponent implements OnInit, OnDestroy { thumbnail: Thumbnail = null; constructor( - private thumbnailService: ThumbnailManagerService, - private sanitizer: DomSanitizer, - public queryService: QueryService + private thumbnailService: ThumbnailManagerService, + private sanitizer: DomSanitizer, + public queryService: QueryService ) { } @@ -33,11 +32,11 @@ export class GalleryDirectoryComponent implements OnInit, OnDestroy { getSanitizedThUrl(): SafeStyle { return this.sanitizer.bypassSecurityTrustStyle( - 'url(' + - this.thumbnail.Src.replace(/\(/g, '%28') - .replace(/'/g, '%27') - .replace(/\)/g, '%29') + - ')' + 'url(' + + this.thumbnail.Src.replace(/\(/g, '%28') + .replace(/'/g, '%27') + .replace(/\)/g, '%29') + + ')' ); } @@ -60,7 +59,7 @@ export class GalleryDirectoryComponent implements OnInit, OnDestroy { ngOnInit(): void { if (this.directory.cover) { this.thumbnail = this.thumbnailService.getThumbnail( - new Media(this.SamplePhoto, this.size, this.size) + new Media(this.SamplePhoto, this.size, this.size) ); } } diff --git a/src/frontend/app/ui/gallery/filter/filter.gallery.component.ts b/src/frontend/app/ui/gallery/filter/filter.gallery.component.ts index fe5b5715..17a1bb31 100644 --- a/src/frontend/app/ui/gallery/filter/filter.gallery.component.ts +++ b/src/frontend/app/ui/gallery/filter/filter.gallery.component.ts @@ -22,21 +22,21 @@ export class GalleryFilterComponent implements OnInit, OnDestroy { get MinDatePrc(): number { return ( - ((this.ActiveFilters.dateFilter.minFilter - - this.ActiveFilters.dateFilter.minDate) / - (this.ActiveFilters.dateFilter.maxDate - - this.ActiveFilters.dateFilter.minDate)) * - 100 + ((this.ActiveFilters.dateFilter.minFilter - + this.ActiveFilters.dateFilter.minDate) / + (this.ActiveFilters.dateFilter.maxDate - + this.ActiveFilters.dateFilter.minDate)) * + 100 ); } get MaxDatePrc(): number { return ( - ((this.ActiveFilters.dateFilter.maxFilter - - this.ActiveFilters.dateFilter.minDate) / - (this.ActiveFilters.dateFilter.maxDate - - this.ActiveFilters.dateFilter.minDate)) * - 100 + ((this.ActiveFilters.dateFilter.maxFilter - + this.ActiveFilters.dateFilter.minDate) / + (this.ActiveFilters.dateFilter.maxDate - + this.ActiveFilters.dateFilter.minDate)) * + 100 ); } @@ -79,9 +79,9 @@ export class GalleryFilterComponent implements OnInit, OnDestroy { } toggleSelectOnly( - filter: SelectedFilter, - option: FilterOption, - event: MouseEvent + filter: SelectedFilter, + option: FilterOption, + event: MouseEvent ): void { if (this.isOnlySelected(filter, option)) { filter.options.forEach((o) => (o.selected = true)); @@ -94,16 +94,16 @@ export class GalleryFilterComponent implements OnInit, OnDestroy { newMinDate($event: Event): void { const diff = - (this.ActiveFilters.dateFilter.maxDate - - this.ActiveFilters.dateFilter.minDate) * - 0.01; + (this.ActiveFilters.dateFilter.maxDate - + this.ActiveFilters.dateFilter.minDate) * + 0.01; if ( - this.ActiveFilters.dateFilter.minFilter > - this.ActiveFilters.dateFilter.maxFilter - diff + this.ActiveFilters.dateFilter.minFilter > + this.ActiveFilters.dateFilter.maxFilter - diff ) { this.ActiveFilters.dateFilter.minFilter = Math.max( - this.ActiveFilters.dateFilter.maxFilter - diff, - this.ActiveFilters.dateFilter.minDate + this.ActiveFilters.dateFilter.maxFilter - diff, + this.ActiveFilters.dateFilter.minDate ); } this.filterService.onFilterChange(); @@ -111,16 +111,16 @@ export class GalleryFilterComponent implements OnInit, OnDestroy { newMaxDate($event: Event): void { const diff = - (this.ActiveFilters.dateFilter.maxDate - - this.ActiveFilters.dateFilter.minDate) * - 0.01; + (this.ActiveFilters.dateFilter.maxDate - + this.ActiveFilters.dateFilter.minDate) * + 0.01; if ( - this.ActiveFilters.dateFilter.maxFilter < - this.ActiveFilters.dateFilter.minFilter + diff + this.ActiveFilters.dateFilter.maxFilter < + this.ActiveFilters.dateFilter.minFilter + diff ) { this.ActiveFilters.dateFilter.maxFilter = Math.min( - this.ActiveFilters.dateFilter.minFilter + diff, - this.ActiveFilters.dateFilter.maxDate + this.ActiveFilters.dateFilter.minFilter + diff, + this.ActiveFilters.dateFilter.maxDate ); } this.filterService.onFilterChange(); diff --git a/src/frontend/app/ui/gallery/fullscreen.service.ts b/src/frontend/app/ui/gallery/fullscreen.service.ts index 36dcab67..b33caaf2 100644 --- a/src/frontend/app/ui/gallery/fullscreen.service.ts +++ b/src/frontend/app/ui/gallery/fullscreen.service.ts @@ -1,5 +1,5 @@ -import { Injectable } from '@angular/core'; -import { Event } from '../../../../common/event/Event'; +import {Injectable} from '@angular/core'; +import {Event} from '../../../../common/event/Event'; declare const document: { fullscreenElement: any; @@ -16,9 +16,9 @@ export class FullScreenService { public isFullScreenEnabled(): boolean { return !!( - document.fullscreenElement || - document.mozFullScreenElement || - document.webkitFullscreenElement + document.fullscreenElement || + document.mozFullScreenElement || + document.webkitFullscreenElement ); } diff --git a/src/frontend/app/ui/gallery/gallery.component.ts b/src/frontend/app/ui/gallery/gallery.component.ts index 8586bcd9..9a11fca1 100644 --- a/src/frontend/app/ui/gallery/gallery.component.ts +++ b/src/frontend/app/ui/gallery/gallery.component.ts @@ -52,18 +52,18 @@ export class GalleryComponent implements OnInit, OnDestroy { }; constructor( - public contentLoader: ContentLoaderService, - public galleryService: ContentService, - private authService: AuthenticationService, - private router: Router, - private shareService: ShareService, - private route: ActivatedRoute, - private navigation: NavigationService, - private filterService: FilterService, - private sortingService: GallerySortingService, - private piTitleService: PiTitleService, - private gpxFilesFilterPipe: GPXFilesFilterPipe, - private mdFilesFilterPipe: MDFilesFilterPipe, + public contentLoader: ContentLoaderService, + public galleryService: ContentService, + private authService: AuthenticationService, + private router: Router, + private shareService: ShareService, + private route: ActivatedRoute, + private navigation: NavigationService, + private filterService: FilterService, + private sortingService: GallerySortingService, + private piTitleService: PiTitleService, + private gpxFilesFilterPipe: GPXFilesFilterPipe, + private mdFilesFilterPipe: MDFilesFilterPipe, ) { this.mapEnabled = Config.Map.enabled; PageHelper.showScrollY(); @@ -79,17 +79,17 @@ export class GalleryComponent implements OnInit, OnDestroy { } // if the timer is longer than 10 years, just do not show it if ( - (this.shareService.sharingSubject.value.expires - Date.now()) / - 1000 / - 86400 / - 365 > - 10 + (this.shareService.sharingSubject.value.expires - Date.now()) / + 1000 / + 86400 / + 365 > + 10 ) { return; } t = Math.floor( - (this.shareService.sharingSubject.value.expires - Date.now()) / 1000 + (this.shareService.sharingSubject.value.expires - Date.now()) / 1000 ); this.countDown = {} as any; this.countDown.day = Math.floor(t / 86400); @@ -119,30 +119,30 @@ export class GalleryComponent implements OnInit, OnDestroy { async ngOnInit(): Promise { await this.shareService.wait(); if ( - !this.authService.isAuthenticated() && - (!this.shareService.isSharing() || - (this.shareService.isSharing() && - Config.Sharing.passwordProtected === true)) + !this.authService.isAuthenticated() && + (!this.shareService.isSharing() || + (this.shareService.isSharing() && + Config.Sharing.passwordProtected === true)) ) { return this.navigation.toLogin(); } this.showSearchBar = this.authService.canSearch(); this.showShare = - Config.Sharing.enabled && - this.authService.isAuthorized(UserRoles.User); + Config.Sharing.enabled && + this.authService.isAuthorized(UserRoles.User); this.showRandomPhotoBuilder = - Config.RandomPhoto.enabled && - this.authService.isAuthorized(UserRoles.User); + Config.RandomPhoto.enabled && + this.authService.isAuthorized(UserRoles.User); this.subscription.content = this.galleryService.sortedFilteredContent - .subscribe((dc: GroupedDirectoryContent) => { - this.onContentChange(dc); - }); + .subscribe((dc: GroupedDirectoryContent) => { + this.onContentChange(dc); + }); this.subscription.route = this.route.params.subscribe(this.onRoute); if (this.shareService.isSharing()) { this.$counter = interval(1000); this.subscription.timer = this.$counter.subscribe((x): void => - this.updateTimer(x) + this.updateTimer(x) ); } } @@ -156,18 +156,18 @@ export class GalleryComponent implements OnInit, OnDestroy { } if ( - params[QueryParams.gallery.sharingKey_params] && - params[QueryParams.gallery.sharingKey_params] !== '' + params[QueryParams.gallery.sharingKey_params] && + params[QueryParams.gallery.sharingKey_params] !== '' ) { const sharing = await this.shareService.currentSharing - .pipe(take(1)) - .toPromise(); + .pipe(take(1)) + .toPromise(); const qParams: { [key: string]: any } = {}; qParams[QueryParams.gallery.sharingKey_query] = - this.shareService.getSharingKey(); + this.shareService.getSharingKey(); this.router - .navigate(['/gallery', sharing.path], {queryParams: qParams}) - .catch(console.error); + .navigate(['/gallery', sharing.path], {queryParams: qParams}) + .catch(console.error); return; } @@ -191,8 +191,8 @@ export class GalleryComponent implements OnInit, OnDestroy { for (const mediaGroup of content.mediaGroups) { if ( - mediaGroup.media - .findIndex((m: PhotoDTO) => !!m.metadata?.positionData?.GPSData?.longitude) !== -1 + mediaGroup.media + .findIndex((m: PhotoDTO) => !!m.metadata?.positionData?.GPSData?.longitude) !== -1 ) { this.isPhotoWithLocation = true; break; diff --git a/src/frontend/app/ui/gallery/grid/GridMedia.ts b/src/frontend/app/ui/gallery/grid/GridMedia.ts index cc288e55..ff9ab3c1 100644 --- a/src/frontend/app/ui/gallery/grid/GridMedia.ts +++ b/src/frontend/app/ui/gallery/grid/GridMedia.ts @@ -5,10 +5,10 @@ import {VideoDTO} from '../../../../../common/entities/VideoDTO'; export class GridMedia extends Media { constructor( - media: MediaDTO, - renderWidth: number, - renderHeight: number, - public rowId: number + media: MediaDTO, + renderWidth: number, + renderHeight: number, + public rowId: number ) { super(media, renderWidth, renderHeight); } diff --git a/src/frontend/app/ui/gallery/grid/photo/loading/loading.photo.grid.gallery.component.ts b/src/frontend/app/ui/gallery/grid/photo/loading/loading.photo.grid.gallery.component.ts index aec0fe61..0950aa79 100644 --- a/src/frontend/app/ui/gallery/grid/photo/loading/loading.photo.grid.gallery.component.ts +++ b/src/frontend/app/ui/gallery/grid/photo/loading/loading.photo.grid.gallery.component.ts @@ -1,4 +1,4 @@ -import { Component, Input } from '@angular/core'; +import {Component, Input} from '@angular/core'; @Component({ selector: 'app-gallery-grid-photo-loading', diff --git a/src/frontend/app/ui/gallery/grid/photo/photo.grid.gallery.component.ts b/src/frontend/app/ui/gallery/grid/photo/photo.grid.gallery.component.ts index 9ce692ef..ce3716e0 100644 --- a/src/frontend/app/ui/gallery/grid/photo/photo.grid.gallery.component.ts +++ b/src/frontend/app/ui/gallery/grid/photo/photo.grid.gallery.component.ts @@ -32,8 +32,8 @@ export class GalleryPhotoComponent implements IRenderable, OnInit, OnDestroy { loaded = false; constructor( - private thumbnailService: ThumbnailManagerService, - private authService: AuthenticationService + private thumbnailService: ThumbnailManagerService, + private authService: AuthenticationService ) { this.searchEnabled = this.authService.canSearch(); } @@ -49,8 +49,8 @@ export class GalleryPhotoComponent implements IRenderable, OnInit, OnDestroy { if ((this.gridMedia.media as PhotoDTO).metadata.caption) { if ((this.gridMedia.media as PhotoDTO).metadata.caption.length > 20) { return ( - (this.gridMedia.media as PhotoDTO).metadata.caption.substring(0, 17) + - '...' + (this.gridMedia.media as PhotoDTO).metadata.caption.substring(0, 17) + + '...' ); } return (this.gridMedia.media as PhotoDTO).metadata.caption; @@ -62,28 +62,28 @@ export class GalleryPhotoComponent implements IRenderable, OnInit, OnDestroy { this.thumbnail = this.thumbnailService.getThumbnail(this.gridMedia); const metadata = this.gridMedia.media.metadata as PhotoMetadata; if ( - (metadata.keywords && metadata.keywords.length > 0) || - (metadata.faces && metadata.faces.length > 0) + (metadata.keywords && metadata.keywords.length > 0) || + (metadata.faces && metadata.faces.length > 0) ) { this.keywords = []; if (Config.Faces.enabled) { const names: string[] = (metadata.faces || []).map( - (f): string => f.name + (f): string => f.name ); this.keywords = names - .filter((name, index): boolean => names.indexOf(name) === index) - .map((n): { type: SearchQueryTypes; value: string } => ({ - value: n, - type: SearchQueryTypes.person, - })); + .filter((name, index): boolean => names.indexOf(name) === index) + .map((n): { type: SearchQueryTypes; value: string } => ({ + value: n, + type: SearchQueryTypes.person, + })); } this.keywords = this.keywords.concat( - (metadata.keywords || []).map( - (k): { type: SearchQueryTypes; value: string } => ({ - value: k, - type: SearchQueryTypes.keyword, - }) - ) + (metadata.keywords || []).map( + (k): { type: SearchQueryTypes; value: string } => ({ + value: k, + type: SearchQueryTypes.keyword, + }) + ) ); } } @@ -98,11 +98,11 @@ export class GalleryPhotoComponent implements IRenderable, OnInit, OnDestroy { isInView(): boolean { return ( - PageHelper.ScrollY < - this.container.nativeElement.offsetTop + - this.container.nativeElement.clientHeight && - PageHelper.ScrollY + window.innerHeight > - this.container.nativeElement.offsetTop + PageHelper.ScrollY < + this.container.nativeElement.offsetTop + + this.container.nativeElement.clientHeight && + PageHelper.ScrollY + window.innerHeight > + this.container.nativeElement.offsetTop ); } @@ -138,9 +138,9 @@ export class GalleryPhotoComponent implements IRenderable, OnInit, OnDestroy { return ''; } return ( - (this.gridMedia.media as PhotoDTO).metadata.positionData.city || - (this.gridMedia.media as PhotoDTO).metadata.positionData.state || - (this.gridMedia.media as PhotoDTO).metadata.positionData.country || '' + (this.gridMedia.media as PhotoDTO).metadata.positionData.city || + (this.gridMedia.media as PhotoDTO).metadata.positionData.state || + (this.gridMedia.media as PhotoDTO).metadata.positionData.country || '' ).trim(); } diff --git a/src/frontend/app/ui/gallery/lightbox/controls/controls.lightbox.gallery.component.ts b/src/frontend/app/ui/gallery/lightbox/controls/controls.lightbox.gallery.component.ts index de191219..4b9a0cf8 100644 --- a/src/frontend/app/ui/gallery/lightbox/controls/controls.lightbox.gallery.component.ts +++ b/src/frontend/app/ui/gallery/lightbox/controls/controls.lightbox.gallery.component.ts @@ -61,10 +61,10 @@ export class ControlsLightboxComponent implements OnDestroy, OnInit, OnChanges { private prevZoom = 1; constructor( - public lightboxService: LightboxService, - public fullScreenService: FullScreenService, - private authService: AuthenticationService, - private cacheService: GalleryCacheService + public lightboxService: LightboxService, + public fullScreenService: FullScreenService, + private authService: AuthenticationService, + private cacheService: GalleryCacheService ) { this.searchEnabled = this.authService.canSearch(); } @@ -271,18 +271,18 @@ export class ControlsLightboxComponent implements OnDestroy, OnInit, OnChanges { private showNextMedia = () => { if (this.mediaElement.imageLoadFinished.this === false || - this.mediaElement.imageLoadFinished.next === false) { + this.mediaElement.imageLoadFinished.next === false) { return; } // do not skip video if its playing if ( - this.activePhoto && - this.activePhoto.gridMedia.isVideo() && - !this.mediaElement.Paused + this.activePhoto && + this.activePhoto.gridMedia.isVideo() && + !this.mediaElement.Paused ) { return; } - // this.nextPhoto.emit(); + // this.nextPhoto.emit(); }; private drawSliderProgress(t: number) { @@ -290,8 +290,8 @@ export class ControlsLightboxComponent implements OnDestroy, OnInit, OnChanges { // Video is a special snowflake. It won't go to next media if a video is playing if (!(this.activePhoto && - this.activePhoto.gridMedia.isVideo() && - !this.mediaElement.Paused)) { + this.activePhoto.gridMedia.isVideo() && + !this.mediaElement.Paused)) { p = (t % (this.selectedSlideshowSpeed * 10)) / this.selectedSlideshowSpeed / 10; // ticks every 100 ms } @@ -322,12 +322,12 @@ export class ControlsLightboxComponent implements OnDestroy, OnInit, OnChanges { this.pause(); this.drawSliderProgress(0); this.timerSub = interval(100) - .pipe(filter((t) => { - this.drawSliderProgress(t); - return t % (this.selectedSlideshowSpeed * 10) === 0; // ticks every 100 ms - })) - .pipe(skip(1)) // do not skip to next photo right away - .subscribe(this.showNextMedia); + .pipe(filter((t) => { + this.drawSliderProgress(t); + return t % (this.selectedSlideshowSpeed * 10) === 0; // ticks every 100 ms + })) + .pipe(skip(1)) // do not skip to next photo right away + .subscribe(this.showNextMedia); this.playBackState = PlayBackStates.Play; } @@ -381,7 +381,7 @@ export class ControlsLightboxComponent implements OnDestroy, OnInit, OnChanges { } const photoAspect = MediaDTOUtils.calcAspectRatio( - this.activePhoto.gridMedia.media + this.activePhoto.gridMedia.media ); const widthFilled = photoAspect > this.photoFrameDim.aspect; const divWidth = this.photoFrameDim.width; @@ -442,7 +442,7 @@ export class ControlsLightboxComponent implements OnDestroy, OnInit, OnChanges { } const photoAspect = MediaDTOUtils.calcAspectRatio( - this.activePhoto.gridMedia.media + this.activePhoto.gridMedia.media ); if (photoAspect < this.photoFrameDim.aspect) { diff --git a/src/frontend/app/ui/gallery/lightbox/infopanel/info-panel.lightbox.gallery.component.ts b/src/frontend/app/ui/gallery/lightbox/infopanel/info-panel.lightbox.gallery.component.ts index 5403a33c..a1254d2a 100644 --- a/src/frontend/app/ui/gallery/lightbox/infopanel/info-panel.lightbox.gallery.component.ts +++ b/src/frontend/app/ui/gallery/lightbox/infopanel/info-panel.lightbox.gallery.component.ts @@ -30,11 +30,11 @@ export class InfoPanelLightboxComponent implements OnInit, OnChanges { public markerLayer: Marker[] = []; constructor( - public queryService: QueryService, - public contentLoaderService: ContentLoaderService, - public mapService: MapService, - private authService: AuthenticationService, - private themeService: ThemeService + public queryService: QueryService, + public contentLoaderService: ContentLoaderService, + public mapService: MapService, + private authService: AuthenticationService, + private themeService: ThemeService ) { this.mapEnabled = Config.Map.enabled; this.searchEnabled = this.authService.canSearch(); @@ -51,16 +51,16 @@ export class InfoPanelLightboxComponent implements OnInit, OnChanges { get FullPath(): string { return Utils.concatUrls( - this.media.directory.path, - this.media.directory.name, - this.media.name + this.media.directory.path, + this.media.directory.name, + this.media.name ); } get DirectoryPath(): string { return Utils.concatUrls( - this.media.directory.path, - this.media.directory.name + this.media.directory.path, + this.media.directory.name ); } @@ -108,28 +108,28 @@ export class InfoPanelLightboxComponent implements OnInit, OnChanges { ngOnInit(): void { const metadata = this.media.metadata as PhotoMetadata; if ( - (metadata.keywords && metadata.keywords.length > 0) || - (metadata.faces && metadata.faces.length > 0) + (metadata.keywords && metadata.keywords.length > 0) || + (metadata.faces && metadata.faces.length > 0) ) { this.keywords = []; if (Config.Faces.enabled) { const names: string[] = (metadata.faces || []).map( - (f): string => f.name + (f): string => f.name ); this.keywords = names - .filter((name, index): boolean => names.indexOf(name) === index) - .map((n): { type: SearchQueryTypes; value: string } => ({ - value: n, - type: SearchQueryTypes.person, - })); + .filter((name, index): boolean => names.indexOf(name) === index) + .map((n): { type: SearchQueryTypes; value: string } => ({ + value: n, + type: SearchQueryTypes.person, + })); } this.keywords = this.keywords.concat( - (metadata.keywords || []).map( - (k): { type: SearchQueryTypes; value: string } => ({ - value: k, - type: SearchQueryTypes.keyword, - }) - ) + (metadata.keywords || []).map( + (k): { type: SearchQueryTypes; value: string } => ({ + value: k, + type: SearchQueryTypes.keyword, + }) + ) ); } } @@ -140,15 +140,15 @@ export class InfoPanelLightboxComponent implements OnInit, OnChanges { calcMpx(): string { return ( - (this.media.metadata.size.width * this.media.metadata.size.height) / - 1000000 + (this.media.metadata.size.width * this.media.metadata.size.height) / + 1000000 ).toFixed(2); } isThisYear(): boolean { return ( - new Date().getFullYear() === - new Date(this.media.metadata.creationDate).getUTCFullYear() + new Date().getFullYear() === + new Date(this.media.metadata.creationDate).getUTCFullYear() ); } @@ -161,21 +161,21 @@ export class InfoPanelLightboxComponent implements OnInit, OnChanges { hasTextPositionData(): boolean { return ( - !!(this.media as PhotoDTO).metadata.positionData && - !!( - (this.media as PhotoDTO).metadata.positionData.city || - (this.media as PhotoDTO).metadata.positionData.state || - (this.media as PhotoDTO).metadata.positionData.country - ) + !!(this.media as PhotoDTO).metadata.positionData && + !!( + (this.media as PhotoDTO).metadata.positionData.city || + (this.media as PhotoDTO).metadata.positionData.state || + (this.media as PhotoDTO).metadata.positionData.country + ) ); } hasGPS(): boolean { return !!( - (this.media as PhotoDTO).metadata.positionData && - (this.media as PhotoDTO).metadata.positionData.GPSData && - (this.media as PhotoDTO).metadata.positionData.GPSData.latitude && - (this.media as PhotoDTO).metadata.positionData.GPSData.longitude + (this.media as PhotoDTO).metadata.positionData && + (this.media as PhotoDTO).metadata.positionData.GPSData && + (this.media as PhotoDTO).metadata.positionData.GPSData.latitude && + (this.media as PhotoDTO).metadata.positionData.GPSData.longitude ); } @@ -184,9 +184,9 @@ export class InfoPanelLightboxComponent implements OnInit, OnChanges { return ''; } let str = - (this.media as PhotoDTO).metadata.positionData.city || - (this.media as PhotoDTO).metadata.positionData.state || - ''; + (this.media as PhotoDTO).metadata.positionData.city || + (this.media as PhotoDTO).metadata.positionData.state || + ''; if (str.length !== 0) { str += ', '; diff --git a/src/frontend/app/ui/gallery/lightbox/lightbox.gallery.component.ts b/src/frontend/app/ui/gallery/lightbox/lightbox.gallery.component.ts index 6fba910e..39a2d514 100644 --- a/src/frontend/app/ui/gallery/lightbox/lightbox.gallery.component.ts +++ b/src/frontend/app/ui/gallery/lightbox/lightbox.gallery.component.ts @@ -67,14 +67,14 @@ export class GalleryLightboxComponent implements OnDestroy, OnInit { }; constructor( - public fullScreenService: FullScreenService, - private changeDetector: ChangeDetectorRef, - private overlayService: OverlayService, - private builder: AnimationBuilder, - private router: Router, - private queryService: QueryService, - private route: ActivatedRoute, - private piTitleService: PiTitleService + public fullScreenService: FullScreenService, + private changeDetector: ChangeDetectorRef, + private overlayService: OverlayService, + private builder: AnimationBuilder, + private router: Router, + private queryService: QueryService, + private route: ActivatedRoute, + private piTitleService: PiTitleService ) { } @@ -104,20 +104,20 @@ export class GalleryLightboxComponent implements OnDestroy, OnInit { this.infoPanelMaxWidth = 1000; this.updatePhotoFrameDim(); this.subscription.route = this.route.queryParams.subscribe( - (params: Params) => { - if ( - params[QueryParams.gallery.photo] && - params[QueryParams.gallery.photo] !== '' - ) { - if (!this.gridPhotoQL) { - return (this.delayedMediaShow = params[QueryParams.gallery.photo]); + (params: Params) => { + if ( + params[QueryParams.gallery.photo] && + params[QueryParams.gallery.photo] !== '' + ) { + if (!this.gridPhotoQL) { + return (this.delayedMediaShow = params[QueryParams.gallery.photo]); + } + this.onNavigateTo(params[QueryParams.gallery.photo]); + } else if (this.status === LightboxStates.Open) { + this.delayedMediaShow = null; + this.hideLightbox(); } - this.onNavigateTo(params[QueryParams.gallery.photo]); - } else if (this.status === LightboxStates.Open) { - this.delayedMediaShow = null; - this.hideLightbox(); } - } ); } @@ -142,9 +142,9 @@ export class GalleryLightboxComponent implements OnDestroy, OnInit { onNavigateTo(photoStringId: string): string { if ( - this.activePhoto && - this.queryService.getMediaStringId(this.activePhoto.gridMedia.media) === - photoStringId + this.activePhoto && + this.queryService.getMediaStringId(this.activePhoto.gridMedia.media) === + photoStringId ) { return; } @@ -153,8 +153,8 @@ export class GalleryLightboxComponent implements OnDestroy, OnInit { this.controls.resetZoom(); } const photo = this.gridPhotoQL.find( - (i): boolean => - this.queryService.getMediaStringId(i.gridMedia.media) === photoStringId + (i): boolean => + this.queryService.getMediaStringId(i.gridMedia.media) === photoStringId ); if (!photo) { return (this.delayedMediaShow = photoStringId); @@ -173,17 +173,17 @@ export class GalleryLightboxComponent implements OnDestroy, OnInit { } this.gridPhotoQL = value; this.subscription.photosChange = this.gridPhotoQL.changes.subscribe( - (): void => { - if ( - this.activePhotoId != null && - this.gridPhotoQL.length > this.activePhotoId - ) { - this.updateActivePhoto(this.activePhotoId); + (): void => { + if ( + this.activePhotoId != null && + this.gridPhotoQL.length > this.activePhotoId + ) { + this.updateActivePhoto(this.activePhotoId); + } + if (this.delayedMediaShow) { + this.onNavigateTo(this.delayedMediaShow); + } } - if (this.delayedMediaShow) { - this.onNavigateTo(this.delayedMediaShow); - } - } ); if (this.delayedMediaShow) { @@ -231,8 +231,8 @@ export class GalleryLightboxComponent implements OnDestroy, OnInit { lightboxDimension.top -= PageHelper.ScrollY; this.animating = true; this.animatePhoto( - selectedPhoto.getDimension(), - this.calcLightBoxPhotoDimension(selectedPhoto.gridMedia.media) + selectedPhoto.getDimension(), + this.calcLightBoxPhotoDimension(selectedPhoto.gridMedia.media) ).onDone((): void => { this.animating = false; this.status = LightboxStates.Open; @@ -255,41 +255,41 @@ export class GalleryLightboxComponent implements OnDestroy, OnInit { public hide(): void { this.router - .navigate([], {queryParams: this.queryService.getParams()}) - .then(() => { - this.piTitleService.setLastNonMedia(); - }) - .catch(console.error); + .navigate([], {queryParams: this.queryService.getParams()}) + .then(() => { + this.piTitleService.setLastNonMedia(); + }) + .catch(console.error); } animatePhoto(from: Dimension, to: Dimension = from): AnimationPlayer { const elem = this.builder - .build([ - style(DimensionUtils.toString(from)), - animate('0.2s ease-in-out', style(DimensionUtils.toString(to))), - ]) - .create(this.mediaElement.elementRef.nativeElement); + .build([ + style(DimensionUtils.toString(from)), + animate('0.2s ease-in-out', style(DimensionUtils.toString(to))), + ]) + .create(this.mediaElement.elementRef.nativeElement); elem.play(); return elem; } animateLightbox( - from: Dimension = { - top: 0, - left: 0, - width: this.photoFrameDim.width, - height: this.photoFrameDim.height, - } as Dimension, - to: Dimension = from + from: Dimension = { + top: 0, + left: 0, + width: this.photoFrameDim.width, + height: this.photoFrameDim.height, + } as Dimension, + to: Dimension = from ): AnimationPlayer { const elem = this.builder - .build([ - style(DimensionUtils.toString(from)), - animate('0.2s ease-in-out', style(DimensionUtils.toString(to))), - ]) - .create(this.lightboxElement.nativeElement); + .build([ + style(DimensionUtils.toString(from)), + animate('0.2s ease-in-out', style(DimensionUtils.toString(to))), + ]) + .create(this.lightboxElement.nativeElement); elem.play(); return elem; } @@ -309,30 +309,30 @@ export class GalleryLightboxComponent implements OnDestroy, OnInit { }, 1000); const starPhotoPos = this.calcLightBoxPhotoDimension( - this.activePhoto.gridMedia.media + this.activePhoto.gridMedia.media ); this.infoPanelWidth = 0; this.updatePhotoFrameDim(); const endPhotoPos = this.calcLightBoxPhotoDimension( - this.activePhoto.gridMedia.media + this.activePhoto.gridMedia.media ); if (enableAnimate) { this.animatePhoto(starPhotoPos, endPhotoPos); } if (enableAnimate) { this.animateLightbox( - { - top: 0, - left: 0, - width: Math.max(this.photoFrameDim.width - this.infoPanelMaxWidth, 0), - height: this.photoFrameDim.height, - } as Dimension, - { - top: 0, - left: 0, - width: this.photoFrameDim.width, - height: this.photoFrameDim.height, - } as Dimension + { + top: 0, + left: 0, + width: Math.max(this.photoFrameDim.width - this.infoPanelMaxWidth, 0), + height: this.photoFrameDim.height, + } as Dimension, + { + top: 0, + left: 0, + width: this.photoFrameDim.width, + height: this.photoFrameDim.height, + } as Dimension ); } } @@ -346,27 +346,27 @@ export class GalleryLightboxComponent implements OnDestroy, OnInit { this.infoPanelVisible = true; const starPhotoPos = this.calcLightBoxPhotoDimension( - this.activePhoto.gridMedia.media + this.activePhoto.gridMedia.media ); this.infoPanelWidth = this.infoPanelMaxWidth; this.updatePhotoFrameDim(); const endPhotoPos = this.calcLightBoxPhotoDimension( - this.activePhoto.gridMedia.media + this.activePhoto.gridMedia.media ); this.animatePhoto(starPhotoPos, endPhotoPos); this.animateLightbox( - { - top: 0, - left: 0, - width: this.photoFrameDim.width + this.infoPanelMaxWidth, - height: this.photoFrameDim.height, - } as Dimension, - { - top: 0, - left: 0, - width: this.photoFrameDim.width, - height: this.photoFrameDim.height, - } as Dimension + { + top: 0, + left: 0, + width: this.photoFrameDim.width + this.infoPanelMaxWidth, + height: this.photoFrameDim.height, + } as Dimension, + { + top: 0, + left: 0, + width: this.photoFrameDim.width, + height: this.photoFrameDim.height, + } as Dimension ); if (this.iPvisibilityTimer != null) { clearTimeout(this.iPvisibilityTimer); @@ -392,28 +392,28 @@ export class GalleryLightboxComponent implements OnDestroy, OnInit { private updatePhotoFrameDim = (): void => { this.photoFrameDim = { width: Math.max( - window.innerWidth - this.infoPanelWidth, - 0 + window.innerWidth - this.infoPanelWidth, + 0 ), height: window.innerHeight, aspect: 0 }; this.photoFrameDim.aspect = - Math.round((this.photoFrameDim.width / this.photoFrameDim.height) * 100) / - 100; + Math.round((this.photoFrameDim.width / this.photoFrameDim.height) * 100) / + 100; }; private navigateToPhoto(photoIndex: number): void { this.router - .navigate([], { - queryParams: this.queryService.getParams( - this.gridPhotoQL.get(photoIndex).gridMedia.media - ), - }) - .then(() => { - this.piTitleService.setMediaTitle(this.gridPhotoQL.get(photoIndex).gridMedia); - }) - .catch(console.error); + .navigate([], { + queryParams: this.queryService.getParams( + this.gridPhotoQL.get(photoIndex).gridMedia.media + ), + }) + .then(() => { + this.piTitleService.setMediaTitle(this.gridPhotoQL.get(photoIndex).gridMedia); + }) + .catch(console.error); } @@ -440,17 +440,17 @@ export class GalleryLightboxComponent implements OnDestroy, OnInit { this.blackCanvasOpacity = 0; this.animatePhoto( - this.calcLightBoxPhotoDimension(this.activePhoto.gridMedia.media), - this.activePhoto.getDimension() + this.calcLightBoxPhotoDimension(this.activePhoto.gridMedia.media), + this.activePhoto.getDimension() ); this.animateLightbox( - { - top: 0, - left: 0, - width: this.photoFrameDim.width, - height: this.photoFrameDim.height, - } as Dimension, - lightboxDimension + { + top: 0, + left: 0, + width: this.photoFrameDim.width, + height: this.photoFrameDim.height, + } as Dimension, + lightboxDimension ).onDone((): void => { this.status = LightboxStates.Closed; this.activePhoto = null; @@ -471,7 +471,7 @@ export class GalleryLightboxComponent implements OnDestroy, OnInit { if (resize) { this.animatePhoto( - this.calcLightBoxPhotoDimension(this.activePhoto.gridMedia.media) + this.calcLightBoxPhotoDimension(this.activePhoto.gridMedia.media) ); } this.navigation.hasPrev = photoIndex > 0; @@ -481,8 +481,8 @@ export class GalleryLightboxComponent implements OnDestroy, OnInit { // if target image out of screen -> scroll to there if ( - PageHelper.ScrollY > to.top || - PageHelper.ScrollY + this.photoFrameDim.height < to.top + PageHelper.ScrollY > to.top || + PageHelper.ScrollY + this.photoFrameDim.height < to.top ) { PageHelper.ScrollY = to.top; } @@ -505,15 +505,15 @@ export class GalleryLightboxComponent implements OnDestroy, OnInit { const windowAspect = this.photoFrameDim.aspect; if (photoAspect < windowAspect) { width = Math.round( - photo.metadata.size.width * - (this.photoFrameDim.height / photo.metadata.size.height) + photo.metadata.size.width * + (this.photoFrameDim.height / photo.metadata.size.height) ); height = this.photoFrameDim.height; } else { width = this.photoFrameDim.width; height = Math.round( - photo.metadata.size.height * - (this.photoFrameDim.width / photo.metadata.size.width) + photo.metadata.size.height * + (this.photoFrameDim.width / photo.metadata.size.width) ); } const top = this.photoFrameDim.height / 2 - height / 2; diff --git a/src/frontend/app/ui/gallery/lightbox/media/media.lightbox.gallery.component.ts b/src/frontend/app/ui/gallery/lightbox/media/media.lightbox.gallery.component.ts index 035efb17..0842d89f 100644 --- a/src/frontend/app/ui/gallery/lightbox/media/media.lightbox.gallery.component.ts +++ b/src/frontend/app/ui/gallery/lightbox/media/media.lightbox.gallery.component.ts @@ -1,12 +1,4 @@ -import { - Component, - ElementRef, - EventEmitter, - Input, - OnChanges, - Output, - ViewChild, -} from '@angular/core'; +import {Component, ElementRef, EventEmitter, Input, OnChanges, Output, ViewChild,} from '@angular/core'; import {GridMedia} from '../../grid/GridMedia'; import {MediaDTOUtils} from '../../../../../../common/entities/MediaDTO'; import {DomSanitizer, SafeStyle} from '@angular/platform-browser'; @@ -56,17 +48,17 @@ export class GalleryLightboxMediaComponent implements OnChanges { get ImageTransform(): SafeStyle { return this.sanitizer.bypassSecurityTrustStyle( - 'scale(' + - this.zoom + - ') translate(calc(' + - -50 / this.zoom + - '% + ' + - this.drag.x / this.zoom + - 'px), calc(' + - -50 / this.zoom + - '% + ' + - this.drag.y / this.zoom + - 'px))' + 'scale(' + + this.zoom + + ') translate(calc(' + + -50 / this.zoom + + '% + ' + + this.drag.x / this.zoom + + 'px), calc(' + + -50 / this.zoom + + '% + ' + + this.drag.y / this.zoom + + 'px))' ); } @@ -79,7 +71,7 @@ export class GalleryLightboxMediaComponent implements OnChanges { return; } this.video.nativeElement.currentTime = - this.video.nativeElement.duration * (value / 100); + this.video.nativeElement.duration * (value / 100); if (this.video.nativeElement.paused) { this.video.nativeElement.play().catch(console.error); } @@ -142,9 +134,9 @@ export class GalleryLightboxMediaComponent implements OnChanges { } this.setImageSize(); if ( - this.thumbnailSrc == null && - this.gridMedia && - this.ThumbnailUrl !== null + this.thumbnailSrc == null && + this.gridMedia && + this.ThumbnailUrl !== null ) { this.thumbnailSrc = this.ThumbnailUrl; } @@ -175,8 +167,8 @@ export class GalleryLightboxMediaComponent implements OnChanges { // TODO:handle error this.imageLoadFinished.this = true; console.error( - 'Error: cannot load media for lightbox url: ' + - this.gridMedia.getBestFitMediaPath() + 'Error: cannot load media for lightbox url: ' + + this.gridMedia.getBestFitMediaPath() ); this.loadNextPhoto(); } @@ -189,11 +181,11 @@ export class GalleryLightboxMediaComponent implements OnChanges { public showThumbnail(): boolean { return ( - this.gridMedia && - !this.mediaLoaded && - this.thumbnailSrc !== null && - (this.gridMedia.isThumbnailAvailable() || - this.gridMedia.isReplacementThumbnailAvailable()) + this.gridMedia && + !this.mediaLoaded && + this.thumbnailSrc !== null && + (this.gridMedia.isThumbnailAvailable() || + this.gridMedia.isReplacementThumbnailAvailable()) ); } @@ -239,8 +231,8 @@ export class GalleryLightboxMediaComponent implements OnChanges { } if ( - this.zoom === 1 || - Config.Media.Photo.Converting.loadFullImageOnZoom === false + this.zoom === 1 || + Config.Media.Photo.Converting.loadFullImageOnZoom === false ) { if (this.photo.src == null) { if (Config.Media.Photo.Converting.enabled === true) { @@ -260,8 +252,8 @@ export class GalleryLightboxMediaComponent implements OnChanges { public onVideoProgress(): void { this.videoProgress = - (100 / this.video.nativeElement.duration) * - this.video.nativeElement.currentTime; + (100 / this.video.nativeElement.duration) * + this.video.nativeElement.currentTime; } private setImageSize(): void { diff --git a/src/frontend/app/ui/gallery/map/MarkerFactory.ts b/src/frontend/app/ui/gallery/map/MarkerFactory.ts index e462823d..40ed0b58 100644 --- a/src/frontend/app/ui/gallery/map/MarkerFactory.ts +++ b/src/frontend/app/ui/gallery/map/MarkerFactory.ts @@ -19,8 +19,8 @@ const SvgIcon: { new(options?: SvgIconOptions): DivIcon } = DivIcon.extend({ popupAnchor: options.small ? [0, -15] : [0, -30], className: 'custom-div-icon' + (options.small ? ' marker-svg-small' : ''), html: '
' + - '
' + - '
' + svg + '
', + '
' + + '
' + svg + '', }); } }); diff --git a/src/frontend/app/ui/gallery/map/lightbox/lightbox.map.gallery.component.ts b/src/frontend/app/ui/gallery/map/lightbox/lightbox.map.gallery.component.ts index dfc6a12e..7a4070fe 100644 --- a/src/frontend/app/ui/gallery/map/lightbox/lightbox.map.gallery.component.ts +++ b/src/frontend/app/ui/gallery/map/lightbox/lightbox.map.gallery.component.ts @@ -72,12 +72,12 @@ export class GalleryMapLightboxComponent implements OnChanges, OnDestroy { defLayer: TileLayer; darkLayer: TileLayer; private smallIconSize = new Point( - Config.Media.Thumbnail.iconSize * 0.75, - Config.Media.Thumbnail.iconSize * 0.75 + Config.Media.Thumbnail.iconSize * 0.75, + Config.Media.Thumbnail.iconSize * 0.75 ); private iconSize = new Point( - Config.Media.Thumbnail.iconSize, - Config.Media.Thumbnail.iconSize + Config.Media.Thumbnail.iconSize, + Config.Media.Thumbnail.iconSize ); private usedIconSize = this.iconSize; private mapLayersControlOption: LeafletControlLayersConfig & { @@ -132,10 +132,10 @@ export class GalleryMapLightboxComponent implements OnChanges, OnDestroy { private longPathSEPairs: { [key: string]: number } = {}; // stores how often a long distance path pair comes up constructor( - public fullScreenService: FullScreenService, - private thumbnailService: ThumbnailManagerService, - public mapService: MapService, - private themeService: ThemeService + public fullScreenService: FullScreenService, + private thumbnailService: ThumbnailManagerService, + public mapService: MapService, + private themeService: ThemeService ) { this.setUpPathLayers(); this.mapOptions.layers = [this.mapLayersControlOption.overlays.Photos]; @@ -157,9 +157,9 @@ export class GalleryMapLightboxComponent implements OnChanges, OnDestroy { this.mapOptions.layers.push(this.themeService.darkMode.value ? this.darkLayer : this.defLayer); this.mapLayerControl = control.layers( - this.mapLayersControlOption.baseLayers, - this.mapLayersControlOption.overlays, - {position: 'bottomright'} + this.mapLayersControlOption.baseLayers, + this.mapLayersControlOption.overlays, + {position: 'bottomright'} ); // update map theme on dark theme @@ -169,7 +169,7 @@ export class GalleryMapLightboxComponent implements OnChanges, OnDestroy { setUpPathLayers() { - Config.Map.MapPathGroupConfig.forEach((conf, i) => { + Config.Map.MapPathGroupConfig.forEach((conf) => { let nameI18n = conf.name; switch (conf.name) { case 'Sport': @@ -297,9 +297,9 @@ export class GalleryMapLightboxComponent implements OnChanges, OnDestroy { // if target image out of screen -> scroll to there if ( - PageHelper.ScrollY > to.top || - PageHelper.ScrollY + GalleryMapLightboxComponent.getScreenHeight() < - to.top + PageHelper.ScrollY > to.top || + PageHelper.ScrollY + GalleryMapLightboxComponent.getScreenHeight() < + to.top ) { PageHelper.ScrollY = to.top; } @@ -320,106 +320,106 @@ export class GalleryMapLightboxComponent implements OnChanges, OnDestroy { // make sure to enable photos layers when opening map if ( - this.leafletMap && - !this.leafletMap.hasLayer(this.mapLayersControlOption.overlays.Photos) + this.leafletMap && + !this.leafletMap.hasLayer(this.mapLayersControlOption.overlays.Photos) ) { this.leafletMap.addLayer(this.mapLayersControlOption.overlays.Photos); } this.thumbnailsOnLoad = []; this.photos - .filter((p): number => { - return ( - p.metadata && - p.metadata.positionData && - p.metadata.positionData.GPSData && - p.metadata.positionData.GPSData.latitude && - p.metadata.positionData.GPSData.longitude - ); - }) - .forEach((p): void => { - const mkr = marker({ - lat: p.metadata.positionData.GPSData.latitude, - lng: p.metadata.positionData.GPSData.longitude, - }); - this.mapLayersControlOption.overlays.Photos.addLayer(mkr); - let width = 500; - let height = 500; - const size = p.metadata.size; - if (size.width > size.height) { - height = width * (size.height / size.width); - } else { - width = height * (size.width / size.height); - } - const photoTh = this.thumbnailService.getLazyThumbnail( - new Media(p, width, height) - ); - this.thumbnailsOnLoad.push(photoTh); - - // Setting popup photo - const setPopUpPhoto = () => { - const photoPopup = - `preview`; - if (!mkr.getPopup()) { - mkr.bindPopup(photoPopup, {minWidth: width}); + .filter((p): number => { + return ( + p.metadata && + p.metadata.positionData && + p.metadata.positionData.GPSData && + p.metadata.positionData.GPSData.latitude && + p.metadata.positionData.GPSData.longitude + ); + }) + .forEach((p): void => { + const mkr = marker({ + lat: p.metadata.positionData.GPSData.latitude, + lng: p.metadata.positionData.GPSData.longitude, + }); + this.mapLayersControlOption.overlays.Photos.addLayer(mkr); + let width = 500; + let height = 500; + const size = p.metadata.size; + if (size.width > size.height) { + height = width * (size.height / size.width); } else { - mkr.setPopupContent(photoPopup); + width = height * (size.width / size.height); } - }; + const photoTh = this.thumbnailService.getLazyThumbnail( + new Media(p, width, height) + ); + this.thumbnailsOnLoad.push(photoTh); - if (photoTh.Available) { - setPopUpPhoto(); - } else { - const noPhotoPopup = `