You've already forked pigallery2
							
							
				mirror of
				https://github.com/bpatrik/pigallery2.git
				synced 2025-10-30 23:57:43 +02:00 
			
		
		
		
	improving tests
This commit is contained in:
		| @@ -1,3 +1,4 @@ | ||||
| dist: trusty | ||||
| language: node_js | ||||
| node_js: | ||||
| - '9' | ||||
| @@ -14,3 +15,9 @@ deploy: | ||||
| cache: | ||||
|   directories: | ||||
|   - node_modules | ||||
|  | ||||
| addons: | ||||
|   chrome: stable | ||||
| before_install: | ||||
|   - # start your web application and listen on `localhost` | ||||
|   - google-chrome-stable --headless --disable-gpu --remote-debugging-port=9222 http://localhost & | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| import * as winston from "winston"; | ||||
| import * as winston from 'winston'; | ||||
|  | ||||
| declare module 'winston' { | ||||
|   interface LoggerInstance { | ||||
| @@ -10,19 +10,19 @@ declare module 'winston' { | ||||
| export const winstonSettings = { | ||||
|   transports: [ | ||||
|     new winston.transports.Console({ | ||||
|       level: process.env.NODE_ENV == "production" ? "info" : 'silly', | ||||
|       level: process.env.NODE_ENV == 'production' ? 'info' : 'silly', | ||||
|       handleExceptions: true, | ||||
|       json: false, | ||||
|       colorize: true, | ||||
|       timestamp: function () { | ||||
|         return (new Date()).toLocaleString(); | ||||
|       }, | ||||
|       label: "innerLabel", | ||||
|       label: 'innerLabel', | ||||
|       formatter: (options) => { | ||||
|         // Return string will be passed to logger. | ||||
|         return options.timestamp() + '[' + winston['config']['colorize'](options.level, options.level.toUpperCase()) + '] ' + | ||||
|           (undefined !== options.message ? options.message : '') + | ||||
|           (options.meta && Object.keys(options.meta).length ? '\n\t' + JSON.stringify(options.meta) : '' ); | ||||
|           (options.meta && Object.keys(options.meta).length ? '\n\t' + JSON.stringify(options.meta) : ''); | ||||
|       }, | ||||
|       debugStdout: true | ||||
|     }) | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| import * as path from "path"; | ||||
| import {Config} from "../common/config/private/Config"; | ||||
| import * as path from 'path'; | ||||
| import {Config} from '../common/config/private/Config'; | ||||
|  | ||||
| class ProjectPathClass { | ||||
|   public Root: string; | ||||
| @@ -24,10 +24,10 @@ class ProjectPathClass { | ||||
|   } | ||||
|  | ||||
|   reset() { | ||||
|     this.Root = path.join(__dirname, "/../"); | ||||
|     this.Root = path.join(__dirname, '/../'); | ||||
|     this.ImageFolder = this.getAbsolutePath(Config.Server.imagesFolder); | ||||
|     this.ThumbnailFolder = this.getAbsolutePath(Config.Server.thumbnail.folder); | ||||
|     this.FrontendFolder = path.join(this.Root, 'dist') | ||||
|     this.FrontendFolder = path.join(this.Root, 'dist'); | ||||
|   } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -1,9 +1,9 @@ | ||||
| import * as cluster from "cluster"; | ||||
| import * as cluster from 'cluster'; | ||||
|  | ||||
| if (cluster.isMaster) { | ||||
|   const Server = require("./server").Server; | ||||
|   new Server(); | ||||
|   const Server = require('./server').Server; | ||||
|   const srv = new Server(); | ||||
| } else { | ||||
|   const Worker = require("./model/threading/Worker").Worker; | ||||
|   const Worker = require('./model/threading/Worker').Worker; | ||||
|   Worker.process(); | ||||
| } | ||||
|   | ||||
| @@ -1,23 +1,18 @@ | ||||
| import {NextFunction, Request, Response} from "express"; | ||||
| import {ErrorCodes, ErrorDTO} from "../../common/entities/Error"; | ||||
| import {ObjectManagerRepository} from "../model/ObjectManagerRepository"; | ||||
| import {Logger} from "../Logger"; | ||||
| import {SQLConnection} from "../model/sql/SQLConnection"; | ||||
| import { | ||||
|   DataBaseConfig, | ||||
|   DatabaseType, | ||||
|   IndexingConfig, | ||||
|   ThumbnailConfig | ||||
| } from "../../common/config/private/IPrivateConfig"; | ||||
| import {Config} from "../../common/config/private/Config"; | ||||
| import {ConfigDiagnostics} from "../model/ConfigDiagnostics"; | ||||
| import {ClientConfig} from "../../common/config/public/ConfigClass"; | ||||
| import {BasicConfigDTO} from "../../common/entities/settings/BasicConfigDTO"; | ||||
| import {OtherConfigDTO} from "../../common/entities/settings/OtherConfigDTO"; | ||||
| import {ProjectPath} from "../ProjectPath"; | ||||
| import {NextFunction, Request, Response} from 'express'; | ||||
| import {ErrorCodes, ErrorDTO} from '../../common/entities/Error'; | ||||
| import {ObjectManagerRepository} from '../model/ObjectManagerRepository'; | ||||
| import {Logger} from '../Logger'; | ||||
| import {SQLConnection} from '../model/sql/SQLConnection'; | ||||
| import {DataBaseConfig, DatabaseType, IndexingConfig, ThumbnailConfig} from '../../common/config/private/IPrivateConfig'; | ||||
| import {Config} from '../../common/config/private/Config'; | ||||
| import {ConfigDiagnostics} from '../model/ConfigDiagnostics'; | ||||
| import {ClientConfig} from '../../common/config/public/ConfigClass'; | ||||
| import {BasicConfigDTO} from '../../common/entities/settings/BasicConfigDTO'; | ||||
| import {OtherConfigDTO} from '../../common/entities/settings/OtherConfigDTO'; | ||||
| import {ProjectPath} from '../ProjectPath'; | ||||
|  | ||||
|  | ||||
| const LOG_TAG = "[AdminMWs]"; | ||||
| const LOG_TAG = '[AdminMWs]'; | ||||
|  | ||||
| export class AdminMWs { | ||||
|  | ||||
| @@ -25,30 +20,30 @@ export class AdminMWs { | ||||
|   public static async updateDatabaseSettings(req: Request, res: Response, next: NextFunction) { | ||||
|  | ||||
|     if ((typeof req.body === 'undefined') || (typeof req.body.settings === 'undefined')) { | ||||
|       return next(new ErrorDTO(ErrorCodes.INPUT_ERROR, "settings is needed")); | ||||
|       return next(new ErrorDTO(ErrorCodes.INPUT_ERROR, 'settings is needed')); | ||||
|     } | ||||
|  | ||||
|     const databaseSettings = <DataBaseConfig>req.body.settings; | ||||
|  | ||||
|     try { | ||||
|       if (databaseSettings.type != DatabaseType.memory) { | ||||
|       if (databaseSettings.type !== DatabaseType.memory) { | ||||
|         await SQLConnection.tryConnection(databaseSettings); | ||||
|       } | ||||
|       Config.Server.database = databaseSettings; | ||||
|       //only updating explicitly set config (not saving config set by the diagnostics) | ||||
|       // only updating explicitly set config (not saving config set by the diagnostics) | ||||
|       const original = Config.original(); | ||||
|       original.Server.database = databaseSettings; | ||||
|       if (databaseSettings.type == DatabaseType.memory) { | ||||
|       if (databaseSettings.type === DatabaseType.memory) { | ||||
|         original.Client.Sharing.enabled = false; | ||||
|         original.Client.Search.enabled = false; | ||||
|       } | ||||
|       original.save(); | ||||
|       await ConfigDiagnostics.runDiagnostics(); | ||||
|       Logger.info(LOG_TAG, "new config:"); | ||||
|       Logger.info(LOG_TAG, 'new config:'); | ||||
|       Logger.info(LOG_TAG, JSON.stringify(Config, null, '\t')); | ||||
|  | ||||
|       ObjectManagerRepository.reset(); | ||||
|       if (Config.Server.database.type != DatabaseType.memory) { | ||||
|       if (Config.Server.database.type !== DatabaseType.memory) { | ||||
|         await ObjectManagerRepository.InitSQLManagers(); | ||||
|       } else { | ||||
|         await ObjectManagerRepository.InitMemoryManagers(); | ||||
| @@ -57,41 +52,41 @@ export class AdminMWs { | ||||
|       return next(); | ||||
|     } catch (err) { | ||||
|       if (err instanceof Error) { | ||||
|         return next(new ErrorDTO(ErrorCodes.SETTINGS_ERROR, "Error while saving database settings: " + err.toString(), err)); | ||||
|         return next(new ErrorDTO(ErrorCodes.SETTINGS_ERROR, 'Error while saving database settings: ' + err.toString(), err)); | ||||
|       } | ||||
|       return next(new ErrorDTO(ErrorCodes.SETTINGS_ERROR, "Error while saving database settings", err)); | ||||
|       return next(new ErrorDTO(ErrorCodes.SETTINGS_ERROR, 'Error while saving database settings', err)); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   public static async updateMapSettings(req: Request, res: Response, next: NextFunction) { | ||||
|     if ((typeof req.body === 'undefined') || (typeof req.body.settings === 'undefined')) { | ||||
|       return next(new ErrorDTO(ErrorCodes.INPUT_ERROR, "settings is needed")); | ||||
|       return next(new ErrorDTO(ErrorCodes.INPUT_ERROR, 'settings is needed')); | ||||
|     } | ||||
|  | ||||
|     try { | ||||
|       await ConfigDiagnostics.testMapConfig(<ClientConfig.MapConfig>req.body.settings); | ||||
|  | ||||
|       Config.Client.Map = <ClientConfig.MapConfig>req.body.settings; | ||||
|       //only updating explicitly set config (not saving config set by the diagnostics) | ||||
|       // only updating explicitly set config (not saving config set by the diagnostics) | ||||
|       const original = Config.original(); | ||||
|       original.Client.Map = <ClientConfig.MapConfig>req.body.settings; | ||||
|       original.save(); | ||||
|       await ConfigDiagnostics.runDiagnostics(); | ||||
|       Logger.info(LOG_TAG, "new config:"); | ||||
|       Logger.info(LOG_TAG, 'new config:'); | ||||
|       Logger.info(LOG_TAG, JSON.stringify(Config, null, '\t')); | ||||
|       return next(); | ||||
|     } catch (err) { | ||||
|       return next(new ErrorDTO(ErrorCodes.SETTINGS_ERROR, "Settings error: " + JSON.stringify(err, null, '  '), err)); | ||||
|       return next(new ErrorDTO(ErrorCodes.SETTINGS_ERROR, 'Settings error: ' + JSON.stringify(err, null, '  '), err)); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   public static async updateShareSettings(req: Request, res: Response, next: NextFunction) { | ||||
|     if ((typeof req.body === 'undefined') || (typeof req.body.settings === 'undefined')) { | ||||
|       return next(new ErrorDTO(ErrorCodes.INPUT_ERROR, "settings is needed")); | ||||
|       return next(new ErrorDTO(ErrorCodes.INPUT_ERROR, 'settings is needed')); | ||||
|     } | ||||
|  | ||||
|     try { | ||||
|       //only updating explicitly set config (not saving config set by the diagnostics) | ||||
|       // only updating explicitly set config (not saving config set by the diagnostics) | ||||
|       const original = Config.original(); | ||||
|       await ConfigDiagnostics.testSharingConfig(<ClientConfig.SharingConfig>req.body.settings, original); | ||||
|  | ||||
| @@ -99,22 +94,22 @@ export class AdminMWs { | ||||
|       original.Client.Sharing = <ClientConfig.SharingConfig>req.body.settings; | ||||
|       original.save(); | ||||
|       await ConfigDiagnostics.runDiagnostics(); | ||||
|       Logger.info(LOG_TAG, "new config:"); | ||||
|       Logger.info(LOG_TAG, 'new config:'); | ||||
|       Logger.info(LOG_TAG, JSON.stringify(Config, null, '\t')); | ||||
|       return next(); | ||||
|     } catch (err) { | ||||
|       return next(new ErrorDTO(ErrorCodes.SETTINGS_ERROR, "Settings error: " + JSON.stringify(err, null, '  '), err)); | ||||
|       return next(new ErrorDTO(ErrorCodes.SETTINGS_ERROR, 'Settings error: ' + JSON.stringify(err, null, '  '), err)); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|  | ||||
|   public static async updateSearchSettings(req: Request, res: Response, next: NextFunction) { | ||||
|     if ((typeof req.body === 'undefined') || (typeof req.body.settings === 'undefined')) { | ||||
|       return next(new ErrorDTO(ErrorCodes.INPUT_ERROR, "settings is needed")); | ||||
|       return next(new ErrorDTO(ErrorCodes.INPUT_ERROR, 'settings is needed')); | ||||
|     } | ||||
|  | ||||
|     try { | ||||
|       //only updating explicitly set config (not saving config set by the diagnostics) | ||||
|       // only updating explicitly set config (not saving config set by the diagnostics) | ||||
|       const original = Config.original(); | ||||
|       await ConfigDiagnostics.testSearchConfig(<ClientConfig.SearchConfig>req.body.settings, original); | ||||
|  | ||||
| @@ -122,38 +117,38 @@ export class AdminMWs { | ||||
|       original.Client.Search = <ClientConfig.SearchConfig>req.body.settings; | ||||
|       original.save(); | ||||
|       await ConfigDiagnostics.runDiagnostics(); | ||||
|       Logger.info(LOG_TAG, "new config:"); | ||||
|       Logger.info(LOG_TAG, 'new config:'); | ||||
|       Logger.info(LOG_TAG, JSON.stringify(Config, null, '\t')); | ||||
|       return next(); | ||||
|     } catch (err) { | ||||
|       return next(new ErrorDTO(ErrorCodes.SETTINGS_ERROR, "Settings error: " + JSON.stringify(err, null, '  '), err)); | ||||
|       return next(new ErrorDTO(ErrorCodes.SETTINGS_ERROR, 'Settings error: ' + JSON.stringify(err, null, '  '), err)); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|  | ||||
|   public static async updateAuthenticationSettings(req: Request, res: Response, next: NextFunction) { | ||||
|     if ((typeof req.body === 'undefined') || (typeof req.body.settings === 'undefined')) { | ||||
|       return next(new ErrorDTO(ErrorCodes.INPUT_ERROR, "settings is needed")); | ||||
|       return next(new ErrorDTO(ErrorCodes.INPUT_ERROR, 'settings is needed')); | ||||
|     } | ||||
|  | ||||
|     try { | ||||
|       Config.Client.authenticationRequired = <boolean>req.body.settings; | ||||
|       //only updating explicitly set config (not saving config set by the diagnostics) | ||||
|       // only updating explicitly set config (not saving config set by the diagnostics) | ||||
|       const original = Config.original(); | ||||
|       original.Client.authenticationRequired = <boolean>req.body.settings; | ||||
|       original.save(); | ||||
|       await ConfigDiagnostics.runDiagnostics(); | ||||
|       Logger.info(LOG_TAG, "new config:"); | ||||
|       Logger.info(LOG_TAG, 'new config:'); | ||||
|       Logger.info(LOG_TAG, JSON.stringify(Config, null, '\t')); | ||||
|       return next(); | ||||
|     } catch (err) { | ||||
|       return next(new ErrorDTO(ErrorCodes.SETTINGS_ERROR, "Settings error: " + JSON.stringify(err, null, '  '), err)); | ||||
|       return next(new ErrorDTO(ErrorCodes.SETTINGS_ERROR, 'Settings error: ' + JSON.stringify(err, null, '  '), err)); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   public static async updateThumbnailSettings(req: Request, res: Response, next: NextFunction) { | ||||
|     if ((typeof req.body === 'undefined') || (typeof req.body.settings === 'undefined')) { | ||||
|       return next(new ErrorDTO(ErrorCodes.INPUT_ERROR, "settings is needed")); | ||||
|       return next(new ErrorDTO(ErrorCodes.INPUT_ERROR, 'settings is needed')); | ||||
|     } | ||||
|  | ||||
|     try { | ||||
| @@ -166,28 +161,28 @@ export class AdminMWs { | ||||
|       await ConfigDiagnostics.testClientThumbnailConfig(settings.client); | ||||
|       Config.Server.thumbnail = settings.server; | ||||
|       Config.Client.Thumbnail = settings.client; | ||||
|       //only updating explicitly set config (not saving config set by the diagnostics) | ||||
|       // only updating explicitly set config (not saving config set by the diagnostics) | ||||
|       const original = Config.original(); | ||||
|       original.Server.thumbnail = settings.server; | ||||
|       original.Client.Thumbnail = settings.client; | ||||
|       original.save(); | ||||
|       ProjectPath.reset(); | ||||
|       await ConfigDiagnostics.runDiagnostics(); | ||||
|       Logger.info(LOG_TAG, "new config:"); | ||||
|       Logger.info(LOG_TAG, 'new config:'); | ||||
|       Logger.info(LOG_TAG, JSON.stringify(Config, null, '\t')); | ||||
|       return next(); | ||||
|     } catch (err) { | ||||
|       if (err instanceof Error) { | ||||
|         return next(new ErrorDTO(ErrorCodes.SETTINGS_ERROR, "Settings error: " + err.toString(), err)); | ||||
|         return next(new ErrorDTO(ErrorCodes.SETTINGS_ERROR, 'Settings error: ' + err.toString(), err)); | ||||
|       } | ||||
|       return next(new ErrorDTO(ErrorCodes.SETTINGS_ERROR, "Settings error: " + JSON.stringify(err, null, '  '), err)); | ||||
|       return next(new ErrorDTO(ErrorCodes.SETTINGS_ERROR, 'Settings error: ' + JSON.stringify(err, null, '  '), err)); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|  | ||||
|   public static async updateBasicSettings(req: Request, res: Response, next: NextFunction) { | ||||
|     if ((typeof req.body === 'undefined') || (typeof req.body.settings === 'undefined')) { | ||||
|       return next(new ErrorDTO(ErrorCodes.INPUT_ERROR, "settings is needed")); | ||||
|       return next(new ErrorDTO(ErrorCodes.INPUT_ERROR, 'settings is needed')); | ||||
|     } | ||||
|  | ||||
|     try { | ||||
| @@ -197,7 +192,7 @@ export class AdminMWs { | ||||
|       Config.Server.imagesFolder = settings.imagesFolder; | ||||
|       Config.Client.publicUrl = settings.publicUrl; | ||||
|       Config.Client.applicationTitle = settings.applicationTitle; | ||||
|       //only updating explicitly set config (not saving config set by the diagnostics) | ||||
|       // only updating explicitly set config (not saving config set by the diagnostics) | ||||
|       const original = Config.original(); | ||||
|       original.Server.port = settings.port; | ||||
|       original.Server.imagesFolder = settings.imagesFolder; | ||||
| @@ -206,18 +201,18 @@ export class AdminMWs { | ||||
|       original.save(); | ||||
|       ProjectPath.reset(); | ||||
|       await ConfigDiagnostics.runDiagnostics(); | ||||
|       Logger.info(LOG_TAG, "new config:"); | ||||
|       Logger.info(LOG_TAG, 'new config:'); | ||||
|       Logger.info(LOG_TAG, JSON.stringify(Config, null, '\t')); | ||||
|       return next(); | ||||
|     } catch (err) { | ||||
|       return next(new ErrorDTO(ErrorCodes.SETTINGS_ERROR, "Settings error: " + JSON.stringify(err, null, '  '), err)); | ||||
|       return next(new ErrorDTO(ErrorCodes.SETTINGS_ERROR, 'Settings error: ' + JSON.stringify(err, null, '  '), err)); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|  | ||||
|   public static async updateOtherSettings(req: Request, res: Response, next: NextFunction) { | ||||
|     if ((typeof req.body === 'undefined') || (typeof req.body.settings === 'undefined')) { | ||||
|       return next(new ErrorDTO(ErrorCodes.INPUT_ERROR, "settings is needed")); | ||||
|       return next(new ErrorDTO(ErrorCodes.INPUT_ERROR, 'settings is needed')); | ||||
|     } | ||||
|  | ||||
|     try { | ||||
| @@ -226,7 +221,7 @@ export class AdminMWs { | ||||
|       Config.Client.enableOnScrollRendering = settings.enableOnScrollRendering; | ||||
|       Config.Client.enableOnScrollThumbnailPrioritising = settings.enableOnScrollThumbnailPrioritising; | ||||
|  | ||||
|       //only updating explicitly set config (not saving config set by the diagnostics) | ||||
|       // only updating explicitly set config (not saving config set by the diagnostics) | ||||
|       const original = Config.original(); | ||||
|       original.Client.enableCache = settings.enableCache; | ||||
|       original.Client.enableOnScrollRendering = settings.enableOnScrollRendering; | ||||
| @@ -234,33 +229,33 @@ export class AdminMWs { | ||||
|       original.Server.enableThreading = settings.enableThreading; | ||||
|       original.save(); | ||||
|       await ConfigDiagnostics.runDiagnostics(); | ||||
|       Logger.info(LOG_TAG, "new config:"); | ||||
|       Logger.info(LOG_TAG, 'new config:'); | ||||
|       Logger.info(LOG_TAG, JSON.stringify(Config, null, '\t')); | ||||
|       return next(); | ||||
|     } catch (err) { | ||||
|       return next(new ErrorDTO(ErrorCodes.SETTINGS_ERROR, "Settings error: " + JSON.stringify(err, null, '  '), err)); | ||||
|       return next(new ErrorDTO(ErrorCodes.SETTINGS_ERROR, 'Settings error: ' + JSON.stringify(err, null, '  '), err)); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   public static async updateIndexingSettings(req: Request, res: Response, next: NextFunction) { | ||||
|     if ((typeof req.body === 'undefined') || (typeof req.body.settings === 'undefined')) { | ||||
|       return next(new ErrorDTO(ErrorCodes.INPUT_ERROR, "settings is needed")); | ||||
|       return next(new ErrorDTO(ErrorCodes.INPUT_ERROR, 'settings is needed')); | ||||
|     } | ||||
|  | ||||
|     try { | ||||
|       const settings: IndexingConfig = req.body.settings; | ||||
|       Config.Server.indexing = settings; | ||||
|  | ||||
|       //only updating explicitly set config (not saving config set by the diagnostics) | ||||
|       // only updating explicitly set config (not saving config set by the diagnostics) | ||||
|       const original = Config.original(); | ||||
|       original.Server.indexing = settings; | ||||
|       original.save(); | ||||
|       await ConfigDiagnostics.runDiagnostics(); | ||||
|       Logger.info(LOG_TAG, "new config:"); | ||||
|       Logger.info(LOG_TAG, 'new config:'); | ||||
|       Logger.info(LOG_TAG, JSON.stringify(Config, null, '\t')); | ||||
|       return next(); | ||||
|     } catch (err) { | ||||
|       return next(new ErrorDTO(ErrorCodes.SETTINGS_ERROR, "Settings error: " + JSON.stringify(err, null, '  '), err)); | ||||
|       return next(new ErrorDTO(ErrorCodes.SETTINGS_ERROR, 'Settings error: ' + JSON.stringify(err, null, '  '), err)); | ||||
|     } | ||||
|   } | ||||
|  | ||||
| @@ -268,10 +263,10 @@ export class AdminMWs { | ||||
|   public static startIndexing(req: Request, res: Response, next: NextFunction) { | ||||
|     try { | ||||
|       ObjectManagerRepository.getInstance().IndexingManager.startIndexing(); | ||||
|       req.resultPipe = "ok"; | ||||
|       req.resultPipe = 'ok'; | ||||
|       return next(); | ||||
|     } catch (err) { | ||||
|       return next(new ErrorDTO(ErrorCodes.SETTINGS_ERROR, "Indexing error: " + JSON.stringify(err, null, '  '), err)); | ||||
|       return next(new ErrorDTO(ErrorCodes.SETTINGS_ERROR, 'Indexing error: ' + JSON.stringify(err, null, '  '), err)); | ||||
|     } | ||||
|   } | ||||
|  | ||||
| @@ -280,27 +275,27 @@ export class AdminMWs { | ||||
|       req.resultPipe = ObjectManagerRepository.getInstance().IndexingManager.getProgress(); | ||||
|       return next(); | ||||
|     } catch (err) { | ||||
|       return next(new ErrorDTO(ErrorCodes.SETTINGS_ERROR, "Indexing error: " + JSON.stringify(err, null, '  '), err)); | ||||
|       return next(new ErrorDTO(ErrorCodes.SETTINGS_ERROR, 'Indexing error: ' + JSON.stringify(err, null, '  '), err)); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   public static cancelIndexing(req: Request, res: Response, next: NextFunction) { | ||||
|     try { | ||||
|       ObjectManagerRepository.getInstance().IndexingManager.cancelIndexing(); | ||||
|       req.resultPipe = "ok"; | ||||
|       req.resultPipe = 'ok'; | ||||
|       return next(); | ||||
|     } catch (err) { | ||||
|       return next(new ErrorDTO(ErrorCodes.SETTINGS_ERROR, "Indexing error: " + JSON.stringify(err, null, '  '), err)); | ||||
|       return next(new ErrorDTO(ErrorCodes.SETTINGS_ERROR, 'Indexing error: ' + JSON.stringify(err, null, '  '), err)); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   public static async resetIndexes(req: Request, res: Response, next: NextFunction) { | ||||
|     try { | ||||
|       await ObjectManagerRepository.getInstance().IndexingManager.reset(); | ||||
|       req.resultPipe = "ok"; | ||||
|       req.resultPipe = 'ok'; | ||||
|       return next(); | ||||
|     } catch (err) { | ||||
|       return next(new ErrorDTO(ErrorCodes.SETTINGS_ERROR, "Indexing error: " + JSON.stringify(err, null, '  '), err)); | ||||
|       return next(new ErrorDTO(ErrorCodes.SETTINGS_ERROR, 'Indexing error: ' + JSON.stringify(err, null, '  '), err)); | ||||
|     } | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -1,29 +1,29 @@ | ||||
| import * as path from "path"; | ||||
| import * as fs from "fs"; | ||||
| import {NextFunction, Request, Response} from "express"; | ||||
| import {ErrorCodes, ErrorDTO} from "../../common/entities/Error"; | ||||
| import {DirectoryDTO} from "../../common/entities/DirectoryDTO"; | ||||
| import {ObjectManagerRepository} from "../model/ObjectManagerRepository"; | ||||
| import {SearchTypes} from "../../common/entities/AutoCompleteItem"; | ||||
| import {ContentWrapper} from "../../common/entities/ConentWrapper"; | ||||
| import {PhotoDTO} from "../../common/entities/PhotoDTO"; | ||||
| import {ProjectPath} from "../ProjectPath"; | ||||
| import {Config} from "../../common/config/private/Config"; | ||||
| import {UserDTO} from "../../common/entities/UserDTO"; | ||||
| import * as path from 'path'; | ||||
| import * as fs from 'fs'; | ||||
| import {NextFunction, Request, Response} from 'express'; | ||||
| import {ErrorCodes, ErrorDTO} from '../../common/entities/Error'; | ||||
| import {DirectoryDTO} from '../../common/entities/DirectoryDTO'; | ||||
| import {ObjectManagerRepository} from '../model/ObjectManagerRepository'; | ||||
| import {SearchTypes} from '../../common/entities/AutoCompleteItem'; | ||||
| import {ContentWrapper} from '../../common/entities/ConentWrapper'; | ||||
| import {PhotoDTO} from '../../common/entities/PhotoDTO'; | ||||
| import {ProjectPath} from '../ProjectPath'; | ||||
| import {Config} from '../../common/config/private/Config'; | ||||
| import {UserDTO} from '../../common/entities/UserDTO'; | ||||
|  | ||||
|  | ||||
| const LOG_TAG = "[GalleryMWs]"; | ||||
| const LOG_TAG = '[GalleryMWs]'; | ||||
|  | ||||
| export class GalleryMWs { | ||||
|  | ||||
|  | ||||
|   public static async listDirectory(req: Request, res: Response, next: NextFunction) { | ||||
|     console.log("listDirectory"); | ||||
|     let directoryName = req.params.directory || "/"; | ||||
|     console.log('listDirectory'); | ||||
|     let directoryName = req.params.directory || '/'; | ||||
|     let absoluteDirectoryName = path.join(ProjectPath.ImageFolder, directoryName); | ||||
|  | ||||
|     if (!fs.statSync(absoluteDirectoryName).isDirectory()) { | ||||
|       console.log("not dir"); | ||||
|       console.log('not dir'); | ||||
|       return next(); | ||||
|     } | ||||
|  | ||||
| @@ -31,7 +31,7 @@ export class GalleryMWs { | ||||
|  | ||||
|       const directory = await ObjectManagerRepository.getInstance().GalleryManager.listDirectory(directoryName, req.query.knownLastModified, req.query.knownLastScanned); | ||||
|       if (directory == null) { | ||||
|         console.log("null dir"); | ||||
|         console.log('null dir'); | ||||
|         req.resultPipe = new ContentWrapper(null, null, true); | ||||
|         return next(); | ||||
|       } | ||||
| @@ -39,7 +39,7 @@ export class GalleryMWs { | ||||
|       console.log(directory); | ||||
|       if (req.session.user.permissions && | ||||
|         req.session.user.permissions.length > 0 && | ||||
|         req.session.user.permissions[0] != "/*") { | ||||
|         req.session.user.permissions[0] != '/*') { | ||||
|         (<DirectoryDTO>directory).directories = (<DirectoryDTO>directory).directories.filter(d => | ||||
|           UserDTO.isDirectoryAvailable(d, req.session.user.permissions)); | ||||
|       } | ||||
| @@ -47,7 +47,7 @@ export class GalleryMWs { | ||||
|       return next(); | ||||
|  | ||||
|     } catch (err) { | ||||
|       return next(new ErrorDTO(ErrorCodes.GENERAL_ERROR, "Error during listing the directory", err)); | ||||
|       return next(new ErrorDTO(ErrorCodes.GENERAL_ERROR, 'Error during listing the directory', err)); | ||||
|     } | ||||
|   } | ||||
|  | ||||
| @@ -90,7 +90,7 @@ export class GalleryMWs { | ||||
|  | ||||
|     //check if thumbnail already exist | ||||
|     if (fs.existsSync(fullImagePath) === false) { | ||||
|       return next(new ErrorDTO(ErrorCodes.GENERAL_ERROR, "no such file:" + fullImagePath)); | ||||
|       return next(new ErrorDTO(ErrorCodes.GENERAL_ERROR, 'no such file:' + fullImagePath)); | ||||
|     } | ||||
|     if (fs.statSync(fullImagePath).isDirectory()) { | ||||
|       return next(); | ||||
| @@ -122,7 +122,7 @@ export class GalleryMWs { | ||||
|       req.resultPipe = new ContentWrapper(null, result); | ||||
|       return next(); | ||||
|     } catch (err) { | ||||
|       return next(new ErrorDTO(ErrorCodes.GENERAL_ERROR, "Error during searching", err)); | ||||
|       return next(new ErrorDTO(ErrorCodes.GENERAL_ERROR, 'Error during searching', err)); | ||||
|     } | ||||
|   } | ||||
|  | ||||
| @@ -142,7 +142,7 @@ export class GalleryMWs { | ||||
|       req.resultPipe = new ContentWrapper(null, result); | ||||
|       return next(); | ||||
|     } catch (err) { | ||||
|       return next(new ErrorDTO(ErrorCodes.GENERAL_ERROR, "Error during searching", err)); | ||||
|       return next(new ErrorDTO(ErrorCodes.GENERAL_ERROR, 'Error during searching', err)); | ||||
|     } | ||||
|   } | ||||
|  | ||||
| @@ -158,7 +158,7 @@ export class GalleryMWs { | ||||
|       req.resultPipe = await ObjectManagerRepository.getInstance().SearchManager.autocomplete(req.params.text); | ||||
|       return next(); | ||||
|     } catch (err) { | ||||
|       return next(new ErrorDTO(ErrorCodes.GENERAL_ERROR, "Error during searching", err)); | ||||
|       return next(new ErrorDTO(ErrorCodes.GENERAL_ERROR, 'Error during searching', err)); | ||||
|     } | ||||
|  | ||||
|   } | ||||
|   | ||||
| @@ -1,8 +1,9 @@ | ||||
| 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'; | ||||
|  | ||||
| const LOG_TAG = '[NotificationMWs]'; | ||||
|  | ||||
| const LOG_TAG = "[NotificationMWs]"; | ||||
| export class NotificationMWs { | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -1,18 +1,18 @@ | ||||
| import {NextFunction, Request, Response} from "express"; | ||||
| import {ErrorCodes, ErrorDTO} from "../../common/entities/Error"; | ||||
| import {Utils} from "../../common/Utils"; | ||||
| import {Message} from "../../common/entities/Message"; | ||||
| import {SharingDTO} from "../../common/entities/SharingDTO"; | ||||
| import {Config} from "../../common/config/private/Config"; | ||||
| import {PrivateConfigClass} from "../../common/config/private/PrivateConfigClass"; | ||||
| import {UserRoles} from "../../common/entities/UserDTO"; | ||||
| import {NotificationManager} from "../model/NotifocationManager"; | ||||
| import {Logger} from "../Logger"; | ||||
| import {NextFunction, Request, Response} from 'express'; | ||||
| import {ErrorCodes, ErrorDTO} from '../../common/entities/Error'; | ||||
| import {Utils} from '../../common/Utils'; | ||||
| import {Message} from '../../common/entities/Message'; | ||||
| import {SharingDTO} from '../../common/entities/SharingDTO'; | ||||
| import {Config} from '../../common/config/private/Config'; | ||||
| import {PrivateConfigClass} from '../../common/config/private/PrivateConfigClass'; | ||||
| import {UserRoles} from '../../common/entities/UserDTO'; | ||||
| import {NotificationManager} from '../model/NotifocationManager'; | ||||
| import {Logger} from '../Logger'; | ||||
|  | ||||
| export class RenderingMWs { | ||||
|  | ||||
|   public static renderResult(req: Request, res: Response, next: NextFunction) { | ||||
|     if (typeof req.resultPipe == "undefined") | ||||
|     if (typeof req.resultPipe == 'undefined') | ||||
|       return next(); | ||||
|  | ||||
|     return RenderingMWs.renderMessage(res, req.resultPipe); | ||||
| @@ -21,7 +21,7 @@ export class RenderingMWs { | ||||
|  | ||||
|   public static renderSessionUser(req: Request, res: Response, next: NextFunction) { | ||||
|     if (!(req.session.user)) { | ||||
|       return next(new ErrorDTO(ErrorCodes.GENERAL_ERROR, "User not exists")); | ||||
|       return next(new ErrorDTO(ErrorCodes.GENERAL_ERROR, 'User not exists')); | ||||
|     } | ||||
|  | ||||
|     const user = Utils.clone(req.session.user); | ||||
| @@ -46,7 +46,7 @@ export class RenderingMWs { | ||||
|   } | ||||
|  | ||||
|   public static renderOK(req: Request, res: Response, next: NextFunction) { | ||||
|     let message = new Message<string>(null, "ok"); | ||||
|     let message = new Message<string>(null, 'ok'); | ||||
|     res.json(message); | ||||
|   } | ||||
|  | ||||
| @@ -62,7 +62,7 @@ export class RenderingMWs { | ||||
|     if (err instanceof ErrorDTO) { | ||||
|       if (err.details) { | ||||
|         if (!(req.session.user && req.session.user.role >= UserRoles.Developer)) { | ||||
|           Logger.warn("Handled error:", err); | ||||
|           Logger.warn('Handled error:', err); | ||||
|           delete (err.details); | ||||
|         } else { | ||||
|           try { | ||||
| @@ -75,7 +75,7 @@ export class RenderingMWs { | ||||
|       let message = new Message<any>(err, null); | ||||
|       return res.json(message); | ||||
|     } | ||||
|     NotificationManager.error("unknown server error", err); | ||||
|     NotificationManager.error('unknown server error', err); | ||||
|     return next(err); | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -1,9 +1,10 @@ | ||||
| import {NextFunction, Request, Response} from "express"; | ||||
| import {CreateSharingDTO, SharingDTO} from "../../common/entities/SharingDTO"; | ||||
| import {ObjectManagerRepository} from "../model/ObjectManagerRepository"; | ||||
| import {ErrorCodes, ErrorDTO} from "../../common/entities/Error"; | ||||
| import {NextFunction, Request, Response} from 'express'; | ||||
| import {CreateSharingDTO, SharingDTO} from '../../common/entities/SharingDTO'; | ||||
| import {ObjectManagerRepository} from '../model/ObjectManagerRepository'; | ||||
| import {ErrorCodes, ErrorDTO} from '../../common/entities/Error'; | ||||
|  | ||||
| const LOG_TAG = '[SharingMWs]'; | ||||
|  | ||||
| const LOG_TAG = "[SharingMWs]"; | ||||
| export class SharingMWs { | ||||
|  | ||||
|  | ||||
| @@ -26,14 +27,14 @@ export class SharingMWs { | ||||
|       return next(); | ||||
|  | ||||
|     } catch (err) { | ||||
|       return next(new ErrorDTO(ErrorCodes.GENERAL_ERROR, "Error during retrieving sharing link", err)); | ||||
|       return next(new ErrorDTO(ErrorCodes.GENERAL_ERROR, 'Error during retrieving sharing link', err)); | ||||
|     } | ||||
|  | ||||
|   } | ||||
|  | ||||
|   public static async createSharing(req: Request, res: Response, next: NextFunction) { | ||||
|     if ((typeof req.body === 'undefined') || (typeof req.body.createSharing === 'undefined')) { | ||||
|       return next(new ErrorDTO(ErrorCodes.INPUT_ERROR, "createSharing filed is missing")); | ||||
|       return next(new ErrorDTO(ErrorCodes.INPUT_ERROR, 'createSharing filed is missing')); | ||||
|     } | ||||
|     const createSharing: CreateSharingDTO = req.body.createSharing; | ||||
|     let sharingKey = SharingMWs.generateKey(); | ||||
| @@ -50,7 +51,7 @@ export class SharingMWs { | ||||
|     } | ||||
|  | ||||
|  | ||||
|     const directoryName = req.params.directory || "/"; | ||||
|     const directoryName = req.params.directory || '/'; | ||||
|     let sharing: SharingDTO = { | ||||
|       id: null, | ||||
|       sharingKey: sharingKey, | ||||
| @@ -68,20 +69,20 @@ export class SharingMWs { | ||||
|       return next(); | ||||
|  | ||||
|     } catch (err) { | ||||
|       return next(new ErrorDTO(ErrorCodes.GENERAL_ERROR, "Error during creating sharing link", err)); | ||||
|       return next(new ErrorDTO(ErrorCodes.GENERAL_ERROR, 'Error during creating sharing link', err)); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   public static async updateSharing(req: Request, res: Response, next: NextFunction) { | ||||
|     if ((typeof req.body === 'undefined') || (typeof req.body.updateSharing === 'undefined')) { | ||||
|       return next(new ErrorDTO(ErrorCodes.INPUT_ERROR, "updateSharing filed is missing")); | ||||
|       return next(new ErrorDTO(ErrorCodes.INPUT_ERROR, 'updateSharing filed is missing')); | ||||
|     } | ||||
|     const updateSharing: CreateSharingDTO = req.body.updateSharing; | ||||
|     const directoryName = req.params.directory || "/"; | ||||
|     const directoryName = req.params.directory || '/'; | ||||
|     let sharing: SharingDTO = { | ||||
|       id: updateSharing.id, | ||||
|       path: directoryName, | ||||
|       sharingKey: "", | ||||
|       sharingKey: '', | ||||
|       password: updateSharing.password, | ||||
|       creator: req.session.user, | ||||
|       expires: Date.now() + updateSharing.valid, | ||||
| @@ -93,7 +94,7 @@ export class SharingMWs { | ||||
|       req.resultPipe = await ObjectManagerRepository.getInstance().SharingManager.updateSharing(sharing); | ||||
|       return next(); | ||||
|     } catch (err) { | ||||
|       return next(new ErrorDTO(ErrorCodes.GENERAL_ERROR, "Error during updating sharing link", err)); | ||||
|       return next(new ErrorDTO(ErrorCodes.GENERAL_ERROR, 'Error during updating sharing link', err)); | ||||
|     } | ||||
|  | ||||
|   } | ||||
|   | ||||
							
								
								
									
										16
									
								
								backend/middlewares/customtypings/jimp.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										16
									
								
								backend/middlewares/customtypings/jimp.d.ts
									
									
									
									
										vendored
									
									
								
							| @@ -1,10 +1,10 @@ | ||||
| declare module "jimp" { | ||||
|   function read(filaname); | ||||
| declare module 'jimp' { | ||||
|   function read(fileName); | ||||
|  | ||||
|   var RESIZE_NEAREST_NEIGHBOR; | ||||
|   var RESIZE_BILINEAR; | ||||
|   var RESIZE_BICUBIC; | ||||
|   var RESIZE_HERMITE; | ||||
|   var RESIZE_BEZIER; | ||||
|   var AUTO: any; | ||||
|   const RESIZE_NEAREST_NEIGHBOR; | ||||
|   const RESIZE_BILINEAR; | ||||
|   const RESIZE_BICUBIC; | ||||
|   const RESIZE_HERMITE; | ||||
|   const RESIZE_BEZIER; | ||||
|   const AUTO: any; | ||||
| } | ||||
|   | ||||
| @@ -1,19 +1,19 @@ | ||||
| ///<reference path="../customtypings/jimp.d.ts"/> | ||||
| import * as path from "path"; | ||||
| import * as crypto from "crypto"; | ||||
| import * as fs from "fs"; | ||||
| import * as os from "os"; | ||||
| import {NextFunction, Request, Response} from "express"; | ||||
| import {ErrorCodes, ErrorDTO} from "../../../common/entities/Error"; | ||||
| import {ContentWrapper} from "../../../common/entities/ConentWrapper"; | ||||
| import {DirectoryDTO} from "../../../common/entities/DirectoryDTO"; | ||||
| import {ProjectPath} from "../../ProjectPath"; | ||||
| import {PhotoDTO} from "../../../common/entities/PhotoDTO"; | ||||
| import {Config} from "../../../common/config/private/Config"; | ||||
| import {ThumbnailProcessingLib} from "../../../common/config/private/IPrivateConfig"; | ||||
| import {ThumbnailTH} from "../../model/threading/ThreadPool"; | ||||
| import {RendererInput} from "../../model/threading/ThumbnailWoker"; | ||||
| import {ITaskQue, TaskQue} from "../../model/threading/TaskQue"; | ||||
| import * as path from 'path'; | ||||
| import * as crypto from 'crypto'; | ||||
| import * as fs from 'fs'; | ||||
| import * as os from 'os'; | ||||
| import {NextFunction, Request, Response} from 'express'; | ||||
| import {ErrorCodes, ErrorDTO} from '../../../common/entities/Error'; | ||||
| import {ContentWrapper} from '../../../common/entities/ConentWrapper'; | ||||
| import {DirectoryDTO} from '../../../common/entities/DirectoryDTO'; | ||||
| import {ProjectPath} from '../../ProjectPath'; | ||||
| import {PhotoDTO} from '../../../common/entities/PhotoDTO'; | ||||
| import {Config} from '../../../common/config/private/Config'; | ||||
| import {ThumbnailProcessingLib} from '../../../common/config/private/IPrivateConfig'; | ||||
| import {ThumbnailTH} from '../../model/threading/ThreadPool'; | ||||
| import {RendererInput} from '../../model/threading/ThumbnailWoker'; | ||||
| import {ITaskQue, TaskQue} from '../../model/threading/TaskQue'; | ||||
|  | ||||
|  | ||||
| export class ThumbnailGeneratorMWs { | ||||
| @@ -21,20 +21,20 @@ export class ThumbnailGeneratorMWs { | ||||
|   private static taskQue: ITaskQue = null; | ||||
|  | ||||
|   public static init() { | ||||
|     if (this.initDone == true) { | ||||
|       return | ||||
|     if (this.initDone === true) { | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|  | ||||
|     if (Config.Server.enableThreading == true || | ||||
|       Config.Server.thumbnail.processingLibrary != ThumbnailProcessingLib.Jimp) { | ||||
|     if (Config.Server.enableThreading === true || | ||||
|       Config.Server.thumbnail.processingLibrary !== ThumbnailProcessingLib.Jimp) { | ||||
|       Config.Client.concurrentThumbnailGenerations = Math.max(1, os.cpus().length - 1); | ||||
|     } else { | ||||
|       Config.Client.concurrentThumbnailGenerations = 1; | ||||
|     } | ||||
|  | ||||
|     if (Config.Server.enableThreading == true && | ||||
|       Config.Server.thumbnail.processingLibrary == ThumbnailProcessingLib.Jimp) { | ||||
|     if (Config.Server.enableThreading === true && | ||||
|       Config.Server.thumbnail.processingLibrary === ThumbnailProcessingLib.Jimp) { | ||||
|       this.taskQue = new ThumbnailTH(Config.Client.concurrentThumbnailGenerations); | ||||
|     } else { | ||||
|       this.taskQue = new TaskQue(Config.Client.concurrentThumbnailGenerations); | ||||
| @@ -43,49 +43,13 @@ export class ThumbnailGeneratorMWs { | ||||
|     this.initDone = true; | ||||
|   } | ||||
|  | ||||
|   private static addThInfoTODir(directory: DirectoryDTO) { | ||||
|     if (typeof  directory.photos == "undefined") { | ||||
|       directory.photos = []; | ||||
|     } | ||||
|     if (typeof  directory.directories == "undefined") { | ||||
|       directory.directories = []; | ||||
|     } | ||||
|     ThumbnailGeneratorMWs.addThInfoToPhotos(directory.photos); | ||||
|  | ||||
|     for (let i = 0; i < directory.directories.length; i++) { | ||||
|       ThumbnailGeneratorMWs.addThInfoTODir(directory.directories[i]); | ||||
|     } | ||||
|  | ||||
|   } | ||||
|  | ||||
|   private static addThInfoToPhotos(photos: Array<PhotoDTO>) { | ||||
|     let thumbnailFolder = ProjectPath.ThumbnailFolder; | ||||
|     for (let i = 0; i < photos.length; i++) { | ||||
|       let fullImagePath = path.join(ProjectPath.ImageFolder, photos[i].directory.path, photos[i].directory.name, photos[i].name); | ||||
|       for (let j = 0; j < Config.Client.Thumbnail.thumbnailSizes.length; j++) { | ||||
|         let size = Config.Client.Thumbnail.thumbnailSizes[j]; | ||||
|         let thPath = path.join(thumbnailFolder, ThumbnailGeneratorMWs.generateThumbnailName(fullImagePath, size)); | ||||
|         if (fs.existsSync(thPath) === true) { | ||||
|           if (typeof  photos[i].readyThumbnails == "undefined") { | ||||
|             photos[i].readyThumbnails = []; | ||||
|           } | ||||
|           photos[i].readyThumbnails.push(size); | ||||
|         } | ||||
|       } | ||||
|       let iconPath = path.join(thumbnailFolder, ThumbnailGeneratorMWs.generateThumbnailName(fullImagePath, Config.Client.Thumbnail.iconSize)); | ||||
|       if (fs.existsSync(iconPath) === true) { | ||||
|         photos[i].readyIcon = true; | ||||
|       } | ||||
|  | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   public static addThumbnailInformation(req: Request, res: Response, next: NextFunction) { | ||||
|     if (!req.resultPipe) | ||||
|     if (!req.resultPipe) { | ||||
|       return next(); | ||||
|     } | ||||
|  | ||||
|     let cw: ContentWrapper = req.resultPipe; | ||||
|     if (cw.notModified == true) { | ||||
|     const cw: ContentWrapper = req.resultPipe; | ||||
|     if (cw.notModified === true) { | ||||
|       return next(); | ||||
|     } | ||||
|     if (cw.directory) { | ||||
| @@ -101,14 +65,15 @@ export class ThumbnailGeneratorMWs { | ||||
|   } | ||||
|  | ||||
|   public static generateThumbnail(req: Request, res: Response, next: NextFunction) { | ||||
|     if (!req.resultPipe) | ||||
|     if (!req.resultPipe) { | ||||
|       return next(); | ||||
|     } | ||||
|  | ||||
|     //load parameters | ||||
|     let imagePath = req.resultPipe; | ||||
|     let size: number = parseInt(req.params.size) || Config.Client.Thumbnail.thumbnailSizes[0]; | ||||
|     // load parameters | ||||
|     const imagePath = req.resultPipe; | ||||
|     let size: number = parseInt(req.params.size, 10) || Config.Client.Thumbnail.thumbnailSizes[0]; | ||||
|  | ||||
|     //validate size | ||||
|     // validate size | ||||
|     if (Config.Client.Thumbnail.thumbnailSizes.indexOf(size) === -1) { | ||||
|       size = Config.Client.Thumbnail.thumbnailSizes[0]; | ||||
|     } | ||||
| @@ -119,37 +84,74 @@ export class ThumbnailGeneratorMWs { | ||||
|   } | ||||
|  | ||||
|   public static generateIcon(req: Request, res: Response, next: NextFunction) { | ||||
|     if (!req.resultPipe) | ||||
|     if (!req.resultPipe) { | ||||
|       return next(); | ||||
|     } | ||||
|  | ||||
|     //load parameters | ||||
|     let imagePath = req.resultPipe; | ||||
|     let size: number = Config.Client.Thumbnail.iconSize; | ||||
|     // load parameters | ||||
|     const imagePath = req.resultPipe; | ||||
|     const size: number = Config.Client.Thumbnail.iconSize; | ||||
|     ThumbnailGeneratorMWs.generateImage(imagePath, size, true, req, res, next); | ||||
|  | ||||
|  | ||||
|   } | ||||
|  | ||||
|   private static addThInfoTODir(directory: DirectoryDTO) { | ||||
|     if (typeof  directory.photos === 'undefined') { | ||||
|       directory.photos = []; | ||||
|     } | ||||
|     if (typeof  directory.directories === 'undefined') { | ||||
|       directory.directories = []; | ||||
|     } | ||||
|     ThumbnailGeneratorMWs.addThInfoToPhotos(directory.photos); | ||||
|  | ||||
|     for (let i = 0; i < directory.directories.length; i++) { | ||||
|       ThumbnailGeneratorMWs.addThInfoTODir(directory.directories[i]); | ||||
|     } | ||||
|  | ||||
|   } | ||||
|  | ||||
|   private static addThInfoToPhotos(photos: Array<PhotoDTO>) { | ||||
|     const thumbnailFolder = ProjectPath.ThumbnailFolder; | ||||
|     for (let i = 0; i < photos.length; i++) { | ||||
|       const fullImagePath = path.join(ProjectPath.ImageFolder, photos[i].directory.path, photos[i].directory.name, photos[i].name); | ||||
|       for (let j = 0; j < Config.Client.Thumbnail.thumbnailSizes.length; j++) { | ||||
|         const size = Config.Client.Thumbnail.thumbnailSizes[j]; | ||||
|         const thPath = path.join(thumbnailFolder, ThumbnailGeneratorMWs.generateThumbnailName(fullImagePath, size)); | ||||
|         if (fs.existsSync(thPath) === true) { | ||||
|           if (typeof  photos[i].readyThumbnails === 'undefined') { | ||||
|             photos[i].readyThumbnails = []; | ||||
|           } | ||||
|           photos[i].readyThumbnails.push(size); | ||||
|         } | ||||
|       } | ||||
|       const iconPath = path.join(thumbnailFolder, ThumbnailGeneratorMWs.generateThumbnailName(fullImagePath, Config.Client.Thumbnail.iconSize)); | ||||
|       if (fs.existsSync(iconPath) === true) { | ||||
|         photos[i].readyIcon = true; | ||||
|       } | ||||
|  | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   private static async generateImage(imagePath: string, size: number, makeSquare: boolean, req: Request, res: Response, next: NextFunction) { | ||||
|     //generate thumbnail path | ||||
|     let thPath = path.join(ProjectPath.ThumbnailFolder, ThumbnailGeneratorMWs.generateThumbnailName(imagePath, size)); | ||||
|     // generate thumbnail path | ||||
|     const thPath = path.join(ProjectPath.ThumbnailFolder, ThumbnailGeneratorMWs.generateThumbnailName(imagePath, size)); | ||||
|  | ||||
|  | ||||
|     req.resultPipe = thPath; | ||||
|  | ||||
|     //check if thumbnail already exist | ||||
|     // check if thumbnail already exist | ||||
|     if (fs.existsSync(thPath) === true) { | ||||
|       return next(); | ||||
|     } | ||||
|  | ||||
|     //create thumbnail folder if not exist | ||||
|     // create thumbnail folder if not exist | ||||
|     if (!fs.existsSync(ProjectPath.ThumbnailFolder)) { | ||||
|       fs.mkdirSync(ProjectPath.ThumbnailFolder); | ||||
|     } | ||||
|  | ||||
|     //run on other thread | ||||
|     let input = <RendererInput>{ | ||||
|     // run on other thread | ||||
|     const input = <RendererInput>{ | ||||
|       imagePath: imagePath, | ||||
|       size: size, | ||||
|       thPath: thPath, | ||||
| @@ -160,12 +162,12 @@ export class ThumbnailGeneratorMWs { | ||||
|       await this.taskQue.execute(input); | ||||
|       return next(); | ||||
|     } catch (error) { | ||||
|       return next(new ErrorDTO(ErrorCodes.THUMBNAIL_GENERATION_ERROR, "Error during generating thumbnail", error)); | ||||
|       return next(new ErrorDTO(ErrorCodes.THUMBNAIL_GENERATION_ERROR, 'Error during generating thumbnail', error)); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   private static generateThumbnailName(imagePath: string, size: number): string { | ||||
|     return crypto.createHash('md5').update(imagePath).digest('hex') + "_" + size + ".jpg"; | ||||
|     return crypto.createHash('md5').update(imagePath).digest('hex') + '_' + size + '.jpg'; | ||||
|   } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -1,42 +1,17 @@ | ||||
| ///<reference path="../customtypings/ExtendedRequest.d.ts"/> | ||||
| import {NextFunction, Request, Response} from "express"; | ||||
| import {ErrorCodes, ErrorDTO} from "../../../common/entities/Error"; | ||||
| import {UserDTO, UserRoles} from "../../../common/entities/UserDTO"; | ||||
| import {ObjectManagerRepository} from "../../model/ObjectManagerRepository"; | ||||
| import {Config} from "../../../common/config/private/Config"; | ||||
| import {PasswordHelper} from "../../model/PasswordHelper"; | ||||
| import {Utils} from "../../../common/Utils"; | ||||
| import {NextFunction, Request, Response} from 'express'; | ||||
| import {ErrorCodes, ErrorDTO} from '../../../common/entities/Error'; | ||||
| import {UserDTO, UserRoles} from '../../../common/entities/UserDTO'; | ||||
| import {ObjectManagerRepository} from '../../model/ObjectManagerRepository'; | ||||
| import {Config} from '../../../common/config/private/Config'; | ||||
| import {PasswordHelper} from '../../model/PasswordHelper'; | ||||
| import {Utils} from '../../../common/Utils'; | ||||
|  | ||||
| export class AuthenticationMWs { | ||||
|  | ||||
|   private static async getSharingUser(req: Request) { | ||||
|     if (Config.Client.Sharing.enabled === true && | ||||
|       (!!req.query.sk || !!req.params.sharingKey)) { | ||||
|       const sharing = await ObjectManagerRepository.getInstance().SharingManager.findOne({ | ||||
|         sharingKey: req.query.sk || req.params.sharingKey, | ||||
|       }); | ||||
|       if (!sharing || sharing.expires < Date.now()) { | ||||
|         return null; | ||||
|       } | ||||
|  | ||||
|       if (Config.Client.Sharing.passwordProtected === true && sharing.password) { | ||||
|         return null; | ||||
|       } | ||||
|  | ||||
|       let path = sharing.path; | ||||
|       if (sharing.includeSubfolders == true) { | ||||
|         path += "*"; | ||||
|       } | ||||
|       return <UserDTO>{name: "Guest", role: UserRoles.LimitedGuest, permissions: [path]}; | ||||
|  | ||||
|     } | ||||
|     return null; | ||||
|   } | ||||
|  | ||||
|  | ||||
|   public static async tryAuthenticate(req: Request, res: Response, next: NextFunction) { | ||||
|     if (Config.Client.authenticationRequired === false) { | ||||
|       req.session.user = <UserDTO>{name: "Admin", role: UserRoles.Admin}; | ||||
|       req.session.user = <UserDTO>{name: 'Admin', role: UserRoles.Admin}; | ||||
|       return next(); | ||||
|     } | ||||
|     try { | ||||
| @@ -55,7 +30,7 @@ export class AuthenticationMWs { | ||||
|   public static async authenticate(req: Request, res: Response, next: NextFunction) { | ||||
|  | ||||
|     if (Config.Client.authenticationRequired === false) { | ||||
|       req.session.user = <UserDTO>{name: "Admin", role: UserRoles.Admin}; | ||||
|       req.session.user = <UserDTO>{name: 'Admin', role: UserRoles.Admin}; | ||||
|       return next(); | ||||
|     } | ||||
|     try { | ||||
| @@ -78,6 +53,21 @@ export class AuthenticationMWs { | ||||
|     return next(); | ||||
|   } | ||||
|  | ||||
|   public static authoriseDirectory(req: Request, res: Response, next: NextFunction) { | ||||
|     if (req.session.user.permissions == null || | ||||
|       req.session.user.permissions.length == 0 || | ||||
|       req.session.user.permissions[0] == '/*') { | ||||
|       return next(); | ||||
|     } | ||||
|  | ||||
|     const directoryName = req.params.directory || '/'; | ||||
|     if (UserDTO.isPathAvailable(directoryName, req.session.user.permissions) == true) { | ||||
|       return next(); | ||||
|     } | ||||
|  | ||||
|     return next(new ErrorDTO(ErrorCodes.PERMISSION_DENIED)); | ||||
|   } | ||||
|  | ||||
|   public static authorise(role: UserRoles) { | ||||
|     return (req: Request, res: Response, next: NextFunction) => { | ||||
|       if (req.session.user.role < role) { | ||||
| @@ -87,19 +77,40 @@ export class AuthenticationMWs { | ||||
|     }; | ||||
|   } | ||||
|  | ||||
|   public static authoriseDirectory(req: Request, res: Response, next: NextFunction) { | ||||
|     if (req.session.user.permissions == null || | ||||
|       req.session.user.permissions.length == 0 || | ||||
|       req.session.user.permissions[0] == "/*") { | ||||
|   public static async shareLogin(req: Request, res: Response, next: NextFunction) { | ||||
|  | ||||
|     if (Config.Client.Sharing.enabled === false) { | ||||
|       return next(); | ||||
|     } | ||||
|  | ||||
|     const directoryName = req.params.directory || "/"; | ||||
|     if (UserDTO.isPathAvailable(directoryName, req.session.user.permissions) == true) { | ||||
|       return next(); | ||||
|     //not enough parameter | ||||
|     if ((!req.query.sk && !req.params.sharingKey)) { | ||||
|       return next(new ErrorDTO(ErrorCodes.INPUT_ERROR, 'no sharing key provided')); | ||||
|     } | ||||
|  | ||||
|     try { | ||||
|       const password = (req.body ? req.body.password : null) || null; | ||||
|  | ||||
|       const sharing = await ObjectManagerRepository.getInstance().SharingManager.findOne({ | ||||
|         sharingKey: req.query.sk || req.params.sharingKey, | ||||
|       }); | ||||
|       if (!sharing || sharing.expires < Date.now() || | ||||
|         (Config.Client.Sharing.passwordProtected === true | ||||
|           && sharing.password && !PasswordHelper.comparePassword(password, sharing.password))) { | ||||
|         return next(new ErrorDTO(ErrorCodes.CREDENTIAL_NOT_FOUND)); | ||||
|       } | ||||
|  | ||||
|       let path = sharing.path; | ||||
|       if (sharing.includeSubfolders == true) { | ||||
|         path += '*'; | ||||
|       } | ||||
|  | ||||
|       req.session.user = <UserDTO>{name: 'Guest', role: UserRoles.LimitedGuest, permissions: [path]}; | ||||
|       return next(); | ||||
|  | ||||
|     } catch (err) { | ||||
|       return next(new ErrorDTO(ErrorCodes.GENERAL_ERROR, null, err)); | ||||
|     } | ||||
|  | ||||
|     return next(new ErrorDTO(ErrorCodes.PERMISSION_DENIED)); | ||||
|   } | ||||
|  | ||||
|   public static inverseAuthenticate(req: Request, res: Response, next: NextFunction) { | ||||
| @@ -136,41 +147,28 @@ export class AuthenticationMWs { | ||||
|  | ||||
|   } | ||||
|  | ||||
|  | ||||
|   public static async shareLogin(req: Request, res: Response, next: NextFunction) { | ||||
|  | ||||
|     if (Config.Client.Sharing.enabled === false) { | ||||
|       return next(); | ||||
|     } | ||||
|     //not enough parameter | ||||
|     if ((!req.query.sk && !req.params.sharingKey)) { | ||||
|       return next(new ErrorDTO(ErrorCodes.INPUT_ERROR, "no sharing key provided")); | ||||
|     } | ||||
|  | ||||
|     try { | ||||
|       const password = (req.body ? req.body.password : null) || null; | ||||
|  | ||||
|   private static async getSharingUser(req: Request) { | ||||
|     if (Config.Client.Sharing.enabled === true && | ||||
|       (!!req.query.sk || !!req.params.sharingKey)) { | ||||
|       const sharing = await ObjectManagerRepository.getInstance().SharingManager.findOne({ | ||||
|         sharingKey: req.query.sk || req.params.sharingKey, | ||||
|       }); | ||||
|       if (!sharing || sharing.expires < Date.now() || | ||||
|         (Config.Client.Sharing.passwordProtected === true | ||||
|           && sharing.password && !PasswordHelper.comparePassword(password, sharing.password))) { | ||||
|         return next(new ErrorDTO(ErrorCodes.CREDENTIAL_NOT_FOUND)); | ||||
|       if (!sharing || sharing.expires < Date.now()) { | ||||
|         return null; | ||||
|       } | ||||
|  | ||||
|       if (Config.Client.Sharing.passwordProtected === true && sharing.password) { | ||||
|         return null; | ||||
|       } | ||||
|  | ||||
|       let path = sharing.path; | ||||
|       if (sharing.includeSubfolders == true) { | ||||
|         path += "*"; | ||||
|         path += '*'; | ||||
|       } | ||||
|       return <UserDTO>{name: 'Guest', role: UserRoles.LimitedGuest, permissions: [path]}; | ||||
|  | ||||
|       req.session.user = <UserDTO>{name: "Guest", role: UserRoles.LimitedGuest, permissions: [path]}; | ||||
|       return next(); | ||||
|  | ||||
|     } catch (err) { | ||||
|       return next(new ErrorDTO(ErrorCodes.GENERAL_ERROR, null, err)); | ||||
|     } | ||||
|  | ||||
|     return null; | ||||
|   } | ||||
|  | ||||
|   public static logout(req: Request, res: Response, next: NextFunction) { | ||||
|   | ||||
| @@ -1,8 +1,8 @@ | ||||
| import {NextFunction, Request, Response} from "express"; | ||||
| import {ErrorCodes, ErrorDTO} from "../../../common/entities/Error"; | ||||
| import {ObjectManagerRepository} from "../../model/ObjectManagerRepository"; | ||||
| import {Utils} from "../../../common/Utils"; | ||||
| import {Config} from "../../../common/config/private/Config"; | ||||
| import {NextFunction, Request, Response} from 'express'; | ||||
| import {ErrorCodes, ErrorDTO} from '../../../common/entities/Error'; | ||||
| import {ObjectManagerRepository} from '../../model/ObjectManagerRepository'; | ||||
| import {Utils} from '../../../common/Utils'; | ||||
| import {Config} from '../../../common/config/private/Config'; | ||||
|  | ||||
| export class UserMWs { | ||||
|  | ||||
| @@ -94,7 +94,7 @@ export class UserMWs { | ||||
|       let result = await ObjectManagerRepository.getInstance().UserManager.find({}); | ||||
|       result = Utils.clone(result); | ||||
|       for (let i = 0; i < result.length; i++) { | ||||
|         result[i].password = ""; | ||||
|         result[i].password = ''; | ||||
|       } | ||||
|       req.resultPipe = result; | ||||
|       next(); | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| import {NextFunction, Request, Response} from "express"; | ||||
| import {ErrorCodes, ErrorDTO} from "../../../common/entities/Error"; | ||||
| import {UserRoles} from "../../../common/entities/UserDTO"; | ||||
| import {ObjectManagerRepository} from "../../model/ObjectManagerRepository"; | ||||
| import {NextFunction, Request, Response} from 'express'; | ||||
| import {ErrorCodes, ErrorDTO} from '../../../common/entities/Error'; | ||||
| import {UserRoles} from '../../../common/entities/UserDTO'; | ||||
| import {ObjectManagerRepository} from '../../model/ObjectManagerRepository'; | ||||
|  | ||||
| export class UserRequestConstrainsMWs { | ||||
|  | ||||
| @@ -38,7 +38,7 @@ export class UserRequestConstrainsMWs { | ||||
|       return next(); | ||||
|     } | ||||
|  | ||||
|     //TODO: fix it! | ||||
|     // TODO: fix it! | ||||
|     try { | ||||
|       const result = await ObjectManagerRepository.getInstance().UserManager.find({minRole: UserRoles.Admin}); | ||||
|       if (result.length <= 1) { | ||||
|   | ||||
| @@ -1,19 +1,20 @@ | ||||
| import {Config} from "../../common/config/private/Config"; | ||||
| import {Config} from '../../common/config/private/Config'; | ||||
| import { | ||||
|   DataBaseConfig, | ||||
|   DatabaseType, | ||||
|   IPrivateConfig, | ||||
|   ThumbnailConfig, | ||||
|   ThumbnailProcessingLib | ||||
| } from "../../common/config/private/IPrivateConfig"; | ||||
| import {Logger} from "../Logger"; | ||||
| import {NotificationManager} from "./NotifocationManager"; | ||||
| import {ProjectPath} from "../ProjectPath"; | ||||
| import {SQLConnection} from "./sql/SQLConnection"; | ||||
| import * as fs from "fs"; | ||||
| import {ClientConfig} from "../../common/config/public/ConfigClass"; | ||||
| } from '../../common/config/private/IPrivateConfig'; | ||||
| import {Logger} from '../Logger'; | ||||
| import {NotificationManager} from './NotifocationManager'; | ||||
| import {ProjectPath} from '../ProjectPath'; | ||||
| import {SQLConnection} from './sql/SQLConnection'; | ||||
| import * as fs from 'fs'; | ||||
| import {ClientConfig} from '../../common/config/public/ConfigClass'; | ||||
|  | ||||
| const LOG_TAG = '[ConfigDiagnostics]'; | ||||
|  | ||||
| const LOG_TAG = "[ConfigDiagnostics]"; | ||||
| export class ConfigDiagnostics { | ||||
|  | ||||
|   static async testDatabase(databaseConfig: DataBaseConfig) { | ||||
| @@ -26,13 +27,13 @@ export class ConfigDiagnostics { | ||||
|   static async testThumbnailLib(processingLibrary: ThumbnailProcessingLib) { | ||||
|     switch (processingLibrary) { | ||||
|       case ThumbnailProcessingLib.sharp: | ||||
|         const sharp = require("sharp"); | ||||
|         const sharp = require('sharp'); | ||||
|         sharp(); | ||||
|         break; | ||||
|       case  ThumbnailProcessingLib.gm: | ||||
|         const gm = require("gm"); | ||||
|         const gm = require('gm'); | ||||
|         await new Promise((resolve, reject) => { | ||||
|           gm(ProjectPath.FrontendFolder + "/assets/icon.png").size((err, value) => { | ||||
|           gm(ProjectPath.FrontendFolder + '/assets/icon.png').size((err, value) => { | ||||
|             if (err) { | ||||
|               return reject(err.toString()); | ||||
|             } | ||||
| @@ -47,7 +48,7 @@ export class ConfigDiagnostics { | ||||
|     await new Promise((resolve, reject) => { | ||||
|       fs.access(folder, fs.constants.W_OK, (err) => { | ||||
|         if (err) { | ||||
|           reject({message: "Error during getting write access to temp folder", error: err.toString()}); | ||||
|           reject({message: 'Error during getting write access to temp folder', error: err.toString()}); | ||||
|         } | ||||
|       }); | ||||
|       resolve(); | ||||
| @@ -57,11 +58,11 @@ export class ConfigDiagnostics { | ||||
|   static async testImageFolder(folder: string) { | ||||
|     await new Promise((resolve, reject) => { | ||||
|       if (!fs.existsSync(folder)) { | ||||
|         reject("Images folder not exists: '" + folder + "'"); | ||||
|         reject('Images folder not exists: \'' + folder + '\''); | ||||
|       } | ||||
|       fs.access(folder, fs.constants.R_OK, (err) => { | ||||
|         if (err) { | ||||
|           reject({message: "Error during getting read access to images folder", error: err.toString()}); | ||||
|           reject({message: 'Error during getting read access to images folder', error: err.toString()}); | ||||
|         } | ||||
|       }); | ||||
|       resolve(); | ||||
| @@ -76,15 +77,15 @@ export class ConfigDiagnostics { | ||||
|  | ||||
|   static async testClientThumbnailConfig(thumbnailConfig: ClientConfig.ThumbnailConfig) { | ||||
|     if (isNaN(thumbnailConfig.iconSize) || thumbnailConfig.iconSize <= 0) { | ||||
|       throw "IconSize has to be >= 0 integer, got: " + thumbnailConfig.iconSize; | ||||
|       throw 'IconSize has to be >= 0 integer, got: ' + thumbnailConfig.iconSize; | ||||
|     } | ||||
|  | ||||
|     if (!thumbnailConfig.thumbnailSizes.length) { | ||||
|       throw "At least one thumbnail size is needed"; | ||||
|       throw 'At least one thumbnail size is needed'; | ||||
|     } | ||||
|     for (let i = 0; i < thumbnailConfig.thumbnailSizes.length; i++) { | ||||
|       if (isNaN(thumbnailConfig.thumbnailSizes[i]) || thumbnailConfig.thumbnailSizes[i] <= 0) { | ||||
|         throw "Thumbnail size has to be >= 0 integer, got: " + thumbnailConfig.thumbnailSizes[i]; | ||||
|         throw 'Thumbnail size has to be >= 0 integer, got: ' + thumbnailConfig.thumbnailSizes[i]; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| @@ -92,20 +93,20 @@ export class ConfigDiagnostics { | ||||
|  | ||||
|   static async testSearchConfig(search: ClientConfig.SearchConfig, config: IPrivateConfig) { | ||||
|     if (search.enabled == true && config.Server.database.type == DatabaseType.memory) { | ||||
|       throw "Memory Database do not support searching"; | ||||
|       throw 'Memory Database do not support searching'; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|  | ||||
|   static async testSharingConfig(sharing: ClientConfig.SharingConfig, config: IPrivateConfig) { | ||||
|     if (sharing.enabled == true && config.Server.database.type == DatabaseType.memory) { | ||||
|       throw "Memory Database do not support sharing"; | ||||
|       throw 'Memory Database do not support sharing'; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   static async testMapConfig(map: ClientConfig.MapConfig) { | ||||
|     if (map.enabled == true && (!map.googleApiKey || map.googleApiKey.length == 0)) { | ||||
|       throw "Maps need a valid google api key"; | ||||
|       throw 'Maps need a valid google api key'; | ||||
|     } | ||||
|   } | ||||
|  | ||||
| @@ -116,9 +117,9 @@ export class ConfigDiagnostics { | ||||
|       try { | ||||
|         await ConfigDiagnostics.testDatabase(Config.Server.database); | ||||
|       } catch (err) { | ||||
|         Logger.warn(LOG_TAG, "[SQL error]", err); | ||||
|         Logger.warn(LOG_TAG, "Error during initializing SQL falling back temporally to memory DB"); | ||||
|         NotificationManager.warning("Error during initializing SQL falling back temporally to memory DB", err); | ||||
|         Logger.warn(LOG_TAG, '[SQL error]', err); | ||||
|         Logger.warn(LOG_TAG, 'Error during initializing SQL falling back temporally to memory DB'); | ||||
|         NotificationManager.warning('Error during initializing SQL falling back temporally to memory DB', err); | ||||
|         Config.setDatabaseType(DatabaseType.memory); | ||||
|       } | ||||
|     } | ||||
| @@ -127,60 +128,60 @@ export class ConfigDiagnostics { | ||||
|       try { | ||||
|         await ConfigDiagnostics.testThumbnailLib(Config.Server.thumbnail.processingLibrary); | ||||
|       } catch (err) { | ||||
|         NotificationManager.warning("Thumbnail hardware acceleration is not possible." + | ||||
|           " '" + ThumbnailProcessingLib[Config.Server.thumbnail.processingLibrary] + "' node module is not found." + | ||||
|           " Falling back temporally to JS based thumbnail generation", err); | ||||
|         Logger.warn(LOG_TAG, "[Thumbnail hardware acceleration] module error: ", err); | ||||
|         Logger.warn(LOG_TAG, "Thumbnail hardware acceleration is not possible." + | ||||
|           " '" + ThumbnailProcessingLib[Config.Server.thumbnail.processingLibrary] + "' node module is not found." + | ||||
|           " Falling back temporally to JS based thumbnail generation"); | ||||
|         NotificationManager.warning('Thumbnail hardware acceleration is not possible.' + | ||||
|           ' \'' + ThumbnailProcessingLib[Config.Server.thumbnail.processingLibrary] + '\' node module is not found.' + | ||||
|           ' Falling back temporally to JS based thumbnail generation', err); | ||||
|         Logger.warn(LOG_TAG, '[Thumbnail hardware acceleration] module error: ', err); | ||||
|         Logger.warn(LOG_TAG, 'Thumbnail hardware acceleration is not possible.' + | ||||
|           ' \'' + ThumbnailProcessingLib[Config.Server.thumbnail.processingLibrary] + '\' node module is not found.' + | ||||
|           ' Falling back temporally to JS based thumbnail generation'); | ||||
|         Config.Server.thumbnail.processingLibrary = ThumbnailProcessingLib.Jimp; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     try { | ||||
|       await ConfigDiagnostics.testThumbnailFolder(Config.Server.thumbnail.folder) | ||||
|       await ConfigDiagnostics.testThumbnailFolder(Config.Server.thumbnail.folder); | ||||
|     } catch (err) { | ||||
|       NotificationManager.error("Thumbnail folder error", err); | ||||
|       Logger.error(LOG_TAG, "Thumbnail folder error", err); | ||||
|       NotificationManager.error('Thumbnail folder error', err); | ||||
|       Logger.error(LOG_TAG, 'Thumbnail folder error', err); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     try { | ||||
|       await ConfigDiagnostics.testImageFolder(Config.Server.imagesFolder) | ||||
|       await ConfigDiagnostics.testImageFolder(Config.Server.imagesFolder); | ||||
|     } catch (err) { | ||||
|       NotificationManager.error("Images folder error", err); | ||||
|       Logger.error(LOG_TAG, "Images folder error", err); | ||||
|       NotificationManager.error('Images folder error', err); | ||||
|       Logger.error(LOG_TAG, 'Images folder error', err); | ||||
|     } | ||||
|     try { | ||||
|       await ConfigDiagnostics.testClientThumbnailConfig(Config.Client.Thumbnail) | ||||
|       await ConfigDiagnostics.testClientThumbnailConfig(Config.Client.Thumbnail); | ||||
|     } catch (err) { | ||||
|       NotificationManager.error("Thumbnail settings error", err); | ||||
|       Logger.error(LOG_TAG, "Thumbnail settings error", err); | ||||
|       NotificationManager.error('Thumbnail settings error', err); | ||||
|       Logger.error(LOG_TAG, 'Thumbnail settings error', err); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     try { | ||||
|       await ConfigDiagnostics.testSearchConfig(Config.Client.Search, Config); | ||||
|     } catch (err) { | ||||
|       NotificationManager.warning("Search is not supported with these settings. Disabling temporally. Please adjust the config properly.", err); | ||||
|       Logger.warn(LOG_TAG, "Search is not supported with these settings, switching off..", err); | ||||
|       NotificationManager.warning('Search is not supported with these settings. Disabling temporally. Please adjust the config properly.', err); | ||||
|       Logger.warn(LOG_TAG, 'Search is not supported with these settings, switching off..', err); | ||||
|       Config.Client.Search.enabled = false; | ||||
|     } | ||||
|  | ||||
|     try { | ||||
|       await ConfigDiagnostics.testSharingConfig(Config.Client.Sharing, Config); | ||||
|     } catch (err) { | ||||
|       NotificationManager.warning("Sharing is not supported with these settings. Disabling temporally. Please adjust the config properly.", err); | ||||
|       Logger.warn(LOG_TAG, "Sharing is not supported with these settings, switching off..", err); | ||||
|       NotificationManager.warning('Sharing is not supported with these settings. Disabling temporally. Please adjust the config properly.', err); | ||||
|       Logger.warn(LOG_TAG, 'Sharing is not supported with these settings, switching off..', err); | ||||
|       Config.Client.Sharing.enabled = false; | ||||
|     } | ||||
|  | ||||
|     try { | ||||
|       await ConfigDiagnostics.testMapConfig(Config.Client.Map); | ||||
|     } catch (err) { | ||||
|       NotificationManager.warning("Maps is not supported with these settings. Disabling temporally. Please adjust the config properly.", err); | ||||
|       Logger.warn(LOG_TAG, "Maps is not supported with these settings. Disabling temporally. Please adjust the config properly.", err); | ||||
|       NotificationManager.warning('Maps is not supported with these settings. Disabling temporally. Please adjust the config properly.', err); | ||||
|       Logger.warn(LOG_TAG, 'Maps is not supported with these settings. Disabling temporally. Please adjust the config properly.', err); | ||||
|       Config.Client.Map.enabled = false; | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -1,12 +1,13 @@ | ||||
| ///<reference path="exif.d.ts"/> | ||||
| import {DirectoryDTO} from "../../common/entities/DirectoryDTO"; | ||||
| import {Logger} from "../Logger"; | ||||
| import {Config} from "../../common/config/private/Config"; | ||||
| import {DiskManagerTH} from "./threading/ThreadPool"; | ||||
| import {DiskMangerWorker} from "./threading/DiskMangerWorker"; | ||||
| import {DirectoryDTO} from '../../common/entities/DirectoryDTO'; | ||||
| import {Logger} from '../Logger'; | ||||
| import {Config} from '../../common/config/private/Config'; | ||||
| import {DiskManagerTH} from './threading/ThreadPool'; | ||||
| import {DiskMangerWorker} from './threading/DiskMangerWorker'; | ||||
|  | ||||
|  | ||||
| const LOG_TAG = "[DiskManager]"; | ||||
| const LOG_TAG = '[DiskManager]'; | ||||
|  | ||||
| export class DiskManager { | ||||
|   static threadPool: DiskManagerTH = null; | ||||
|  | ||||
| @@ -17,7 +18,7 @@ export class DiskManager { | ||||
|   } | ||||
|  | ||||
|   public static async scanDirectory(relativeDirectoryName: string): Promise<DirectoryDTO> { | ||||
|     Logger.silly(LOG_TAG, "scanning directory:", relativeDirectoryName); | ||||
|     Logger.silly(LOG_TAG, 'scanning directory:', relativeDirectoryName); | ||||
|  | ||||
|  | ||||
|     let directory: DirectoryDTO = null; | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| import {ProjectPath} from "../ProjectPath"; | ||||
| import *  as fs from "fs"; | ||||
| import *  as path from "path"; | ||||
| import {Config} from "../../common/config/private/Config"; | ||||
| import {ProjectPath} from '../ProjectPath'; | ||||
| import *  as fs from 'fs'; | ||||
| import *  as path from 'path'; | ||||
| import {Config} from '../../common/config/private/Config'; | ||||
|  | ||||
| export class Localizations { | ||||
|  | ||||
| @@ -12,7 +12,7 @@ export class Localizations { | ||||
|     const notLanguage = ['assets']; | ||||
|     const dirCont = fs.readdirSync(ProjectPath.FrontendFolder).filter(f => fs.statSync(path.resolve(ProjectPath.FrontendFolder, f)).isDirectory()); | ||||
|     Config.Client.languages = dirCont.filter(d => notLanguage.indexOf(d) == -1); | ||||
|     Config.Client.languages.push("en"); | ||||
|     Config.Client.languages.push('en'); | ||||
|   } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -1,11 +1,12 @@ | ||||
| import {NotificationDTO, NotificationType} from "../../common/entities/NotificationDTO"; | ||||
| import {NotificationDTO, NotificationType} from '../../common/entities/NotificationDTO'; | ||||
|  | ||||
| export class NotificationManager { | ||||
|   public static notifications: NotificationDTO[] = []; | ||||
|   public static HasNotification: NotificationDTO[] = | ||||
|     [ | ||||
|       { | ||||
|         type: NotificationType.info, | ||||
|         message: "There are unhandled server notification. Login as Administrator to handle them." | ||||
|         message: 'There are unhandled server notification. Login as Administrator to handle them.' | ||||
|       } | ||||
|     ]; | ||||
|  | ||||
|   | ||||
| @@ -1,10 +1,10 @@ | ||||
| import {IUserManager} from "./interfaces/IUserManager"; | ||||
| import {IGalleryManager} from "./interfaces/IGalleryManager"; | ||||
| import {ISearchManager} from "./interfaces/ISearchManager"; | ||||
| import {SQLConnection} from "./sql/SQLConnection"; | ||||
| import {ISharingManager} from "./interfaces/ISharingManager"; | ||||
| import {Logger} from "../Logger"; | ||||
| import {IIndexingManager} from "./interfaces/IIndexingManager"; | ||||
| import {IUserManager} from './interfaces/IUserManager'; | ||||
| import {IGalleryManager} from './interfaces/IGalleryManager'; | ||||
| import {ISearchManager} from './interfaces/ISearchManager'; | ||||
| import {SQLConnection} from './sql/SQLConnection'; | ||||
| import {ISharingManager} from './interfaces/ISharingManager'; | ||||
| import {Logger} from '../Logger'; | ||||
| import {IIndexingManager} from './interfaces/IIndexingManager'; | ||||
|  | ||||
| export class ObjectManagerRepository { | ||||
|  | ||||
| @@ -70,11 +70,11 @@ export class ObjectManagerRepository { | ||||
|  | ||||
|   public static async InitMemoryManagers() { | ||||
|     await ObjectManagerRepository.reset(); | ||||
|     const GalleryManager = require("./memory/GalleryManager").GalleryManager; | ||||
|     const UserManager = require("./memory/UserManager").UserManager; | ||||
|     const SearchManager = require("./memory/SearchManager").SearchManager; | ||||
|     const SharingManager = require("./memory/SharingManager").SharingManager; | ||||
|     const IndexingManager = require("./memory/IndexingManager").IndexingManager; | ||||
|     const GalleryManager = require('./memory/GalleryManager').GalleryManager; | ||||
|     const UserManager = require('./memory/UserManager').UserManager; | ||||
|     const SearchManager = require('./memory/SearchManager').SearchManager; | ||||
|     const SharingManager = require('./memory/SharingManager').SharingManager; | ||||
|     const IndexingManager = require('./memory/IndexingManager').IndexingManager; | ||||
|     ObjectManagerRepository.getInstance().GalleryManager = new GalleryManager(); | ||||
|     ObjectManagerRepository.getInstance().UserManager = new UserManager(); | ||||
|     ObjectManagerRepository.getInstance().SearchManager = new SearchManager(); | ||||
| @@ -85,17 +85,17 @@ export class ObjectManagerRepository { | ||||
|   public static async InitSQLManagers() { | ||||
|     await ObjectManagerRepository.reset(); | ||||
|     await SQLConnection.init(); | ||||
|     const GalleryManager = require("./sql/GalleryManager").GalleryManager; | ||||
|     const UserManager = require("./sql/UserManager").UserManager; | ||||
|     const SearchManager = require("./sql/SearchManager").SearchManager; | ||||
|     const SharingManager = require("./sql/SharingManager").SharingManager; | ||||
|     const IndexingManager = require("./sql/IndexingManager").IndexingManager; | ||||
|     const GalleryManager = require('./sql/GalleryManager').GalleryManager; | ||||
|     const UserManager = require('./sql/UserManager').UserManager; | ||||
|     const SearchManager = require('./sql/SearchManager').SearchManager; | ||||
|     const SharingManager = require('./sql/SharingManager').SharingManager; | ||||
|     const IndexingManager = require('./sql/IndexingManager').IndexingManager; | ||||
|     ObjectManagerRepository.getInstance().GalleryManager = new GalleryManager(); | ||||
|     ObjectManagerRepository.getInstance().UserManager = new UserManager(); | ||||
|     ObjectManagerRepository.getInstance().SearchManager = new SearchManager(); | ||||
|     ObjectManagerRepository.getInstance().SharingManager = new SharingManager(); | ||||
|     ObjectManagerRepository.getInstance().IndexingManager = new IndexingManager(); | ||||
|     Logger.debug("SQL DB inited"); | ||||
|     Logger.debug('SQL DB inited'); | ||||
|   } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -1,8 +1,8 @@ | ||||
| let bcrypt; | ||||
| try { | ||||
|   bcrypt = require("bcrypt"); | ||||
|   bcrypt = require('bcrypt'); | ||||
| } catch (err) { | ||||
|   bcrypt = require("bcryptjs"); | ||||
|   bcrypt = require('bcryptjs'); | ||||
| } | ||||
|  | ||||
| export class PasswordHelper { | ||||
|   | ||||
							
								
								
									
										11
									
								
								backend/model/exif.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										11
									
								
								backend/model/exif.d.ts
									
									
									
									
										vendored
									
									
								
							| @@ -1,26 +1,31 @@ | ||||
| declare module "node-iptc" { | ||||
| declare module 'node-iptc' { | ||||
|  | ||||
|   function e(data): any; | ||||
|  | ||||
|   module e { | ||||
|   } | ||||
|  | ||||
|   export =  e; | ||||
|   export = e; | ||||
| } | ||||
|  | ||||
|  | ||||
| declare module "exif-parser" { | ||||
| declare module 'exif-parser' { | ||||
|   export interface ExifData { | ||||
|     tags: any; | ||||
|     imageSize: any; | ||||
|   } | ||||
|  | ||||
|   export interface ExifObject { | ||||
|     enableTagNames(value: boolean); | ||||
|  | ||||
|     enableImageSize(value: boolean); | ||||
|  | ||||
|     enableReturnTags(value: boolean); | ||||
|  | ||||
|     parse(): ExifData; | ||||
|  | ||||
|   } | ||||
|  | ||||
|   export function create(data: any): ExifObject; | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| import {DirectoryDTO} from "../../../common/entities/DirectoryDTO"; | ||||
| import {DirectoryDTO} from '../../../common/entities/DirectoryDTO'; | ||||
|  | ||||
| export interface IGalleryManager { | ||||
|   listDirectory(relativeDirectoryName: string, | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| import {IndexingProgressDTO} from "../../../common/entities/settings/IndexingProgressDTO"; | ||||
| import {IndexingProgressDTO} from '../../../common/entities/settings/IndexingProgressDTO'; | ||||
|  | ||||
| export interface IIndexingManager { | ||||
|   startIndexing(): void; | ||||
| @@ -7,5 +7,5 @@ export interface IIndexingManager { | ||||
|  | ||||
|   cancelIndexing(): void; | ||||
|  | ||||
|   reset(): Promise<void> ; | ||||
|   reset(): Promise<void>; | ||||
| } | ||||
|   | ||||
| @@ -1,8 +1,10 @@ | ||||
| import {AutoCompleteItem, SearchTypes} from "../../../common/entities/AutoCompleteItem"; | ||||
| import {SearchResultDTO} from "../../../common/entities/SearchResultDTO"; | ||||
| import {AutoCompleteItem, SearchTypes} from '../../../common/entities/AutoCompleteItem'; | ||||
| import {SearchResultDTO} from '../../../common/entities/SearchResultDTO'; | ||||
|  | ||||
| export interface ISearchManager { | ||||
|   autocomplete(text: string): Promise<AutoCompleteItem[]>; | ||||
|  | ||||
|   search(text: string, searchType: SearchTypes): Promise<SearchResultDTO>; | ||||
|  | ||||
|   instantSearch(text: string): Promise<SearchResultDTO>; | ||||
| } | ||||
|   | ||||
| @@ -1,6 +1,9 @@ | ||||
| import {SharingDTO} from "../../../common/entities/SharingDTO"; | ||||
| import {SharingDTO} from '../../../common/entities/SharingDTO'; | ||||
|  | ||||
| export interface ISharingManager { | ||||
|   findOne(filter: any): Promise<SharingDTO>; | ||||
|  | ||||
|   createSharing(sharing: SharingDTO): Promise<SharingDTO>; | ||||
|  | ||||
|   updateSharing(sharing: SharingDTO): Promise<SharingDTO>; | ||||
| } | ||||
|   | ||||
| @@ -1,9 +1,15 @@ | ||||
| import {UserDTO, UserRoles} from "../../../common/entities/UserDTO"; | ||||
| import {UserDTO, UserRoles} from '../../../common/entities/UserDTO'; | ||||
|  | ||||
| export interface IUserManager { | ||||
|   findOne(filter: any): Promise<UserDTO>; | ||||
|  | ||||
|   find(filter: any): Promise<UserDTO[]>; | ||||
|  | ||||
|   createUser(user: UserDTO): Promise<UserDTO>; | ||||
|  | ||||
|   deleteUser(id: number): Promise<UserDTO>; | ||||
|  | ||||
|   changeRole(id: number, newRole: UserRoles): Promise<UserDTO>; | ||||
|  | ||||
|   changePassword(request: any): Promise<void>; | ||||
| } | ||||
|   | ||||
| @@ -1,11 +1,11 @@ | ||||
| import {DirectoryDTO} from "../../../common/entities/DirectoryDTO"; | ||||
| import {IGalleryManager} from "../interfaces/IGalleryManager"; | ||||
| import * as path from "path"; | ||||
| import * as fs from "fs"; | ||||
| import {DiskManager} from "../DiskManger"; | ||||
| import {ProjectPath} from "../../ProjectPath"; | ||||
| import {Config} from "../../../common/config/private/Config"; | ||||
| import {ReIndexingSensitivity} from "../../../common/config/private/IPrivateConfig"; | ||||
| import {DirectoryDTO} from '../../../common/entities/DirectoryDTO'; | ||||
| import {IGalleryManager} from '../interfaces/IGalleryManager'; | ||||
| import * as path from 'path'; | ||||
| import * as fs from 'fs'; | ||||
| import {DiskManager} from '../DiskManger'; | ||||
| import {ProjectPath} from '../../ProjectPath'; | ||||
| import {Config} from '../../../common/config/private/Config'; | ||||
| import {ReIndexingSensitivity} from '../../../common/config/private/IPrivateConfig'; | ||||
|  | ||||
| export class GalleryManager implements IGalleryManager { | ||||
|  | ||||
|   | ||||
| @@ -1,21 +1,21 @@ | ||||
| import {IIndexingManager} from "../interfaces/IIndexingManager"; | ||||
| import {IndexingProgressDTO} from "../../../common/entities/settings/IndexingProgressDTO"; | ||||
| import {IIndexingManager} from '../interfaces/IIndexingManager'; | ||||
| import {IndexingProgressDTO} from '../../../common/entities/settings/IndexingProgressDTO'; | ||||
|  | ||||
| export class IndexingManager implements IIndexingManager { | ||||
|  | ||||
|   startIndexing(): void { | ||||
|     throw new Error("not supported by memory DB"); | ||||
|     throw new Error('not supported by memory DB'); | ||||
|   } | ||||
|  | ||||
|   getProgress(): IndexingProgressDTO { | ||||
|     throw new Error("not supported by memory DB"); | ||||
|     throw new Error('not supported by memory DB'); | ||||
|   } | ||||
|  | ||||
|   cancelIndexing(): void { | ||||
|     throw new Error("not supported by memory DB"); | ||||
|     throw new Error('not supported by memory DB'); | ||||
|   } | ||||
|  | ||||
|   reset(): Promise<void> { | ||||
|     throw new Error("Method not implemented."); | ||||
|     throw new Error('Method not implemented.'); | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -1,18 +1,18 @@ | ||||
| import {AutoCompleteItem, SearchTypes} from "../../../common/entities/AutoCompleteItem"; | ||||
| import {ISearchManager} from "../interfaces/ISearchManager"; | ||||
| import {SearchResultDTO} from "../../../common/entities/SearchResultDTO"; | ||||
| import {AutoCompleteItem, SearchTypes} from '../../../common/entities/AutoCompleteItem'; | ||||
| import {ISearchManager} from '../interfaces/ISearchManager'; | ||||
| import {SearchResultDTO} from '../../../common/entities/SearchResultDTO'; | ||||
|  | ||||
| export class SearchManager implements ISearchManager { | ||||
|   autocomplete(text: string): Promise<AutoCompleteItem[]> { | ||||
|     throw new Error("Method not implemented."); | ||||
|     throw new Error('Method not implemented.'); | ||||
|   } | ||||
|  | ||||
|   search(text: string, searchType: SearchTypes): Promise<SearchResultDTO> { | ||||
|     throw new Error("Method not implemented."); | ||||
|     throw new Error('Method not implemented.'); | ||||
|   } | ||||
|  | ||||
|   instantSearch(text: string): Promise<SearchResultDTO> { | ||||
|     throw new Error("Method not implemented."); | ||||
|     throw new Error('Method not implemented.'); | ||||
|   } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -1,19 +1,19 @@ | ||||
| import {ISharingManager} from "../interfaces/ISharingManager"; | ||||
| import {SharingDTO} from "../../../common/entities/SharingDTO"; | ||||
| import {ISharingManager} from '../interfaces/ISharingManager'; | ||||
| import {SharingDTO} from '../../../common/entities/SharingDTO'; | ||||
|  | ||||
| export class SharingManager implements ISharingManager { | ||||
|  | ||||
|  | ||||
|   findOne(filter: any): Promise<SharingDTO> { | ||||
|     throw new Error("not implemented"); | ||||
|     throw new Error('not implemented'); | ||||
|   } | ||||
|  | ||||
|   createSharing(sharing: SharingDTO): Promise<SharingDTO> { | ||||
|     throw new Error("not implemented"); | ||||
|     throw new Error('not implemented'); | ||||
|   } | ||||
|  | ||||
|   updateSharing(sharing: SharingDTO): Promise<SharingDTO> { | ||||
|     throw new Error("not implemented"); | ||||
|     throw new Error('not implemented'); | ||||
|   } | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -1,10 +1,10 @@ | ||||
| import {UserDTO, UserRoles} from "../../../common/entities/UserDTO"; | ||||
| import {IUserManager} from "../interfaces/IUserManager"; | ||||
| import {ProjectPath} from "../../ProjectPath"; | ||||
| import {Utils} from "../../../common/Utils"; | ||||
| import * as path from "path"; | ||||
| import * as fs from "fs"; | ||||
| import {PasswordHelper} from "../PasswordHelper"; | ||||
| import {UserDTO, UserRoles} from '../../../common/entities/UserDTO'; | ||||
| import {IUserManager} from '../interfaces/IUserManager'; | ||||
| import {ProjectPath} from '../../ProjectPath'; | ||||
| import {Utils} from '../../../common/Utils'; | ||||
| import * as path from 'path'; | ||||
| import * as fs from 'fs'; | ||||
| import {PasswordHelper} from '../PasswordHelper'; | ||||
|  | ||||
|  | ||||
| export class UserManager implements IUserManager { | ||||
| @@ -28,14 +28,14 @@ export class UserManager implements IUserManager { | ||||
|     } | ||||
|  | ||||
|     if (!this.db.idCounter) { | ||||
|       console.log("creating counter"); | ||||
|       console.log('creating counter'); | ||||
|       this.db.idCounter = 1; | ||||
|     } | ||||
|  | ||||
|     if (!this.db.users) { | ||||
|       this.db.users = []; | ||||
|       //TODO: remove defaults | ||||
|       this.createUser(<UserDTO>{name: "admin", password: "admin", role: UserRoles.Admin}); | ||||
|       this.createUser(<UserDTO>{name: 'admin', password: 'admin', role: UserRoles.Admin}); | ||||
|     } | ||||
|     this.saveDB(); | ||||
|  | ||||
| @@ -46,7 +46,7 @@ export class UserManager implements IUserManager { | ||||
|     const result = await this.find(filter); | ||||
|  | ||||
|     if (result.length == 0) { | ||||
|       throw "UserDTO not found"; | ||||
|       throw 'UserDTO not found'; | ||||
|     } | ||||
|     return result[0]; | ||||
|   } | ||||
| @@ -97,7 +97,7 @@ export class UserManager implements IUserManager { | ||||
|   } | ||||
|  | ||||
|   public async changePassword(request: any) { | ||||
|     throw new Error("not implemented"); //TODO: implement | ||||
|     throw new Error('not implemented'); //TODO: implement | ||||
|   } | ||||
|  | ||||
|   private loadDB() { | ||||
|   | ||||
| @@ -1,16 +1,16 @@ | ||||
| import {IGalleryManager} from "../interfaces/IGalleryManager"; | ||||
| import {DirectoryDTO} from "../../../common/entities/DirectoryDTO"; | ||||
| import * as path from "path"; | ||||
| import * as fs from "fs"; | ||||
| import {DirectoryEntity} from "./enitites/DirectoryEntity"; | ||||
| import {SQLConnection} from "./SQLConnection"; | ||||
| import {DiskManager} from "../DiskManger"; | ||||
| import {PhotoEntity} from "./enitites/PhotoEntity"; | ||||
| import {Utils} from "../../../common/Utils"; | ||||
| import {ProjectPath} from "../../ProjectPath"; | ||||
| import {Config} from "../../../common/config/private/Config"; | ||||
| import {ISQLGalleryManager} from "./IGalleryManager"; | ||||
| import {ReIndexingSensitivity} from "../../../common/config/private/IPrivateConfig"; | ||||
| import {IGalleryManager} from '../interfaces/IGalleryManager'; | ||||
| import {DirectoryDTO} from '../../../common/entities/DirectoryDTO'; | ||||
| import * as path from 'path'; | ||||
| import * as fs from 'fs'; | ||||
| import {DirectoryEntity} from './enitites/DirectoryEntity'; | ||||
| import {SQLConnection} from './SQLConnection'; | ||||
| import {DiskManager} from '../DiskManger'; | ||||
| import {PhotoEntity} from './enitites/PhotoEntity'; | ||||
| import {Utils} from '../../../common/Utils'; | ||||
| import {ProjectPath} from '../../ProjectPath'; | ||||
| import {Config} from '../../../common/config/private/Config'; | ||||
| import {ISQLGalleryManager} from './IGalleryManager'; | ||||
| import {ReIndexingSensitivity} from '../../../common/config/private/IPrivateConfig'; | ||||
|  | ||||
| export class GalleryManager implements IGalleryManager, ISQLGalleryManager { | ||||
|  | ||||
| @@ -18,7 +18,7 @@ export class GalleryManager implements IGalleryManager, ISQLGalleryManager { | ||||
|   public async listDirectory(relativeDirectoryName: string, | ||||
|                              knownLastModified?: number, | ||||
|                              knownLastScanned?: number): Promise<DirectoryDTO> { | ||||
|     relativeDirectoryName = path.normalize(path.join("." + path.sep, relativeDirectoryName)); | ||||
|     relativeDirectoryName = path.normalize(path.join('.' + path.sep, relativeDirectoryName)); | ||||
|     const directoryName = path.basename(relativeDirectoryName); | ||||
|     const directoryParent = path.join(path.dirname(relativeDirectoryName), path.sep); | ||||
|     const connection = await SQLConnection.getConnection(); | ||||
| @@ -26,13 +26,13 @@ export class GalleryManager implements IGalleryManager, ISQLGalleryManager { | ||||
|     const lastModified = Math.max(stat.ctime.getTime(), stat.mtime.getTime()); | ||||
|     let dir = await connection | ||||
|       .getRepository(DirectoryEntity) | ||||
|       .createQueryBuilder("directory") | ||||
|       .where("directory.name = :name AND directory.path = :path", { | ||||
|       .createQueryBuilder('directory') | ||||
|       .where('directory.name = :name AND directory.path = :path', { | ||||
|         name: directoryName, | ||||
|         path: directoryParent | ||||
|       }) | ||||
|       .leftJoinAndSelect("directory.directories", "directories") | ||||
|       .leftJoinAndSelect("directory.photos", "photos") | ||||
|       .leftJoinAndSelect('directory.directories', 'directories') | ||||
|       .leftJoinAndSelect('directory.photos', 'photos') | ||||
|       .getOne(); | ||||
|  | ||||
|  | ||||
| @@ -61,11 +61,11 @@ export class GalleryManager implements IGalleryManager, ISQLGalleryManager { | ||||
|         for (let i = 0; i < dir.directories.length; i++) { | ||||
|           dir.directories[i].photos = await connection | ||||
|             .getRepository(PhotoEntity) | ||||
|             .createQueryBuilder("photo") | ||||
|             .where("photo.directory = :dir", { | ||||
|             .createQueryBuilder('photo') | ||||
|             .where('photo.directory = :dir', { | ||||
|               dir: dir.directories[i].id | ||||
|             }) | ||||
|             .orderBy("photo.metadata.creationDate", "ASC") | ||||
|             .orderBy('photo.metadata.creationDate', 'ASC') | ||||
|             .limit(Config.Server.indexing.folderPreviewSize) | ||||
|             .getMany(); | ||||
|           dir.directories[i].isPartial = true; | ||||
| @@ -85,7 +85,7 @@ export class GalleryManager implements IGalleryManager, ISQLGalleryManager { | ||||
|  | ||||
|       //not indexed since a while, index it in a lazy manner | ||||
|       if ((Date.now() - dir.lastScanned > Config.Server.indexing.cachedFolderTimeout && | ||||
|           Config.Server.indexing.reIndexingSensitivity >= ReIndexingSensitivity.medium) || | ||||
|         Config.Server.indexing.reIndexingSensitivity >= ReIndexingSensitivity.medium) || | ||||
|         Config.Server.indexing.reIndexingSensitivity >= ReIndexingSensitivity.high) { | ||||
|         //on the fly reindexing | ||||
|         this.indexDirectory(relativeDirectoryName).catch((err) => { | ||||
| @@ -132,8 +132,8 @@ export class GalleryManager implements IGalleryManager, ISQLGalleryManager { | ||||
|     const photosRepository = connection.getRepository(PhotoEntity); | ||||
|  | ||||
|  | ||||
|     let currentDir = await directoryRepository.createQueryBuilder("directory") | ||||
|       .where("directory.name = :name AND directory.path = :path", { | ||||
|     let currentDir = await directoryRepository.createQueryBuilder('directory') | ||||
|       .where('directory.name = :name AND directory.path = :path', { | ||||
|         name: scannedDirectory.name, | ||||
|         path: scannedDirectory.path | ||||
|       }).getOne(); | ||||
| @@ -147,8 +147,8 @@ export class GalleryManager implements IGalleryManager, ISQLGalleryManager { | ||||
|       currentDir = await directoryRepository.save(<DirectoryEntity>scannedDirectory); | ||||
|     } | ||||
|  | ||||
|     let childDirectories = await directoryRepository.createQueryBuilder("directory") | ||||
|       .where("directory.parent = :dir", { | ||||
|     let childDirectories = await directoryRepository.createQueryBuilder('directory') | ||||
|       .where('directory.parent = :dir', { | ||||
|         dir: currentDir.id | ||||
|       }).getMany(); | ||||
|  | ||||
| @@ -185,8 +185,8 @@ export class GalleryManager implements IGalleryManager, ISQLGalleryManager { | ||||
|     await directoryRepository.remove(childDirectories); | ||||
|  | ||||
|  | ||||
|     let indexedPhotos = await photosRepository.createQueryBuilder("photo") | ||||
|       .where("photo.directory = :dir", { | ||||
|     let indexedPhotos = await photosRepository.createQueryBuilder('photo') | ||||
|       .where('photo.directory = :dir', { | ||||
|         dir: currentDir.id | ||||
|       }).getMany(); | ||||
|  | ||||
|   | ||||
| @@ -1,16 +1,16 @@ | ||||
| import "reflect-metadata"; | ||||
| import {Connection, ConnectionOptions, createConnection, getConnection} from "typeorm"; | ||||
| import {UserEntity} from "./enitites/UserEntity"; | ||||
| import {UserRoles} from "../../../common/entities/UserDTO"; | ||||
| import {PhotoEntity} from "./enitites/PhotoEntity"; | ||||
| import {DirectoryEntity} from "./enitites/DirectoryEntity"; | ||||
| import {Config} from "../../../common/config/private/Config"; | ||||
| import {SharingEntity} from "./enitites/SharingEntity"; | ||||
| import {DataBaseConfig, DatabaseType} from "../../../common/config/private/IPrivateConfig"; | ||||
| import {PasswordHelper} from "../PasswordHelper"; | ||||
| import {ProjectPath} from "../../ProjectPath"; | ||||
| import {VersionEntity} from "./enitites/VersionEntity"; | ||||
| import {Logger} from "../../Logger"; | ||||
| import 'reflect-metadata'; | ||||
| import {Connection, ConnectionOptions, createConnection, getConnection} from 'typeorm'; | ||||
| import {UserEntity} from './enitites/UserEntity'; | ||||
| import {UserRoles} from '../../../common/entities/UserDTO'; | ||||
| import {PhotoEntity} from './enitites/PhotoEntity'; | ||||
| import {DirectoryEntity} from './enitites/DirectoryEntity'; | ||||
| import {Config} from '../../../common/config/private/Config'; | ||||
| import {SharingEntity} from './enitites/SharingEntity'; | ||||
| import {DataBaseConfig, DatabaseType} from '../../../common/config/private/IPrivateConfig'; | ||||
| import {PasswordHelper} from '../PasswordHelper'; | ||||
| import {ProjectPath} from '../../ProjectPath'; | ||||
| import {VersionEntity} from './enitites/VersionEntity'; | ||||
| import {Logger} from '../../Logger'; | ||||
|  | ||||
|  | ||||
| export class SQLConnection { | ||||
| @@ -27,7 +27,7 @@ export class SQLConnection { | ||||
|     if (this.connection == null) { | ||||
|  | ||||
|       let options: any = this.getDriver(Config.Server.database); | ||||
|       options.name = "main"; | ||||
|       options.name = 'main'; | ||||
|       options.entities = [ | ||||
|         UserEntity, | ||||
|         PhotoEntity, | ||||
| @@ -46,11 +46,11 @@ export class SQLConnection { | ||||
|  | ||||
|   public static async tryConnection(config: DataBaseConfig) { | ||||
|     try { | ||||
|       await getConnection("test").close(); | ||||
|       await getConnection('test').close(); | ||||
|     } catch (err) { | ||||
|     } | ||||
|     const options: any = this.getDriver(config); | ||||
|     options.name = "test"; | ||||
|     options.name = 'test'; | ||||
|     options.entities = [ | ||||
|       UserEntity, | ||||
|       PhotoEntity, | ||||
| @@ -66,6 +66,20 @@ export class SQLConnection { | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   public static async init(): Promise<void> { | ||||
|     const connection = await this.getConnection(); | ||||
|     let userRepository = connection.getRepository(UserEntity); | ||||
|     let admins = await userRepository.find({role: UserRoles.Admin}); | ||||
|     if (admins.length == 0) { | ||||
|       let a = new UserEntity(); | ||||
|       a.name = 'admin'; | ||||
|       a.password = PasswordHelper.cryptPassword('admin'); | ||||
|       a.role = UserRoles.Admin; | ||||
|       await userRepository.save(a); | ||||
|     } | ||||
|  | ||||
|   } | ||||
|  | ||||
|   private static async schemeSync(connection: Connection) { | ||||
|     let version = null; | ||||
|     try { | ||||
| @@ -75,7 +89,7 @@ export class SQLConnection { | ||||
|     if (version && version.version == SQLConnection.VERSION) { | ||||
|       return; | ||||
|     } | ||||
|     Logger.info("Updating database scheme"); | ||||
|     Logger.info('Updating database scheme'); | ||||
|     if (!version) { | ||||
|       version = new VersionEntity(); | ||||
|     } | ||||
| @@ -87,25 +101,11 @@ export class SQLConnection { | ||||
|     await connection.getRepository(VersionEntity).save(version); | ||||
|   } | ||||
|  | ||||
|   public static async init(): Promise<void> { | ||||
|     const connection = await this.getConnection(); | ||||
|     let userRepository = connection.getRepository(UserEntity); | ||||
|     let admins = await userRepository.find({role: UserRoles.Admin}); | ||||
|     if (admins.length == 0) { | ||||
|       let a = new UserEntity(); | ||||
|       a.name = "admin"; | ||||
|       a.password = PasswordHelper.cryptPassword("admin"); | ||||
|       a.role = UserRoles.Admin; | ||||
|       await userRepository.save(a); | ||||
|     } | ||||
|  | ||||
|   } | ||||
|  | ||||
|   private static getDriver(config: DataBaseConfig): ConnectionOptions { | ||||
|     let driver: ConnectionOptions = null; | ||||
|     if (config.type == DatabaseType.mysql) { | ||||
|       driver = { | ||||
|         type: "mysql", | ||||
|         type: 'mysql', | ||||
|         host: config.mysql.host, | ||||
|         port: 3306, | ||||
|         username: config.mysql.username, | ||||
| @@ -114,7 +114,7 @@ export class SQLConnection { | ||||
|       }; | ||||
|     } else if (config.type == DatabaseType.sqlite) { | ||||
|       driver = { | ||||
|         type: "sqlite", | ||||
|         type: 'sqlite', | ||||
|         database: ProjectPath.getAbsolutePath(config.sqlite.storage) | ||||
|       }; | ||||
|     } | ||||
|   | ||||
| @@ -1,9 +1,9 @@ | ||||
| import {AutoCompleteItem, SearchTypes} from "../../../common/entities/AutoCompleteItem"; | ||||
| import {ISearchManager} from "../interfaces/ISearchManager"; | ||||
| import {SearchResultDTO} from "../../../common/entities/SearchResultDTO"; | ||||
| import {SQLConnection} from "./SQLConnection"; | ||||
| import {PhotoEntity} from "./enitites/PhotoEntity"; | ||||
| import {DirectoryEntity} from "./enitites/DirectoryEntity"; | ||||
| import {AutoCompleteItem, SearchTypes} from '../../../common/entities/AutoCompleteItem'; | ||||
| import {ISearchManager} from '../interfaces/ISearchManager'; | ||||
| import {SearchResultDTO} from '../../../common/entities/SearchResultDTO'; | ||||
| import {SQLConnection} from './SQLConnection'; | ||||
| import {PhotoEntity} from './enitites/PhotoEntity'; | ||||
| import {DirectoryEntity} from './enitites/DirectoryEntity'; | ||||
|  | ||||
| export class SearchManager implements ISearchManager { | ||||
|  | ||||
| @@ -31,10 +31,10 @@ export class SearchManager implements ISearchManager { | ||||
|     (await photoRepository | ||||
|       .createQueryBuilder('photo') | ||||
|       .select('DISTINCT(photo.metadata.keywords)') | ||||
|       .where('photo.metadata.keywords LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"}) | ||||
|       .where('photo.metadata.keywords LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'}) | ||||
|       .limit(5) | ||||
|       .getRawMany()) | ||||
|       .map(r => <Array<string>>r.metadataKeywords.split(",")) | ||||
|       .map(r => <Array<string>>r.metadataKeywords.split(',')) | ||||
|       .forEach(keywords => { | ||||
|         result = result.concat(this.encapsulateAutoComplete(keywords.filter(k => k.toLowerCase().indexOf(text.toLowerCase()) != -1), SearchTypes.keyword)); | ||||
|       }); | ||||
| @@ -43,14 +43,14 @@ export class SearchManager implements ISearchManager { | ||||
|     (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 utf8_general_ci', {text: "%" + text + "%"}) | ||||
|       .orWhere('photo.metadata.positionData.state LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"}) | ||||
|       .orWhere('photo.metadata.positionData.city LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"}) | ||||
|       .where('photo.metadata.positionData.country LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'}) | ||||
|       .orWhere('photo.metadata.positionData.state LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'}) | ||||
|       .orWhere('photo.metadata.positionData.city LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'}) | ||||
|       .groupBy('photo.metadata.positionData.country, photo.metadata.positionData.state, photo.metadata.positionData.city') | ||||
|       .limit(5) | ||||
|       .getRawMany()) | ||||
|       .filter(pm => !!pm) | ||||
|       .map(pm => <Array<string>>[pm.city || "", pm.country || "", pm.state || ""]) | ||||
|       .map(pm => <Array<string>>[pm.city || '', pm.country || '', pm.state || '']) | ||||
|       .forEach(positions => { | ||||
|         result = result.concat(this.encapsulateAutoComplete(positions.filter(p => p.toLowerCase().indexOf(text.toLowerCase()) != -1), SearchTypes.position)); | ||||
|       }); | ||||
| @@ -58,7 +58,7 @@ export class SearchManager implements ISearchManager { | ||||
|     result = result.concat(this.encapsulateAutoComplete((await photoRepository | ||||
|       .createQueryBuilder('photo') | ||||
|       .select('DISTINCT(photo.name)') | ||||
|       .where('photo.name LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"}) | ||||
|       .where('photo.name LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'}) | ||||
|       .limit(5) | ||||
|       .getRawMany()) | ||||
|       .map(r => r.name), SearchTypes.image)); | ||||
| @@ -66,7 +66,7 @@ export class SearchManager implements ISearchManager { | ||||
|     result = result.concat(this.encapsulateAutoComplete((await directoryRepository | ||||
|       .createQueryBuilder('dir') | ||||
|       .select('DISTINCT(dir.name)') | ||||
|       .where('dir.name LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"}) | ||||
|       .where('dir.name LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'}) | ||||
|       .limit(5) | ||||
|       .getRawMany()) | ||||
|       .map(r => r.name), SearchTypes.directory)); | ||||
| @@ -88,27 +88,27 @@ export class SearchManager implements ISearchManager { | ||||
|  | ||||
|     let query = connection | ||||
|       .getRepository(PhotoEntity) | ||||
|       .createQueryBuilder("photo") | ||||
|       .innerJoinAndSelect("photo.directory", "directory") | ||||
|       .orderBy("photo.metadata.creationDate", "ASC"); | ||||
|       .createQueryBuilder('photo') | ||||
|       .innerJoinAndSelect('photo.directory', 'directory') | ||||
|       .orderBy('photo.metadata.creationDate', 'ASC'); | ||||
|  | ||||
|  | ||||
|     if (!searchType || searchType === SearchTypes.directory) { | ||||
|       query.orWhere('directory.name LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"}); | ||||
|       query.orWhere('directory.name LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'}); | ||||
|     } | ||||
|  | ||||
|     if (!searchType || searchType === SearchTypes.image) { | ||||
|       query.orWhere('photo.name LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"}); | ||||
|       query.orWhere('photo.name LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'}); | ||||
|     } | ||||
|  | ||||
|     if (!searchType || searchType === SearchTypes.position) { | ||||
|       query.orWhere('photo.metadata.positionData.country LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"}) | ||||
|         .orWhere('photo.metadata.positionData.state LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"}) | ||||
|         .orWhere('photo.metadata.positionData.city LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"}); | ||||
|       query.orWhere('photo.metadata.positionData.country LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'}) | ||||
|         .orWhere('photo.metadata.positionData.state LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'}) | ||||
|         .orWhere('photo.metadata.positionData.city LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'}); | ||||
|  | ||||
|     } | ||||
|     if (!searchType || searchType === SearchTypes.keyword) { | ||||
|       query.orWhere('photo.metadata.keywords LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"}); | ||||
|       query.orWhere('photo.metadata.keywords LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'}); | ||||
|     } | ||||
|  | ||||
|     result.photos = await query | ||||
| @@ -121,8 +121,8 @@ export class SearchManager implements ISearchManager { | ||||
|  | ||||
|     result.directories = await connection | ||||
|       .getRepository(DirectoryEntity) | ||||
|       .createQueryBuilder("dir") | ||||
|       .where('dir.name LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"}) | ||||
|       .createQueryBuilder('dir') | ||||
|       .where('dir.name LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'}) | ||||
|       .limit(201) | ||||
|       .getMany(); | ||||
|  | ||||
| @@ -146,22 +146,22 @@ export class SearchManager implements ISearchManager { | ||||
|  | ||||
|     result.photos = await connection | ||||
|       .getRepository(PhotoEntity) | ||||
|       .createQueryBuilder("photo") | ||||
|       .orderBy("photo.metadata.creationDate", "ASC") | ||||
|       .where('photo.metadata.keywords LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"}) | ||||
|       .orWhere('photo.metadata.positionData.country LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"}) | ||||
|       .orWhere('photo.metadata.positionData.state LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"}) | ||||
|       .orWhere('photo.metadata.positionData.city LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"}) | ||||
|       .orWhere('photo.name LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"}) | ||||
|       .innerJoinAndSelect("photo.directory", "directory") | ||||
|       .createQueryBuilder('photo') | ||||
|       .orderBy('photo.metadata.creationDate', 'ASC') | ||||
|       .where('photo.metadata.keywords LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'}) | ||||
|       .orWhere('photo.metadata.positionData.country LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'}) | ||||
|       .orWhere('photo.metadata.positionData.state LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'}) | ||||
|       .orWhere('photo.metadata.positionData.city LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'}) | ||||
|       .orWhere('photo.name LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'}) | ||||
|       .innerJoinAndSelect('photo.directory', 'directory') | ||||
|       .limit(10) | ||||
|       .getMany(); | ||||
|  | ||||
|  | ||||
|     result.directories = await connection | ||||
|       .getRepository(DirectoryEntity) | ||||
|       .createQueryBuilder("dir") | ||||
|       .where('dir.name LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"}) | ||||
|       .createQueryBuilder('dir') | ||||
|       .where('dir.name LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'}) | ||||
|       .limit(10) | ||||
|       .getMany(); | ||||
|  | ||||
|   | ||||
| @@ -1,9 +1,9 @@ | ||||
| import {ISharingManager} from "../interfaces/ISharingManager"; | ||||
| import {SharingDTO} from "../../../common/entities/SharingDTO"; | ||||
| import {SQLConnection} from "./SQLConnection"; | ||||
| import {SharingEntity} from "./enitites/SharingEntity"; | ||||
| import {Config} from "../../../common/config/private/Config"; | ||||
| import {PasswordHelper} from "../PasswordHelper"; | ||||
| import {ISharingManager} from '../interfaces/ISharingManager'; | ||||
| import {SharingDTO} from '../../../common/entities/SharingDTO'; | ||||
| import {SQLConnection} from './SQLConnection'; | ||||
| import {SharingEntity} from './enitites/SharingEntity'; | ||||
| import {Config} from '../../../common/config/private/Config'; | ||||
| import {PasswordHelper} from '../PasswordHelper'; | ||||
|  | ||||
| export class SharingManager implements ISharingManager { | ||||
|  | ||||
| @@ -11,8 +11,8 @@ export class SharingManager implements ISharingManager { | ||||
|     const connection = await SQLConnection.getConnection(); | ||||
|     return connection | ||||
|       .getRepository(SharingEntity) | ||||
|       .createQueryBuilder("share") | ||||
|       .where("expires < :now", {now: Date.now()}) | ||||
|       .createQueryBuilder('share') | ||||
|       .where('expires < :now', {now: Date.now()}) | ||||
|       .delete() | ||||
|       .execute(); | ||||
|   } | ||||
| @@ -42,7 +42,7 @@ export class SharingManager implements ISharingManager { | ||||
|     }); | ||||
|  | ||||
|     if (sharing.timeStamp < Date.now() - Config.Server.sharing.updateTimeout) { | ||||
|       throw "Sharing is locked, can't update anymore" | ||||
|       throw 'Sharing is locked, can\'t update anymore'; | ||||
|     } | ||||
|     if (inSharing.password == null) { | ||||
|       sharing.password = null; | ||||
|   | ||||
| @@ -1,8 +1,8 @@ | ||||
| import {UserDTO, UserRoles} from "../../../common/entities/UserDTO"; | ||||
| import {IUserManager} from "../interfaces/IUserManager"; | ||||
| import {UserEntity} from "./enitites/UserEntity"; | ||||
| import {SQLConnection} from "./SQLConnection"; | ||||
| import {PasswordHelper} from "../PasswordHelper"; | ||||
| import {UserDTO, UserRoles} from '../../../common/entities/UserDTO'; | ||||
| import {IUserManager} from '../interfaces/IUserManager'; | ||||
| import {UserEntity} from './enitites/UserEntity'; | ||||
| import {SQLConnection} from './SQLConnection'; | ||||
| import {PasswordHelper} from '../PasswordHelper'; | ||||
|  | ||||
|  | ||||
| export class UserManager implements IUserManager { | ||||
| @@ -22,7 +22,7 @@ export class UserManager implements IUserManager { | ||||
|     } | ||||
|  | ||||
|     if (pass && !PasswordHelper.comparePassword(pass, user.password)) { | ||||
|       throw "No entry found"; | ||||
|       throw 'No entry found'; | ||||
|     } | ||||
|     return user; | ||||
|  | ||||
| @@ -64,7 +64,7 @@ export class UserManager implements IUserManager { | ||||
|   } | ||||
|  | ||||
|   public async changePassword(request: any) { | ||||
|     throw new Error("not implemented"); //TODO: implement | ||||
|     throw new Error('not implemented'); //TODO: implement | ||||
|   } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| import {Column, Entity, ManyToOne, OneToMany, PrimaryGeneratedColumn} from "typeorm"; | ||||
| import {DirectoryDTO} from "../../../../common/entities/DirectoryDTO"; | ||||
| import {PhotoEntity} from "./PhotoEntity"; | ||||
| import {Column, Entity, ManyToOne, OneToMany, PrimaryGeneratedColumn} from 'typeorm'; | ||||
| import {DirectoryDTO} from '../../../../common/entities/DirectoryDTO'; | ||||
| import {PhotoEntity} from './PhotoEntity'; | ||||
|  | ||||
| @Entity() | ||||
| export class DirectoryEntity implements DirectoryDTO { | ||||
| @@ -23,12 +23,12 @@ export class DirectoryEntity implements DirectoryDTO { | ||||
|   /** | ||||
|    * Last time the directory was fully scanned, not only for a few photos to create a preview | ||||
|    */ | ||||
|   @Column({type: "bigint", nullable: true}) | ||||
|   @Column({type: 'bigint', nullable: true}) | ||||
|   public lastScanned: number; | ||||
|  | ||||
|   isPartial?: boolean; | ||||
|  | ||||
|   @ManyToOne(type => DirectoryEntity, directory => directory.directories, {onDelete: "CASCADE"}) | ||||
|   @ManyToOne(type => DirectoryEntity, directory => directory.directories, {onDelete: 'CASCADE'}) | ||||
|   public parent: DirectoryEntity; | ||||
|  | ||||
|   @OneToMany(type => DirectoryEntity, dir => dir.parent) | ||||
|   | ||||
| @@ -1,37 +1,30 @@ | ||||
| import {Column, Entity, ManyToOne, PrimaryGeneratedColumn} from "typeorm"; | ||||
| import { | ||||
|   CameraMetadata, | ||||
|   GPSMetadata, | ||||
|   ImageSize, | ||||
|   PhotoDTO, | ||||
|   PhotoMetadata, | ||||
|   PositionMetaData | ||||
| } from "../../../../common/entities/PhotoDTO"; | ||||
| import {DirectoryEntity} from "./DirectoryEntity"; | ||||
| import {Column, Entity, ManyToOne, PrimaryGeneratedColumn} from 'typeorm'; | ||||
| import {CameraMetadata, GPSMetadata, ImageSize, PhotoDTO, PhotoMetadata, PositionMetaData} from '../../../../common/entities/PhotoDTO'; | ||||
| import {DirectoryEntity} from './DirectoryEntity'; | ||||
|  | ||||
|  | ||||
| @Entity() | ||||
| export class CameraMetadataEntity implements CameraMetadata { | ||||
|  | ||||
|   @Column("text", {nullable: true}) | ||||
|   @Column('text', {nullable: true}) | ||||
|   ISO: number; | ||||
|  | ||||
|   @Column("text", {nullable: true}) | ||||
|   @Column('text', {nullable: true}) | ||||
|   model: string; | ||||
|  | ||||
|   @Column("text", {nullable: true}) | ||||
|   @Column('text', {nullable: true}) | ||||
|   maker: string; | ||||
|  | ||||
|   @Column("int", {nullable: true}) | ||||
|   @Column('int', {nullable: true}) | ||||
|   fStop: number; | ||||
|  | ||||
|   @Column("int", {nullable: true}) | ||||
|   @Column('int', {nullable: true}) | ||||
|   exposure: number; | ||||
|  | ||||
|   @Column("int", {nullable: true}) | ||||
|   @Column('int', {nullable: true}) | ||||
|   focalLength: number; | ||||
|  | ||||
|   @Column("text", {nullable: true}) | ||||
|   @Column('text', {nullable: true}) | ||||
|   lens: string; | ||||
| } | ||||
|  | ||||
| @@ -39,21 +32,21 @@ export class CameraMetadataEntity implements CameraMetadata { | ||||
| @Entity() | ||||
| export class GPSMetadataEntity implements GPSMetadata { | ||||
|  | ||||
|   @Column("int", {nullable: true}) | ||||
|   @Column('int', {nullable: true}) | ||||
|   latitude: number; | ||||
|   @Column("int", {nullable: true}) | ||||
|   @Column('int', {nullable: true}) | ||||
|   longitude: number; | ||||
|   @Column("int", {nullable: true}) | ||||
|   @Column('int', {nullable: true}) | ||||
|   altitude: number; | ||||
| } | ||||
|  | ||||
| @Entity() | ||||
| export class ImageSizeEntity implements ImageSize { | ||||
|  | ||||
|   @Column("int") | ||||
|   @Column('int') | ||||
|   width: number; | ||||
|  | ||||
|   @Column("int") | ||||
|   @Column('int') | ||||
|   height: number; | ||||
| } | ||||
|  | ||||
| @@ -64,13 +57,13 @@ export class PositionMetaDataEntity implements PositionMetaData { | ||||
|   @Column(type => GPSMetadataEntity) | ||||
|   GPSData: GPSMetadataEntity; | ||||
|  | ||||
|   @Column("text", {nullable: true}) | ||||
|   @Column('text', {nullable: true}) | ||||
|   country: string; | ||||
|  | ||||
|   @Column("text", {nullable: true}) | ||||
|   @Column('text', {nullable: true}) | ||||
|   state: string; | ||||
|  | ||||
|   @Column("text", {nullable: true}) | ||||
|   @Column('text', {nullable: true}) | ||||
|   city: string; | ||||
| } | ||||
|  | ||||
| @@ -78,7 +71,7 @@ export class PositionMetaDataEntity implements PositionMetaData { | ||||
| @Entity() | ||||
| export class PhotoMetadataEntity implements PhotoMetadata { | ||||
|  | ||||
|   @Column("simple-array") | ||||
|   @Column('simple-array') | ||||
|   keywords: Array<string>; | ||||
|  | ||||
|   @Column(type => CameraMetadataEntity) | ||||
| @@ -90,10 +83,10 @@ export class PhotoMetadataEntity implements PhotoMetadata { | ||||
|   @Column(type => ImageSizeEntity) | ||||
|   size: ImageSizeEntity; | ||||
|  | ||||
|   @Column("bigint") | ||||
|   @Column('bigint') | ||||
|   creationDate: number; | ||||
|  | ||||
|   @Column("int") | ||||
|   @Column('int') | ||||
|   fileSize: number; | ||||
| } | ||||
|  | ||||
| @@ -104,10 +97,10 @@ export class PhotoEntity implements PhotoDTO { | ||||
|   @PrimaryGeneratedColumn() | ||||
|   id: number; | ||||
|  | ||||
|   @Column("text") | ||||
|   @Column('text') | ||||
|   name: string; | ||||
|  | ||||
|   @ManyToOne(type => DirectoryEntity, directory => directory.photos, {onDelete: "CASCADE"}) | ||||
|   @ManyToOne(type => DirectoryEntity, directory => directory.photos, {onDelete: 'CASCADE'}) | ||||
|   directory: DirectoryEntity; | ||||
|  | ||||
|   @Column(type => PhotoMetadataEntity) | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| 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 { | ||||
| @@ -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() | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| import {UserDTO, UserRoles} from "../../../../common/entities/UserDTO"; | ||||
| import {Column, Entity, PrimaryGeneratedColumn} from "typeorm"; | ||||
| import {UserDTO, UserRoles} from '../../../../common/entities/UserDTO'; | ||||
| import {Column, Entity, PrimaryGeneratedColumn} from 'typeorm'; | ||||
|  | ||||
| @Entity() | ||||
| export class UserEntity implements UserDTO { | ||||
| @@ -13,10 +13,10 @@ export class UserEntity implements UserDTO { | ||||
|   @Column() | ||||
|   password: string; | ||||
|  | ||||
|   @Column("smallint") | ||||
|   @Column('smallint') | ||||
|   role: UserRoles; | ||||
|  | ||||
|   @Column("text", {nullable: true}) | ||||
|   @Column('text', {nullable: true}) | ||||
|   permissions: string[]; | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| import {Column, Entity, PrimaryGeneratedColumn} from "typeorm"; | ||||
| import {Column, Entity, PrimaryGeneratedColumn} from 'typeorm'; | ||||
|  | ||||
| @Entity() | ||||
| export class VersionEntity { | ||||
|   | ||||
| @@ -1,14 +1,14 @@ | ||||
| import * as fs from "fs"; | ||||
| import * as path from "path"; | ||||
| import {DirectoryDTO} from "../../../common/entities/DirectoryDTO"; | ||||
| import {CameraMetadata, GPSMetadata, ImageSize, PhotoDTO, PhotoMetadata} from "../../../common/entities/PhotoDTO"; | ||||
| import {Logger} from "../../Logger"; | ||||
| import {IptcParser} from "ts-node-iptc"; | ||||
| import {ExifParserFactory} from "ts-exif-parser"; | ||||
| import {ProjectPath} from "../../ProjectPath"; | ||||
| import {Config} from "../../../common/config/private/Config"; | ||||
| import * as fs from 'fs'; | ||||
| import * as path from 'path'; | ||||
| import {DirectoryDTO} from '../../../common/entities/DirectoryDTO'; | ||||
| import {CameraMetadata, GPSMetadata, ImageSize, PhotoDTO, PhotoMetadata} from '../../../common/entities/PhotoDTO'; | ||||
| import {Logger} from '../../Logger'; | ||||
| import {IptcParser} from 'ts-node-iptc'; | ||||
| import {ExifParserFactory} from 'ts-exif-parser'; | ||||
| import {ProjectPath} from '../../ProjectPath'; | ||||
| import {Config} from '../../../common/config/private/Config'; | ||||
|  | ||||
| const LOG_TAG = "[DiskManagerTask]"; | ||||
| const LOG_TAG = '[DiskManagerTask]'; | ||||
|  | ||||
| export class DiskMangerWorker { | ||||
|   private static isImage(fullPath: string) { | ||||
| @@ -139,7 +139,7 @@ export class DiskMangerWorker { | ||||
|                 metadata.size = <ImageSize> {width: 1, height: 1}; | ||||
|               } | ||||
|             } catch (err) { | ||||
|               Logger.debug(LOG_TAG, "Error parsing exif", fullPath, err); | ||||
|               Logger.debug(LOG_TAG, 'Error parsing exif', fullPath, err); | ||||
|               metadata.size = <ImageSize> {width: 1, height: 1}; | ||||
|             } | ||||
|  | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| import {RendererInput, ThumbnailWoker} from "./ThumbnailWoker"; | ||||
| import {Config} from "../../../common/config/private/Config"; | ||||
| import {RendererInput, ThumbnailWoker} from './ThumbnailWoker'; | ||||
| import {Config} from '../../../common/config/private/Config'; | ||||
|  | ||||
|  | ||||
| interface QueTask { | ||||
|   | ||||
| @@ -1,10 +1,10 @@ | ||||
| import * as cluster from "cluster"; | ||||
| import {Logger} from "../../Logger"; | ||||
| import {DiskManagerTask, ThumbnailTask, WorkerMessage, WorkerTask, WorkerTaskTypes} from "./Worker"; | ||||
| import {DirectoryDTO} from "../../../common/entities/DirectoryDTO"; | ||||
| import {RendererInput} from "./ThumbnailWoker"; | ||||
| import {Config} from "../../../common/config/private/Config"; | ||||
| import {ITaskQue} from "./TaskQue"; | ||||
| import * as cluster from 'cluster'; | ||||
| import {Logger} from '../../Logger'; | ||||
| import {DiskManagerTask, ThumbnailTask, WorkerMessage, WorkerTask, WorkerTaskTypes} from './Worker'; | ||||
| import {DirectoryDTO} from '../../../common/entities/DirectoryDTO'; | ||||
| import {RendererInput} from './ThumbnailWoker'; | ||||
| import {Config} from '../../../common/config/private/Config'; | ||||
| import {ITaskQue} from './TaskQue'; | ||||
|  | ||||
|  | ||||
| interface PoolTask { | ||||
| @@ -24,7 +24,7 @@ export class ThreadPool { | ||||
|   private tasks: PoolTask[] = []; | ||||
|  | ||||
|   constructor(private size: number) { | ||||
|     Logger.silly("Creating thread pool with", size, "workers"); | ||||
|     Logger.silly('Creating thread pool with', size, 'workers'); | ||||
|     for (let i = 0; i < size; i++) { | ||||
|       this.startWorker(); | ||||
|     } | ||||
| @@ -39,14 +39,14 @@ export class ThreadPool { | ||||
|     }); | ||||
|     worker.worker.on('exit', (code, signal) => { | ||||
|       ThreadPool.WorkerCount--; | ||||
|       Logger.warn('Worker ' + worker.worker.process.pid + ' died with code: ' + code + ', and signal: ' + signal + ", worker count:", ThreadPool.WorkerCount); | ||||
|       Logger.warn('Worker ' + worker.worker.process.pid + ' died with code: ' + code + ', and signal: ' + signal + ', worker count:', ThreadPool.WorkerCount); | ||||
|       Logger.debug('Starting a new worker'); | ||||
|       this.startWorker(); | ||||
|     }); | ||||
|  | ||||
|     worker.worker.on("message", (msg: WorkerMessage) => { | ||||
|     worker.worker.on('message', (msg: WorkerMessage) => { | ||||
|       if (worker.poolTask == null) { | ||||
|         throw "No worker task after worker task is completed" | ||||
|         throw 'No worker task after worker task is completed'; | ||||
|       } | ||||
|       if (msg.error) { | ||||
|         worker.poolTask.promise.reject(msg.error); | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| import {Metadata, SharpInstance} from "sharp"; | ||||
| import {Dimensions, State} from "gm"; | ||||
| import {Logger} from "../../Logger"; | ||||
| import {ThumbnailProcessingLib} from "../../../common/config/private/IPrivateConfig"; | ||||
| import {Metadata, SharpInstance} from 'sharp'; | ||||
| import {Dimensions, State} from 'gm'; | ||||
| import {Logger} from '../../Logger'; | ||||
| import {ThumbnailProcessingLib} from '../../../common/config/private/IPrivateConfig'; | ||||
|  | ||||
| export class ThumbnailWoker { | ||||
|  | ||||
| @@ -39,14 +39,14 @@ export class RendererFactory { | ||||
|       case ThumbnailProcessingLib.sharp: | ||||
|         return RendererFactory.Sharp(); | ||||
|     } | ||||
|     throw "unknown renderer" | ||||
|     throw 'unknown renderer'; | ||||
|   } | ||||
|  | ||||
|   public static Jimp() { | ||||
|     const Jimp = require("jimp"); | ||||
|     const Jimp = require('jimp'); | ||||
|     return async (input: RendererInput): Promise<void> => { | ||||
|       //generate thumbnail | ||||
|       Logger.silly("[JimpThRenderer] rendering thumbnail:", input.imagePath); | ||||
|       Logger.silly('[JimpThRenderer] rendering thumbnail:', input.imagePath); | ||||
|       const image = await Jimp.read(input.imagePath); | ||||
|       /** | ||||
|        * newWidth * newHeight = size*size | ||||
| @@ -83,10 +83,10 @@ export class RendererFactory { | ||||
|  | ||||
|  | ||||
|   public static Sharp() { | ||||
|     const sharp = require("sharp"); | ||||
|     const sharp = require('sharp'); | ||||
|     return async (input: RendererInput): Promise<void> => { | ||||
|  | ||||
|       Logger.silly("[SharpThRenderer] rendering thumbnail:", input.imagePath); | ||||
|       Logger.silly('[SharpThRenderer] rendering thumbnail:', input.imagePath); | ||||
|       const image: SharpInstance = sharp(input.imagePath); | ||||
|       const metadata: Metadata = await image.metadata(); | ||||
|  | ||||
| @@ -120,10 +120,10 @@ export class RendererFactory { | ||||
|  | ||||
|  | ||||
|   public static Gm() { | ||||
|     const gm = require("gm"); | ||||
|     const gm = require('gm'); | ||||
|     return (input: RendererInput): Promise<void> => { | ||||
|       return new Promise((resolve, reject) => { | ||||
|         Logger.silly("[GMThRenderer] rendering thumbnail:", input.imagePath); | ||||
|         Logger.silly('[GMThRenderer] rendering thumbnail:', input.imagePath); | ||||
|         let image: State = gm(input.imagePath); | ||||
|         image.size((err, value: Dimensions) => { | ||||
|           if (err) { | ||||
|   | ||||
| @@ -1,13 +1,13 @@ | ||||
| import {DiskMangerWorker} from "./DiskMangerWorker"; | ||||
| import {Logger} from "../../Logger"; | ||||
| import {RendererInput, ThumbnailWoker} from "./ThumbnailWoker"; | ||||
| import {ThumbnailProcessingLib} from "../../../common/config/private/IPrivateConfig"; | ||||
| import {DiskMangerWorker} from './DiskMangerWorker'; | ||||
| import {Logger} from '../../Logger'; | ||||
| import {RendererInput, ThumbnailWoker} from './ThumbnailWoker'; | ||||
| import {ThumbnailProcessingLib} from '../../../common/config/private/IPrivateConfig'; | ||||
|  | ||||
| export class Worker { | ||||
|  | ||||
|  | ||||
|   public static process() { | ||||
|     Logger.debug("Worker is waiting for tasks"); | ||||
|     Logger.debug('Worker is waiting for tasks'); | ||||
|     process.on('message', async (task: WorkerTask) => { | ||||
|       try { | ||||
|         let result = null; | ||||
| @@ -22,8 +22,8 @@ export class Worker { | ||||
|             result = await ThumbnailWoker.render((<ThumbnailTask>task).input, (<ThumbnailTask>task).renderer); | ||||
|             break; | ||||
|           default: | ||||
|             Logger.error("Unknown worker task type"); | ||||
|             throw "Unknown worker task type"; | ||||
|             Logger.error('Unknown worker task type'); | ||||
|             throw 'Unknown worker task type'; | ||||
|         } | ||||
|         process.send(<WorkerMessage>{ | ||||
|           error: null, | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| import {AuthenticationMWs} from "../middlewares/user/AuthenticationMWs"; | ||||
| import {UserRoles} from "../../common/entities/UserDTO"; | ||||
| import {RenderingMWs} from "../middlewares/RenderingMWs"; | ||||
| import {AdminMWs} from "../middlewares/AdminMWs"; | ||||
| import {AuthenticationMWs} from '../middlewares/user/AuthenticationMWs'; | ||||
| import {UserRoles} from '../../common/entities/UserDTO'; | ||||
| import {RenderingMWs} from '../middlewares/RenderingMWs'; | ||||
| import {AdminMWs} from '../middlewares/AdminMWs'; | ||||
|  | ||||
| export class AdminRouter { | ||||
|   public static route(app: any) { | ||||
| @@ -12,98 +12,97 @@ export class AdminRouter { | ||||
|  | ||||
|  | ||||
|   private static addIndexGallery(app) { | ||||
|     app.get("/api/admin/indexes/job/progress", | ||||
|     app.get('/api/admin/indexes/job/progress', | ||||
|       AuthenticationMWs.authenticate, | ||||
|       AuthenticationMWs.authorise(UserRoles.Admin), | ||||
|       AdminMWs.getIndexingProgress, | ||||
|       RenderingMWs.renderResult | ||||
|     ); | ||||
|     app.put("/api/admin/indexes/job", | ||||
|     app.put('/api/admin/indexes/job', | ||||
|       AuthenticationMWs.authenticate, | ||||
|       AuthenticationMWs.authorise(UserRoles.Admin), | ||||
|       AdminMWs.startIndexing, | ||||
|       RenderingMWs.renderResult | ||||
|     ); | ||||
|     app.delete("/api/admin/indexes/job", | ||||
|     app.delete('/api/admin/indexes/job', | ||||
|       AuthenticationMWs.authenticate, | ||||
|       AuthenticationMWs.authorise(UserRoles.Admin), | ||||
|       AdminMWs.cancelIndexing, | ||||
|       RenderingMWs.renderResult | ||||
|     ); | ||||
|     app.delete("/api/admin/indexes", | ||||
|     app.delete('/api/admin/indexes', | ||||
|       AuthenticationMWs.authenticate, | ||||
|       AuthenticationMWs.authorise(UserRoles.Admin), | ||||
|       AdminMWs.resetIndexes, | ||||
|       RenderingMWs.renderResult | ||||
|     ); | ||||
|   }; | ||||
|   } | ||||
|  | ||||
|   private static addSettings(app) { | ||||
|     app.get("/api/settings", | ||||
|     app.get('/api/settings', | ||||
|       AuthenticationMWs.authenticate, | ||||
|       AuthenticationMWs.authorise(UserRoles.Admin), | ||||
|       RenderingMWs.renderConfig | ||||
|     ); | ||||
|  | ||||
|  | ||||
|     app.put("/api/settings/database", | ||||
|     app.put('/api/settings/database', | ||||
|       AuthenticationMWs.authenticate, | ||||
|       AuthenticationMWs.authorise(UserRoles.Admin), | ||||
|       AdminMWs.updateDatabaseSettings, | ||||
|       RenderingMWs.renderOK | ||||
|     ); | ||||
|  | ||||
|     app.put("/api/settings/map", | ||||
|     app.put('/api/settings/map', | ||||
|       AuthenticationMWs.authenticate, | ||||
|       AuthenticationMWs.authorise(UserRoles.Admin), | ||||
|       AdminMWs.updateMapSettings, | ||||
|       RenderingMWs.renderOK | ||||
|     ); | ||||
|  | ||||
|     app.put("/api/settings/authentication", | ||||
|     app.put('/api/settings/authentication', | ||||
|       AuthenticationMWs.authenticate, | ||||
|       AuthenticationMWs.authorise(UserRoles.Admin), | ||||
|       AdminMWs.updateAuthenticationSettings, | ||||
|       RenderingMWs.renderOK | ||||
|     ); | ||||
|     app.put("/api/settings/thumbnail", | ||||
|     app.put('/api/settings/thumbnail', | ||||
|       AuthenticationMWs.authenticate, | ||||
|       AuthenticationMWs.authorise(UserRoles.Admin), | ||||
|       AdminMWs.updateThumbnailSettings, | ||||
|       RenderingMWs.renderOK | ||||
|     ); | ||||
|     app.put("/api/settings/search", | ||||
|     app.put('/api/settings/search', | ||||
|       AuthenticationMWs.authenticate, | ||||
|       AuthenticationMWs.authorise(UserRoles.Admin), | ||||
|       AdminMWs.updateSearchSettings, | ||||
|       RenderingMWs.renderOK | ||||
|     ); | ||||
|     app.put("/api/settings/share", | ||||
|     app.put('/api/settings/share', | ||||
|       AuthenticationMWs.authenticate, | ||||
|       AuthenticationMWs.authorise(UserRoles.Admin), | ||||
|       AdminMWs.updateShareSettings, | ||||
|       RenderingMWs.renderOK | ||||
|     ); | ||||
|     app.put("/api/settings/basic", | ||||
|     app.put('/api/settings/basic', | ||||
|       AuthenticationMWs.authenticate, | ||||
|       AuthenticationMWs.authorise(UserRoles.Admin), | ||||
|       AdminMWs.updateBasicSettings, | ||||
|       RenderingMWs.renderOK | ||||
|     ); | ||||
|     app.put("/api/settings/other", | ||||
|     app.put('/api/settings/other', | ||||
|       AuthenticationMWs.authenticate, | ||||
|       AuthenticationMWs.authorise(UserRoles.Admin), | ||||
|       AdminMWs.updateOtherSettings, | ||||
|       RenderingMWs.renderOK | ||||
|     ); | ||||
|     app.put("/api/settings/indexing", | ||||
|     app.put('/api/settings/indexing', | ||||
|       AuthenticationMWs.authenticate, | ||||
|       AuthenticationMWs.authorise(UserRoles.Admin), | ||||
|       AdminMWs.updateIndexingSettings, | ||||
|       RenderingMWs.renderOK | ||||
|     ); | ||||
|  | ||||
|   }; | ||||
|   } | ||||
|  | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| import {RenderingMWs} from "../middlewares/RenderingMWs"; | ||||
| import {ErrorCodes, ErrorDTO} from "../../common/entities/Error"; | ||||
| import {Logger} from "../Logger"; | ||||
| import {RenderingMWs} from '../middlewares/RenderingMWs'; | ||||
| import {ErrorCodes, ErrorDTO} from '../../common/entities/Error'; | ||||
| import {Logger} from '../Logger'; | ||||
| import Request = Express.Request; | ||||
| import Response = Express.Response; | ||||
|  | ||||
| @@ -12,17 +12,17 @@ export class ErrorRouter { | ||||
|   } | ||||
|  | ||||
|   private static addApiErrorHandler(app) { | ||||
|     app.use("/api/*", | ||||
|     app.use('/api/*', | ||||
|       RenderingMWs.renderError | ||||
|     ); | ||||
|   }; | ||||
|   } | ||||
|  | ||||
|   private static addGenericHandler(app) { | ||||
|     app.use((err: any, req: Request, res: Response, next: Function) => { | ||||
|         //Flush out the stack to the console | ||||
|         Logger.error("Unexpected error:"); | ||||
|         // Flush out the stack to the console | ||||
|         Logger.error('Unexpected error:'); | ||||
|         console.error(err); | ||||
|         next(new ErrorDTO(ErrorCodes.SERVER_ERROR, "Unknown server side error", err)); | ||||
|         next(new ErrorDTO(ErrorCodes.SERVER_ERROR, 'Unknown server side error', err)); | ||||
|       }, | ||||
|       RenderingMWs.renderError | ||||
|     ); | ||||
|   | ||||
| @@ -1,8 +1,8 @@ | ||||
| import {AuthenticationMWs} from "../middlewares/user/AuthenticationMWs"; | ||||
| import {GalleryMWs} from "../middlewares/GalleryMWs"; | ||||
| import {RenderingMWs} from "../middlewares/RenderingMWs"; | ||||
| import {ThumbnailGeneratorMWs} from "../middlewares/thumbnail/ThumbnailGeneratorMWs"; | ||||
| import {UserRoles} from "../../common/entities/UserDTO"; | ||||
| import {AuthenticationMWs} from '../middlewares/user/AuthenticationMWs'; | ||||
| import {GalleryMWs} from '../middlewares/GalleryMWs'; | ||||
| import {RenderingMWs} from '../middlewares/RenderingMWs'; | ||||
| import {ThumbnailGeneratorMWs} from '../middlewares/thumbnail/ThumbnailGeneratorMWs'; | ||||
| import {UserRoles} from '../../common/entities/UserDTO'; | ||||
|  | ||||
| export class GalleryRouter { | ||||
|   public static route(app: any) { | ||||
| @@ -18,7 +18,7 @@ export class GalleryRouter { | ||||
|   } | ||||
|  | ||||
|   private static addDirectoryList(app) { | ||||
|     app.get(["/api/gallery/content/:directory(*)", "/api/gallery/", "/api/gallery//"], | ||||
|     app.get(['/api/gallery/content/:directory(*)', '/api/gallery/', '/api/gallery//'], | ||||
|       AuthenticationMWs.authenticate, | ||||
|       AuthenticationMWs.authoriseDirectory, | ||||
|       GalleryMWs.listDirectory, | ||||
| @@ -26,40 +26,40 @@ export class GalleryRouter { | ||||
|       GalleryMWs.removeCyclicDirectoryReferences, | ||||
|       RenderingMWs.renderResult | ||||
|     ); | ||||
|   }; | ||||
|   } | ||||
|  | ||||
|  | ||||
|   private static addGetImage(app) { | ||||
|     app.get(["/api/gallery/content/:imagePath(*\.(jpg|bmp|png|gif|jpeg))"], | ||||
|     app.get(['/api/gallery/content/:imagePath(*\.(jpg|bmp|png|gif|jpeg))'], | ||||
|       AuthenticationMWs.authenticate, | ||||
|       //TODO: authorize path | ||||
|       // TODO: authorize path | ||||
|       GalleryMWs.loadImage, | ||||
|       RenderingMWs.renderFile | ||||
|     ); | ||||
|   }; | ||||
|   } | ||||
|  | ||||
|   private static addGetImageThumbnail(app) { | ||||
|     app.get("/api/gallery/content/:imagePath(*\.(jpg|bmp|png|gif|jpeg))/thumbnail/:size?", | ||||
|     app.get('/api/gallery/content/:imagePath(*\.(jpg|bmp|png|gif|jpeg))/thumbnail/:size?', | ||||
|       AuthenticationMWs.authenticate, | ||||
|       //TODO: authorize path | ||||
|       // TODO: authorize path | ||||
|       GalleryMWs.loadImage, | ||||
|       ThumbnailGeneratorMWs.generateThumbnail, | ||||
|       RenderingMWs.renderFile | ||||
|     ); | ||||
|   }; | ||||
|   } | ||||
|  | ||||
|   private static addGetImageIcon(app) { | ||||
|     app.get("/api/gallery/content/:imagePath(*\.(jpg|bmp|png|gif|jpeg))/icon", | ||||
|     app.get('/api/gallery/content/:imagePath(*\.(jpg|bmp|png|gif|jpeg))/icon', | ||||
|       AuthenticationMWs.authenticate, | ||||
|       //TODO: authorize path | ||||
|       // TODO: authorize path | ||||
|       GalleryMWs.loadImage, | ||||
|       ThumbnailGeneratorMWs.generateIcon, | ||||
|       RenderingMWs.renderFile | ||||
|     ); | ||||
|   }; | ||||
|   } | ||||
|  | ||||
|   private static addSearch(app) { | ||||
|     app.get("/api/search/:text", | ||||
|     app.get('/api/search/:text', | ||||
|       AuthenticationMWs.authenticate, | ||||
|       AuthenticationMWs.authorise(UserRoles.Guest), | ||||
|       GalleryMWs.search, | ||||
| @@ -67,10 +67,10 @@ export class GalleryRouter { | ||||
|       GalleryMWs.removeCyclicDirectoryReferences, | ||||
|       RenderingMWs.renderResult | ||||
|     ); | ||||
|   }; | ||||
|   } | ||||
|  | ||||
|   private static addInstantSearch(app) { | ||||
|     app.get("/api/instant-search/:text", | ||||
|     app.get('/api/instant-search/:text', | ||||
|       AuthenticationMWs.authenticate, | ||||
|       AuthenticationMWs.authorise(UserRoles.Guest), | ||||
|       GalleryMWs.instantSearch, | ||||
| @@ -78,16 +78,15 @@ export class GalleryRouter { | ||||
|       GalleryMWs.removeCyclicDirectoryReferences, | ||||
|       RenderingMWs.renderResult | ||||
|     ); | ||||
|   }; | ||||
|   } | ||||
|  | ||||
|   private static addAutoComplete(app) { | ||||
|     app.get("/api/autocomplete/:text", | ||||
|     app.get('/api/autocomplete/:text', | ||||
|       AuthenticationMWs.authenticate, | ||||
|       AuthenticationMWs.authorise(UserRoles.Guest), | ||||
|       GalleryMWs.autocomplete, | ||||
|       RenderingMWs.renderResult | ||||
|     ); | ||||
|   }; | ||||
|  | ||||
|   } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| import {NextFunction, Request, Response} from "express"; | ||||
| import {Logger} from "../Logger"; | ||||
| import {NextFunction, Request, Response} from 'express'; | ||||
| import {Logger} from '../Logger'; | ||||
|  | ||||
| /** | ||||
|  * Adds logging to express | ||||
| @@ -7,32 +7,32 @@ import {Logger} from "../Logger"; | ||||
| export class LoggerRouter { | ||||
|   public static route(app: any) { | ||||
|  | ||||
|     app.get("/api*", (req: Request, res: Response, next: NextFunction) => { | ||||
|     app.get('/api*', (req: Request, res: Response, next: NextFunction) => { | ||||
|       req['_startTime'] = Date.now(); | ||||
|       req['logged'] = true; | ||||
|       const end = res.end; | ||||
|       res.end = (a?: any, b?: any, c?: any) => { | ||||
|         res.end = end; | ||||
|         res.end(a, b, c); | ||||
|         Logger.verbose(req.method, req.url, res.statusCode, (Date.now() - req['_startTime']) + "ms"); | ||||
|         Logger.verbose(req.method, req.url, res.statusCode, (Date.now() - req['_startTime']) + 'ms'); | ||||
|       }; | ||||
|       return next(); | ||||
|     }); | ||||
|  | ||||
|     app.get("/node_modules*", (req: Request, res: Response, next: NextFunction) => { | ||||
|     app.get('/node_modules*', (req: Request, res: Response, next: NextFunction) => { | ||||
|       req['_startTime'] = Date.now(); | ||||
|       req['logged'] = true; | ||||
|       const end = res.end; | ||||
|       res.end = (a?: any, b?: any, c?: any) => { | ||||
|         res.end = end; | ||||
|         res.end(a, b, c); | ||||
|         Logger.silly(req.method, req.url, res.statusCode, (Date.now() - req['_startTime']) + "ms"); | ||||
|         Logger.silly(req.method, req.url, res.statusCode, (Date.now() - req['_startTime']) + 'ms'); | ||||
|       }; | ||||
|       return next(); | ||||
|     }); | ||||
|  | ||||
|     app.use((req: Request, res: Response, next: NextFunction) => { | ||||
|       if (req['logged'] == true) { | ||||
|       if (req['logged'] === true) { | ||||
|         return next(); | ||||
|       } | ||||
|       req['_startTime'] = Date.now(); | ||||
| @@ -40,7 +40,7 @@ export class LoggerRouter { | ||||
|       res.end = (a?: any, b?: any, c?: any) => { | ||||
|         res.end = end; | ||||
|         res.end(a, b, c); | ||||
|         Logger.debug(req.method, req.url, res.statusCode, (Date.now() - req['_startTime']) + "ms"); | ||||
|         Logger.debug(req.method, req.url, res.statusCode, (Date.now() - req['_startTime']) + 'ms'); | ||||
|       }; | ||||
|       return next(); | ||||
|     }); | ||||
|   | ||||
| @@ -1,9 +1,7 @@ | ||||
| import {UserRoles} from "../../common/entities/UserDTO"; | ||||
| import {AuthenticationMWs} from "../middlewares/user/AuthenticationMWs"; | ||||
| import {RenderingMWs} from "../middlewares/RenderingMWs"; | ||||
| import {NotificationMWs} from "../middlewares/NotificationMWs"; | ||||
| import Request = Express.Request; | ||||
| import Response = Express.Response; | ||||
| import {UserRoles} from '../../common/entities/UserDTO'; | ||||
| import {AuthenticationMWs} from '../middlewares/user/AuthenticationMWs'; | ||||
| import {RenderingMWs} from '../middlewares/RenderingMWs'; | ||||
| import {NotificationMWs} from '../middlewares/NotificationMWs'; | ||||
|  | ||||
| export class NotificationRouter { | ||||
|   public static route(app: any) { | ||||
| @@ -12,13 +10,12 @@ export class NotificationRouter { | ||||
|   } | ||||
|  | ||||
|   private static addGetNotifications(app) { | ||||
|     app.get("/api/notifications", | ||||
|     app.get('/api/notifications', | ||||
|       AuthenticationMWs.authenticate, | ||||
|       AuthenticationMWs.authorise(UserRoles.Guest), | ||||
|       NotificationMWs.list, | ||||
|       RenderingMWs.renderResult | ||||
|     ); | ||||
|   }; | ||||
|  | ||||
|   } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -1,18 +1,18 @@ | ||||
| import {NextFunction, Request, Response} from "express"; | ||||
| import * as path from "path"; | ||||
| import * as fs from "fs"; | ||||
| import {Utils} from "../../common/Utils"; | ||||
| import {Config} from "../../common/config/private/Config"; | ||||
| import {ProjectPath} from "../ProjectPath"; | ||||
| import {AuthenticationMWs} from "../middlewares/user/AuthenticationMWs"; | ||||
| import {CookieNames} from "../../common/CookieNames"; | ||||
| import {NextFunction, Request, Response} from 'express'; | ||||
| import * as path from 'path'; | ||||
| import * as fs from 'fs'; | ||||
| import {Utils} from '../../common/Utils'; | ||||
| import {Config} from '../../common/config/private/Config'; | ||||
| import {ProjectPath} from '../ProjectPath'; | ||||
| import {AuthenticationMWs} from '../middlewares/user/AuthenticationMWs'; | ||||
| import {CookieNames} from '../../common/CookieNames'; | ||||
|  | ||||
|  | ||||
| export class PublicRouter { | ||||
|  | ||||
|   public static route(app) { | ||||
|     const setLocale = (req: Request, res: Response, next: Function) => { | ||||
|       let localePath = ""; | ||||
|       let localePath = ''; | ||||
|       let selectedLocale = req['locale']; | ||||
|       if (req.cookies && req.cookies[CookieNames.lang]) { | ||||
|         if (Config.Client.languages.indexOf(req.cookies[CookieNames.lang]) !== -1) { | ||||
| @@ -37,7 +37,7 @@ export class PublicRouter { | ||||
|         if (Config.Client.languages.indexOf(locale) !== -1) { | ||||
|           res.cookie(CookieNames.lang, locale); | ||||
|         } | ||||
|         res.redirect("/?ln=" + locale); | ||||
|         res.redirect('/?ln=' + locale); | ||||
|       }; | ||||
|     }; | ||||
|  | ||||
| @@ -47,7 +47,7 @@ export class PublicRouter { | ||||
|  | ||||
|         res.tpl.user = null; | ||||
|         if (req.session.user) { | ||||
|           let user = Utils.clone(req.session.user); | ||||
|           const user = Utils.clone(req.session.user); | ||||
|           delete user.password; | ||||
|           res.tpl.user = user; | ||||
|         } | ||||
| @@ -60,13 +60,13 @@ export class PublicRouter { | ||||
|       res.render(path.resolve(ProjectPath.FrontendFolder, 'config_inject.ejs'), res.tpl); | ||||
|     }); | ||||
|  | ||||
|     app.get(['/', '/login', "/gallery*", "/share*", "/admin", "/search*"], | ||||
|     app.get(['/', '/login', '/gallery*', '/share*', '/admin', '/search*'], | ||||
|       AuthenticationMWs.tryAuthenticate, | ||||
|       setLocale, | ||||
|       renderIndex | ||||
|     ); | ||||
|     Config.Client.languages.forEach(l => { | ||||
|       app.get(['/' + l + '/', '/' + l + '/login', '/' + l + "/gallery*", '/' + l + "/share*", '/' + l + "/admin", '/' + l + "/search*"], | ||||
|       app.get(['/' + l + '/', '/' + l + '/login', '/' + l + '/gallery*', '/' + l + '/share*', '/' + l + '/admin', '/' + l + '/search*'], | ||||
|         redirectToBase(l) | ||||
|       ); | ||||
|     }); | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| import {AuthenticationMWs} from "../middlewares/user/AuthenticationMWs"; | ||||
| import {UserRoles} from "../../common/entities/UserDTO"; | ||||
| import {RenderingMWs} from "../middlewares/RenderingMWs"; | ||||
| import {SharingMWs} from "../middlewares/SharingMWs"; | ||||
| import {AuthenticationMWs} from '../middlewares/user/AuthenticationMWs'; | ||||
| import {UserRoles} from '../../common/entities/UserDTO'; | ||||
| import {RenderingMWs} from '../middlewares/RenderingMWs'; | ||||
| import {SharingMWs} from '../middlewares/SharingMWs'; | ||||
|  | ||||
| export class SharingRouter { | ||||
|   public static route(app: any) { | ||||
| @@ -13,7 +13,7 @@ export class SharingRouter { | ||||
|   } | ||||
|  | ||||
|   private static addShareLogin(app) { | ||||
|     app.post("/api/share/login", | ||||
|     app.post('/api/share/login', | ||||
|       AuthenticationMWs.inverseAuthenticate, | ||||
|       AuthenticationMWs.shareLogin, | ||||
|       RenderingMWs.renderSessionUser | ||||
| @@ -21,7 +21,7 @@ export class SharingRouter { | ||||
|   }; | ||||
|  | ||||
|   private static addGetSharing(app) { | ||||
|     app.get("/api/share/:sharingKey", | ||||
|     app.get('/api/share/:sharingKey', | ||||
|       AuthenticationMWs.authenticate, | ||||
|       AuthenticationMWs.authorise(UserRoles.LimitedGuest), | ||||
|       SharingMWs.getSharing, | ||||
| @@ -30,7 +30,7 @@ export class SharingRouter { | ||||
|   }; | ||||
|  | ||||
|   private static addCreateSharing(app) { | ||||
|     app.post(["/api/share/:directory(*)", "/api/share/", "/api/share//"], | ||||
|     app.post(['/api/share/:directory(*)', '/api/share/', '/api/share//'], | ||||
|       AuthenticationMWs.authenticate, | ||||
|       AuthenticationMWs.authorise(UserRoles.User), | ||||
|       SharingMWs.createSharing, | ||||
| @@ -39,7 +39,7 @@ export class SharingRouter { | ||||
|   }; | ||||
|  | ||||
|   private static addUpdateSharing(app) { | ||||
|     app.put(["/api/share/:directory(*)", "/api/share/", "/api/share//"], | ||||
|     app.put(['/api/share/:directory(*)', '/api/share/', '/api/share//'], | ||||
|       AuthenticationMWs.authenticate, | ||||
|       AuthenticationMWs.authorise(UserRoles.User), | ||||
|       SharingMWs.updateSharing, | ||||
|   | ||||
| @@ -1,8 +1,8 @@ | ||||
| import {UserMWs} from "../middlewares/user/UserMWs"; | ||||
| import {UserRoles} from "../../common/entities/UserDTO"; | ||||
| import {AuthenticationMWs} from "../middlewares/user/AuthenticationMWs"; | ||||
| import {UserRequestConstrainsMWs} from "../middlewares/user/UserRequestConstrainsMWs"; | ||||
| import {RenderingMWs} from "../middlewares/RenderingMWs"; | ||||
| import {UserMWs} from '../middlewares/user/UserMWs'; | ||||
| import {UserRoles} from '../../common/entities/UserDTO'; | ||||
| import {AuthenticationMWs} from '../middlewares/user/AuthenticationMWs'; | ||||
| import {UserRequestConstrainsMWs} from '../middlewares/user/UserRequestConstrainsMWs'; | ||||
| import {RenderingMWs} from '../middlewares/RenderingMWs'; | ||||
|  | ||||
| export class UserRouter { | ||||
|   public static route(app) { | ||||
| @@ -19,77 +19,77 @@ export class UserRouter { | ||||
|   } | ||||
|  | ||||
|   private static addLogin(app) { | ||||
|     app.post("/api/user/login", | ||||
|     app.post('/api/user/login', | ||||
|       AuthenticationMWs.inverseAuthenticate, | ||||
|       AuthenticationMWs.login, | ||||
|       RenderingMWs.renderSessionUser | ||||
|     ); | ||||
|   }; | ||||
|   } | ||||
|  | ||||
|   private static addLogout(app) { | ||||
|     app.post("/api/user/logout", | ||||
|     app.post('/api/user/logout', | ||||
|       AuthenticationMWs.logout, | ||||
|       RenderingMWs.renderOK | ||||
|     ); | ||||
|   }; | ||||
|   } | ||||
|  | ||||
|  | ||||
|   private static addGetSessionUser(app) { | ||||
|     app.get("/api/user/login", | ||||
|     app.get('/api/user/login', | ||||
|       AuthenticationMWs.authenticate, | ||||
|       RenderingMWs.renderSessionUser | ||||
|     ); | ||||
|   }; | ||||
|   } | ||||
|  | ||||
|  | ||||
|   private static addChangePassword(app) { | ||||
|     app.post("/api/user/:id/password", | ||||
|     app.post('/api/user/:id/password', | ||||
|       AuthenticationMWs.authenticate, | ||||
|       UserRequestConstrainsMWs.forceSelfRequest, | ||||
|       UserMWs.changePassword, | ||||
|       RenderingMWs.renderOK | ||||
|     ); | ||||
|   }; | ||||
|   } | ||||
|  | ||||
|  | ||||
|   private static addCreateUser(app) { | ||||
|     app.put("/api/user", | ||||
|     app.put('/api/user', | ||||
|       AuthenticationMWs.authenticate, | ||||
|       AuthenticationMWs.authorise(UserRoles.Admin), | ||||
|       UserMWs.createUser, | ||||
|       RenderingMWs.renderOK | ||||
|     ); | ||||
|   }; | ||||
|   } | ||||
|  | ||||
|   private static addDeleteUser(app) { | ||||
|     app.delete("/api/user/:id", | ||||
|     app.delete('/api/user/:id', | ||||
|       AuthenticationMWs.authenticate, | ||||
|       AuthenticationMWs.authorise(UserRoles.Admin), | ||||
|       UserRequestConstrainsMWs.notSelfRequest, | ||||
|       UserMWs.deleteUser, | ||||
|       RenderingMWs.renderOK | ||||
|     ); | ||||
|   }; | ||||
|   } | ||||
|  | ||||
|  | ||||
|   private static addListUsers(app) { | ||||
|     app.get("/api/user/list", | ||||
|     app.get('/api/user/list', | ||||
|       AuthenticationMWs.authenticate, | ||||
|       AuthenticationMWs.authorise(UserRoles.Admin), | ||||
|       UserMWs.listUsers, | ||||
|       RenderingMWs.renderResult | ||||
|     ); | ||||
|   }; | ||||
|   } | ||||
|  | ||||
|   private static addChangeRole(app) { | ||||
|     app.post("/api/user/:id/role", | ||||
|     app.post('/api/user/:id/role', | ||||
|       AuthenticationMWs.authenticate, | ||||
|       AuthenticationMWs.authorise(UserRoles.Admin), | ||||
|       UserRequestConstrainsMWs.notSelfRequestOr2Admins, | ||||
|       UserMWs.changeRole, | ||||
|       RenderingMWs.renderOK | ||||
|     ); | ||||
|   }; | ||||
|   } | ||||
|  | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -1,29 +1,29 @@ | ||||
| import * as _express from "express"; | ||||
| import * as _bodyParser from "body-parser"; | ||||
| import * as cookieParser from "cookie-parser"; | ||||
| import * as _http from "http"; | ||||
| import * as locale from "locale"; | ||||
| import {PublicRouter} from "./routes/PublicRouter"; | ||||
| import {UserRouter} from "./routes/UserRouter"; | ||||
| import {GalleryRouter} from "./routes/GalleryRouter"; | ||||
| import {AdminRouter} from "./routes/AdminRouter"; | ||||
| import {ErrorRouter} from "./routes/ErrorRouter"; | ||||
| import {SharingRouter} from "./routes/SharingRouter"; | ||||
| import {ObjectManagerRepository} from "./model/ObjectManagerRepository"; | ||||
| import {Logger} from "./Logger"; | ||||
| import {Config} from "../common/config/private/Config"; | ||||
| import {DatabaseType} from "../common/config/private/IPrivateConfig"; | ||||
| import {LoggerRouter} from "./routes/LoggerRouter"; | ||||
| import {ThumbnailGeneratorMWs} from "./middlewares/thumbnail/ThumbnailGeneratorMWs"; | ||||
| import {DiskManager} from "./model/DiskManger"; | ||||
| import {NotificationRouter} from "./routes/NotificationRouter"; | ||||
| import {ConfigDiagnostics} from "./model/ConfigDiagnostics"; | ||||
| import {Localizations} from "./model/Localizations"; | ||||
| import {CookieNames} from "../common/CookieNames"; | ||||
| import * as _express from 'express'; | ||||
| import * as _bodyParser from 'body-parser'; | ||||
| import * as cookieParser from 'cookie-parser'; | ||||
| import * as _http from 'http'; | ||||
| import * as locale from 'locale'; | ||||
| import {PublicRouter} from './routes/PublicRouter'; | ||||
| import {UserRouter} from './routes/UserRouter'; | ||||
| import {GalleryRouter} from './routes/GalleryRouter'; | ||||
| import {AdminRouter} from './routes/AdminRouter'; | ||||
| import {ErrorRouter} from './routes/ErrorRouter'; | ||||
| import {SharingRouter} from './routes/SharingRouter'; | ||||
| import {ObjectManagerRepository} from './model/ObjectManagerRepository'; | ||||
| import {Logger} from './Logger'; | ||||
| import {Config} from '../common/config/private/Config'; | ||||
| import {DatabaseType} from '../common/config/private/IPrivateConfig'; | ||||
| import {LoggerRouter} from './routes/LoggerRouter'; | ||||
| import {ThumbnailGeneratorMWs} from './middlewares/thumbnail/ThumbnailGeneratorMWs'; | ||||
| import {DiskManager} from './model/DiskManger'; | ||||
| import {NotificationRouter} from './routes/NotificationRouter'; | ||||
| import {ConfigDiagnostics} from './model/ConfigDiagnostics'; | ||||
| import {Localizations} from './model/Localizations'; | ||||
| import {CookieNames} from '../common/CookieNames'; | ||||
|  | ||||
| const _session = require('cookie-session'); | ||||
|  | ||||
| const LOG_TAG = "[server]"; | ||||
| const LOG_TAG = '[server]'; | ||||
|  | ||||
| export class Server { | ||||
|  | ||||
| @@ -31,16 +31,16 @@ export class Server { | ||||
|   private server: any; | ||||
|  | ||||
|   constructor() { | ||||
|     if (!(process.env.NODE_ENV == "production")) { | ||||
|       Logger.debug(LOG_TAG, "Running in DEBUG mode"); | ||||
|     if (!(process.env.NODE_ENV == 'production')) { | ||||
|       Logger.debug(LOG_TAG, 'Running in DEBUG mode'); | ||||
|     } | ||||
|     this.init(); | ||||
|   } | ||||
|  | ||||
|   async init() { | ||||
|     Logger.info(LOG_TAG, "running diagnostics..."); | ||||
|     Logger.info(LOG_TAG, 'running diagnostics...'); | ||||
|     await ConfigDiagnostics.runDiagnostics(); | ||||
|     Logger.info(LOG_TAG, "using config:"); | ||||
|     Logger.info(LOG_TAG, 'using config:'); | ||||
|     Logger.info(LOG_TAG, JSON.stringify(Config, null, '\t')); | ||||
|  | ||||
|     this.app = _express(); | ||||
| @@ -61,7 +61,7 @@ export class Server { | ||||
|  | ||||
|     this.app.use(_session({ | ||||
|       name: CookieNames.session, | ||||
|       keys: ["key1" + s4() + s4() + s4() + s4(), "key2" + s4() + s4() + s4() + s4(), "key3" + s4() + s4() + s4() + s4()] | ||||
|       keys: ['key1' + s4() + s4() + s4() + s4(), 'key2' + s4() + s4() + s4() + s4(), 'key3' + s4() + s4() + s4() + s4()] | ||||
|     })); | ||||
|  | ||||
|     /* this.app.use((req: Request, res: Response, next: NextFunction) => { | ||||
| @@ -81,7 +81,7 @@ export class Server { | ||||
|     ThumbnailGeneratorMWs.init(); | ||||
|     Localizations.init(); | ||||
|  | ||||
|     this.app.use(locale(Config.Client.languages, "en")); | ||||
|     this.app.use(locale(Config.Client.languages, 'en')); | ||||
|     if (Config.Server.database.type != DatabaseType.memory) { | ||||
|       await  ObjectManagerRepository.InitSQLManagers(); | ||||
|     } else { | ||||
|   | ||||
| @@ -1,10 +1,10 @@ | ||||
| import {Component, OnInit} from "@angular/core"; | ||||
| import {AuthenticationService} from "../model/network/authentication.service"; | ||||
| import {UserRoles} from "../../../common/entities/UserDTO"; | ||||
| import {NotificationService} from "../model/notification.service"; | ||||
| import {NotificationType} from "../../../common/entities/NotificationDTO"; | ||||
| import {NavigationService} from "../model/navigation.service"; | ||||
| import {I18n} from "@ngx-translate/i18n-polyfill"; | ||||
| import {Component, OnInit} from '@angular/core'; | ||||
| import {AuthenticationService} from '../model/network/authentication.service'; | ||||
| import {UserRoles} from '../../../common/entities/UserDTO'; | ||||
| import {NotificationService} from '../model/notification.service'; | ||||
| import {NotificationType} from '../../../common/entities/NotificationDTO'; | ||||
| import {NavigationService} from '../model/navigation.service'; | ||||
| import {I18n} from '@ngx-translate/i18n-polyfill'; | ||||
|  | ||||
| @Component({ | ||||
|   selector: 'admin', | ||||
| @@ -15,16 +15,16 @@ export class AdminComponent implements OnInit { | ||||
|  | ||||
|   simplifiedMode = true; | ||||
|   text = { | ||||
|     Advanced: "Advanced", | ||||
|     Simplified: "Simplified" | ||||
|     Advanced: 'Advanced', | ||||
|     Simplified: 'Simplified' | ||||
|   }; | ||||
|  | ||||
|   constructor(private _authService: AuthenticationService, | ||||
|               private _navigation: NavigationService, | ||||
|               public notificationService: NotificationService, | ||||
|               public i18n: I18n) { | ||||
|     this.text.Advanced = i18n("Advanced"); | ||||
|     this.text.Simplified = i18n("Simplified"); | ||||
|     this.text.Advanced = i18n('Advanced'); | ||||
|     this.text.Simplified = i18n('Simplified'); | ||||
|   } | ||||
|  | ||||
|   ngOnInit() { | ||||
| @@ -38,13 +38,13 @@ export class AdminComponent implements OnInit { | ||||
|   public getCss(type: NotificationType) { | ||||
|     switch (type) { | ||||
|       case NotificationType.error: | ||||
|         return "danger"; | ||||
|         return 'danger'; | ||||
|       case NotificationType.warning: | ||||
|         return "warning"; | ||||
|         return 'warning'; | ||||
|       case NotificationType.info: | ||||
|         return "info"; | ||||
|         return 'info'; | ||||
|     } | ||||
|     return "info"; | ||||
|     return 'info'; | ||||
|   } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -1,15 +1,15 @@ | ||||
| import {Component, OnDestroy, OnInit, ViewContainerRef} from "@angular/core"; | ||||
| import {AuthenticationService} from "./model/network/authentication.service"; | ||||
| import {UserDTO} from "../../common/entities/UserDTO"; | ||||
| import {Router} from "@angular/router"; | ||||
| import {Config} from "../../common/config/public/Config"; | ||||
| import {Title} from "@angular/platform-browser"; | ||||
| import {NotificationService} from "./model/notification.service"; | ||||
| import {ShareService} from "./gallery/share.service"; | ||||
| import "hammerjs"; | ||||
| import {Component, OnDestroy, OnInit, ViewContainerRef} from '@angular/core'; | ||||
| import {AuthenticationService} from './model/network/authentication.service'; | ||||
| import {UserDTO} from '../../common/entities/UserDTO'; | ||||
| import {Router} from '@angular/router'; | ||||
| import {Config} from '../../common/config/public/Config'; | ||||
| import {Title} from '@angular/platform-browser'; | ||||
| import {NotificationService} from './model/notification.service'; | ||||
| import {ShareService} from './gallery/share.service'; | ||||
| import 'hammerjs'; | ||||
|  | ||||
| @Component({ | ||||
|   selector: 'pi-gallery2-app', | ||||
|   selector: 'app-pi-gallery2', | ||||
|   template: `<router-outlet></router-outlet>`, | ||||
|  | ||||
| }) | ||||
| @@ -55,17 +55,17 @@ export class AppComponent implements OnInit, OnDestroy { | ||||
|  | ||||
|   private toLogin() { | ||||
|     if (this._shareService.isSharing()) { | ||||
|       return this._router.navigate(["shareLogin"], {queryParams: {sk: this._shareService.getSharingKey()}}); | ||||
|       return this._router.navigate(['shareLogin'], {queryParams: {sk: this._shareService.getSharingKey()}}); | ||||
|     } else { | ||||
|       return this._router.navigate(["login"]); | ||||
|       return this._router.navigate(['login']); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   private toGallery() { | ||||
|     if (this._shareService.isSharing()) { | ||||
|       return this._router.navigate(["share", this._shareService.getSharingKey()]); | ||||
|       return this._router.navigate(['share', this._shareService.getSharingKey()]); | ||||
|     } else { | ||||
|       return this._router.navigate(["gallery", ""]); | ||||
|       return this._router.navigate(['gallery', '']); | ||||
|     } | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -1,62 +1,62 @@ | ||||
| import {Injectable, LOCALE_ID, NgModule, TRANSLATIONS} from "@angular/core"; | ||||
| import {BrowserModule, HAMMER_GESTURE_CONFIG, HammerGestureConfig} from "@angular/platform-browser"; | ||||
| import {FormsModule} from "@angular/forms"; | ||||
| import {HttpModule} from "@angular/http"; | ||||
| import {AgmCoreModule} from "@agm/core"; | ||||
| import {AppComponent} from "./app.component"; | ||||
| import {appRoutes} from "./app.routing"; | ||||
| import {UserService} from "./model/network/user.service"; | ||||
| import {GalleryService} from "./gallery/gallery.service"; | ||||
| import {NetworkService} from "./model/network/network.service"; | ||||
| import {ThumbnailLoaderService} from "./gallery/thumnailLoader.service"; | ||||
| import {GalleryCacheService} from "./gallery/cache.gallery.service"; | ||||
| import {FullScreenService} from "./gallery/fullscreen.service"; | ||||
| import {AuthenticationService} from "./model/network/authentication.service"; | ||||
| import {UserMangerSettingsComponent} from "./settings/usermanager/usermanager.settings.component"; | ||||
| import {FrameComponent} from "./frame/frame.component"; | ||||
| import {GalleryLightboxPhotoComponent} from "./gallery/lightbox/photo/photo.lightbox.gallery.component"; | ||||
| import {GalleryPhotoLoadingComponent} from "./gallery/grid/photo/loading/loading.photo.grid.gallery.component"; | ||||
| import {GalleryNavigatorComponent} from "./gallery/navigator/navigator.gallery.component"; | ||||
| import {GallerySearchComponent} from "./gallery/search/search.gallery.component"; | ||||
| import {GalleryLightboxComponent} from "./gallery/lightbox/lightbox.gallery.component"; | ||||
| import {GalleryDirectoryComponent} from "./gallery/directory/directory.gallery.component"; | ||||
| import {GalleryGridComponent} from "./gallery/grid/grid.gallery.component"; | ||||
| import {GalleryPhotoComponent} from "./gallery/grid/photo/photo.grid.gallery.component"; | ||||
| import {LoginComponent} from "./login/login.component"; | ||||
| import {AdminComponent} from "./admin/admin.component"; | ||||
| import {GalleryComponent} from "./gallery/gallery.component"; | ||||
| import {StringifyRole} from "./pipes/StringifyRolePipe"; | ||||
| import {GalleryMapComponent} from "./gallery/map/map.gallery.component"; | ||||
| import {GalleryMapLightboxComponent} from "./gallery/map/lightbox/lightbox.map.gallery.component"; | ||||
| import {ThumbnailManagerService} from "./gallery/thumnailManager.service"; | ||||
| import {OverlayService} from "./gallery/overlay.service"; | ||||
| import {Config} from "../../common/config/public/Config"; | ||||
| import {LAZY_MAPS_API_CONFIG} from "@agm/core/services"; | ||||
| import {SlimLoadingBarModule} from "ng2-slim-loading-bar"; | ||||
| import {GalleryShareComponent} from "./gallery/share/share.gallery.component"; | ||||
| import {ShareLoginComponent} from "./sharelogin/share-login.component"; | ||||
| import {ShareService} from "./gallery/share.service"; | ||||
| import {ModalModule} from "ngx-bootstrap/modal"; | ||||
| import {DatabaseSettingsComponent} from "./settings/database/database.settings.component"; | ||||
| import {ToastModule} from "ng2-toastr/ng2-toastr"; | ||||
| import {BrowserAnimationsModule} from "@angular/platform-browser/animations"; | ||||
| import {NotificationService} from "./model/notification.service"; | ||||
| import {JWBootstrapSwitchModule} from "jw-bootstrap-switch-ng2"; | ||||
| import {ClipboardModule} from "ngx-clipboard"; | ||||
| import {NavigationService} from "./model/navigation.service"; | ||||
| import {InfoPanelLightboxComponent} from "./gallery/lightbox/infopanel/info-panel.lightbox.gallery.component"; | ||||
| import {MapSettingsComponent} from "./settings/map/map.settings.component"; | ||||
| import {TooltipModule} from "ngx-bootstrap/tooltip"; | ||||
| import {BsDropdownModule} from "ngx-bootstrap/dropdown"; | ||||
| import {ThumbnailSettingsComponent} from "./settings/thumbnail/thumbanil.settings.component"; | ||||
| import {SearchSettingsComponent} from "./settings/search/search.settings.component"; | ||||
| import {SettingsService} from "./settings/settings.service"; | ||||
| import {ShareSettingsComponent} from "./settings/share/share.settings.component"; | ||||
| import {BasicSettingsComponent} from "./settings/basic/basic.settings.component"; | ||||
| import {OtherSettingsComponent} from "./settings/other/other.settings.component"; | ||||
| import {Injectable, LOCALE_ID, NgModule, TRANSLATIONS} from '@angular/core'; | ||||
| import {BrowserModule, HAMMER_GESTURE_CONFIG, HammerGestureConfig} from '@angular/platform-browser'; | ||||
| import {FormsModule} from '@angular/forms'; | ||||
| import {AgmCoreModule} from '@agm/core'; | ||||
| import {AppComponent} from './app.component'; | ||||
| import {appRoutes} from './app.routing'; | ||||
| import {UserService} from './model/network/user.service'; | ||||
| import {GalleryService} from './gallery/gallery.service'; | ||||
| import {NetworkService} from './model/network/network.service'; | ||||
| import {ThumbnailLoaderService} from './gallery/thumnailLoader.service'; | ||||
| import {GalleryCacheService} from './gallery/cache.gallery.service'; | ||||
| import {FullScreenService} from './gallery/fullscreen.service'; | ||||
| import {AuthenticationService} from './model/network/authentication.service'; | ||||
| import {UserMangerSettingsComponent} from './settings/usermanager/usermanager.settings.component'; | ||||
| import {FrameComponent} from './frame/frame.component'; | ||||
| import {GalleryLightboxPhotoComponent} from './gallery/lightbox/photo/photo.lightbox.gallery.component'; | ||||
| import {GalleryPhotoLoadingComponent} from './gallery/grid/photo/loading/loading.photo.grid.gallery.component'; | ||||
| import {GalleryNavigatorComponent} from './gallery/navigator/navigator.gallery.component'; | ||||
| import {GallerySearchComponent} from './gallery/search/search.gallery.component'; | ||||
| import {GalleryLightboxComponent} from './gallery/lightbox/lightbox.gallery.component'; | ||||
| import {GalleryDirectoryComponent} from './gallery/directory/directory.gallery.component'; | ||||
| import {GalleryGridComponent} from './gallery/grid/grid.gallery.component'; | ||||
| import {GalleryPhotoComponent} from './gallery/grid/photo/photo.grid.gallery.component'; | ||||
| import {LoginComponent} from './login/login.component'; | ||||
| import {AdminComponent} from './admin/admin.component'; | ||||
| import {GalleryComponent} from './gallery/gallery.component'; | ||||
| import {StringifyRole} from './pipes/StringifyRolePipe'; | ||||
| import {GalleryMapComponent} from './gallery/map/map.gallery.component'; | ||||
| import {GalleryMapLightboxComponent} from './gallery/map/lightbox/lightbox.map.gallery.component'; | ||||
| import {ThumbnailManagerService} from './gallery/thumnailManager.service'; | ||||
| import {OverlayService} from './gallery/overlay.service'; | ||||
| import {Config} from '../../common/config/public/Config'; | ||||
| import {LAZY_MAPS_API_CONFIG} from '@agm/core/services'; | ||||
| import {SlimLoadingBarModule} from 'ng2-slim-loading-bar'; | ||||
| import {GalleryShareComponent} from './gallery/share/share.gallery.component'; | ||||
| import {ShareLoginComponent} from './sharelogin/share-login.component'; | ||||
| import {ShareService} from './gallery/share.service'; | ||||
| import {ModalModule} from 'ngx-bootstrap/modal'; | ||||
| import {DatabaseSettingsComponent} from './settings/database/database.settings.component'; | ||||
| import {ToastModule} from 'ng2-toastr/ng2-toastr'; | ||||
| import {BrowserAnimationsModule} from '@angular/platform-browser/animations'; | ||||
| import {NotificationService} from './model/notification.service'; | ||||
| import {JWBootstrapSwitchModule} from 'jw-bootstrap-switch-ng2'; | ||||
| import {ClipboardModule} from 'ngx-clipboard'; | ||||
| import {NavigationService} from './model/navigation.service'; | ||||
| import {InfoPanelLightboxComponent} from './gallery/lightbox/infopanel/info-panel.lightbox.gallery.component'; | ||||
| import {MapSettingsComponent} from './settings/map/map.settings.component'; | ||||
| import {TooltipModule} from 'ngx-bootstrap/tooltip'; | ||||
| import {BsDropdownModule} from 'ngx-bootstrap/dropdown'; | ||||
| import {ThumbnailSettingsComponent} from './settings/thumbnail/thumbanil.settings.component'; | ||||
| import {SearchSettingsComponent} from './settings/search/search.settings.component'; | ||||
| import {SettingsService} from './settings/settings.service'; | ||||
| import {ShareSettingsComponent} from './settings/share/share.settings.component'; | ||||
| import {BasicSettingsComponent} from './settings/basic/basic.settings.component'; | ||||
| import {OtherSettingsComponent} from './settings/other/other.settings.component'; | ||||
| import {HttpClientModule} from '@angular/common/http'; | ||||
| import {DefaultUrlSerializer, UrlSerializer, UrlTree} from '@angular/router'; | ||||
| import {IndexingSettingsComponent} from "./settings/indexing/indexing.settings.component"; | ||||
| import {LanguageComponent} from "./language/language.component"; | ||||
| import {IndexingSettingsComponent} from './settings/indexing/indexing.settings.component'; | ||||
| import {LanguageComponent} from './language/language.component'; | ||||
| import {I18n} from '@ngx-translate/i18n-polyfill'; | ||||
|  | ||||
| @Injectable() | ||||
| @@ -71,7 +71,7 @@ export class GoogleMapsConfig { | ||||
| export class MyHammerConfig extends HammerGestureConfig { | ||||
|   overrides = <any>{ | ||||
|     'swipe': {direction: 31} // enable swipe up | ||||
|   } | ||||
|   }; | ||||
| } | ||||
|  | ||||
| export class CustomUrlSerializer implements UrlSerializer { | ||||
| @@ -81,7 +81,7 @@ export class CustomUrlSerializer implements UrlSerializer { | ||||
|     // Encode parentheses | ||||
|     url = url.replace(/\(/g, '%28').replace(/\)/g, '%29'); | ||||
|     // Use the default serializer. | ||||
|     return this._defaultUrlSerializer.parse(url) | ||||
|     return this._defaultUrlSerializer.parse(url); | ||||
|   } | ||||
|  | ||||
|   serialize(tree: UrlTree): string { | ||||
| @@ -93,7 +93,7 @@ declare const require; | ||||
|  | ||||
| export function translationsFactory(locale: string) { | ||||
|   locale = locale || 'en'; // default to english if no locale | ||||
|   console.log("locale", locale); | ||||
|   console.log('locale', locale); | ||||
|   return require(`raw-loader!../translate/messages.${locale}.xlf`); | ||||
| } | ||||
|  | ||||
| @@ -101,7 +101,7 @@ export function translationsFactory(locale: string) { | ||||
|   imports: [ | ||||
|     BrowserModule, | ||||
|     FormsModule, | ||||
|     HttpModule, | ||||
|     HttpClientModule, | ||||
|     BrowserAnimationsModule, | ||||
|     appRoutes, | ||||
|     ClipboardModule, | ||||
| @@ -117,10 +117,10 @@ export function translationsFactory(locale: string) { | ||||
|     LoginComponent, | ||||
|     ShareLoginComponent, | ||||
|     GalleryComponent, | ||||
|     //misc | ||||
|     // misc | ||||
|     FrameComponent, | ||||
|     LanguageComponent, | ||||
|     //Gallery | ||||
|     // Gallery | ||||
|     GalleryLightboxPhotoComponent, | ||||
|     GalleryPhotoLoadingComponent, | ||||
|     GalleryGridComponent, | ||||
| @@ -135,7 +135,7 @@ export function translationsFactory(locale: string) { | ||||
|     GalleryPhotoComponent, | ||||
|     AdminComponent, | ||||
|     InfoPanelLightboxComponent, | ||||
|     //Settings | ||||
|     // Settings | ||||
|     UserMangerSettingsComponent, | ||||
|     DatabaseSettingsComponent, | ||||
|     MapSettingsComponent, | ||||
|   | ||||
| @@ -1,9 +1,9 @@ | ||||
| import {ModuleWithProviders} from "@angular/core"; | ||||
| import {RouterModule, Routes} from "@angular/router"; | ||||
| import {LoginComponent} from "./login/login.component"; | ||||
| import {GalleryComponent} from "./gallery/gallery.component"; | ||||
| import {AdminComponent} from "./admin/admin.component"; | ||||
| import {ShareLoginComponent} from "./sharelogin/share-login.component"; | ||||
| import {ModuleWithProviders} from '@angular/core'; | ||||
| import {RouterModule, Routes} from '@angular/router'; | ||||
| import {LoginComponent} from './login/login.component'; | ||||
| import {GalleryComponent} from './gallery/gallery.component'; | ||||
| import {AdminComponent} from './admin/admin.component'; | ||||
| import {ShareLoginComponent} from './sharelogin/share-login.component'; | ||||
|  | ||||
| const ROUTES: Routes = [ | ||||
|   { | ||||
|   | ||||
| @@ -53,7 +53,6 @@ ng2-slim-loading-bar { | ||||
|   } | ||||
| } | ||||
|  | ||||
|  | ||||
| .badge { | ||||
|   margin-left: -5px; | ||||
|   padding: 0; | ||||
|   | ||||
| @@ -1,10 +1,10 @@ | ||||
| import {Component, ViewEncapsulation} from "@angular/core"; | ||||
| import {RouterLink} from "@angular/router"; | ||||
| import {AuthenticationService} from "../model/network/authentication.service"; | ||||
| import {UserDTO, UserRoles} from "../../../common/entities/UserDTO"; | ||||
| import {Config} from "../../../common/config/public/Config"; | ||||
| import {BehaviorSubject} from "rxjs/BehaviorSubject"; | ||||
| import {NotificationService} from "../model/notification.service"; | ||||
| import {Component, ViewEncapsulation} from '@angular/core'; | ||||
| import {RouterLink} from '@angular/router'; | ||||
| import {AuthenticationService} from '../model/network/authentication.service'; | ||||
| import {UserDTO, UserRoles} from '../../../common/entities/UserDTO'; | ||||
| import {Config} from '../../../common/config/public/Config'; | ||||
| import {BehaviorSubject} from 'rxjs/BehaviorSubject'; | ||||
| import {NotificationService} from '../model/notification.service'; | ||||
|  | ||||
| @Component({ | ||||
|   selector: 'app-frame', | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| import {PhotoDTO} from "../../../common/entities/PhotoDTO"; | ||||
| import {Utils} from "../../../common/Utils"; | ||||
| import {PhotoDTO} from '../../../common/entities/PhotoDTO'; | ||||
| import {Utils} from '../../../common/Utils'; | ||||
|  | ||||
| export class IconPhoto { | ||||
|  | ||||
|  | ||||
| @@ -18,23 +19,23 @@ export class IconPhoto { | ||||
|   } | ||||
|  | ||||
|   getIconPath() { | ||||
|     return Utils.concatUrls("/api/gallery/content/", this.photo.directory.path, this.photo.directory.name, this.photo.name, "icon"); | ||||
|     return Utils.concatUrls('/api/gallery/content/', this.photo.directory.path, this.photo.directory.name, this.photo.name, 'icon'); | ||||
|   } | ||||
|  | ||||
|   getPhotoPath() { | ||||
|     return Utils.concatUrls("/api/gallery/content/", this.photo.directory.path, this.photo.directory.name, this.photo.name); | ||||
|     return Utils.concatUrls('/api/gallery/content/', this.photo.directory.path, this.photo.directory.name, this.photo.name); | ||||
|   } | ||||
|  | ||||
|  | ||||
|   equals(other: PhotoDTO | IconPhoto): boolean { | ||||
|     //is gridphoto | ||||
|     if (other instanceof IconPhoto) { | ||||
|       return this.photo.directory.path === other.photo.directory.path && this.photo.directory.name === other.photo.directory.name && this.photo.name === other.photo.name | ||||
|       return this.photo.directory.path === other.photo.directory.path && this.photo.directory.name === other.photo.directory.name && this.photo.name === other.photo.name; | ||||
|     } | ||||
|  | ||||
|     //is photo | ||||
|     if (other.directory) { | ||||
|       return this.photo.directory.path === other.directory.path && this.photo.directory.name === other.directory.name && this.photo.name === other.name | ||||
|       return this.photo.directory.path === other.directory.path && this.photo.directory.name === other.directory.name && this.photo.name === other.name; | ||||
|     } | ||||
|  | ||||
|     return false; | ||||
|   | ||||
| @@ -1,7 +1,8 @@ | ||||
| import {PhotoDTO} from "../../../common/entities/PhotoDTO"; | ||||
| import {Utils} from "../../../common/Utils"; | ||||
| import {IconPhoto} from "./IconPhoto"; | ||||
| import {Config} from "../../../common/config/public/Config"; | ||||
| import {PhotoDTO} from '../../../common/entities/PhotoDTO'; | ||||
| import {Utils} from '../../../common/Utils'; | ||||
| import {IconPhoto} from './IconPhoto'; | ||||
| import {Config} from '../../../common/config/public/Config'; | ||||
|  | ||||
| export class Photo extends IconPhoto { | ||||
|  | ||||
|  | ||||
| @@ -50,13 +51,13 @@ export class Photo extends IconPhoto { | ||||
|  | ||||
|   getReplacementThumbnailPath() { | ||||
|     let size = this.getReplacementThumbnailSize(); | ||||
|     return Utils.concatUrls("/api/gallery/content/", this.photo.directory.path, this.photo.directory.name, this.photo.name, "thumbnail", size.toString()); | ||||
|     return Utils.concatUrls('/api/gallery/content/', this.photo.directory.path, this.photo.directory.name, this.photo.name, 'thumbnail', size.toString()); | ||||
|  | ||||
|   } | ||||
|  | ||||
|   getThumbnailPath() { | ||||
|     let size = this.getThumbnailSize(); | ||||
|     return Utils.concatUrls("/api/gallery/content/", this.photo.directory.path, this.photo.directory.name, this.photo.name, "thumbnail", size.toString()); | ||||
|     return Utils.concatUrls('/api/gallery/content/', this.photo.directory.path, this.photo.directory.name, this.photo.name, 'thumbnail', size.toString()); | ||||
|   } | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -1,10 +1,10 @@ | ||||
| import {Injectable} from "@angular/core"; | ||||
| import {PhotoDTO} from "../../../common/entities/PhotoDTO"; | ||||
| import {DirectoryDTO} from "../../../common/entities/DirectoryDTO"; | ||||
| import {Utils} from "../../../common/Utils"; | ||||
| import {Config} from "../../../common/config/public/Config"; | ||||
| import {AutoCompleteItem, SearchTypes} from "../../../common/entities/AutoCompleteItem"; | ||||
| import {SearchResultDTO} from "../../../common/entities/SearchResultDTO"; | ||||
| import {Injectable} from '@angular/core'; | ||||
| import {PhotoDTO} from '../../../common/entities/PhotoDTO'; | ||||
| import {DirectoryDTO} from '../../../common/entities/DirectoryDTO'; | ||||
| import {Utils} from '../../../common/Utils'; | ||||
| import {Config} from '../../../common/config/public/Config'; | ||||
| import {AutoCompleteItem, SearchTypes} from '../../../common/entities/AutoCompleteItem'; | ||||
| import {SearchResultDTO} from '../../../common/entities/SearchResultDTO'; | ||||
|  | ||||
| interface CacheItem<T> { | ||||
|   timestamp: number; | ||||
| @@ -14,11 +14,11 @@ interface CacheItem<T> { | ||||
| @Injectable() | ||||
| export class GalleryCacheService { | ||||
|  | ||||
|   private static CONTENT_PREFIX = "content:"; | ||||
|   private static AUTO_COMPLETE_PREFIX = "autocomplete:"; | ||||
|   private static INSTANT_SEARCH_PREFIX = "instant_search:"; | ||||
|   private static SEARCH_PREFIX = "search:"; | ||||
|   private static SEARCH_TYPE_PREFIX = ":type:"; | ||||
|   private static CONTENT_PREFIX = 'content:'; | ||||
|   private static AUTO_COMPLETE_PREFIX = 'autocomplete:'; | ||||
|   private static INSTANT_SEARCH_PREFIX = 'instant_search:'; | ||||
|   private static SEARCH_PREFIX = 'search:'; | ||||
|   private static SEARCH_TYPE_PREFIX = ':type:'; | ||||
|  | ||||
|  | ||||
|   public getAutoComplete(text: string): Array<AutoCompleteItem> { | ||||
| @@ -68,7 +68,7 @@ export class GalleryCacheService { | ||||
|  | ||||
|   public getSearch(text: string, type?: SearchTypes): SearchResultDTO { | ||||
|     let key = GalleryCacheService.SEARCH_PREFIX + text; | ||||
|     if (typeof type != "undefined") { | ||||
|     if (typeof type != 'undefined') { | ||||
|       key += GalleryCacheService.SEARCH_TYPE_PREFIX + type; | ||||
|     } | ||||
|     const tmp = localStorage.getItem(key); | ||||
| @@ -89,7 +89,7 @@ export class GalleryCacheService { | ||||
|       item: searchResult | ||||
|     }; | ||||
|     let key = GalleryCacheService.SEARCH_PREFIX + text; | ||||
|     if (typeof type != "undefined") { | ||||
|     if (typeof type != 'undefined') { | ||||
|       key += GalleryCacheService.SEARCH_TYPE_PREFIX + type; | ||||
|     } | ||||
|     localStorage.setItem(key, JSON.stringify(tmp)); | ||||
|   | ||||
| @@ -1,11 +1,11 @@ | ||||
| import {Component, ElementRef, Input, OnDestroy, OnInit, ViewChild} from "@angular/core"; | ||||
| import {DomSanitizer} from "@angular/platform-browser"; | ||||
| import {DirectoryDTO} from "../../../../common/entities/DirectoryDTO"; | ||||
| import {RouterLink} from "@angular/router"; | ||||
| import {Utils} from "../../../../common/Utils"; | ||||
| import {Photo} from "../Photo"; | ||||
| import {Thumbnail, ThumbnailManagerService} from "../thumnailManager.service"; | ||||
| import {ShareService} from "../share.service"; | ||||
| import {Component, ElementRef, Input, OnDestroy, OnInit, ViewChild} from '@angular/core'; | ||||
| import {DomSanitizer} from '@angular/platform-browser'; | ||||
| import {DirectoryDTO} from '../../../../common/entities/DirectoryDTO'; | ||||
| import {RouterLink} from '@angular/router'; | ||||
| import {Utils} from '../../../../common/Utils'; | ||||
| import {Photo} from '../Photo'; | ||||
| import {Thumbnail, ThumbnailManagerService} from '../thumnailManager.service'; | ||||
| import {ShareService} from '../share.service'; | ||||
|  | ||||
| @Component({ | ||||
|   selector: 'gallery-directory', | ||||
| @@ -15,7 +15,7 @@ import {ShareService} from "../share.service"; | ||||
| }) | ||||
| export class GalleryDirectoryComponent implements OnInit, OnDestroy { | ||||
|   @Input() directory: DirectoryDTO; | ||||
|   @ViewChild("dirContainer") container: ElementRef; | ||||
|   @ViewChild('dirContainer') container: ElementRef; | ||||
|   thumbnail: Thumbnail = null; | ||||
|  | ||||
|   constructor(private thumbnailService: ThumbnailManagerService, | ||||
| @@ -27,7 +27,7 @@ export class GalleryDirectoryComponent implements OnInit, OnDestroy { | ||||
|   size: number = null; | ||||
|  | ||||
|   getSanitizedThUrl() { | ||||
|     return this._sanitizer.bypassSecurityTrustStyle('url(' + encodeURI(this.thumbnail.Src).replace(/\(/g, "%28").replace(/\)/g, "%29") + ')'); | ||||
|     return this._sanitizer.bypassSecurityTrustStyle('url(' + encodeURI(this.thumbnail.Src).replace(/\(/g, '%28').replace(/\)/g, '%29') + ')'); | ||||
|   } | ||||
|  | ||||
|   //TODO: implement scroll | ||||
|   | ||||
| @@ -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'; | ||||
|  | ||||
| @Injectable() | ||||
| export class FullScreenService { | ||||
|   | ||||
| @@ -1,9 +1,9 @@ | ||||
| gallery-map { | ||||
|     margin-right: 0; | ||||
|     margin-left: auto; | ||||
|     display: block; | ||||
|     height: 80px; | ||||
|     width: 100px; | ||||
|   margin-right: 0; | ||||
|   margin-left: auto; | ||||
|   display: block; | ||||
|   height: 80px; | ||||
|   width: 100px; | ||||
| } | ||||
|  | ||||
| .directories { | ||||
|   | ||||
| @@ -1,18 +1,18 @@ | ||||
| import {Component, OnDestroy, OnInit, ViewChild} from "@angular/core"; | ||||
| import {AuthenticationService} from "../model/network/authentication.service"; | ||||
| import {ActivatedRoute, Params, Router} from "@angular/router"; | ||||
| import {GalleryService} from "./gallery.service"; | ||||
| import {GalleryGridComponent} from "./grid/grid.gallery.component"; | ||||
| import {GallerySearchComponent} from "./search/search.gallery.component"; | ||||
| import {SearchTypes} from "../../../common/entities/AutoCompleteItem"; | ||||
| import {Config} from "../../../common/config/public/Config"; | ||||
| import {DirectoryDTO} from "../../../common/entities/DirectoryDTO"; | ||||
| import {SearchResultDTO} from "../../../common/entities/SearchResultDTO"; | ||||
| import {ShareService} from "./share.service"; | ||||
| import {NavigationService} from "../model/navigation.service"; | ||||
| import {UserRoles} from "../../../common/entities/UserDTO"; | ||||
| import {Observable} from "rxjs/Rx"; | ||||
| import {ContentWrapper} from "../../../common/entities/ConentWrapper"; | ||||
| import {Component, OnDestroy, OnInit, ViewChild} from '@angular/core'; | ||||
| import {AuthenticationService} from '../model/network/authentication.service'; | ||||
| import {ActivatedRoute, Params, Router} from '@angular/router'; | ||||
| import {GalleryService} from './gallery.service'; | ||||
| import {GalleryGridComponent} from './grid/grid.gallery.component'; | ||||
| import {GallerySearchComponent} from './search/search.gallery.component'; | ||||
| import {SearchTypes} from '../../../common/entities/AutoCompleteItem'; | ||||
| import {Config} from '../../../common/config/public/Config'; | ||||
| import {DirectoryDTO} from '../../../common/entities/DirectoryDTO'; | ||||
| import {SearchResultDTO} from '../../../common/entities/SearchResultDTO'; | ||||
| import {ShareService} from './share.service'; | ||||
| import {NavigationService} from '../model/navigation.service'; | ||||
| import {UserRoles} from '../../../common/entities/UserDTO'; | ||||
| import {Observable} from 'rxjs/Rx'; | ||||
| import {ContentWrapper} from '../../../common/entities/ConentWrapper'; | ||||
|  | ||||
| @Component({ | ||||
|   selector: 'gallery', | ||||
| @@ -62,26 +62,33 @@ export class GalleryComponent implements OnInit, OnDestroy { | ||||
|     this.countDown.second = t % 60; | ||||
|   } | ||||
|  | ||||
|   async ngOnInit() { | ||||
|     await this.shareService.wait(); | ||||
|     if (!this._authService.isAuthenticated() && | ||||
|       (!this.shareService.isSharing() || | ||||
|       (this.shareService.isSharing() && Config.Client.Sharing.passwordProtected == true))) { | ||||
|   private onRoute = async (params: Params) => { | ||||
|     const searchText = params['searchText']; | ||||
|     if (searchText && searchText != '') { | ||||
|       let typeString = params['type']; | ||||
|  | ||||
|       return this._navigation.toLogin(); | ||||
|     } | ||||
|     this.showSearchBar = Config.Client.Search.enabled && this._authService.isAuthorized(UserRoles.Guest); | ||||
|     this.showShare = Config.Client.Sharing.enabled && this._authService.isAuthorized(UserRoles.User); | ||||
|       if (typeString && typeString != '') { | ||||
|         let type: SearchTypes = <any>SearchTypes[typeString]; | ||||
|         this._galleryService.search(searchText, type); | ||||
|         return; | ||||
|       } | ||||
|  | ||||
|     this.subscription.content = this._galleryService.content.subscribe(this.onContentChange); | ||||
|     this.subscription.route = this._route.params.subscribe(this.onRoute); | ||||
|  | ||||
|     if (this.shareService.isSharing()) { | ||||
|       this.$counter = Observable.interval(1000); | ||||
|       this.subscription.timer = this.$counter.subscribe((x) => this.updateTimer(x)); | ||||
|       this._galleryService.search(searchText); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|   } | ||||
|     if (params['sharingKey'] && params['sharingKey'] != '') { | ||||
|       const sharing = await this.shareService.getSharing(); | ||||
|       this._router.navigate(['/gallery', sharing.path], {queryParams: {sk: this.shareService.getSharingKey()}}); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     let directoryName = params['directory']; | ||||
|     directoryName = directoryName || ''; | ||||
|  | ||||
|     this._galleryService.getDirectory(directoryName); | ||||
|  | ||||
|   }; | ||||
|  | ||||
|   ngOnDestroy() { | ||||
|     if (this.subscription.content !== null) { | ||||
| @@ -118,33 +125,26 @@ export class GalleryComponent implements OnInit, OnDestroy { | ||||
|     } | ||||
|   }; | ||||
|  | ||||
|   private onRoute = async (params: Params) => { | ||||
|     const searchText = params['searchText']; | ||||
|     if (searchText && searchText != "") { | ||||
|       let typeString = params['type']; | ||||
|   async ngOnInit() { | ||||
|     await this.shareService.wait(); | ||||
|     if (!this._authService.isAuthenticated() && | ||||
|       (!this.shareService.isSharing() || | ||||
|         (this.shareService.isSharing() && Config.Client.Sharing.passwordProtected == true))) { | ||||
|  | ||||
|       if (typeString && typeString != "") { | ||||
|         let type: SearchTypes = <any>SearchTypes[typeString]; | ||||
|         this._galleryService.search(searchText, type); | ||||
|         return; | ||||
|       } | ||||
|       return this._navigation.toLogin(); | ||||
|     } | ||||
|     this.showSearchBar = Config.Client.Search.enabled && this._authService.isAuthorized(UserRoles.Guest); | ||||
|     this.showShare = Config.Client.Sharing.enabled && this._authService.isAuthorized(UserRoles.User); | ||||
|  | ||||
|       this._galleryService.search(searchText); | ||||
|       return; | ||||
|     this.subscription.content = this._galleryService.content.subscribe(this.onContentChange); | ||||
|     this.subscription.route = this._route.params.subscribe(this.onRoute); | ||||
|  | ||||
|     if (this.shareService.isSharing()) { | ||||
|       this.$counter = Observable.interval(1000); | ||||
|       this.subscription.timer = this.$counter.subscribe((x) => this.updateTimer(x)); | ||||
|     } | ||||
|  | ||||
|     if (params['sharingKey'] && params['sharingKey'] != "") { | ||||
|       const sharing = await this.shareService.getSharing(); | ||||
|       this._router.navigate(['/gallery', sharing.path], {queryParams: {sk: this.shareService.getSharingKey()}}); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     let directoryName = params['directory']; | ||||
|     directoryName = directoryName || ""; | ||||
|  | ||||
|     this._galleryService.getDirectory(directoryName); | ||||
|  | ||||
|   }; | ||||
|   } | ||||
|  | ||||
|  | ||||
|   onLightboxLastElement() { | ||||
|   | ||||
| @@ -1,13 +1,13 @@ | ||||
| import {Injectable} from "@angular/core"; | ||||
| import {NetworkService} from "../model/network/network.service"; | ||||
| import {ContentWrapper} from "../../../common/entities/ConentWrapper"; | ||||
| import {DirectoryDTO} from "../../../common/entities/DirectoryDTO"; | ||||
| import {SearchTypes} from "../../../common/entities/AutoCompleteItem"; | ||||
| import {GalleryCacheService} from "./cache.gallery.service"; | ||||
| import {BehaviorSubject} from "rxjs/BehaviorSubject"; | ||||
| import {SharingDTO} from "../../../common/entities/SharingDTO"; | ||||
| import {Config} from "../../../common/config/public/Config"; | ||||
| import {ShareService} from "./share.service"; | ||||
| import {Injectable} from '@angular/core'; | ||||
| import {NetworkService} from '../model/network/network.service'; | ||||
| import {ContentWrapper} from '../../../common/entities/ConentWrapper'; | ||||
| import {DirectoryDTO} from '../../../common/entities/DirectoryDTO'; | ||||
| import {SearchTypes} from '../../../common/entities/AutoCompleteItem'; | ||||
| import {GalleryCacheService} from './cache.gallery.service'; | ||||
| import {BehaviorSubject} from 'rxjs/BehaviorSubject'; | ||||
| import {SharingDTO} from '../../../common/entities/SharingDTO'; | ||||
| import {Config} from '../../../common/config/public/Config'; | ||||
| import {ShareService} from './share.service'; | ||||
|  | ||||
| @Injectable() | ||||
| export class GalleryService { | ||||
| @@ -49,7 +49,7 @@ export class GalleryService { | ||||
|     } | ||||
|  | ||||
|  | ||||
|     const cw = await this.networkService.getJson<ContentWrapper>("/gallery/content/" + directoryName, params); | ||||
|     const cw = await this.networkService.getJson<ContentWrapper>('/gallery/content/' + directoryName, params); | ||||
|  | ||||
|  | ||||
|     if (!cw || cw.notModified == true) { | ||||
| @@ -78,8 +78,8 @@ export class GalleryService { | ||||
|     if (this.searchId != null) { | ||||
|       clearTimeout(this.searchId); | ||||
|     } | ||||
|     if (text === null || text === '' || text.trim() == ".") { | ||||
|       return null | ||||
|     if (text === null || text === '' || text.trim() == '.') { | ||||
|       return null; | ||||
|     } | ||||
|  | ||||
|     this.content.next(new ContentWrapper()); | ||||
| @@ -87,10 +87,10 @@ export class GalleryService { | ||||
|     cw.searchResult = this.galleryCacheService.getSearch(text, type); | ||||
|     if (cw.searchResult == null) { | ||||
|       const params = {}; | ||||
|       if (typeof type != "undefined") { | ||||
|       if (typeof type != 'undefined') { | ||||
|         params['type'] = type; | ||||
|       } | ||||
|       cw.searchResult = (await this.networkService.getJson<ContentWrapper>("/search/" + text, params)).searchResult; | ||||
|       cw.searchResult = (await this.networkService.getJson<ContentWrapper>('/search/' + text, params)).searchResult; | ||||
|       this.galleryCacheService.setSearch(text, type, cw.searchResult); | ||||
|     } | ||||
|     this.content.next(cw); | ||||
| @@ -98,16 +98,16 @@ export class GalleryService { | ||||
|   } | ||||
|  | ||||
|   public async instantSearch(text: string): Promise<ContentWrapper> { | ||||
|     if (text === null || text === '' || text.trim() == ".") { | ||||
|     if (text === null || text === '' || text.trim() == '.') { | ||||
|       const content = new ContentWrapper(this.lastDirectory); | ||||
|       this.content.next(content); | ||||
|       if (this.searchId != null) { | ||||
|         clearTimeout(this.searchId); | ||||
|       } | ||||
|       if (!this.lastDirectory) { | ||||
|         this.getDirectory("/"); | ||||
|         this.getDirectory('/'); | ||||
|       } | ||||
|       return null | ||||
|       return null; | ||||
|     } | ||||
|  | ||||
|     if (this.searchId != null) { | ||||
| @@ -128,7 +128,7 @@ export class GalleryService { | ||||
|       cw.searchResult = this.galleryCacheService.getInstantSearch(text); | ||||
|  | ||||
|       if (cw.searchResult == null) { | ||||
|         cw.searchResult = (await this.networkService.getJson<ContentWrapper>("/instant-search/" + text)).searchResult; | ||||
|         cw.searchResult = (await this.networkService.getJson<ContentWrapper>('/instant-search/' + text)).searchResult; | ||||
|         this.galleryCacheService.setInstantSearch(text, cw.searchResult); | ||||
|       } | ||||
|     } | ||||
| @@ -145,7 +145,7 @@ export class GalleryService { | ||||
|   } | ||||
|  | ||||
|   public async getSharing(sharingKey: string): Promise<SharingDTO> { | ||||
|     return this.networkService.getJson<SharingDTO>("/share/" + sharingKey); | ||||
|     return this.networkService.getJson<SharingDTO>('/share/' + sharingKey); | ||||
|   } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| import {PhotoDTO} from "../../../../common/entities/PhotoDTO"; | ||||
| import {Photo} from "../Photo"; | ||||
| import {PhotoDTO} from '../../../../common/entities/PhotoDTO'; | ||||
| import {Photo} from '../Photo'; | ||||
|  | ||||
| export class GridPhoto extends Photo { | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| import {PhotoDTO} from "../../../../common/entities/PhotoDTO"; | ||||
| import {PhotoDTO} from '../../../../common/entities/PhotoDTO'; | ||||
|  | ||||
| export class GridRowBuilder { | ||||
|  | ||||
|   | ||||
| @@ -1,12 +1,12 @@ | ||||
| div { | ||||
|     /*display: block;*/ | ||||
|     line-height: normal; | ||||
|     font-size: 0; | ||||
|   /*display: block;*/ | ||||
|   line-height: normal; | ||||
|   font-size: 0; | ||||
| } | ||||
|  | ||||
| gallery-grid-photo { | ||||
|     display: inline-block; | ||||
|   display: inline-block; | ||||
|  | ||||
|     cursor: pointer; | ||||
|     margin: 2px; | ||||
|   cursor: pointer; | ||||
|   margin: 2px; | ||||
| } | ||||
|   | ||||
| @@ -1,12 +1,12 @@ | ||||
| <div #gridContainer> | ||||
|     <gallery-grid-photo | ||||
|             *ngFor="let gridPhoto of photosToRender" | ||||
|             (click)="lightbox.show(gridPhoto.photo)" | ||||
|             [gridPhoto]="gridPhoto" | ||||
|             [style.width.px]="gridPhoto.renderWidth" | ||||
|             [style.height.px]="gridPhoto.renderHeight" | ||||
|             [style.marginLeft.px]="IMAGE_MARGIN" | ||||
|             [style.marginRight.px]="IMAGE_MARGIN"> | ||||
|   <gallery-grid-photo | ||||
|     *ngFor="let gridPhoto of photosToRender" | ||||
|     (click)="lightbox.show(gridPhoto.photo)" | ||||
|     [gridPhoto]="gridPhoto" | ||||
|     [style.width.px]="gridPhoto.renderWidth" | ||||
|     [style.height.px]="gridPhoto.renderHeight" | ||||
|     [style.marginLeft.px]="IMAGE_MARGIN" | ||||
|     [style.marginRight.px]="IMAGE_MARGIN"> | ||||
|  | ||||
|     </gallery-grid-photo> | ||||
| </div> | ||||
|   </gallery-grid-photo> | ||||
| </div> | ||||
|   | ||||
| @@ -10,14 +10,14 @@ import { | ||||
|   QueryList, | ||||
|   ViewChild, | ||||
|   ViewChildren | ||||
| } from "@angular/core"; | ||||
| import {PhotoDTO} from "../../../../common/entities/PhotoDTO"; | ||||
| import {GridRowBuilder} from "./GridRowBuilder"; | ||||
| import {GalleryLightboxComponent} from "../lightbox/lightbox.gallery.component"; | ||||
| import {GridPhoto} from "./GridPhoto"; | ||||
| import {GalleryPhotoComponent} from "./photo/photo.grid.gallery.component"; | ||||
| import {OverlayService} from "../overlay.service"; | ||||
| import {Config} from "../../../../common/config/public/Config"; | ||||
| } from '@angular/core'; | ||||
| import {PhotoDTO} from '../../../../common/entities/PhotoDTO'; | ||||
| import {GridRowBuilder} from './GridRowBuilder'; | ||||
| import {GalleryLightboxComponent} from '../lightbox/lightbox.gallery.component'; | ||||
| import {GridPhoto} from './GridPhoto'; | ||||
| import {GalleryPhotoComponent} from './photo/photo.grid.gallery.component'; | ||||
| import {OverlayService} from '../overlay.service'; | ||||
| import {Config} from '../../../../common/config/public/Config'; | ||||
|  | ||||
| @Component({ | ||||
|   selector: 'gallery-grid', | ||||
| @@ -154,7 +154,7 @@ export class GalleryGridComponent implements OnChanges, AfterViewInit, OnDestroy | ||||
|       this.renderedPhotoIndex < numberOfPhotos)) { | ||||
|       let ret = this.renderARow(); | ||||
|       if (ret === null) { | ||||
|         throw new Error("Grid photos rendering failed"); | ||||
|         throw new Error('Grid photos rendering failed'); | ||||
|       } | ||||
|       renderedContentHeight += ret; | ||||
|     } | ||||
|   | ||||
| @@ -1,97 +1,97 @@ | ||||
| .static { | ||||
|     width: 100%; | ||||
|     height: 100%; | ||||
|     background-color: #bbbbbb; | ||||
|     color: #7f7f7f; | ||||
|     font-size: 50px; | ||||
|   width: 100%; | ||||
|   height: 100%; | ||||
|   background-color: #bbbbbb; | ||||
|   color: #7f7f7f; | ||||
|   font-size: 50px; | ||||
| } | ||||
|  | ||||
| .static span { | ||||
|     top: calc(50% - 25px); | ||||
|     left: calc(50% - 25px); | ||||
|   top: calc(50% - 25px); | ||||
|   left: calc(50% - 25px); | ||||
| } | ||||
|  | ||||
| .sk-cube-grid { | ||||
|     width: 100%; | ||||
|     height: 100%; | ||||
|   width: 100%; | ||||
|   height: 100%; | ||||
| } | ||||
|  | ||||
| .sk-cube-grid .sk-cube { | ||||
|     width: calc(100% / 3); | ||||
|     height: calc(100% / 3); | ||||
|     background-color: #bbbbbb; | ||||
|     float: left; | ||||
|   width: calc(100% / 3); | ||||
|   height: calc(100% / 3); | ||||
|   background-color: #bbbbbb; | ||||
|   float: left; | ||||
| } | ||||
|  | ||||
| .sk-cube-grid.animate .sk-cube { | ||||
|     -webkit-animation: sk-cubeGridScaleDelay 4.6s infinite ease-in-out; | ||||
|     animation: sk-cubeGridScaleDelay 4.6s infinite ease-in-out; | ||||
|   -webkit-animation: sk-cubeGridScaleDelay 4.6s infinite ease-in-out; | ||||
|   animation: sk-cubeGridScaleDelay 4.6s infinite ease-in-out; | ||||
| } | ||||
|  | ||||
| .sk-cube-grid.animate .sk-cube1 { | ||||
|     -webkit-animation-delay: 0.4s; | ||||
|     animation-delay: 0.4s; | ||||
|   -webkit-animation-delay: 0.4s; | ||||
|   animation-delay: 0.4s; | ||||
| } | ||||
|  | ||||
| .sk-cube-grid.animate .sk-cube2 { | ||||
|     -webkit-animation-delay: 0.6s; | ||||
|     animation-delay: 0.6s; | ||||
|   -webkit-animation-delay: 0.6s; | ||||
|   animation-delay: 0.6s; | ||||
| } | ||||
|  | ||||
| .sk-cube-grid.animate .sk-cube3 { | ||||
|     -webkit-animation-delay: 0.8s; | ||||
|     animation-delay: 0.8s; | ||||
|   -webkit-animation-delay: 0.8s; | ||||
|   animation-delay: 0.8s; | ||||
| } | ||||
|  | ||||
| .sk-cube-grid.animate .sk-cube4 { | ||||
|     -webkit-animation-delay: 0.2s; | ||||
|     animation-delay: 0.2s; | ||||
|   -webkit-animation-delay: 0.2s; | ||||
|   animation-delay: 0.2s; | ||||
| } | ||||
|  | ||||
| .sk-cube-grid.animate .sk-cube5 { | ||||
|     -webkit-animation-delay: 0.4s; | ||||
|     animation-delay: 0.4s; | ||||
|   -webkit-animation-delay: 0.4s; | ||||
|   animation-delay: 0.4s; | ||||
| } | ||||
|  | ||||
| .sk-cube-grid.animate .sk-cube6 { | ||||
|     -webkit-animation-delay: 0.6s; | ||||
|     animation-delay: 0.6s; | ||||
|   -webkit-animation-delay: 0.6s; | ||||
|   animation-delay: 0.6s; | ||||
| } | ||||
|  | ||||
| .sk-cube-grid.animate .sk-cube7 { | ||||
|     -webkit-animation-delay: 0s; | ||||
|     animation-delay: 0s; | ||||
|   -webkit-animation-delay: 0s; | ||||
|   animation-delay: 0s; | ||||
| } | ||||
|  | ||||
| .sk-cube-grid.animate .sk-cube8 { | ||||
|     -webkit-animation-delay: 0.2s; | ||||
|     animation-delay: 0.2s; | ||||
|   -webkit-animation-delay: 0.2s; | ||||
|   animation-delay: 0.2s; | ||||
| } | ||||
|  | ||||
| .sk-cube-grid.animate .sk-cube9 { | ||||
|     -webkit-animation-delay: 0.4s; | ||||
|     animation-delay: 0.4s; | ||||
|   -webkit-animation-delay: 0.4s; | ||||
|   animation-delay: 0.4s; | ||||
| } | ||||
|  | ||||
| @-webkit-keyframes sk-cubeGridScaleDelay { | ||||
|     0%, 70%, 100% { | ||||
|         -webkit-transform: scale3D(1, 1, 1); | ||||
|         transform: scale3D(1, 1, 1); | ||||
|     } | ||||
|     35% { | ||||
|         -webkit-transform: scale3D(0, 0, 1); | ||||
|         transform: scale3D(0, 0, 1); | ||||
|     } | ||||
|   0%, 70%, 100% { | ||||
|     -webkit-transform: scale3D(1, 1, 1); | ||||
|     transform: scale3D(1, 1, 1); | ||||
|   } | ||||
|   35% { | ||||
|     -webkit-transform: scale3D(0, 0, 1); | ||||
|     transform: scale3D(0, 0, 1); | ||||
|   } | ||||
| } | ||||
|  | ||||
| @keyframes sk-cubeGridScaleDelay { | ||||
|     0%, 70%, 100% { | ||||
|         -webkit-transform: scale3D(1, 1, 1); | ||||
|         transform: scale3D(1, 1, 1); | ||||
|     } | ||||
|     35% { | ||||
|         -webkit-transform: scale3D(0, 0, 1); | ||||
|         transform: scale3D(0, 0, 1); | ||||
|     } | ||||
|   0%, 70%, 100% { | ||||
|     -webkit-transform: scale3D(1, 1, 1); | ||||
|     transform: scale3D(1, 1, 1); | ||||
|   } | ||||
|   35% { | ||||
|     -webkit-transform: scale3D(0, 0, 1); | ||||
|     transform: scale3D(0, 0, 1); | ||||
|   } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -4,13 +4,13 @@ | ||||
|     </span> | ||||
| </div> | ||||
| <div class="sk-cube-grid animate" *ngIf="animate == true"> | ||||
|     <div class="sk-cube sk-cube1"></div> | ||||
|     <div class="sk-cube sk-cube2"></div> | ||||
|     <div class="sk-cube sk-cube3"></div> | ||||
|     <div class="sk-cube sk-cube4"></div> | ||||
|     <div class="sk-cube sk-cube5"></div> | ||||
|     <div class="sk-cube sk-cube6"></div> | ||||
|     <div class="sk-cube sk-cube7"></div> | ||||
|     <div class="sk-cube sk-cube8"></div> | ||||
|     <div class="sk-cube sk-cube9"></div> | ||||
|   <div class="sk-cube sk-cube1"></div> | ||||
|   <div class="sk-cube sk-cube2"></div> | ||||
|   <div class="sk-cube sk-cube3"></div> | ||||
|   <div class="sk-cube sk-cube4"></div> | ||||
|   <div class="sk-cube sk-cube5"></div> | ||||
|   <div class="sk-cube sk-cube6"></div> | ||||
|   <div class="sk-cube sk-cube7"></div> | ||||
|   <div class="sk-cube sk-cube8"></div> | ||||
|   <div class="sk-cube sk-cube9"></div> | ||||
| </div> | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| import {Component, Input} from "@angular/core"; | ||||
| import {Component, Input} from '@angular/core'; | ||||
|  | ||||
| @Component({ | ||||
|   selector: 'gallery-grid-photo-loading', | ||||
|   | ||||
| @@ -49,11 +49,11 @@ img { | ||||
| } | ||||
|  | ||||
| .info { | ||||
|     background-color: transparent; | ||||
|     color: white; | ||||
|     font-size: medium; | ||||
|     position: relative; | ||||
|     padding: 5px; | ||||
|   background-color: transparent; | ||||
|   color: white; | ||||
|   font-size: medium; | ||||
|   position: relative; | ||||
|   padding: 5px; | ||||
|   margin-top: 0; | ||||
|  | ||||
|   transition: margin .3s ease-out, background-color .3s ease-out; | ||||
|   | ||||
| @@ -1,11 +1,11 @@ | ||||
| import {Component, ElementRef, Input, OnDestroy, OnInit, ViewChild} from "@angular/core"; | ||||
| import {Dimension, IRenderable} from "../../../model/IRenderable"; | ||||
| import {GridPhoto} from "../GridPhoto"; | ||||
| import {SearchTypes} from "../../../../../common/entities/AutoCompleteItem"; | ||||
| import {RouterLink} from "@angular/router"; | ||||
| import {Thumbnail, ThumbnailManagerService} from "../../thumnailManager.service"; | ||||
| import {Config} from "../../../../../common/config/public/Config"; | ||||
| import {AnimationBuilder} from "@angular/animations"; | ||||
| import {Component, ElementRef, Input, OnDestroy, OnInit, ViewChild} from '@angular/core'; | ||||
| import {Dimension, IRenderable} from '../../../model/IRenderable'; | ||||
| import {GridPhoto} from '../GridPhoto'; | ||||
| import {SearchTypes} from '../../../../../common/entities/AutoCompleteItem'; | ||||
| import {RouterLink} from '@angular/router'; | ||||
| import {Thumbnail, ThumbnailManagerService} from '../../thumnailManager.service'; | ||||
| import {Config} from '../../../../../common/config/public/Config'; | ||||
| import {AnimationBuilder} from '@angular/animations'; | ||||
|  | ||||
| @Component({ | ||||
|   selector: 'gallery-grid-photo', | ||||
| @@ -15,9 +15,9 @@ import {AnimationBuilder} from "@angular/animations"; | ||||
| }) | ||||
| export class GalleryPhotoComponent implements IRenderable, OnInit, OnDestroy { | ||||
|   @Input() gridPhoto: GridPhoto; | ||||
|   @ViewChild("img") imageRef: ElementRef; | ||||
|   @ViewChild("info") infoDiv: ElementRef; | ||||
|   @ViewChild("photoContainer") container: ElementRef; | ||||
|   @ViewChild('img') imageRef: ElementRef; | ||||
|   @ViewChild('info') infoDiv: ElementRef; | ||||
|   @ViewChild('photoContainer') container: ElementRef; | ||||
|  | ||||
|   thumbnail: Thumbnail; | ||||
|   /* | ||||
| @@ -35,7 +35,7 @@ export class GalleryPhotoComponent implements IRenderable, OnInit, OnDestroy { | ||||
|   infoBar = { | ||||
|     marginTop: 0, | ||||
|     visible: false, | ||||
|     background: "rgba(0,0,0,0.0)" | ||||
|     background: 'rgba(0,0,0,0.0)' | ||||
|   }; | ||||
|   animationTimer = null; | ||||
|  | ||||
| @@ -83,7 +83,7 @@ export class GalleryPhotoComponent implements IRenderable, OnInit, OnDestroy { | ||||
|  | ||||
|   getPositionText(): string { | ||||
|     if (!this.gridPhoto) { | ||||
|       return "" | ||||
|       return ''; | ||||
|     } | ||||
|     return this.gridPhoto.photo.metadata.positionData.city || | ||||
|       this.gridPhoto.photo.metadata.positionData.state || | ||||
| @@ -97,7 +97,7 @@ export class GalleryPhotoComponent implements IRenderable, OnInit, OnDestroy { | ||||
|       clearTimeout(this.animationTimer); | ||||
|     } | ||||
|     this.animationTimer = setTimeout(() => { | ||||
|       this.infoBar.background = "rgba(0,0,0,0.8)"; | ||||
|       this.infoBar.background = 'rgba(0,0,0,0.8)'; | ||||
|       if (!this.infoDiv) { | ||||
|         this.animationTimer = setTimeout(() => { | ||||
|           if (!this.infoDiv) { | ||||
| @@ -115,7 +115,7 @@ export class GalleryPhotoComponent implements IRenderable, OnInit, OnDestroy { | ||||
|  | ||||
|   mouseOut() { | ||||
|     this.infoBar.marginTop = 0; | ||||
|     this.infoBar.background = "rgba(0,0,0,0.0)"; | ||||
|     this.infoBar.background = 'rgba(0,0,0,0.0)'; | ||||
|     if (this.animationTimer != null) { | ||||
|       clearTimeout(this.animationTimer); | ||||
|     } | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| import {Component, ElementRef, EventEmitter, Input, Output} from "@angular/core"; | ||||
| import {PhotoDTO} from "../../../../../common/entities/PhotoDTO"; | ||||
| import {Config} from "../../../../../common/config/public/Config"; | ||||
| import {Component, ElementRef, EventEmitter, Input, Output} from '@angular/core'; | ||||
| import {PhotoDTO} from '../../../../../common/entities/PhotoDTO'; | ||||
| import {Config} from '../../../../../common/config/public/Config'; | ||||
|  | ||||
| @Component({ | ||||
|   selector: 'info-panel', | ||||
| @@ -21,7 +21,7 @@ export class InfoPanelLightboxComponent { | ||||
|   } | ||||
|  | ||||
|   calcFileSize() { | ||||
|     let postFixes = ["B", "KB", "MB", "GB", "TB"]; | ||||
|     let postFixes = ['B', 'KB', 'MB', 'GB', 'TB']; | ||||
|     let index = 0; | ||||
|     let size = this.photo.metadata.fileSize; | ||||
|     while (size > 1000 && index < postFixes.length - 1) { | ||||
| @@ -42,8 +42,8 @@ export class InfoPanelLightboxComponent { | ||||
|  | ||||
|   getDate() { | ||||
|     const date = new Date(this.photo.metadata.creationDate); | ||||
|     let locale = "en-us"; | ||||
|     return date.toLocaleString(locale, {month: "long"}) + " " + date.getDate(); | ||||
|     let locale = 'en-us'; | ||||
|     return date.toLocaleString(locale, {month: 'long'}) + ' ' + date.getDate(); | ||||
|   } | ||||
|  | ||||
|   getTime() { | ||||
| @@ -53,31 +53,31 @@ export class InfoPanelLightboxComponent { | ||||
|  | ||||
|   getDay() { | ||||
|     const date = new Date(this.photo.metadata.creationDate); | ||||
|     let locale = "en-us"; | ||||
|     return date.toLocaleString(locale, {weekday: "long"}); | ||||
|     let locale = 'en-us'; | ||||
|     return date.toLocaleString(locale, {weekday: 'long'}); | ||||
|   } | ||||
|  | ||||
|   toFraction(f) { | ||||
|     if (f > 1) { | ||||
|       return f; | ||||
|     } | ||||
|     return "1/" + (1 / f); | ||||
|     return '1/' + (1 / f); | ||||
|   } | ||||
|  | ||||
|   hasGPS() { | ||||
|     return this.photo.metadata.positionData && this.photo.metadata.positionData.GPSData && | ||||
|       this.photo.metadata.positionData.GPSData.latitude && this.photo.metadata.positionData.GPSData.longitude | ||||
|       this.photo.metadata.positionData.GPSData.latitude && this.photo.metadata.positionData.GPSData.longitude; | ||||
|   } | ||||
|  | ||||
|   getPositionText(): string { | ||||
|     if (!this.photo.metadata.positionData) { | ||||
|       return ""; | ||||
|       return ''; | ||||
|     } | ||||
|     let str = this.photo.metadata.positionData.city || | ||||
|       this.photo.metadata.positionData.state; | ||||
|  | ||||
|     if (str.length != 0) { | ||||
|       str += ", "; | ||||
|       str += ', '; | ||||
|     } | ||||
|     str += this.photo.metadata.positionData.country; | ||||
|  | ||||
|   | ||||
| @@ -1,23 +1,13 @@ | ||||
| import { | ||||
|   ChangeDetectorRef, | ||||
|   Component, | ||||
|   ElementRef, | ||||
|   EventEmitter, | ||||
|   HostListener, | ||||
|   OnDestroy, | ||||
|   Output, | ||||
|   QueryList, | ||||
|   ViewChild | ||||
| } from "@angular/core"; | ||||
| import {PhotoDTO} from "../../../../common/entities/PhotoDTO"; | ||||
| import {GalleryPhotoComponent} from "../grid/photo/photo.grid.gallery.component"; | ||||
| import {Dimension} from "../../model/IRenderable"; | ||||
| import {FullScreenService} from "../fullscreen.service"; | ||||
| import {OverlayService} from "../overlay.service"; | ||||
| import {Subscription} from "rxjs"; | ||||
| import {animate, AnimationBuilder, AnimationPlayer, style} from "@angular/animations"; | ||||
| import {GalleryLightboxPhotoComponent} from "./photo/photo.lightbox.gallery.component"; | ||||
| import {Observable} from "rxjs/Observable"; | ||||
| import {ChangeDetectorRef, Component, ElementRef, EventEmitter, HostListener, OnDestroy, Output, QueryList, ViewChild} from '@angular/core'; | ||||
| import {PhotoDTO} from '../../../../common/entities/PhotoDTO'; | ||||
| import {GalleryPhotoComponent} from '../grid/photo/photo.grid.gallery.component'; | ||||
| import {Dimension} from '../../model/IRenderable'; | ||||
| import {FullScreenService} from '../fullscreen.service'; | ||||
| import {OverlayService} from '../overlay.service'; | ||||
| import {Subscription} from 'rxjs'; | ||||
| import {animate, AnimationBuilder, AnimationPlayer, style} from '@angular/animations'; | ||||
| import {GalleryLightboxPhotoComponent} from './photo/photo.lightbox.gallery.component'; | ||||
| import {Observable} from 'rxjs/Observable'; | ||||
|  | ||||
| @Component({ | ||||
|   selector: 'gallery-lightbox', | ||||
| @@ -28,8 +18,8 @@ export class GalleryLightboxComponent implements OnDestroy { | ||||
|  | ||||
|  | ||||
|   @Output('onLastElement') onLastElement = new EventEmitter(); | ||||
|   @ViewChild("photo") photoElement: GalleryLightboxPhotoComponent; | ||||
|   @ViewChild("lightbox") lightboxElement: ElementRef; | ||||
|   @ViewChild('photo') photoElement: GalleryLightboxPhotoComponent; | ||||
|   @ViewChild('lightbox') lightboxElement: ElementRef; | ||||
|  | ||||
|   public navigation = {hasPrev: true, hasNext: true}; | ||||
|   public blackCanvasOpacity: any = 0; | ||||
| @@ -108,40 +98,13 @@ export class GalleryLightboxComponent implements OnDestroy { | ||||
|     this.updateActivePhoto(photoIndex, resize); | ||||
|   } | ||||
|  | ||||
|   private updateActivePhoto(photoIndex: number, resize: boolean = true) { | ||||
|     let pcList = this.gridPhotoQL.toArray(); | ||||
|  | ||||
|  | ||||
|     if (photoIndex < 0 || photoIndex > this.gridPhotoQL.length) { | ||||
|       throw new Error("Can't find the photo"); | ||||
|     } | ||||
|     this.activePhotoId = photoIndex; | ||||
|     this.activePhoto = pcList[photoIndex]; | ||||
|  | ||||
|     if (resize) { | ||||
|       this.animatePhoto(this.calcLightBoxPhotoDimension(this.activePhoto.gridPhoto.photo)); | ||||
|     } | ||||
|     this.navigation.hasPrev = photoIndex > 0; | ||||
|     this.navigation.hasNext = photoIndex + 1 < pcList.length; | ||||
|  | ||||
|     let to = this.activePhoto.getDimension(); | ||||
|  | ||||
|     //if target image out of screen -> scroll to there | ||||
|     if (this.getBodyScrollTop() > to.top || this.getBodyScrollTop() + this.getPhotoFrameHeight() < to.top) { | ||||
|       this.setBodyScrollTop(to.top); | ||||
|     } | ||||
|  | ||||
|   } | ||||
|  | ||||
|   startPhotoDimension: Dimension = <Dimension>{top: 0, left: 0, width: 0, height: 0}; | ||||
|  | ||||
|   public show(photo: PhotoDTO) { | ||||
|     this.controllersVisible = true; | ||||
|     this.showControls(); | ||||
|     this.visible = true; | ||||
|     let selectedPhoto = this.findPhotoComponent(photo); | ||||
|     if (selectedPhoto === null) { | ||||
|       throw new Error("Can't find Photo"); | ||||
|       throw new Error('Can\'t find Photo'); | ||||
|     } | ||||
|  | ||||
|     const lightboxDimension = selectedPhoto.getDimension(); | ||||
| @@ -168,6 +131,33 @@ export class GalleryLightboxComponent implements OnDestroy { | ||||
|     this.showPhoto(this.gridPhotoQL.toArray().indexOf(selectedPhoto), false); | ||||
|   } | ||||
|  | ||||
|   startPhotoDimension: Dimension = <Dimension>{top: 0, left: 0, width: 0, height: 0}; | ||||
|  | ||||
|   private updateActivePhoto(photoIndex: number, resize: boolean = true) { | ||||
|     let pcList = this.gridPhotoQL.toArray(); | ||||
|  | ||||
|  | ||||
|     if (photoIndex < 0 || photoIndex > this.gridPhotoQL.length) { | ||||
|       throw new Error('Can\'t find the photo'); | ||||
|     } | ||||
|     this.activePhotoId = photoIndex; | ||||
|     this.activePhoto = pcList[photoIndex]; | ||||
|  | ||||
|     if (resize) { | ||||
|       this.animatePhoto(this.calcLightBoxPhotoDimension(this.activePhoto.gridPhoto.photo)); | ||||
|     } | ||||
|     this.navigation.hasPrev = photoIndex > 0; | ||||
|     this.navigation.hasNext = photoIndex + 1 < pcList.length; | ||||
|  | ||||
|     let to = this.activePhoto.getDimension(); | ||||
|  | ||||
|     //if target image out of screen -> scroll to there | ||||
|     if (this.getBodyScrollTop() > to.top || this.getBodyScrollTop() + this.getPhotoFrameHeight() < to.top) { | ||||
|       this.setBodyScrollTop(to.top); | ||||
|     } | ||||
|  | ||||
|   } | ||||
|  | ||||
|   public hide() { | ||||
|     this.controllersVisible = false; | ||||
|     this.fullScreenService.exitFullScreen(); | ||||
|   | ||||
| @@ -1,9 +1,9 @@ | ||||
| .imgContainer img { | ||||
|     position: absolute; | ||||
|   position: absolute; | ||||
| } | ||||
|  | ||||
| .imgContainer { | ||||
|     justify-content: center; /* add to align horizontal */ | ||||
|     align-items: center; /* add to align vertical */ | ||||
|   justify-content: center; /* add to align horizontal */ | ||||
|   align-items: center; /* add to align vertical */ | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -1,8 +1,8 @@ | ||||
| <div class="imgContainer" #imgContainer> | ||||
|     <img *ngIf="showThumbnail()" | ||||
|          [style.width.%]="imageSize.width" | ||||
|          [style.height.%]="imageSize.height" | ||||
|          [src]="thumbnailPath()"/> | ||||
|   <img *ngIf="showThumbnail()" | ||||
|        [style.width.%]="imageSize.width" | ||||
|        [style.height.%]="imageSize.height" | ||||
|        [src]="thumbnailPath()"/> | ||||
|  | ||||
|   <img *ngIf="gridPhoto !== null && loadImage" | ||||
|        [style.width.%]="imageSize.width" | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| import {Component, ElementRef, Input, OnChanges} from "@angular/core"; | ||||
| import {GridPhoto} from "../../grid/GridPhoto"; | ||||
| import {Component, ElementRef, Input, OnChanges} from '@angular/core'; | ||||
| import {GridPhoto} from '../../grid/GridPhoto'; | ||||
|  | ||||
| @Component({ | ||||
|   selector: 'gallery-lightbox-photo', | ||||
| @@ -12,7 +12,7 @@ export class GalleryLightboxPhotoComponent implements OnChanges { | ||||
|   @Input() loadImage: boolean = false; | ||||
|   @Input() windowAspect: number = 1; | ||||
|  | ||||
|   public imageSize = {width: "auto", height: "100"}; | ||||
|   public imageSize = {width: 'auto', height: '100'}; | ||||
|  | ||||
|   imageLoaded: boolean = false; | ||||
|   public imageLoadFinished: boolean = false; | ||||
| @@ -27,6 +27,32 @@ export class GalleryLightboxPhotoComponent implements OnChanges { | ||||
|     this.setImageSize(); | ||||
|   } | ||||
|  | ||||
|   onImageError() { | ||||
|     //TODO:handle error | ||||
|     this.imageLoadFinished = true; | ||||
|     console.error('cant load image'); | ||||
|   } | ||||
|  | ||||
|  | ||||
|   onImageLoad() { | ||||
|     this.imageLoadFinished = true; | ||||
|     this.imageLoaded = true; | ||||
|   } | ||||
|  | ||||
|   public thumbnailPath(): string { | ||||
|     if (this.gridPhoto.isThumbnailAvailable() === true) | ||||
|       return this.gridPhoto.getThumbnailPath(); | ||||
|  | ||||
|     if (this.gridPhoto.isReplacementThumbnailAvailable() === true) | ||||
|       return this.gridPhoto.getReplacementThumbnailPath(); | ||||
|     return null; | ||||
|   } | ||||
|  | ||||
|   public showThumbnail(): boolean { | ||||
|     return this.gridPhoto && !this.imageLoaded && | ||||
|       (this.gridPhoto.isThumbnailAvailable() || this.gridPhoto.isReplacementThumbnailAvailable()); | ||||
|   } | ||||
|  | ||||
|   private setImageSize() { | ||||
|     if (!this.gridPhoto) { | ||||
|       return; | ||||
| @@ -36,39 +62,13 @@ export class GalleryLightboxPhotoComponent implements OnChanges { | ||||
|     const photoAspect = this.gridPhoto.photo.metadata.size.width / this.gridPhoto.photo.metadata.size.height; | ||||
|  | ||||
|     if (photoAspect < this.windowAspect) { | ||||
|       this.imageSize.height = "100"; | ||||
|       this.imageSize.height = '100'; | ||||
|       this.imageSize.width = null; | ||||
|     } else { | ||||
|       this.imageSize.height = null; | ||||
|       this.imageSize.width = "100"; | ||||
|       this.imageSize.width = '100'; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|  | ||||
|   onImageLoad() { | ||||
|     this.imageLoadFinished = true; | ||||
|     this.imageLoaded = true; | ||||
|   } | ||||
|  | ||||
|   onImageError() { | ||||
|     //TODO:handle error | ||||
|     this.imageLoadFinished = true; | ||||
|     console.error("cant load image"); | ||||
|   } | ||||
|  | ||||
|   public showThumbnail(): boolean { | ||||
|     return this.gridPhoto && !this.imageLoaded && | ||||
|       (this.gridPhoto.isThumbnailAvailable() || this.gridPhoto.isReplacementThumbnailAvailable()); | ||||
|   } | ||||
|  | ||||
|   public thumbnailPath(): string { | ||||
|     if (this.gridPhoto.isThumbnailAvailable() === true) | ||||
|       return this.gridPhoto.getThumbnailPath(); | ||||
|  | ||||
|     if (this.gridPhoto.isReplacementThumbnailAvailable() === true) | ||||
|       return this.gridPhoto.getReplacementThumbnailPath(); | ||||
|     return null | ||||
|   } | ||||
|  | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -1,67 +1,67 @@ | ||||
| .lightbox { | ||||
|     position: fixed; /* Stay in place */ | ||||
|     z-index: 1100; /* Sit on top */ | ||||
|     left: 0; | ||||
|     top: 0; | ||||
|     width: 100%; /* Full width */ | ||||
|     height: 100%; /* Full height */ | ||||
|     overflow: hidden; | ||||
|     display: flex; /* add */ | ||||
|     justify-content: center; /* add to align horizontal */ | ||||
|     align-items: center; /* add to align vertical */ | ||||
|     cursor: pointer; | ||||
|     transition: all 0.3s ease-in-out; | ||||
|   position: fixed; /* Stay in place */ | ||||
|   z-index: 1100; /* Sit on top */ | ||||
|   left: 0; | ||||
|   top: 0; | ||||
|   width: 100%; /* Full width */ | ||||
|   height: 100%; /* Full height */ | ||||
|   overflow: hidden; | ||||
|   display: flex; /* add */ | ||||
|   justify-content: center; /* add to align horizontal */ | ||||
|   align-items: center; /* add to align vertical */ | ||||
|   cursor: pointer; | ||||
|   transition: all 0.3s ease-in-out; | ||||
| } | ||||
|  | ||||
| .sebm-google-map-container { | ||||
|     width: 100%; | ||||
|     height: 100%; | ||||
|   width: 100%; | ||||
|   height: 100%; | ||||
| } | ||||
|  | ||||
| .blackCanvas { | ||||
|     position: fixed; /* Stay in place */ | ||||
|     z-index: 1099; /* Sit on top */ | ||||
|     left: 0; | ||||
|     top: 0; | ||||
|     width: 100%; /* Full width */ | ||||
|     height: 100%; /* Full height */ | ||||
|     background-color: black; | ||||
|     transition: all 0.3s ease-in-out; | ||||
|   position: fixed; /* Stay in place */ | ||||
|   z-index: 1099; /* Sit on top */ | ||||
|   left: 0; | ||||
|   top: 0; | ||||
|   width: 100%; /* Full width */ | ||||
|   height: 100%; /* Full height */ | ||||
|   background-color: black; | ||||
|   transition: all 0.3s ease-in-out; | ||||
| } | ||||
|  | ||||
| #controllers-container { | ||||
|     z-index: 1100; | ||||
|     right: 0; | ||||
|     top: 0; | ||||
|     position: fixed; | ||||
|   z-index: 1100; | ||||
|   right: 0; | ||||
|   top: 0; | ||||
|   position: fixed; | ||||
| } | ||||
|  | ||||
| #controls { | ||||
|     top: 0; | ||||
|     height: initial; | ||||
|     text-align: right; | ||||
|     width: 100%; | ||||
|     padding: 5px; | ||||
|     font-size: large; | ||||
|   top: 0; | ||||
|   height: initial; | ||||
|   text-align: right; | ||||
|   width: 100%; | ||||
|   padding: 5px; | ||||
|   font-size: large; | ||||
| } | ||||
|  | ||||
| #controls span { | ||||
|     margin-left: 6px; | ||||
|     margin-right: 6px; | ||||
|     color: black; | ||||
|     cursor: pointer; | ||||
|   margin-left: 6px; | ||||
|   margin-right: 6px; | ||||
|   color: black; | ||||
|   cursor: pointer; | ||||
| } | ||||
|  | ||||
| .highlight { | ||||
|     opacity: 0.4; | ||||
|     transition: opacity .2s ease-out; | ||||
|     -moz-transition: opacity .2s ease-out; | ||||
|     -webkit-transition: opacity .2s ease-out; | ||||
|     -o-transition: opacity .2s ease-out; | ||||
|   opacity: 0.4; | ||||
|   transition: opacity .2s ease-out; | ||||
|   -moz-transition: opacity .2s ease-out; | ||||
|   -webkit-transition: opacity .2s ease-out; | ||||
|   -o-transition: opacity .2s ease-out; | ||||
| } | ||||
|  | ||||
| .highlight:hover { | ||||
|     opacity: 1.0; | ||||
|   opacity: 1.0; | ||||
| } | ||||
|  | ||||
| .preview-loading { | ||||
|   | ||||
| @@ -1,11 +1,11 @@ | ||||
| import {Component, ElementRef, HostListener, Input, OnChanges, ViewChild} from "@angular/core"; | ||||
| import {PhotoDTO} from "../../../../../common/entities/PhotoDTO"; | ||||
| import {Dimension} from "../../../model/IRenderable"; | ||||
| import {FullScreenService} from "../../fullscreen.service"; | ||||
| import {AgmMap} from "@agm/core"; | ||||
| import {IconThumbnail, Thumbnail, ThumbnailManagerService} from "../../thumnailManager.service"; | ||||
| import {IconPhoto} from "../../IconPhoto"; | ||||
| import {Photo} from "../../Photo"; | ||||
| import {Component, ElementRef, HostListener, Input, OnChanges, ViewChild} from '@angular/core'; | ||||
| import {PhotoDTO} from '../../../../../common/entities/PhotoDTO'; | ||||
| import {Dimension} from '../../../model/IRenderable'; | ||||
| import {FullScreenService} from '../../fullscreen.service'; | ||||
| import {AgmMap} from '@agm/core'; | ||||
| import {IconThumbnail, Thumbnail, ThumbnailManagerService} from '../../thumnailManager.service'; | ||||
| import {IconPhoto} from '../../IconPhoto'; | ||||
| import {Photo} from '../../Photo'; | ||||
|  | ||||
| @Component({ | ||||
|   selector: 'gallery-map-lightbox', | ||||
| @@ -23,7 +23,7 @@ export class GalleryMapLightboxComponent implements OnChanges { | ||||
|   mapPhotos: MapPhoto[] = []; | ||||
|   mapCenter = {latitude: 0, longitude: 0}; | ||||
|  | ||||
|   @ViewChild("root") elementRef: ElementRef; | ||||
|   @ViewChild('root') elementRef: ElementRef; | ||||
|  | ||||
|   @ViewChild(AgmMap) map: AgmMap; | ||||
|  | ||||
|   | ||||
| @@ -1,10 +1,10 @@ | ||||
| .sebm-google-map-container { | ||||
|     width: 100%; | ||||
|     height: 100%; | ||||
|   width: 100%; | ||||
|   height: 100%; | ||||
| } | ||||
|  | ||||
| #map { | ||||
|  | ||||
|     width: 100%; | ||||
|     height: 100%; | ||||
| } | ||||
|   width: 100%; | ||||
|   height: 100%; | ||||
| } | ||||
|   | ||||
| @@ -1,7 +1,8 @@ | ||||
| import {Component, ElementRef, Input, OnChanges, ViewChild} from "@angular/core"; | ||||
| import {PhotoDTO} from "../../../../common/entities/PhotoDTO"; | ||||
| import {Dimension, IRenderable} from "../../model/IRenderable"; | ||||
| import {GalleryMapLightboxComponent} from "./lightbox/lightbox.map.gallery.component"; | ||||
| import {Component, ElementRef, Input, OnChanges, ViewChild} from '@angular/core'; | ||||
| import {PhotoDTO} from '../../../../common/entities/PhotoDTO'; | ||||
| import {Dimension, IRenderable} from '../../model/IRenderable'; | ||||
| import {GalleryMapLightboxComponent} from './lightbox/lightbox.map.gallery.component'; | ||||
|  | ||||
| @Component({ | ||||
|   selector: 'gallery-map', | ||||
|   templateUrl: './map.gallery.component.html', | ||||
| @@ -14,7 +15,7 @@ export class GalleryMapComponent implements OnChanges, IRenderable { | ||||
|  | ||||
|   mapPhotos: Array<{ latitude: number, longitude: number }> = []; | ||||
|   mapCenter = {latitude: 0, longitude: 0}; | ||||
|   @ViewChild("map") map: ElementRef; | ||||
|   @ViewChild('map') map: ElementRef; | ||||
|  | ||||
|   //TODO: fix zooming | ||||
|   ngOnChanges() { | ||||
|   | ||||
| @@ -1,10 +1,10 @@ | ||||
| import {Component, Input, OnChanges} from "@angular/core"; | ||||
| import {DirectoryDTO} from "../../../../common/entities/DirectoryDTO"; | ||||
| import {RouterLink} from "@angular/router"; | ||||
| import {UserDTO} from "../../../../common/entities/UserDTO"; | ||||
| import {AuthenticationService} from "../../model/network/authentication.service"; | ||||
| import {ShareService} from "../share.service"; | ||||
| import {I18n} from "@ngx-translate/i18n-polyfill"; | ||||
| import {Component, Input, OnChanges} from '@angular/core'; | ||||
| import {DirectoryDTO} from '../../../../common/entities/DirectoryDTO'; | ||||
| import {RouterLink} from '@angular/router'; | ||||
| import {UserDTO} from '../../../../common/entities/UserDTO'; | ||||
| import {AuthenticationService} from '../../model/network/authentication.service'; | ||||
| import {ShareService} from '../share.service'; | ||||
| import {I18n} from '@ngx-translate/i18n-polyfill'; | ||||
|  | ||||
| @Component({ | ||||
|   selector: 'gallery-navbar', | ||||
| @@ -31,14 +31,14 @@ export class GalleryNavigatorComponent implements OnChanges { | ||||
|       return []; | ||||
|     } | ||||
|  | ||||
|     let path = this.directory.path.replace(new RegExp("\\\\", 'g'), "/"); | ||||
|     let path = this.directory.path.replace(new RegExp('\\\\', 'g'), '/'); | ||||
|  | ||||
|     let dirs = path.split("/"); | ||||
|     let dirs = path.split('/'); | ||||
|     dirs.push(this.directory.name); | ||||
|  | ||||
|     //removing empty strings | ||||
|     for (let i = 0; i < dirs.length; i++) { | ||||
|       if (!dirs[i] || 0 === dirs[i].length || "." === dirs[i]) { | ||||
|       if (!dirs[i] || 0 === dirs[i].length || '.' === dirs[i]) { | ||||
|         dirs.splice(i, 1); | ||||
|         i--; | ||||
|       } | ||||
| @@ -49,14 +49,14 @@ export class GalleryNavigatorComponent implements OnChanges { | ||||
|  | ||||
|     //create root link | ||||
|     if (dirs.length == 0) { | ||||
|       arr.push({name: this.i18n("Images"), route: null}); | ||||
|       arr.push({name: this.i18n('Images'), route: null}); | ||||
|     } else { | ||||
|       arr.push({name: this.i18n("Images"), route: UserDTO.isPathAvailable("/", user.permissions) ? "/" : null}); | ||||
|       arr.push({name: this.i18n('Images'), route: UserDTO.isPathAvailable('/', user.permissions) ? '/' : null}); | ||||
|     } | ||||
|  | ||||
|     //create rest navigation | ||||
|     dirs.forEach((name, index) => { | ||||
|       const route = dirs.slice(0, dirs.indexOf(name) + 1).join("/"); | ||||
|       const route = dirs.slice(0, dirs.indexOf(name) + 1).join('/'); | ||||
|       if (dirs.length - 1 == index) { | ||||
|         arr.push({name: name, route: null}); | ||||
|       } else { | ||||
|   | ||||
| @@ -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'; | ||||
|  | ||||
| @Injectable() | ||||
| export class OverlayService { | ||||
| @@ -24,20 +24,20 @@ export class OverlayService { | ||||
|     if (this.scrollWidth == null) { | ||||
|  | ||||
|  | ||||
|       let outer = document.createElement("div"); | ||||
|       outer.style.visibility = "hidden"; | ||||
|       outer.style.width = "100px"; | ||||
|       outer.style.msOverflowStyle = "scrollbar"; // needed for WinJS apps | ||||
|       let outer = document.createElement('div'); | ||||
|       outer.style.visibility = 'hidden'; | ||||
|       outer.style.width = '100px'; | ||||
|       outer.style.msOverflowStyle = 'scrollbar'; // needed for WinJS apps | ||||
|  | ||||
|       document.body.appendChild(outer); | ||||
|  | ||||
|       let widthNoScroll = outer.offsetWidth; | ||||
|       // force scrollbars | ||||
|       outer.style.overflowY = "scroll"; | ||||
|       outer.style.overflowY = 'scroll'; | ||||
|  | ||||
|       // add innerdiv | ||||
|       let inner = document.createElement("div"); | ||||
|       inner.style.width = "100%"; | ||||
|       let inner = document.createElement('div'); | ||||
|       inner.style.width = '100%'; | ||||
|       outer.appendChild(inner); | ||||
|  | ||||
|       let widthWithScroll = inner.offsetWidth; | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| import {Injectable} from "@angular/core"; | ||||
| import {NetworkService} from "../../model/network/network.service"; | ||||
| import {AutoCompleteItem} from "../../../../common/entities/AutoCompleteItem"; | ||||
| import {GalleryCacheService} from "../cache.gallery.service"; | ||||
| import {Injectable} from '@angular/core'; | ||||
| import {NetworkService} from '../../model/network/network.service'; | ||||
| import {AutoCompleteItem} from '../../../../common/entities/AutoCompleteItem'; | ||||
| import {GalleryCacheService} from '../cache.gallery.service'; | ||||
|  | ||||
| @Injectable() | ||||
| export class AutoCompleteService { | ||||
| @@ -14,7 +14,7 @@ export class AutoCompleteService { | ||||
|   public async autoComplete(text: string): Promise<Array<AutoCompleteItem>> { | ||||
|     let items: Array<AutoCompleteItem> = this.galleryCacheService.getAutoComplete(text); | ||||
|     if (items == null) { | ||||
|       items = await  this._networkService.getJson<Array<AutoCompleteItem>>("/autocomplete/" + text); | ||||
|       items = await  this._networkService.getJson<Array<AutoCompleteItem>>('/autocomplete/' + text); | ||||
|       this.galleryCacheService.setAutoComplete(text, items); | ||||
|     } | ||||
|     return items; | ||||
|   | ||||
| @@ -1,9 +1,9 @@ | ||||
| import {Component} from "@angular/core"; | ||||
| import {AutoCompleteService} from "./autocomplete.service"; | ||||
| import {AutoCompleteItem, SearchTypes} from "../../../../common/entities/AutoCompleteItem"; | ||||
| import {ActivatedRoute, Params, RouterLink} from "@angular/router"; | ||||
| import {GalleryService} from "../gallery.service"; | ||||
| import {Config} from "../../../../common/config/public/Config"; | ||||
| import {Component} from '@angular/core'; | ||||
| import {AutoCompleteService} from './autocomplete.service'; | ||||
| import {AutoCompleteItem, SearchTypes} from '../../../../common/entities/AutoCompleteItem'; | ||||
| import {ActivatedRoute, Params, RouterLink} from '@angular/router'; | ||||
| import {GalleryService} from '../gallery.service'; | ||||
| import {Config} from '../../../../common/config/public/Config'; | ||||
|  | ||||
| @Component({ | ||||
|   selector: 'gallery-search', | ||||
| @@ -14,10 +14,10 @@ import {Config} from "../../../../common/config/public/Config"; | ||||
| export class GallerySearchComponent { | ||||
|  | ||||
|   autoCompleteItems: Array<AutoCompleteRenderItem> = []; | ||||
|   public searchText: string = ""; | ||||
|   public searchText: string = ''; | ||||
|   private cache = { | ||||
|     lastAutocomplete: "", | ||||
|     lastInstantSearch: "" | ||||
|     lastAutocomplete: '', | ||||
|     lastInstantSearch: '' | ||||
|   }; | ||||
|  | ||||
|   SearchTypes: any = []; | ||||
| @@ -32,7 +32,7 @@ export class GallerySearchComponent { | ||||
|  | ||||
|     this.subscription = this._route.params.subscribe((params: Params) => { | ||||
|       let searchText = params['searchText']; | ||||
|       if (searchText && searchText != "") { | ||||
|       if (searchText && searchText != '') { | ||||
|         this.searchText = searchText; | ||||
|       } | ||||
|     }); | ||||
| @@ -41,7 +41,7 @@ export class GallerySearchComponent { | ||||
|  | ||||
|   ngOnDestroy() { | ||||
|     if (this.subscription !== null) { | ||||
|       this.subscription.unsubscribe() | ||||
|       this.subscription.unsubscribe(); | ||||
|     } | ||||
|   } | ||||
|  | ||||
| @@ -94,9 +94,9 @@ export class GallerySearchComponent { | ||||
|  | ||||
|   private async autocomplete(searchText: string) { | ||||
|     if (!Config.Client.Search.autocompleteEnabled) { | ||||
|       return | ||||
|       return; | ||||
|     } | ||||
|     if (searchText.trim() == ".") { | ||||
|     if (searchText.trim() == '.') { | ||||
|       return; | ||||
|     } | ||||
|  | ||||
| @@ -129,9 +129,9 @@ export class GallerySearchComponent { | ||||
| } | ||||
|  | ||||
| class AutoCompleteRenderItem { | ||||
|   public preText: string = ""; | ||||
|   public highLightText: string = ""; | ||||
|   public postText: string = ""; | ||||
|   public preText: string = ''; | ||||
|   public highLightText: string = ''; | ||||
|   public postText: string = ''; | ||||
|   public type: SearchTypes; | ||||
|  | ||||
|   constructor(public text: string, searchText: string, type: SearchTypes) { | ||||
|   | ||||
| @@ -1,8 +1,8 @@ | ||||
| import {Injectable} from "@angular/core"; | ||||
| import {NetworkService} from "../model/network/network.service"; | ||||
| import {CreateSharingDTO, SharingDTO} from "../../../common/entities/SharingDTO"; | ||||
| import {Router, RoutesRecognized} from "@angular/router"; | ||||
| import {BehaviorSubject} from "rxjs/BehaviorSubject"; | ||||
| import {Injectable} from '@angular/core'; | ||||
| import {NetworkService} from '../model/network/network.service'; | ||||
| import {CreateSharingDTO, SharingDTO} from '../../../common/entities/SharingDTO'; | ||||
| import {Router, RoutesRecognized} from '@angular/router'; | ||||
| import {BehaviorSubject} from 'rxjs/BehaviorSubject'; | ||||
|  | ||||
| @Injectable() | ||||
| export class ShareService { | ||||
| @@ -27,8 +27,8 @@ export class ShareService { | ||||
|  | ||||
|     this.router.events.subscribe(val => { | ||||
|       if (val instanceof RoutesRecognized) { | ||||
|         this.param = val.state.root.firstChild.params["sharingKey"] || null; | ||||
|         this.queryParam = val.state.root.firstChild.queryParams["sk"] || null; | ||||
|         this.param = val.state.root.firstChild.params['sharingKey'] || null; | ||||
|         this.queryParam = val.state.root.firstChild.queryParams['sk'] || null; | ||||
|         const changed = this.sharingKey != this.param || this.queryParam; | ||||
|         if (changed) { | ||||
|           this.sharingKey = this.param || this.queryParam; | ||||
| @@ -50,7 +50,7 @@ export class ShareService { | ||||
|   } | ||||
|  | ||||
|   public createSharing(dir: string, includeSubfolders: boolean, valid: number): Promise<SharingDTO> { | ||||
|     return this._networkService.postJson("/share/" + dir, { | ||||
|     return this._networkService.postJson('/share/' + dir, { | ||||
|       createSharing: <CreateSharingDTO>{ | ||||
|         includeSubfolders: includeSubfolders, | ||||
|         valid: valid | ||||
| @@ -59,7 +59,7 @@ export class ShareService { | ||||
|   } | ||||
|  | ||||
|   public updateSharing(dir: string, sharingId: number, includeSubfolders: boolean, password: string, valid: number): Promise<SharingDTO> { | ||||
|     return this._networkService.putJson("/share/" + dir, { | ||||
|     return this._networkService.putJson('/share/' + dir, { | ||||
|       updateSharing: <CreateSharingDTO>{ | ||||
|         id: sharingId, | ||||
|         includeSubfolders: includeSubfolders, | ||||
| @@ -79,7 +79,7 @@ export class ShareService { | ||||
|   } | ||||
|  | ||||
|   public async getSharing(): Promise<SharingDTO> { | ||||
|     const sharing = await this._networkService.getJson<SharingDTO>("/share/" + this.getSharingKey()); | ||||
|     const sharing = await this._networkService.getJson<SharingDTO>('/share/' + this.getSharingKey()); | ||||
|     this.sharing.next(sharing); | ||||
|     return sharing; | ||||
|   } | ||||
|   | ||||
| @@ -1,14 +1,14 @@ | ||||
| import {Component, OnDestroy, OnInit, ViewChild} from "@angular/core"; | ||||
| import {Utils} from "../../../../common/Utils"; | ||||
| import {ShareService} from "../share.service"; | ||||
| import {GalleryService} from "../gallery.service"; | ||||
| import {ContentWrapper} from "../../../../common/entities/ConentWrapper"; | ||||
| import {SharingDTO} from "../../../../common/entities/SharingDTO"; | ||||
| import {ModalDirective} from "ngx-bootstrap/modal"; | ||||
| import {Config} from "../../../../common/config/public/Config"; | ||||
| import {NotificationService} from "../../model/notification.service"; | ||||
| import {DirectoryDTO} from "../../../../common/entities/DirectoryDTO"; | ||||
| import {I18n} from "@ngx-translate/i18n-polyfill"; | ||||
| import {Component, OnDestroy, OnInit, ViewChild} from '@angular/core'; | ||||
| import {Utils} from '../../../../common/Utils'; | ||||
| import {ShareService} from '../share.service'; | ||||
| import {GalleryService} from '../gallery.service'; | ||||
| import {ContentWrapper} from '../../../../common/entities/ConentWrapper'; | ||||
| import {SharingDTO} from '../../../../common/entities/SharingDTO'; | ||||
| import {ModalDirective} from 'ngx-bootstrap/modal'; | ||||
| import {Config} from '../../../../common/config/public/Config'; | ||||
| import {NotificationService} from '../../model/notification.service'; | ||||
| import {DirectoryDTO} from '../../../../common/entities/DirectoryDTO'; | ||||
| import {I18n} from '@ngx-translate/i18n-polyfill'; | ||||
|  | ||||
|  | ||||
| @Component({ | ||||
| @@ -20,7 +20,7 @@ export class GalleryShareComponent implements OnInit, OnDestroy { | ||||
|   @ViewChild('shareModal') public childModal: ModalDirective; | ||||
|  | ||||
|   enabled: boolean = true; | ||||
|   url: string = ""; | ||||
|   url: string = ''; | ||||
|  | ||||
|   input = { | ||||
|     includeSubfolders: true, | ||||
| @@ -28,9 +28,9 @@ export class GalleryShareComponent implements OnInit, OnDestroy { | ||||
|       amount: 30, | ||||
|       type: ValidityTypes.Days | ||||
|     }, | ||||
|     password: "" | ||||
|     password: '' | ||||
|   }; | ||||
|   currentDir: string = ""; | ||||
|   currentDir: string = ''; | ||||
|   sharing: SharingDTO = null; | ||||
|   contentSubscription = null; | ||||
|   passwordProtection = false; | ||||
| @@ -72,33 +72,33 @@ export class GalleryShareComponent implements OnInit, OnDestroy { | ||||
|       case ValidityTypes.Months: | ||||
|         return this.input.valid.amount * 1000 * 60 * 60 * 24 * 30; | ||||
|     } | ||||
|     throw new Error("unknown type: " + this.input.valid.type); | ||||
|     throw new Error('unknown type: ' + this.input.valid.type); | ||||
|   } | ||||
|  | ||||
|   async update() { | ||||
|     if (this.sharing == null) { | ||||
|       return; | ||||
|     } | ||||
|     this.url = "loading.."; | ||||
|     this.url = 'loading..'; | ||||
|     this.sharing = await this._sharingService.updateSharing(this.currentDir, this.sharing.id, this.input.includeSubfolders, this.input.password, this.calcValidity()); | ||||
|     this.url = Config.Client.publicUrl + "/share/" + this.sharing.sharingKey | ||||
|     this.url = Config.Client.publicUrl + '/share/' + this.sharing.sharingKey; | ||||
|   } | ||||
|  | ||||
|   async get() { | ||||
|     this.url = "loading.."; | ||||
|     this.url = 'loading..'; | ||||
|     this.sharing = await this._sharingService.createSharing(this.currentDir, this.input.includeSubfolders, this.calcValidity()); | ||||
|     this.url = Config.Client.publicUrl + "/share/" + this.sharing.sharingKey | ||||
|     this.url = Config.Client.publicUrl + '/share/' + this.sharing.sharingKey; | ||||
|   } | ||||
|  | ||||
|   async showModal() { | ||||
|     await this.get(); | ||||
|     this.input.password = ""; | ||||
|     this.input.password = ''; | ||||
|     this.childModal.show(); | ||||
|     document.body.style.paddingRight = "0px"; | ||||
|     document.body.style.paddingRight = '0px'; | ||||
|   } | ||||
|  | ||||
|   onCopy() { | ||||
|     this._notification.success(this.i18n("Url has been copied to clipboard")); | ||||
|     this._notification.success(this.i18n('Url has been copied to clipboard')); | ||||
|   } | ||||
|  | ||||
|   public hideModal() { | ||||
|   | ||||
| @@ -1,9 +1,9 @@ | ||||
| import {Injectable} from "@angular/core"; | ||||
| import {GalleryCacheService} from "./cache.gallery.service"; | ||||
| import {Photo} from "./Photo"; | ||||
| import {IconPhoto} from "./IconPhoto"; | ||||
| import {PhotoDTO} from "../../../common/entities/PhotoDTO"; | ||||
| import {Config} from "../../../common/config/public/Config"; | ||||
| import {Injectable} from '@angular/core'; | ||||
| import {GalleryCacheService} from './cache.gallery.service'; | ||||
| import {Photo} from './Photo'; | ||||
| import {IconPhoto} from './IconPhoto'; | ||||
| import {PhotoDTO} from '../../../common/entities/PhotoDTO'; | ||||
| import {Config} from '../../../common/config/public/Config'; | ||||
|  | ||||
| export enum ThumbnailLoadingPriority { | ||||
|   extraHigh = 4, high = 3, medium = 2, low = 1 | ||||
| @@ -23,7 +23,7 @@ export class ThumbnailLoaderService { | ||||
|  | ||||
|     let index = taskEntry.parentTask.taskEntities.indexOf(taskEntry); | ||||
|     if (index == -1) { | ||||
|       throw new Error("ThumbnailTaskEntity not exist on Task"); | ||||
|       throw new Error('ThumbnailTaskEntity not exist on Task'); | ||||
|     } | ||||
|     taskEntry.parentTask.taskEntities.splice(index, 1); | ||||
|  | ||||
| @@ -31,7 +31,7 @@ export class ThumbnailLoaderService { | ||||
|       && taskEntry.parentTask.inProgress == false) { | ||||
|       let i = this.que.indexOf(taskEntry.parentTask); | ||||
|       if (i == -1) { | ||||
|         throw new Error("ThumbnailTask not exist"); | ||||
|         throw new Error('ThumbnailTask not exist'); | ||||
|       } | ||||
|       this.que.splice(i, 1); | ||||
|     } | ||||
| @@ -136,7 +136,7 @@ export class ThumbnailLoaderService { | ||||
|     let i = this.que.indexOf(task); | ||||
|     if (i == -1) { | ||||
|       if (task.taskEntities.length !== 0) { | ||||
|         console.error("ThumbnailLoader: can't find poolTask to remove"); | ||||
|         console.error('ThumbnailLoader: can\'t find poolTask to remove'); | ||||
|       } | ||||
|       return; | ||||
|     } | ||||
|   | ||||
| @@ -1,12 +1,7 @@ | ||||
| import {Injectable} from "@angular/core"; | ||||
| import { | ||||
|   ThumbnailLoaderService, | ||||
|   ThumbnailLoadingListener, | ||||
|   ThumbnailLoadingPriority, | ||||
|   ThumbnailTaskEntity | ||||
| } from "./thumnailLoader.service"; | ||||
| import {Photo} from "./Photo"; | ||||
| import {IconPhoto} from "./IconPhoto"; | ||||
| import {Injectable} from '@angular/core'; | ||||
| import {ThumbnailLoaderService, ThumbnailLoadingListener, ThumbnailLoadingPriority, ThumbnailTaskEntity} from './thumnailLoader.service'; | ||||
| import {Photo} from './Photo'; | ||||
| import {IconPhoto} from './IconPhoto'; | ||||
|  | ||||
|  | ||||
| @Injectable() | ||||
| @@ -80,7 +75,7 @@ export class IconThumbnail extends ThumbnailBase { | ||||
|  | ||||
|   constructor(private photo: IconPhoto, thumbnailService: ThumbnailLoaderService) { | ||||
|     super(thumbnailService); | ||||
|     this.src = ""; | ||||
|     this.src = ''; | ||||
|     this.error = false; | ||||
|     if (this.photo.isIconAvailable()) { | ||||
|       this.src = this.photo.getIconPath(); | ||||
| @@ -166,28 +161,28 @@ export class Thumbnail extends ThumbnailBase { | ||||
|   public load() { | ||||
|     if (!this.photo.isThumbnailAvailable() && this.thumbnailTask == null) { | ||||
|       //    setTimeout(() => { | ||||
|         let listener: ThumbnailLoadingListener = { | ||||
|           onStartedLoading: () => { //onLoadStarted | ||||
|             this.loading = true; | ||||
|           }, | ||||
|           onLoad: () => {//onLoaded | ||||
|             this.src = this.photo.getThumbnailPath(); | ||||
|             if (this.onLoad) this.onLoad(); | ||||
|             this.available = true; | ||||
|             this.loading = false; | ||||
|             this.thumbnailTask = null; | ||||
|           }, | ||||
|           onError: (error) => {//onError | ||||
|             this.thumbnailTask = null; | ||||
|             this.loading = false; | ||||
|             this.error = true; | ||||
|           } | ||||
|         }; | ||||
|         if (this.photo.isReplacementThumbnailAvailable()) { | ||||
|           this.thumbnailTask = this.thumbnailService.loadImage(this.photo, ThumbnailLoadingPriority.medium, listener); | ||||
|         } else { | ||||
|           this.thumbnailTask = this.thumbnailService.loadImage(this.photo, ThumbnailLoadingPriority.high, listener); | ||||
|       let listener: ThumbnailLoadingListener = { | ||||
|         onStartedLoading: () => { //onLoadStarted | ||||
|           this.loading = true; | ||||
|         }, | ||||
|         onLoad: () => {//onLoaded | ||||
|           this.src = this.photo.getThumbnailPath(); | ||||
|           if (this.onLoad) this.onLoad(); | ||||
|           this.available = true; | ||||
|           this.loading = false; | ||||
|           this.thumbnailTask = null; | ||||
|         }, | ||||
|         onError: (error) => {//onError | ||||
|           this.thumbnailTask = null; | ||||
|           this.loading = false; | ||||
|           this.error = true; | ||||
|         } | ||||
|       }; | ||||
|       if (this.photo.isReplacementThumbnailAvailable()) { | ||||
|         this.thumbnailTask = this.thumbnailService.loadImage(this.photo, ThumbnailLoadingPriority.medium, listener); | ||||
|       } else { | ||||
|         this.thumbnailTask = this.thumbnailService.loadImage(this.photo, ThumbnailLoadingPriority.high, listener); | ||||
|       } | ||||
|       // }, 0); | ||||
|     } | ||||
|   } | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| import {Component, Input} from "@angular/core"; | ||||
| import {Config} from "../../../common/config/public/Config"; | ||||
| import {Cookie} from "ng2-cookies"; | ||||
| import {CookieNames} from "../../../common/CookieNames"; | ||||
| import {Component, Input} from '@angular/core'; | ||||
| import {Config} from '../../../common/config/public/Config'; | ||||
| import {Cookie} from 'ng2-cookies'; | ||||
| import {CookieNames} from '../../../common/CookieNames'; | ||||
|  | ||||
| @Component({ | ||||
|   selector: 'language', | ||||
|   | ||||
| @@ -1,9 +1,9 @@ | ||||
| import {Component, OnInit} from "@angular/core"; | ||||
| import {LoginCredential} from "../../../common/entities/LoginCredential"; | ||||
| import {AuthenticationService} from "../model/network/authentication.service"; | ||||
| import {ErrorCodes} from "../../../common/entities/Error"; | ||||
| import {Config} from "../../../common/config/public/Config"; | ||||
| import {NavigationService} from "../model/navigation.service"; | ||||
| import {Component, OnInit} from '@angular/core'; | ||||
| import {LoginCredential} from '../../../common/entities/LoginCredential'; | ||||
| import {AuthenticationService} from '../model/network/authentication.service'; | ||||
| import {ErrorCodes} from '../../../common/entities/Error'; | ||||
| import {Config} from '../../../common/config/public/Config'; | ||||
| import {NavigationService} from '../model/navigation.service'; | ||||
|  | ||||
| @Component({ | ||||
|   selector: 'login', | ||||
|   | ||||
| @@ -11,6 +11,6 @@ export interface Dimension { | ||||
|  | ||||
| export module Dimension { | ||||
|   export const toString = (dim: Dimension) => { | ||||
|     return {top: dim.top + "px", left: dim.left + "px", width: dim.width + "px", height: dim.height + "px"}; | ||||
|   } | ||||
|     return {top: dim.top + 'px', left: dim.left + 'px', width: dim.width + 'px', height: dim.height + 'px'}; | ||||
|   }; | ||||
| } | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| import {Injectable} from "@angular/core"; | ||||
| import {Injectable} from '@angular/core'; | ||||
|  | ||||
| import {Router} from "@angular/router"; | ||||
| import {ShareService} from "../gallery/share.service"; | ||||
| import {Router} from '@angular/router'; | ||||
| import {ShareService} from '../gallery/share.service'; | ||||
|  | ||||
| @Injectable() | ||||
| export class NavigationService { | ||||
| @@ -17,22 +17,22 @@ export class NavigationService { | ||||
|   } | ||||
|  | ||||
|   public async toLogin() { | ||||
|     console.log("toLogin"); | ||||
|     console.log('toLogin'); | ||||
|     await this._shareService.wait(); | ||||
|     if (this._shareService.isSharing()) { | ||||
|       return this._router.navigate(["shareLogin"], {queryParams: {sk: this._shareService.getSharingKey()}}); | ||||
|       return this._router.navigate(['shareLogin'], {queryParams: {sk: this._shareService.getSharingKey()}}); | ||||
|     } else { | ||||
|       return this._router.navigate(["login"]); | ||||
|       return this._router.navigate(['login']); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   public async toGallery() { | ||||
|     console.log("toGallery"); | ||||
|     console.log('toGallery'); | ||||
|     await this._shareService.wait(); | ||||
|     if (this._shareService.isSharing()) { | ||||
|       return this._router.navigate(["gallery", ""], {queryParams: {sk: this._shareService.getSharingKey()}}); | ||||
|       return this._router.navigate(['gallery', ''], {queryParams: {sk: this._shareService.getSharingKey()}}); | ||||
|     } else { | ||||
|       return this._router.navigate(["gallery", ""]); | ||||
|       return this._router.navigate(['gallery', '']); | ||||
|     } | ||||
|   } | ||||
| } | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user