improving tests

This commit is contained in:
Patrik J. Braun 2018-03-30 15:30:30 -04:00
parent 9412fcba4d
commit f8e4542c66
144 changed files with 2041 additions and 2001 deletions

View File

@ -1,3 +1,4 @@
dist: trusty
language: node_js language: node_js
node_js: node_js:
- '9' - '9'
@ -14,3 +15,9 @@ deploy:
cache: cache:
directories: directories:
- node_modules - 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 &

View File

@ -1,4 +1,4 @@
import * as winston from "winston"; import * as winston from 'winston';
declare module 'winston' { declare module 'winston' {
interface LoggerInstance { interface LoggerInstance {
@ -10,19 +10,19 @@ declare module 'winston' {
export const winstonSettings = { export const winstonSettings = {
transports: [ transports: [
new winston.transports.Console({ new winston.transports.Console({
level: process.env.NODE_ENV == "production" ? "info" : 'silly', level: process.env.NODE_ENV == 'production' ? 'info' : 'silly',
handleExceptions: true, handleExceptions: true,
json: false, json: false,
colorize: true, colorize: true,
timestamp: function () { timestamp: function () {
return (new Date()).toLocaleString(); return (new Date()).toLocaleString();
}, },
label: "innerLabel", label: 'innerLabel',
formatter: (options) => { formatter: (options) => {
// Return string will be passed to logger. // Return string will be passed to logger.
return options.timestamp() + '[' + winston['config']['colorize'](options.level, options.level.toUpperCase()) + '] ' + return options.timestamp() + '[' + winston['config']['colorize'](options.level, options.level.toUpperCase()) + '] ' +
(undefined !== options.message ? options.message : '') + (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 debugStdout: true
}) })

View File

@ -1,5 +1,5 @@
import * as path from "path"; import * as path from 'path';
import {Config} from "../common/config/private/Config"; import {Config} from '../common/config/private/Config';
class ProjectPathClass { class ProjectPathClass {
public Root: string; public Root: string;
@ -24,10 +24,10 @@ class ProjectPathClass {
} }
reset() { reset() {
this.Root = path.join(__dirname, "/../"); this.Root = path.join(__dirname, '/../');
this.ImageFolder = this.getAbsolutePath(Config.Server.imagesFolder); this.ImageFolder = this.getAbsolutePath(Config.Server.imagesFolder);
this.ThumbnailFolder = this.getAbsolutePath(Config.Server.thumbnail.folder); this.ThumbnailFolder = this.getAbsolutePath(Config.Server.thumbnail.folder);
this.FrontendFolder = path.join(this.Root, 'dist') this.FrontendFolder = path.join(this.Root, 'dist');
} }
} }

View File

@ -1,9 +1,9 @@
import * as cluster from "cluster"; import * as cluster from 'cluster';
if (cluster.isMaster) { if (cluster.isMaster) {
const Server = require("./server").Server; const Server = require('./server').Server;
new Server(); const srv = new Server();
} else { } else {
const Worker = require("./model/threading/Worker").Worker; const Worker = require('./model/threading/Worker').Worker;
Worker.process(); Worker.process();
} }

View File

@ -1,23 +1,18 @@
import {NextFunction, Request, Response} from "express"; import {NextFunction, Request, Response} from 'express';
import {ErrorCodes, ErrorDTO} from "../../common/entities/Error"; import {ErrorCodes, ErrorDTO} from '../../common/entities/Error';
import {ObjectManagerRepository} from "../model/ObjectManagerRepository"; import {ObjectManagerRepository} from '../model/ObjectManagerRepository';
import {Logger} from "../Logger"; import {Logger} from '../Logger';
import {SQLConnection} from "../model/sql/SQLConnection"; import {SQLConnection} from '../model/sql/SQLConnection';
import { import {DataBaseConfig, DatabaseType, IndexingConfig, ThumbnailConfig} from '../../common/config/private/IPrivateConfig';
DataBaseConfig, import {Config} from '../../common/config/private/Config';
DatabaseType, import {ConfigDiagnostics} from '../model/ConfigDiagnostics';
IndexingConfig, import {ClientConfig} from '../../common/config/public/ConfigClass';
ThumbnailConfig import {BasicConfigDTO} from '../../common/entities/settings/BasicConfigDTO';
} from "../../common/config/private/IPrivateConfig"; import {OtherConfigDTO} from '../../common/entities/settings/OtherConfigDTO';
import {Config} from "../../common/config/private/Config"; import {ProjectPath} from '../ProjectPath';
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 { export class AdminMWs {
@ -25,30 +20,30 @@ export class AdminMWs {
public static async updateDatabaseSettings(req: Request, res: Response, next: NextFunction) { public static async updateDatabaseSettings(req: Request, res: Response, next: NextFunction) {
if ((typeof req.body === 'undefined') || (typeof req.body.settings === 'undefined')) { 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; const databaseSettings = <DataBaseConfig>req.body.settings;
try { try {
if (databaseSettings.type != DatabaseType.memory) { if (databaseSettings.type !== DatabaseType.memory) {
await SQLConnection.tryConnection(databaseSettings); await SQLConnection.tryConnection(databaseSettings);
} }
Config.Server.database = 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(); const original = Config.original();
original.Server.database = databaseSettings; original.Server.database = databaseSettings;
if (databaseSettings.type == DatabaseType.memory) { if (databaseSettings.type === DatabaseType.memory) {
original.Client.Sharing.enabled = false; original.Client.Sharing.enabled = false;
original.Client.Search.enabled = false; original.Client.Search.enabled = false;
} }
original.save(); original.save();
await ConfigDiagnostics.runDiagnostics(); await ConfigDiagnostics.runDiagnostics();
Logger.info(LOG_TAG, "new config:"); Logger.info(LOG_TAG, 'new config:');
Logger.info(LOG_TAG, JSON.stringify(Config, null, '\t')); Logger.info(LOG_TAG, JSON.stringify(Config, null, '\t'));
ObjectManagerRepository.reset(); ObjectManagerRepository.reset();
if (Config.Server.database.type != DatabaseType.memory) { if (Config.Server.database.type !== DatabaseType.memory) {
await ObjectManagerRepository.InitSQLManagers(); await ObjectManagerRepository.InitSQLManagers();
} else { } else {
await ObjectManagerRepository.InitMemoryManagers(); await ObjectManagerRepository.InitMemoryManagers();
@ -57,41 +52,41 @@ export class AdminMWs {
return next(); return next();
} catch (err) { } catch (err) {
if (err instanceof Error) { 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) { public static async updateMapSettings(req: Request, res: Response, next: NextFunction) {
if ((typeof req.body === 'undefined') || (typeof req.body.settings === 'undefined')) { 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 { try {
await ConfigDiagnostics.testMapConfig(<ClientConfig.MapConfig>req.body.settings); await ConfigDiagnostics.testMapConfig(<ClientConfig.MapConfig>req.body.settings);
Config.Client.Map = <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(); const original = Config.original();
original.Client.Map = <ClientConfig.MapConfig>req.body.settings; original.Client.Map = <ClientConfig.MapConfig>req.body.settings;
original.save(); original.save();
await ConfigDiagnostics.runDiagnostics(); await ConfigDiagnostics.runDiagnostics();
Logger.info(LOG_TAG, "new config:"); Logger.info(LOG_TAG, 'new config:');
Logger.info(LOG_TAG, JSON.stringify(Config, null, '\t')); Logger.info(LOG_TAG, JSON.stringify(Config, null, '\t'));
return next(); return next();
} catch (err) { } 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) { public static async updateShareSettings(req: Request, res: Response, next: NextFunction) {
if ((typeof req.body === 'undefined') || (typeof req.body.settings === 'undefined')) { 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 { 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(); const original = Config.original();
await ConfigDiagnostics.testSharingConfig(<ClientConfig.SharingConfig>req.body.settings, 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.Client.Sharing = <ClientConfig.SharingConfig>req.body.settings;
original.save(); original.save();
await ConfigDiagnostics.runDiagnostics(); await ConfigDiagnostics.runDiagnostics();
Logger.info(LOG_TAG, "new config:"); Logger.info(LOG_TAG, 'new config:');
Logger.info(LOG_TAG, JSON.stringify(Config, null, '\t')); Logger.info(LOG_TAG, JSON.stringify(Config, null, '\t'));
return next(); return next();
} catch (err) { } 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) { public static async updateSearchSettings(req: Request, res: Response, next: NextFunction) {
if ((typeof req.body === 'undefined') || (typeof req.body.settings === 'undefined')) { 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 { 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(); const original = Config.original();
await ConfigDiagnostics.testSearchConfig(<ClientConfig.SearchConfig>req.body.settings, 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.Client.Search = <ClientConfig.SearchConfig>req.body.settings;
original.save(); original.save();
await ConfigDiagnostics.runDiagnostics(); await ConfigDiagnostics.runDiagnostics();
Logger.info(LOG_TAG, "new config:"); Logger.info(LOG_TAG, 'new config:');
Logger.info(LOG_TAG, JSON.stringify(Config, null, '\t')); Logger.info(LOG_TAG, JSON.stringify(Config, null, '\t'));
return next(); return next();
} catch (err) { } 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) { public static async updateAuthenticationSettings(req: Request, res: Response, next: NextFunction) {
if ((typeof req.body === 'undefined') || (typeof req.body.settings === 'undefined')) { 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 { try {
Config.Client.authenticationRequired = <boolean>req.body.settings; 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(); const original = Config.original();
original.Client.authenticationRequired = <boolean>req.body.settings; original.Client.authenticationRequired = <boolean>req.body.settings;
original.save(); original.save();
await ConfigDiagnostics.runDiagnostics(); await ConfigDiagnostics.runDiagnostics();
Logger.info(LOG_TAG, "new config:"); Logger.info(LOG_TAG, 'new config:');
Logger.info(LOG_TAG, JSON.stringify(Config, null, '\t')); Logger.info(LOG_TAG, JSON.stringify(Config, null, '\t'));
return next(); return next();
} catch (err) { } 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) { public static async updateThumbnailSettings(req: Request, res: Response, next: NextFunction) {
if ((typeof req.body === 'undefined') || (typeof req.body.settings === 'undefined')) { 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 { try {
@ -166,28 +161,28 @@ export class AdminMWs {
await ConfigDiagnostics.testClientThumbnailConfig(settings.client); await ConfigDiagnostics.testClientThumbnailConfig(settings.client);
Config.Server.thumbnail = settings.server; Config.Server.thumbnail = settings.server;
Config.Client.Thumbnail = settings.client; 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(); const original = Config.original();
original.Server.thumbnail = settings.server; original.Server.thumbnail = settings.server;
original.Client.Thumbnail = settings.client; original.Client.Thumbnail = settings.client;
original.save(); original.save();
ProjectPath.reset(); ProjectPath.reset();
await ConfigDiagnostics.runDiagnostics(); await ConfigDiagnostics.runDiagnostics();
Logger.info(LOG_TAG, "new config:"); Logger.info(LOG_TAG, 'new config:');
Logger.info(LOG_TAG, JSON.stringify(Config, null, '\t')); Logger.info(LOG_TAG, JSON.stringify(Config, null, '\t'));
return next(); return next();
} catch (err) { } catch (err) {
if (err instanceof Error) { 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) { public static async updateBasicSettings(req: Request, res: Response, next: NextFunction) {
if ((typeof req.body === 'undefined') || (typeof req.body.settings === 'undefined')) { 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 { try {
@ -197,7 +192,7 @@ export class AdminMWs {
Config.Server.imagesFolder = settings.imagesFolder; Config.Server.imagesFolder = settings.imagesFolder;
Config.Client.publicUrl = settings.publicUrl; Config.Client.publicUrl = settings.publicUrl;
Config.Client.applicationTitle = settings.applicationTitle; 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(); const original = Config.original();
original.Server.port = settings.port; original.Server.port = settings.port;
original.Server.imagesFolder = settings.imagesFolder; original.Server.imagesFolder = settings.imagesFolder;
@ -206,18 +201,18 @@ export class AdminMWs {
original.save(); original.save();
ProjectPath.reset(); ProjectPath.reset();
await ConfigDiagnostics.runDiagnostics(); await ConfigDiagnostics.runDiagnostics();
Logger.info(LOG_TAG, "new config:"); Logger.info(LOG_TAG, 'new config:');
Logger.info(LOG_TAG, JSON.stringify(Config, null, '\t')); Logger.info(LOG_TAG, JSON.stringify(Config, null, '\t'));
return next(); return next();
} catch (err) { } 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) { public static async updateOtherSettings(req: Request, res: Response, next: NextFunction) {
if ((typeof req.body === 'undefined') || (typeof req.body.settings === 'undefined')) { 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 { try {
@ -226,7 +221,7 @@ export class AdminMWs {
Config.Client.enableOnScrollRendering = settings.enableOnScrollRendering; Config.Client.enableOnScrollRendering = settings.enableOnScrollRendering;
Config.Client.enableOnScrollThumbnailPrioritising = settings.enableOnScrollThumbnailPrioritising; 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(); const original = Config.original();
original.Client.enableCache = settings.enableCache; original.Client.enableCache = settings.enableCache;
original.Client.enableOnScrollRendering = settings.enableOnScrollRendering; original.Client.enableOnScrollRendering = settings.enableOnScrollRendering;
@ -234,33 +229,33 @@ export class AdminMWs {
original.Server.enableThreading = settings.enableThreading; original.Server.enableThreading = settings.enableThreading;
original.save(); original.save();
await ConfigDiagnostics.runDiagnostics(); await ConfigDiagnostics.runDiagnostics();
Logger.info(LOG_TAG, "new config:"); Logger.info(LOG_TAG, 'new config:');
Logger.info(LOG_TAG, JSON.stringify(Config, null, '\t')); Logger.info(LOG_TAG, JSON.stringify(Config, null, '\t'));
return next(); return next();
} catch (err) { } 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) { public static async updateIndexingSettings(req: Request, res: Response, next: NextFunction) {
if ((typeof req.body === 'undefined') || (typeof req.body.settings === 'undefined')) { 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 { try {
const settings: IndexingConfig = req.body.settings; const settings: IndexingConfig = req.body.settings;
Config.Server.indexing = 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(); const original = Config.original();
original.Server.indexing = settings; original.Server.indexing = settings;
original.save(); original.save();
await ConfigDiagnostics.runDiagnostics(); await ConfigDiagnostics.runDiagnostics();
Logger.info(LOG_TAG, "new config:"); Logger.info(LOG_TAG, 'new config:');
Logger.info(LOG_TAG, JSON.stringify(Config, null, '\t')); Logger.info(LOG_TAG, JSON.stringify(Config, null, '\t'));
return next(); return next();
} catch (err) { } 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) { public static startIndexing(req: Request, res: Response, next: NextFunction) {
try { try {
ObjectManagerRepository.getInstance().IndexingManager.startIndexing(); ObjectManagerRepository.getInstance().IndexingManager.startIndexing();
req.resultPipe = "ok"; req.resultPipe = 'ok';
return next(); return next();
} catch (err) { } 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(); req.resultPipe = ObjectManagerRepository.getInstance().IndexingManager.getProgress();
return next(); return next();
} catch (err) { } 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) { public static cancelIndexing(req: Request, res: Response, next: NextFunction) {
try { try {
ObjectManagerRepository.getInstance().IndexingManager.cancelIndexing(); ObjectManagerRepository.getInstance().IndexingManager.cancelIndexing();
req.resultPipe = "ok"; req.resultPipe = 'ok';
return next(); return next();
} catch (err) { } 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) { public static async resetIndexes(req: Request, res: Response, next: NextFunction) {
try { try {
await ObjectManagerRepository.getInstance().IndexingManager.reset(); await ObjectManagerRepository.getInstance().IndexingManager.reset();
req.resultPipe = "ok"; req.resultPipe = 'ok';
return next(); return next();
} catch (err) { } 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));
} }
} }
} }

View File

@ -1,29 +1,29 @@
import * as path from "path"; import * as path from 'path';
import * as fs from "fs"; import * as fs from 'fs';
import {NextFunction, Request, Response} from "express"; import {NextFunction, Request, Response} from 'express';
import {ErrorCodes, ErrorDTO} from "../../common/entities/Error"; import {ErrorCodes, ErrorDTO} from '../../common/entities/Error';
import {DirectoryDTO} from "../../common/entities/DirectoryDTO"; import {DirectoryDTO} from '../../common/entities/DirectoryDTO';
import {ObjectManagerRepository} from "../model/ObjectManagerRepository"; import {ObjectManagerRepository} from '../model/ObjectManagerRepository';
import {SearchTypes} from "../../common/entities/AutoCompleteItem"; import {SearchTypes} from '../../common/entities/AutoCompleteItem';
import {ContentWrapper} from "../../common/entities/ConentWrapper"; import {ContentWrapper} from '../../common/entities/ConentWrapper';
import {PhotoDTO} from "../../common/entities/PhotoDTO"; import {PhotoDTO} from '../../common/entities/PhotoDTO';
import {ProjectPath} from "../ProjectPath"; import {ProjectPath} from '../ProjectPath';
import {Config} from "../../common/config/private/Config"; import {Config} from '../../common/config/private/Config';
import {UserDTO} from "../../common/entities/UserDTO"; import {UserDTO} from '../../common/entities/UserDTO';
const LOG_TAG = "[GalleryMWs]"; const LOG_TAG = '[GalleryMWs]';
export class GalleryMWs { export class GalleryMWs {
public static async listDirectory(req: Request, res: Response, next: NextFunction) { public static async listDirectory(req: Request, res: Response, next: NextFunction) {
console.log("listDirectory"); console.log('listDirectory');
let directoryName = req.params.directory || "/"; let directoryName = req.params.directory || '/';
let absoluteDirectoryName = path.join(ProjectPath.ImageFolder, directoryName); let absoluteDirectoryName = path.join(ProjectPath.ImageFolder, directoryName);
if (!fs.statSync(absoluteDirectoryName).isDirectory()) { if (!fs.statSync(absoluteDirectoryName).isDirectory()) {
console.log("not dir"); console.log('not dir');
return next(); return next();
} }
@ -31,7 +31,7 @@ export class GalleryMWs {
const directory = await ObjectManagerRepository.getInstance().GalleryManager.listDirectory(directoryName, req.query.knownLastModified, req.query.knownLastScanned); const directory = await ObjectManagerRepository.getInstance().GalleryManager.listDirectory(directoryName, req.query.knownLastModified, req.query.knownLastScanned);
if (directory == null) { if (directory == null) {
console.log("null dir"); console.log('null dir');
req.resultPipe = new ContentWrapper(null, null, true); req.resultPipe = new ContentWrapper(null, null, true);
return next(); return next();
} }
@ -39,7 +39,7 @@ export class GalleryMWs {
console.log(directory); console.log(directory);
if (req.session.user.permissions && if (req.session.user.permissions &&
req.session.user.permissions.length > 0 && req.session.user.permissions.length > 0 &&
req.session.user.permissions[0] != "/*") { req.session.user.permissions[0] != '/*') {
(<DirectoryDTO>directory).directories = (<DirectoryDTO>directory).directories.filter(d => (<DirectoryDTO>directory).directories = (<DirectoryDTO>directory).directories.filter(d =>
UserDTO.isDirectoryAvailable(d, req.session.user.permissions)); UserDTO.isDirectoryAvailable(d, req.session.user.permissions));
} }
@ -47,7 +47,7 @@ export class GalleryMWs {
return next(); return next();
} catch (err) { } 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 //check if thumbnail already exist
if (fs.existsSync(fullImagePath) === false) { 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()) { if (fs.statSync(fullImagePath).isDirectory()) {
return next(); return next();
@ -122,7 +122,7 @@ export class GalleryMWs {
req.resultPipe = new ContentWrapper(null, result); req.resultPipe = new ContentWrapper(null, result);
return next(); return next();
} catch (err) { } 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); req.resultPipe = new ContentWrapper(null, result);
return next(); return next();
} catch (err) { } 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); req.resultPipe = await ObjectManagerRepository.getInstance().SearchManager.autocomplete(req.params.text);
return next(); return next();
} catch (err) { } catch (err) {
return next(new ErrorDTO(ErrorCodes.GENERAL_ERROR, "Error during searching", err)); return next(new ErrorDTO(ErrorCodes.GENERAL_ERROR, 'Error during searching', err));
} }
} }

View File

@ -1,8 +1,9 @@
import {NextFunction, Request, Response} from "express"; import {NextFunction, Request, Response} from 'express';
import {UserRoles} from "../../common/entities/UserDTO"; import {UserRoles} from '../../common/entities/UserDTO';
import {NotificationManager} from "../model/NotifocationManager"; import {NotificationManager} from '../model/NotifocationManager';
const LOG_TAG = '[NotificationMWs]';
const LOG_TAG = "[NotificationMWs]";
export class NotificationMWs { export class NotificationMWs {

View File

@ -1,18 +1,18 @@
import {NextFunction, Request, Response} from "express"; import {NextFunction, Request, Response} from 'express';
import {ErrorCodes, ErrorDTO} from "../../common/entities/Error"; import {ErrorCodes, ErrorDTO} from '../../common/entities/Error';
import {Utils} from "../../common/Utils"; import {Utils} from '../../common/Utils';
import {Message} from "../../common/entities/Message"; import {Message} from '../../common/entities/Message';
import {SharingDTO} from "../../common/entities/SharingDTO"; import {SharingDTO} from '../../common/entities/SharingDTO';
import {Config} from "../../common/config/private/Config"; import {Config} from '../../common/config/private/Config';
import {PrivateConfigClass} from "../../common/config/private/PrivateConfigClass"; import {PrivateConfigClass} from '../../common/config/private/PrivateConfigClass';
import {UserRoles} from "../../common/entities/UserDTO"; import {UserRoles} from '../../common/entities/UserDTO';
import {NotificationManager} from "../model/NotifocationManager"; import {NotificationManager} from '../model/NotifocationManager';
import {Logger} from "../Logger"; import {Logger} from '../Logger';
export class RenderingMWs { export class RenderingMWs {
public static renderResult(req: Request, res: Response, next: NextFunction) { public static renderResult(req: Request, res: Response, next: NextFunction) {
if (typeof req.resultPipe == "undefined") if (typeof req.resultPipe == 'undefined')
return next(); return next();
return RenderingMWs.renderMessage(res, req.resultPipe); return RenderingMWs.renderMessage(res, req.resultPipe);
@ -21,7 +21,7 @@ export class RenderingMWs {
public static renderSessionUser(req: Request, res: Response, next: NextFunction) { public static renderSessionUser(req: Request, res: Response, next: NextFunction) {
if (!(req.session.user)) { 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); const user = Utils.clone(req.session.user);
@ -46,7 +46,7 @@ export class RenderingMWs {
} }
public static renderOK(req: Request, res: Response, next: NextFunction) { 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); res.json(message);
} }
@ -62,7 +62,7 @@ export class RenderingMWs {
if (err instanceof ErrorDTO) { if (err instanceof ErrorDTO) {
if (err.details) { if (err.details) {
if (!(req.session.user && req.session.user.role >= UserRoles.Developer)) { if (!(req.session.user && req.session.user.role >= UserRoles.Developer)) {
Logger.warn("Handled error:", err); Logger.warn('Handled error:', err);
delete (err.details); delete (err.details);
} else { } else {
try { try {
@ -75,7 +75,7 @@ export class RenderingMWs {
let message = new Message<any>(err, null); let message = new Message<any>(err, null);
return res.json(message); return res.json(message);
} }
NotificationManager.error("unknown server error", err); NotificationManager.error('unknown server error', err);
return next(err); return next(err);
} }

View File

@ -1,9 +1,10 @@
import {NextFunction, Request, Response} from "express"; import {NextFunction, Request, Response} from 'express';
import {CreateSharingDTO, SharingDTO} from "../../common/entities/SharingDTO"; import {CreateSharingDTO, SharingDTO} from '../../common/entities/SharingDTO';
import {ObjectManagerRepository} from "../model/ObjectManagerRepository"; import {ObjectManagerRepository} from '../model/ObjectManagerRepository';
import {ErrorCodes, ErrorDTO} from "../../common/entities/Error"; import {ErrorCodes, ErrorDTO} from '../../common/entities/Error';
const LOG_TAG = '[SharingMWs]';
const LOG_TAG = "[SharingMWs]";
export class SharingMWs { export class SharingMWs {
@ -26,14 +27,14 @@ export class SharingMWs {
return next(); return next();
} catch (err) { } 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) { public static async createSharing(req: Request, res: Response, next: NextFunction) {
if ((typeof req.body === 'undefined') || (typeof req.body.createSharing === 'undefined')) { 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; const createSharing: CreateSharingDTO = req.body.createSharing;
let sharingKey = SharingMWs.generateKey(); let sharingKey = SharingMWs.generateKey();
@ -50,7 +51,7 @@ export class SharingMWs {
} }
const directoryName = req.params.directory || "/"; const directoryName = req.params.directory || '/';
let sharing: SharingDTO = { let sharing: SharingDTO = {
id: null, id: null,
sharingKey: sharingKey, sharingKey: sharingKey,
@ -68,20 +69,20 @@ export class SharingMWs {
return next(); return next();
} catch (err) { } 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) { public static async updateSharing(req: Request, res: Response, next: NextFunction) {
if ((typeof req.body === 'undefined') || (typeof req.body.updateSharing === 'undefined')) { 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 updateSharing: CreateSharingDTO = req.body.updateSharing;
const directoryName = req.params.directory || "/"; const directoryName = req.params.directory || '/';
let sharing: SharingDTO = { let sharing: SharingDTO = {
id: updateSharing.id, id: updateSharing.id,
path: directoryName, path: directoryName,
sharingKey: "", sharingKey: '',
password: updateSharing.password, password: updateSharing.password,
creator: req.session.user, creator: req.session.user,
expires: Date.now() + updateSharing.valid, expires: Date.now() + updateSharing.valid,
@ -93,7 +94,7 @@ export class SharingMWs {
req.resultPipe = await ObjectManagerRepository.getInstance().SharingManager.updateSharing(sharing); req.resultPipe = await ObjectManagerRepository.getInstance().SharingManager.updateSharing(sharing);
return next(); return next();
} catch (err) { } 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));
} }
} }

View File

@ -1,10 +1,10 @@
declare module "jimp" { declare module 'jimp' {
function read(filaname); function read(fileName);
var RESIZE_NEAREST_NEIGHBOR; const RESIZE_NEAREST_NEIGHBOR;
var RESIZE_BILINEAR; const RESIZE_BILINEAR;
var RESIZE_BICUBIC; const RESIZE_BICUBIC;
var RESIZE_HERMITE; const RESIZE_HERMITE;
var RESIZE_BEZIER; const RESIZE_BEZIER;
var AUTO: any; const AUTO: any;
} }

View File

@ -1,19 +1,19 @@
///<reference path="../customtypings/jimp.d.ts"/> ///<reference path="../customtypings/jimp.d.ts"/>
import * as path from "path"; import * as path from 'path';
import * as crypto from "crypto"; import * as crypto from 'crypto';
import * as fs from "fs"; import * as fs from 'fs';
import * as os from "os"; import * as os from 'os';
import {NextFunction, Request, Response} from "express"; import {NextFunction, Request, Response} from 'express';
import {ErrorCodes, ErrorDTO} from "../../../common/entities/Error"; import {ErrorCodes, ErrorDTO} from '../../../common/entities/Error';
import {ContentWrapper} from "../../../common/entities/ConentWrapper"; import {ContentWrapper} from '../../../common/entities/ConentWrapper';
import {DirectoryDTO} from "../../../common/entities/DirectoryDTO"; import {DirectoryDTO} from '../../../common/entities/DirectoryDTO';
import {ProjectPath} from "../../ProjectPath"; import {ProjectPath} from '../../ProjectPath';
import {PhotoDTO} from "../../../common/entities/PhotoDTO"; import {PhotoDTO} from '../../../common/entities/PhotoDTO';
import {Config} from "../../../common/config/private/Config"; import {Config} from '../../../common/config/private/Config';
import {ThumbnailProcessingLib} from "../../../common/config/private/IPrivateConfig"; import {ThumbnailProcessingLib} from '../../../common/config/private/IPrivateConfig';
import {ThumbnailTH} from "../../model/threading/ThreadPool"; import {ThumbnailTH} from '../../model/threading/ThreadPool';
import {RendererInput} from "../../model/threading/ThumbnailWoker"; import {RendererInput} from '../../model/threading/ThumbnailWoker';
import {ITaskQue, TaskQue} from "../../model/threading/TaskQue"; import {ITaskQue, TaskQue} from '../../model/threading/TaskQue';
export class ThumbnailGeneratorMWs { export class ThumbnailGeneratorMWs {
@ -21,20 +21,20 @@ export class ThumbnailGeneratorMWs {
private static taskQue: ITaskQue = null; private static taskQue: ITaskQue = null;
public static init() { public static init() {
if (this.initDone == true) { if (this.initDone === true) {
return return;
} }
if (Config.Server.enableThreading == true || if (Config.Server.enableThreading === true ||
Config.Server.thumbnail.processingLibrary != ThumbnailProcessingLib.Jimp) { Config.Server.thumbnail.processingLibrary !== ThumbnailProcessingLib.Jimp) {
Config.Client.concurrentThumbnailGenerations = Math.max(1, os.cpus().length - 1); Config.Client.concurrentThumbnailGenerations = Math.max(1, os.cpus().length - 1);
} else { } else {
Config.Client.concurrentThumbnailGenerations = 1; Config.Client.concurrentThumbnailGenerations = 1;
} }
if (Config.Server.enableThreading == true && if (Config.Server.enableThreading === true &&
Config.Server.thumbnail.processingLibrary == ThumbnailProcessingLib.Jimp) { Config.Server.thumbnail.processingLibrary === ThumbnailProcessingLib.Jimp) {
this.taskQue = new ThumbnailTH(Config.Client.concurrentThumbnailGenerations); this.taskQue = new ThumbnailTH(Config.Client.concurrentThumbnailGenerations);
} else { } else {
this.taskQue = new TaskQue(Config.Client.concurrentThumbnailGenerations); this.taskQue = new TaskQue(Config.Client.concurrentThumbnailGenerations);
@ -43,49 +43,13 @@ export class ThumbnailGeneratorMWs {
this.initDone = true; 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) { public static addThumbnailInformation(req: Request, res: Response, next: NextFunction) {
if (!req.resultPipe) if (!req.resultPipe) {
return next(); return next();
}
let cw: ContentWrapper = req.resultPipe; const cw: ContentWrapper = req.resultPipe;
if (cw.notModified == true) { if (cw.notModified === true) {
return next(); return next();
} }
if (cw.directory) { if (cw.directory) {
@ -101,14 +65,15 @@ export class ThumbnailGeneratorMWs {
} }
public static generateThumbnail(req: Request, res: Response, next: NextFunction) { public static generateThumbnail(req: Request, res: Response, next: NextFunction) {
if (!req.resultPipe) if (!req.resultPipe) {
return next(); return next();
}
//load parameters // load parameters
let imagePath = req.resultPipe; const imagePath = req.resultPipe;
let size: number = parseInt(req.params.size) || Config.Client.Thumbnail.thumbnailSizes[0]; 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) { if (Config.Client.Thumbnail.thumbnailSizes.indexOf(size) === -1) {
size = Config.Client.Thumbnail.thumbnailSizes[0]; size = Config.Client.Thumbnail.thumbnailSizes[0];
} }
@ -119,37 +84,74 @@ export class ThumbnailGeneratorMWs {
} }
public static generateIcon(req: Request, res: Response, next: NextFunction) { public static generateIcon(req: Request, res: Response, next: NextFunction) {
if (!req.resultPipe) if (!req.resultPipe) {
return next(); return next();
}
//load parameters // load parameters
let imagePath = req.resultPipe; const imagePath = req.resultPipe;
let size: number = Config.Client.Thumbnail.iconSize; const size: number = Config.Client.Thumbnail.iconSize;
ThumbnailGeneratorMWs.generateImage(imagePath, size, true, req, res, next); 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) { private static async generateImage(imagePath: string, size: number, makeSquare: boolean, req: Request, res: Response, next: NextFunction) {
//generate thumbnail path // generate thumbnail path
let thPath = path.join(ProjectPath.ThumbnailFolder, ThumbnailGeneratorMWs.generateThumbnailName(imagePath, size)); const thPath = path.join(ProjectPath.ThumbnailFolder, ThumbnailGeneratorMWs.generateThumbnailName(imagePath, size));
req.resultPipe = thPath; req.resultPipe = thPath;
//check if thumbnail already exist // check if thumbnail already exist
if (fs.existsSync(thPath) === true) { if (fs.existsSync(thPath) === true) {
return next(); return next();
} }
//create thumbnail folder if not exist // create thumbnail folder if not exist
if (!fs.existsSync(ProjectPath.ThumbnailFolder)) { if (!fs.existsSync(ProjectPath.ThumbnailFolder)) {
fs.mkdirSync(ProjectPath.ThumbnailFolder); fs.mkdirSync(ProjectPath.ThumbnailFolder);
} }
//run on other thread // run on other thread
let input = <RendererInput>{ const input = <RendererInput>{
imagePath: imagePath, imagePath: imagePath,
size: size, size: size,
thPath: thPath, thPath: thPath,
@ -160,12 +162,12 @@ export class ThumbnailGeneratorMWs {
await this.taskQue.execute(input); await this.taskQue.execute(input);
return next(); return next();
} catch (error) { } 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 { 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';
} }
} }

View File

@ -1,42 +1,17 @@
///<reference path="../customtypings/ExtendedRequest.d.ts"/> ///<reference path="../customtypings/ExtendedRequest.d.ts"/>
import {NextFunction, Request, Response} from "express"; import {NextFunction, Request, Response} from 'express';
import {ErrorCodes, ErrorDTO} from "../../../common/entities/Error"; import {ErrorCodes, ErrorDTO} from '../../../common/entities/Error';
import {UserDTO, UserRoles} from "../../../common/entities/UserDTO"; import {UserDTO, UserRoles} from '../../../common/entities/UserDTO';
import {ObjectManagerRepository} from "../../model/ObjectManagerRepository"; import {ObjectManagerRepository} from '../../model/ObjectManagerRepository';
import {Config} from "../../../common/config/private/Config"; import {Config} from '../../../common/config/private/Config';
import {PasswordHelper} from "../../model/PasswordHelper"; import {PasswordHelper} from '../../model/PasswordHelper';
import {Utils} from "../../../common/Utils"; import {Utils} from '../../../common/Utils';
export class AuthenticationMWs { 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) { public static async tryAuthenticate(req: Request, res: Response, next: NextFunction) {
if (Config.Client.authenticationRequired === false) { 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(); return next();
} }
try { try {
@ -55,7 +30,7 @@ export class AuthenticationMWs {
public static async authenticate(req: Request, res: Response, next: NextFunction) { public static async authenticate(req: Request, res: Response, next: NextFunction) {
if (Config.Client.authenticationRequired === false) { 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(); return next();
} }
try { try {
@ -78,6 +53,21 @@ export class AuthenticationMWs {
return next(); 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) { public static authorise(role: UserRoles) {
return (req: Request, res: Response, next: NextFunction) => { return (req: Request, res: Response, next: NextFunction) => {
if (req.session.user.role < role) { if (req.session.user.role < role) {
@ -87,19 +77,40 @@ export class AuthenticationMWs {
}; };
} }
public static authoriseDirectory(req: Request, res: Response, next: NextFunction) { public static async shareLogin(req: Request, res: Response, next: NextFunction) {
if (req.session.user.permissions == null ||
req.session.user.permissions.length == 0 || if (Config.Client.Sharing.enabled === false) {
req.session.user.permissions[0] == "/*") {
return next(); return next();
} }
//not enough parameter
const directoryName = req.params.directory || "/"; if ((!req.query.sk && !req.params.sharingKey)) {
if (UserDTO.isPathAvailable(directoryName, req.session.user.permissions) == true) { return next(new ErrorDTO(ErrorCodes.INPUT_ERROR, 'no sharing key provided'));
return next(); }
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) { public static inverseAuthenticate(req: Request, res: Response, next: NextFunction) {
@ -136,41 +147,28 @@ export class AuthenticationMWs {
} }
private static async getSharingUser(req: Request) {
public static async shareLogin(req: Request, res: Response, next: NextFunction) { if (Config.Client.Sharing.enabled === true &&
(!!req.query.sk || !!req.params.sharingKey)) {
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;
const sharing = await ObjectManagerRepository.getInstance().SharingManager.findOne({ const sharing = await ObjectManagerRepository.getInstance().SharingManager.findOne({
sharingKey: req.query.sk || req.params.sharingKey, sharingKey: req.query.sk || req.params.sharingKey,
}); });
if (!sharing || sharing.expires < Date.now() || if (!sharing || sharing.expires < Date.now()) {
(Config.Client.Sharing.passwordProtected === true return null;
&& sharing.password && !PasswordHelper.comparePassword(password, sharing.password))) { }
return next(new ErrorDTO(ErrorCodes.CREDENTIAL_NOT_FOUND));
if (Config.Client.Sharing.passwordProtected === true && sharing.password) {
return null;
} }
let path = sharing.path; let path = sharing.path;
if (sharing.includeSubfolders == true) { 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) { public static logout(req: Request, res: Response, next: NextFunction) {

View File

@ -1,8 +1,8 @@
import {NextFunction, Request, Response} from "express"; import {NextFunction, Request, Response} from 'express';
import {ErrorCodes, ErrorDTO} from "../../../common/entities/Error"; import {ErrorCodes, ErrorDTO} from '../../../common/entities/Error';
import {ObjectManagerRepository} from "../../model/ObjectManagerRepository"; import {ObjectManagerRepository} from '../../model/ObjectManagerRepository';
import {Utils} from "../../../common/Utils"; import {Utils} from '../../../common/Utils';
import {Config} from "../../../common/config/private/Config"; import {Config} from '../../../common/config/private/Config';
export class UserMWs { export class UserMWs {
@ -94,7 +94,7 @@ export class UserMWs {
let result = await ObjectManagerRepository.getInstance().UserManager.find({}); let result = await ObjectManagerRepository.getInstance().UserManager.find({});
result = Utils.clone(result); result = Utils.clone(result);
for (let i = 0; i < result.length; i++) { for (let i = 0; i < result.length; i++) {
result[i].password = ""; result[i].password = '';
} }
req.resultPipe = result; req.resultPipe = result;
next(); next();

View File

@ -1,7 +1,7 @@
import {NextFunction, Request, Response} from "express"; import {NextFunction, Request, Response} from 'express';
import {ErrorCodes, ErrorDTO} from "../../../common/entities/Error"; import {ErrorCodes, ErrorDTO} from '../../../common/entities/Error';
import {UserRoles} from "../../../common/entities/UserDTO"; import {UserRoles} from '../../../common/entities/UserDTO';
import {ObjectManagerRepository} from "../../model/ObjectManagerRepository"; import {ObjectManagerRepository} from '../../model/ObjectManagerRepository';
export class UserRequestConstrainsMWs { export class UserRequestConstrainsMWs {
@ -38,7 +38,7 @@ export class UserRequestConstrainsMWs {
return next(); return next();
} }
//TODO: fix it! // TODO: fix it!
try { try {
const result = await ObjectManagerRepository.getInstance().UserManager.find({minRole: UserRoles.Admin}); const result = await ObjectManagerRepository.getInstance().UserManager.find({minRole: UserRoles.Admin});
if (result.length <= 1) { if (result.length <= 1) {

View File

@ -1,19 +1,20 @@
import {Config} from "../../common/config/private/Config"; import {Config} from '../../common/config/private/Config';
import { import {
DataBaseConfig, DataBaseConfig,
DatabaseType, DatabaseType,
IPrivateConfig, IPrivateConfig,
ThumbnailConfig, ThumbnailConfig,
ThumbnailProcessingLib ThumbnailProcessingLib
} from "../../common/config/private/IPrivateConfig"; } from '../../common/config/private/IPrivateConfig';
import {Logger} from "../Logger"; import {Logger} from '../Logger';
import {NotificationManager} from "./NotifocationManager"; import {NotificationManager} from './NotifocationManager';
import {ProjectPath} from "../ProjectPath"; import {ProjectPath} from '../ProjectPath';
import {SQLConnection} from "./sql/SQLConnection"; import {SQLConnection} from './sql/SQLConnection';
import * as fs from "fs"; import * as fs from 'fs';
import {ClientConfig} from "../../common/config/public/ConfigClass"; import {ClientConfig} from '../../common/config/public/ConfigClass';
const LOG_TAG = '[ConfigDiagnostics]';
const LOG_TAG = "[ConfigDiagnostics]";
export class ConfigDiagnostics { export class ConfigDiagnostics {
static async testDatabase(databaseConfig: DataBaseConfig) { static async testDatabase(databaseConfig: DataBaseConfig) {
@ -26,13 +27,13 @@ export class ConfigDiagnostics {
static async testThumbnailLib(processingLibrary: ThumbnailProcessingLib) { static async testThumbnailLib(processingLibrary: ThumbnailProcessingLib) {
switch (processingLibrary) { switch (processingLibrary) {
case ThumbnailProcessingLib.sharp: case ThumbnailProcessingLib.sharp:
const sharp = require("sharp"); const sharp = require('sharp');
sharp(); sharp();
break; break;
case ThumbnailProcessingLib.gm: case ThumbnailProcessingLib.gm:
const gm = require("gm"); const gm = require('gm');
await new Promise((resolve, reject) => { 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) { if (err) {
return reject(err.toString()); return reject(err.toString());
} }
@ -47,7 +48,7 @@ export class ConfigDiagnostics {
await new Promise((resolve, reject) => { await new Promise((resolve, reject) => {
fs.access(folder, fs.constants.W_OK, (err) => { fs.access(folder, fs.constants.W_OK, (err) => {
if (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(); resolve();
@ -57,11 +58,11 @@ export class ConfigDiagnostics {
static async testImageFolder(folder: string) { static async testImageFolder(folder: string) {
await new Promise((resolve, reject) => { await new Promise((resolve, reject) => {
if (!fs.existsSync(folder)) { if (!fs.existsSync(folder)) {
reject("Images folder not exists: '" + folder + "'"); reject('Images folder not exists: \'' + folder + '\'');
} }
fs.access(folder, fs.constants.R_OK, (err) => { fs.access(folder, fs.constants.R_OK, (err) => {
if (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(); resolve();
@ -76,15 +77,15 @@ export class ConfigDiagnostics {
static async testClientThumbnailConfig(thumbnailConfig: ClientConfig.ThumbnailConfig) { static async testClientThumbnailConfig(thumbnailConfig: ClientConfig.ThumbnailConfig) {
if (isNaN(thumbnailConfig.iconSize) || thumbnailConfig.iconSize <= 0) { 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) { 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++) { for (let i = 0; i < thumbnailConfig.thumbnailSizes.length; i++) {
if (isNaN(thumbnailConfig.thumbnailSizes[i]) || thumbnailConfig.thumbnailSizes[i] <= 0) { 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) { static async testSearchConfig(search: ClientConfig.SearchConfig, config: IPrivateConfig) {
if (search.enabled == true && config.Server.database.type == DatabaseType.memory) { 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) { static async testSharingConfig(sharing: ClientConfig.SharingConfig, config: IPrivateConfig) {
if (sharing.enabled == true && config.Server.database.type == DatabaseType.memory) { 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) { static async testMapConfig(map: ClientConfig.MapConfig) {
if (map.enabled == true && (!map.googleApiKey || map.googleApiKey.length == 0)) { 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 { try {
await ConfigDiagnostics.testDatabase(Config.Server.database); await ConfigDiagnostics.testDatabase(Config.Server.database);
} catch (err) { } catch (err) {
Logger.warn(LOG_TAG, "[SQL error]", err); Logger.warn(LOG_TAG, '[SQL error]', err);
Logger.warn(LOG_TAG, "Error during initializing SQL falling back temporally to memory DB"); 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); NotificationManager.warning('Error during initializing SQL falling back temporally to memory DB', err);
Config.setDatabaseType(DatabaseType.memory); Config.setDatabaseType(DatabaseType.memory);
} }
} }
@ -127,60 +128,60 @@ export class ConfigDiagnostics {
try { try {
await ConfigDiagnostics.testThumbnailLib(Config.Server.thumbnail.processingLibrary); await ConfigDiagnostics.testThumbnailLib(Config.Server.thumbnail.processingLibrary);
} catch (err) { } catch (err) {
NotificationManager.warning("Thumbnail hardware acceleration is not possible." + NotificationManager.warning('Thumbnail hardware acceleration is not possible.' +
" '" + ThumbnailProcessingLib[Config.Server.thumbnail.processingLibrary] + "' node module is not found." + ' \'' + ThumbnailProcessingLib[Config.Server.thumbnail.processingLibrary] + '\' node module is not found.' +
" Falling back temporally to JS based thumbnail generation", err); ' 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] module error: ', err);
Logger.warn(LOG_TAG, "Thumbnail hardware acceleration is not possible." + Logger.warn(LOG_TAG, 'Thumbnail hardware acceleration is not possible.' +
" '" + ThumbnailProcessingLib[Config.Server.thumbnail.processingLibrary] + "' node module is not found." + ' \'' + ThumbnailProcessingLib[Config.Server.thumbnail.processingLibrary] + '\' node module is not found.' +
" Falling back temporally to JS based thumbnail generation"); ' Falling back temporally to JS based thumbnail generation');
Config.Server.thumbnail.processingLibrary = ThumbnailProcessingLib.Jimp; Config.Server.thumbnail.processingLibrary = ThumbnailProcessingLib.Jimp;
} }
} }
try { try {
await ConfigDiagnostics.testThumbnailFolder(Config.Server.thumbnail.folder) await ConfigDiagnostics.testThumbnailFolder(Config.Server.thumbnail.folder);
} catch (err) { } catch (err) {
NotificationManager.error("Thumbnail folder error", err); NotificationManager.error('Thumbnail folder error', err);
Logger.error(LOG_TAG, "Thumbnail folder error", err); Logger.error(LOG_TAG, 'Thumbnail folder error', err);
} }
try { try {
await ConfigDiagnostics.testImageFolder(Config.Server.imagesFolder) await ConfigDiagnostics.testImageFolder(Config.Server.imagesFolder);
} catch (err) { } catch (err) {
NotificationManager.error("Images folder error", err); NotificationManager.error('Images folder error', err);
Logger.error(LOG_TAG, "Images folder error", err); Logger.error(LOG_TAG, 'Images folder error', err);
} }
try { try {
await ConfigDiagnostics.testClientThumbnailConfig(Config.Client.Thumbnail) await ConfigDiagnostics.testClientThumbnailConfig(Config.Client.Thumbnail);
} catch (err) { } catch (err) {
NotificationManager.error("Thumbnail settings error", err); NotificationManager.error('Thumbnail settings error', err);
Logger.error(LOG_TAG, "Thumbnail settings error", err); Logger.error(LOG_TAG, 'Thumbnail settings error', err);
} }
try { try {
await ConfigDiagnostics.testSearchConfig(Config.Client.Search, Config); await ConfigDiagnostics.testSearchConfig(Config.Client.Search, Config);
} catch (err) { } catch (err) {
NotificationManager.warning("Search is not supported with these settings. Disabling temporally. Please adjust the config properly.", 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); Logger.warn(LOG_TAG, 'Search is not supported with these settings, switching off..', err);
Config.Client.Search.enabled = false; Config.Client.Search.enabled = false;
} }
try { try {
await ConfigDiagnostics.testSharingConfig(Config.Client.Sharing, Config); await ConfigDiagnostics.testSharingConfig(Config.Client.Sharing, Config);
} catch (err) { } catch (err) {
NotificationManager.warning("Sharing is not supported with these settings. Disabling temporally. Please adjust the config properly.", 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); Logger.warn(LOG_TAG, 'Sharing is not supported with these settings, switching off..', err);
Config.Client.Sharing.enabled = false; Config.Client.Sharing.enabled = false;
} }
try { try {
await ConfigDiagnostics.testMapConfig(Config.Client.Map); await ConfigDiagnostics.testMapConfig(Config.Client.Map);
} catch (err) { } catch (err) {
NotificationManager.warning("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); Logger.warn(LOG_TAG, 'Maps is not supported with these settings. Disabling temporally. Please adjust the config properly.', err);
Config.Client.Map.enabled = false; Config.Client.Map.enabled = false;
} }

View File

@ -1,12 +1,13 @@
///<reference path="exif.d.ts"/> ///<reference path="exif.d.ts"/>
import {DirectoryDTO} from "../../common/entities/DirectoryDTO"; import {DirectoryDTO} from '../../common/entities/DirectoryDTO';
import {Logger} from "../Logger"; import {Logger} from '../Logger';
import {Config} from "../../common/config/private/Config"; import {Config} from '../../common/config/private/Config';
import {DiskManagerTH} from "./threading/ThreadPool"; import {DiskManagerTH} from './threading/ThreadPool';
import {DiskMangerWorker} from "./threading/DiskMangerWorker"; import {DiskMangerWorker} from './threading/DiskMangerWorker';
const LOG_TAG = "[DiskManager]"; const LOG_TAG = '[DiskManager]';
export class DiskManager { export class DiskManager {
static threadPool: DiskManagerTH = null; static threadPool: DiskManagerTH = null;
@ -17,7 +18,7 @@ export class DiskManager {
} }
public static async scanDirectory(relativeDirectoryName: string): Promise<DirectoryDTO> { 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; let directory: DirectoryDTO = null;

View File

@ -1,7 +1,7 @@
import {ProjectPath} from "../ProjectPath"; import {ProjectPath} from '../ProjectPath';
import * as fs from "fs"; import * as fs from 'fs';
import * as path from "path"; import * as path from 'path';
import {Config} from "../../common/config/private/Config"; import {Config} from '../../common/config/private/Config';
export class Localizations { export class Localizations {
@ -12,7 +12,7 @@ export class Localizations {
const notLanguage = ['assets']; const notLanguage = ['assets'];
const dirCont = fs.readdirSync(ProjectPath.FrontendFolder).filter(f => fs.statSync(path.resolve(ProjectPath.FrontendFolder, f)).isDirectory()); 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 = dirCont.filter(d => notLanguage.indexOf(d) == -1);
Config.Client.languages.push("en"); Config.Client.languages.push('en');
} }
} }

View File

@ -1,11 +1,12 @@
import {NotificationDTO, NotificationType} from "../../common/entities/NotificationDTO"; import {NotificationDTO, NotificationType} from '../../common/entities/NotificationDTO';
export class NotificationManager { export class NotificationManager {
public static notifications: NotificationDTO[] = []; public static notifications: NotificationDTO[] = [];
public static HasNotification: NotificationDTO[] = public static HasNotification: NotificationDTO[] =
[ [
{ {
type: NotificationType.info, 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.'
} }
]; ];

View File

@ -1,10 +1,10 @@
import {IUserManager} from "./interfaces/IUserManager"; import {IUserManager} from './interfaces/IUserManager';
import {IGalleryManager} from "./interfaces/IGalleryManager"; import {IGalleryManager} from './interfaces/IGalleryManager';
import {ISearchManager} from "./interfaces/ISearchManager"; import {ISearchManager} from './interfaces/ISearchManager';
import {SQLConnection} from "./sql/SQLConnection"; import {SQLConnection} from './sql/SQLConnection';
import {ISharingManager} from "./interfaces/ISharingManager"; import {ISharingManager} from './interfaces/ISharingManager';
import {Logger} from "../Logger"; import {Logger} from '../Logger';
import {IIndexingManager} from "./interfaces/IIndexingManager"; import {IIndexingManager} from './interfaces/IIndexingManager';
export class ObjectManagerRepository { export class ObjectManagerRepository {
@ -70,11 +70,11 @@ export class ObjectManagerRepository {
public static async InitMemoryManagers() { public static async InitMemoryManagers() {
await ObjectManagerRepository.reset(); await ObjectManagerRepository.reset();
const GalleryManager = require("./memory/GalleryManager").GalleryManager; const GalleryManager = require('./memory/GalleryManager').GalleryManager;
const UserManager = require("./memory/UserManager").UserManager; const UserManager = require('./memory/UserManager').UserManager;
const SearchManager = require("./memory/SearchManager").SearchManager; const SearchManager = require('./memory/SearchManager').SearchManager;
const SharingManager = require("./memory/SharingManager").SharingManager; const SharingManager = require('./memory/SharingManager').SharingManager;
const IndexingManager = require("./memory/IndexingManager").IndexingManager; const IndexingManager = require('./memory/IndexingManager').IndexingManager;
ObjectManagerRepository.getInstance().GalleryManager = new GalleryManager(); ObjectManagerRepository.getInstance().GalleryManager = new GalleryManager();
ObjectManagerRepository.getInstance().UserManager = new UserManager(); ObjectManagerRepository.getInstance().UserManager = new UserManager();
ObjectManagerRepository.getInstance().SearchManager = new SearchManager(); ObjectManagerRepository.getInstance().SearchManager = new SearchManager();
@ -85,17 +85,17 @@ export class ObjectManagerRepository {
public static async InitSQLManagers() { public static async InitSQLManagers() {
await ObjectManagerRepository.reset(); await ObjectManagerRepository.reset();
await SQLConnection.init(); await SQLConnection.init();
const GalleryManager = require("./sql/GalleryManager").GalleryManager; const GalleryManager = require('./sql/GalleryManager').GalleryManager;
const UserManager = require("./sql/UserManager").UserManager; const UserManager = require('./sql/UserManager').UserManager;
const SearchManager = require("./sql/SearchManager").SearchManager; const SearchManager = require('./sql/SearchManager').SearchManager;
const SharingManager = require("./sql/SharingManager").SharingManager; const SharingManager = require('./sql/SharingManager').SharingManager;
const IndexingManager = require("./sql/IndexingManager").IndexingManager; const IndexingManager = require('./sql/IndexingManager').IndexingManager;
ObjectManagerRepository.getInstance().GalleryManager = new GalleryManager(); ObjectManagerRepository.getInstance().GalleryManager = new GalleryManager();
ObjectManagerRepository.getInstance().UserManager = new UserManager(); ObjectManagerRepository.getInstance().UserManager = new UserManager();
ObjectManagerRepository.getInstance().SearchManager = new SearchManager(); ObjectManagerRepository.getInstance().SearchManager = new SearchManager();
ObjectManagerRepository.getInstance().SharingManager = new SharingManager(); ObjectManagerRepository.getInstance().SharingManager = new SharingManager();
ObjectManagerRepository.getInstance().IndexingManager = new IndexingManager(); ObjectManagerRepository.getInstance().IndexingManager = new IndexingManager();
Logger.debug("SQL DB inited"); Logger.debug('SQL DB inited');
} }
} }

View File

@ -1,8 +1,8 @@
let bcrypt; let bcrypt;
try { try {
bcrypt = require("bcrypt"); bcrypt = require('bcrypt');
} catch (err) { } catch (err) {
bcrypt = require("bcryptjs"); bcrypt = require('bcryptjs');
} }
export class PasswordHelper { export class PasswordHelper {

View File

@ -1,26 +1,31 @@
declare module "node-iptc" { declare module 'node-iptc' {
function e(data): any; function e(data): any;
module e { module e {
} }
export = e; export = e;
} }
declare module "exif-parser" { declare module 'exif-parser' {
export interface ExifData { export interface ExifData {
tags: any; tags: any;
imageSize: any; imageSize: any;
} }
export interface ExifObject { export interface ExifObject {
enableTagNames(value: boolean); enableTagNames(value: boolean);
enableImageSize(value: boolean); enableImageSize(value: boolean);
enableReturnTags(value: boolean); enableReturnTags(value: boolean);
parse(): ExifData; parse(): ExifData;
} }
export function create(data: any): ExifObject; export function create(data: any): ExifObject;
} }

View File

@ -1,4 +1,4 @@
import {DirectoryDTO} from "../../../common/entities/DirectoryDTO"; import {DirectoryDTO} from '../../../common/entities/DirectoryDTO';
export interface IGalleryManager { export interface IGalleryManager {
listDirectory(relativeDirectoryName: string, listDirectory(relativeDirectoryName: string,

View File

@ -1,4 +1,4 @@
import {IndexingProgressDTO} from "../../../common/entities/settings/IndexingProgressDTO"; import {IndexingProgressDTO} from '../../../common/entities/settings/IndexingProgressDTO';
export interface IIndexingManager { export interface IIndexingManager {
startIndexing(): void; startIndexing(): void;
@ -7,5 +7,5 @@ export interface IIndexingManager {
cancelIndexing(): void; cancelIndexing(): void;
reset(): Promise<void> ; reset(): Promise<void>;
} }

View File

@ -1,8 +1,10 @@
import {AutoCompleteItem, SearchTypes} from "../../../common/entities/AutoCompleteItem"; import {AutoCompleteItem, SearchTypes} from '../../../common/entities/AutoCompleteItem';
import {SearchResultDTO} from "../../../common/entities/SearchResultDTO"; import {SearchResultDTO} from '../../../common/entities/SearchResultDTO';
export interface ISearchManager { export interface ISearchManager {
autocomplete(text: string): Promise<AutoCompleteItem[]>; autocomplete(text: string): Promise<AutoCompleteItem[]>;
search(text: string, searchType: SearchTypes): Promise<SearchResultDTO>; search(text: string, searchType: SearchTypes): Promise<SearchResultDTO>;
instantSearch(text: string): Promise<SearchResultDTO>; instantSearch(text: string): Promise<SearchResultDTO>;
} }

View File

@ -1,6 +1,9 @@
import {SharingDTO} from "../../../common/entities/SharingDTO"; import {SharingDTO} from '../../../common/entities/SharingDTO';
export interface ISharingManager { export interface ISharingManager {
findOne(filter: any): Promise<SharingDTO>; findOne(filter: any): Promise<SharingDTO>;
createSharing(sharing: SharingDTO): Promise<SharingDTO>; createSharing(sharing: SharingDTO): Promise<SharingDTO>;
updateSharing(sharing: SharingDTO): Promise<SharingDTO>; updateSharing(sharing: SharingDTO): Promise<SharingDTO>;
} }

View File

@ -1,9 +1,15 @@
import {UserDTO, UserRoles} from "../../../common/entities/UserDTO"; import {UserDTO, UserRoles} from '../../../common/entities/UserDTO';
export interface IUserManager { export interface IUserManager {
findOne(filter: any): Promise<UserDTO>; findOne(filter: any): Promise<UserDTO>;
find(filter: any): Promise<UserDTO[]>; find(filter: any): Promise<UserDTO[]>;
createUser(user: UserDTO): Promise<UserDTO>; createUser(user: UserDTO): Promise<UserDTO>;
deleteUser(id: number): Promise<UserDTO>; deleteUser(id: number): Promise<UserDTO>;
changeRole(id: number, newRole: UserRoles): Promise<UserDTO>; changeRole(id: number, newRole: UserRoles): Promise<UserDTO>;
changePassword(request: any): Promise<void>; changePassword(request: any): Promise<void>;
} }

View File

@ -1,11 +1,11 @@
import {DirectoryDTO} from "../../../common/entities/DirectoryDTO"; import {DirectoryDTO} from '../../../common/entities/DirectoryDTO';
import {IGalleryManager} from "../interfaces/IGalleryManager"; import {IGalleryManager} from '../interfaces/IGalleryManager';
import * as path from "path"; import * as path from 'path';
import * as fs from "fs"; import * as fs from 'fs';
import {DiskManager} from "../DiskManger"; import {DiskManager} from '../DiskManger';
import {ProjectPath} from "../../ProjectPath"; import {ProjectPath} from '../../ProjectPath';
import {Config} from "../../../common/config/private/Config"; import {Config} from '../../../common/config/private/Config';
import {ReIndexingSensitivity} from "../../../common/config/private/IPrivateConfig"; import {ReIndexingSensitivity} from '../../../common/config/private/IPrivateConfig';
export class GalleryManager implements IGalleryManager { export class GalleryManager implements IGalleryManager {

View File

@ -1,21 +1,21 @@
import {IIndexingManager} from "../interfaces/IIndexingManager"; import {IIndexingManager} from '../interfaces/IIndexingManager';
import {IndexingProgressDTO} from "../../../common/entities/settings/IndexingProgressDTO"; import {IndexingProgressDTO} from '../../../common/entities/settings/IndexingProgressDTO';
export class IndexingManager implements IIndexingManager { export class IndexingManager implements IIndexingManager {
startIndexing(): void { startIndexing(): void {
throw new Error("not supported by memory DB"); throw new Error('not supported by memory DB');
} }
getProgress(): IndexingProgressDTO { getProgress(): IndexingProgressDTO {
throw new Error("not supported by memory DB"); throw new Error('not supported by memory DB');
} }
cancelIndexing(): void { cancelIndexing(): void {
throw new Error("not supported by memory DB"); throw new Error('not supported by memory DB');
} }
reset(): Promise<void> { reset(): Promise<void> {
throw new Error("Method not implemented."); throw new Error('Method not implemented.');
} }
} }

View File

@ -1,18 +1,18 @@
import {AutoCompleteItem, SearchTypes} from "../../../common/entities/AutoCompleteItem"; import {AutoCompleteItem, SearchTypes} from '../../../common/entities/AutoCompleteItem';
import {ISearchManager} from "../interfaces/ISearchManager"; import {ISearchManager} from '../interfaces/ISearchManager';
import {SearchResultDTO} from "../../../common/entities/SearchResultDTO"; import {SearchResultDTO} from '../../../common/entities/SearchResultDTO';
export class SearchManager implements ISearchManager { export class SearchManager implements ISearchManager {
autocomplete(text: string): Promise<AutoCompleteItem[]> { autocomplete(text: string): Promise<AutoCompleteItem[]> {
throw new Error("Method not implemented."); throw new Error('Method not implemented.');
} }
search(text: string, searchType: SearchTypes): Promise<SearchResultDTO> { search(text: string, searchType: SearchTypes): Promise<SearchResultDTO> {
throw new Error("Method not implemented."); throw new Error('Method not implemented.');
} }
instantSearch(text: string): Promise<SearchResultDTO> { instantSearch(text: string): Promise<SearchResultDTO> {
throw new Error("Method not implemented."); throw new Error('Method not implemented.');
} }
} }

View File

@ -1,19 +1,19 @@
import {ISharingManager} from "../interfaces/ISharingManager"; import {ISharingManager} from '../interfaces/ISharingManager';
import {SharingDTO} from "../../../common/entities/SharingDTO"; import {SharingDTO} from '../../../common/entities/SharingDTO';
export class SharingManager implements ISharingManager { export class SharingManager implements ISharingManager {
findOne(filter: any): Promise<SharingDTO> { findOne(filter: any): Promise<SharingDTO> {
throw new Error("not implemented"); throw new Error('not implemented');
} }
createSharing(sharing: SharingDTO): Promise<SharingDTO> { createSharing(sharing: SharingDTO): Promise<SharingDTO> {
throw new Error("not implemented"); throw new Error('not implemented');
} }
updateSharing(sharing: SharingDTO): Promise<SharingDTO> { updateSharing(sharing: SharingDTO): Promise<SharingDTO> {
throw new Error("not implemented"); throw new Error('not implemented');
} }

View File

@ -1,10 +1,10 @@
import {UserDTO, UserRoles} from "../../../common/entities/UserDTO"; import {UserDTO, UserRoles} from '../../../common/entities/UserDTO';
import {IUserManager} from "../interfaces/IUserManager"; import {IUserManager} from '../interfaces/IUserManager';
import {ProjectPath} from "../../ProjectPath"; import {ProjectPath} from '../../ProjectPath';
import {Utils} from "../../../common/Utils"; import {Utils} from '../../../common/Utils';
import * as path from "path"; import * as path from 'path';
import * as fs from "fs"; import * as fs from 'fs';
import {PasswordHelper} from "../PasswordHelper"; import {PasswordHelper} from '../PasswordHelper';
export class UserManager implements IUserManager { export class UserManager implements IUserManager {
@ -28,14 +28,14 @@ export class UserManager implements IUserManager {
} }
if (!this.db.idCounter) { if (!this.db.idCounter) {
console.log("creating counter"); console.log('creating counter');
this.db.idCounter = 1; this.db.idCounter = 1;
} }
if (!this.db.users) { if (!this.db.users) {
this.db.users = []; this.db.users = [];
//TODO: remove defaults //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(); this.saveDB();
@ -46,7 +46,7 @@ export class UserManager implements IUserManager {
const result = await this.find(filter); const result = await this.find(filter);
if (result.length == 0) { if (result.length == 0) {
throw "UserDTO not found"; throw 'UserDTO not found';
} }
return result[0]; return result[0];
} }
@ -97,7 +97,7 @@ export class UserManager implements IUserManager {
} }
public async changePassword(request: any) { public async changePassword(request: any) {
throw new Error("not implemented"); //TODO: implement throw new Error('not implemented'); //TODO: implement
} }
private loadDB() { private loadDB() {

View File

@ -1,16 +1,16 @@
import {IGalleryManager} from "../interfaces/IGalleryManager"; import {IGalleryManager} from '../interfaces/IGalleryManager';
import {DirectoryDTO} from "../../../common/entities/DirectoryDTO"; import {DirectoryDTO} from '../../../common/entities/DirectoryDTO';
import * as path from "path"; import * as path from 'path';
import * as fs from "fs"; import * as fs from 'fs';
import {DirectoryEntity} from "./enitites/DirectoryEntity"; import {DirectoryEntity} from './enitites/DirectoryEntity';
import {SQLConnection} from "./SQLConnection"; import {SQLConnection} from './SQLConnection';
import {DiskManager} from "../DiskManger"; import {DiskManager} from '../DiskManger';
import {PhotoEntity} from "./enitites/PhotoEntity"; import {PhotoEntity} from './enitites/PhotoEntity';
import {Utils} from "../../../common/Utils"; import {Utils} from '../../../common/Utils';
import {ProjectPath} from "../../ProjectPath"; import {ProjectPath} from '../../ProjectPath';
import {Config} from "../../../common/config/private/Config"; import {Config} from '../../../common/config/private/Config';
import {ISQLGalleryManager} from "./IGalleryManager"; import {ISQLGalleryManager} from './IGalleryManager';
import {ReIndexingSensitivity} from "../../../common/config/private/IPrivateConfig"; import {ReIndexingSensitivity} from '../../../common/config/private/IPrivateConfig';
export class GalleryManager implements IGalleryManager, ISQLGalleryManager { export class GalleryManager implements IGalleryManager, ISQLGalleryManager {
@ -18,7 +18,7 @@ export class GalleryManager implements IGalleryManager, ISQLGalleryManager {
public async listDirectory(relativeDirectoryName: string, public async listDirectory(relativeDirectoryName: string,
knownLastModified?: number, knownLastModified?: number,
knownLastScanned?: number): Promise<DirectoryDTO> { 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 directoryName = path.basename(relativeDirectoryName);
const directoryParent = path.join(path.dirname(relativeDirectoryName), path.sep); const directoryParent = path.join(path.dirname(relativeDirectoryName), path.sep);
const connection = await SQLConnection.getConnection(); 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()); const lastModified = Math.max(stat.ctime.getTime(), stat.mtime.getTime());
let dir = await connection let dir = await connection
.getRepository(DirectoryEntity) .getRepository(DirectoryEntity)
.createQueryBuilder("directory") .createQueryBuilder('directory')
.where("directory.name = :name AND directory.path = :path", { .where('directory.name = :name AND directory.path = :path', {
name: directoryName, name: directoryName,
path: directoryParent path: directoryParent
}) })
.leftJoinAndSelect("directory.directories", "directories") .leftJoinAndSelect('directory.directories', 'directories')
.leftJoinAndSelect("directory.photos", "photos") .leftJoinAndSelect('directory.photos', 'photos')
.getOne(); .getOne();
@ -61,11 +61,11 @@ export class GalleryManager implements IGalleryManager, ISQLGalleryManager {
for (let i = 0; i < dir.directories.length; i++) { for (let i = 0; i < dir.directories.length; i++) {
dir.directories[i].photos = await connection dir.directories[i].photos = await connection
.getRepository(PhotoEntity) .getRepository(PhotoEntity)
.createQueryBuilder("photo") .createQueryBuilder('photo')
.where("photo.directory = :dir", { .where('photo.directory = :dir', {
dir: dir.directories[i].id dir: dir.directories[i].id
}) })
.orderBy("photo.metadata.creationDate", "ASC") .orderBy('photo.metadata.creationDate', 'ASC')
.limit(Config.Server.indexing.folderPreviewSize) .limit(Config.Server.indexing.folderPreviewSize)
.getMany(); .getMany();
dir.directories[i].isPartial = true; 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 //not indexed since a while, index it in a lazy manner
if ((Date.now() - dir.lastScanned > Config.Server.indexing.cachedFolderTimeout && 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) { Config.Server.indexing.reIndexingSensitivity >= ReIndexingSensitivity.high) {
//on the fly reindexing //on the fly reindexing
this.indexDirectory(relativeDirectoryName).catch((err) => { this.indexDirectory(relativeDirectoryName).catch((err) => {
@ -132,8 +132,8 @@ export class GalleryManager implements IGalleryManager, ISQLGalleryManager {
const photosRepository = connection.getRepository(PhotoEntity); const photosRepository = connection.getRepository(PhotoEntity);
let currentDir = await directoryRepository.createQueryBuilder("directory") let currentDir = await directoryRepository.createQueryBuilder('directory')
.where("directory.name = :name AND directory.path = :path", { .where('directory.name = :name AND directory.path = :path', {
name: scannedDirectory.name, name: scannedDirectory.name,
path: scannedDirectory.path path: scannedDirectory.path
}).getOne(); }).getOne();
@ -147,8 +147,8 @@ export class GalleryManager implements IGalleryManager, ISQLGalleryManager {
currentDir = await directoryRepository.save(<DirectoryEntity>scannedDirectory); currentDir = await directoryRepository.save(<DirectoryEntity>scannedDirectory);
} }
let childDirectories = await directoryRepository.createQueryBuilder("directory") let childDirectories = await directoryRepository.createQueryBuilder('directory')
.where("directory.parent = :dir", { .where('directory.parent = :dir', {
dir: currentDir.id dir: currentDir.id
}).getMany(); }).getMany();
@ -185,8 +185,8 @@ export class GalleryManager implements IGalleryManager, ISQLGalleryManager {
await directoryRepository.remove(childDirectories); await directoryRepository.remove(childDirectories);
let indexedPhotos = await photosRepository.createQueryBuilder("photo") let indexedPhotos = await photosRepository.createQueryBuilder('photo')
.where("photo.directory = :dir", { .where('photo.directory = :dir', {
dir: currentDir.id dir: currentDir.id
}).getMany(); }).getMany();

View File

@ -1,16 +1,16 @@
import "reflect-metadata"; import 'reflect-metadata';
import {Connection, ConnectionOptions, createConnection, getConnection} from "typeorm"; import {Connection, ConnectionOptions, createConnection, getConnection} from 'typeorm';
import {UserEntity} from "./enitites/UserEntity"; import {UserEntity} from './enitites/UserEntity';
import {UserRoles} from "../../../common/entities/UserDTO"; import {UserRoles} from '../../../common/entities/UserDTO';
import {PhotoEntity} from "./enitites/PhotoEntity"; import {PhotoEntity} from './enitites/PhotoEntity';
import {DirectoryEntity} from "./enitites/DirectoryEntity"; import {DirectoryEntity} from './enitites/DirectoryEntity';
import {Config} from "../../../common/config/private/Config"; import {Config} from '../../../common/config/private/Config';
import {SharingEntity} from "./enitites/SharingEntity"; import {SharingEntity} from './enitites/SharingEntity';
import {DataBaseConfig, DatabaseType} from "../../../common/config/private/IPrivateConfig"; import {DataBaseConfig, DatabaseType} from '../../../common/config/private/IPrivateConfig';
import {PasswordHelper} from "../PasswordHelper"; import {PasswordHelper} from '../PasswordHelper';
import {ProjectPath} from "../../ProjectPath"; import {ProjectPath} from '../../ProjectPath';
import {VersionEntity} from "./enitites/VersionEntity"; import {VersionEntity} from './enitites/VersionEntity';
import {Logger} from "../../Logger"; import {Logger} from '../../Logger';
export class SQLConnection { export class SQLConnection {
@ -27,7 +27,7 @@ export class SQLConnection {
if (this.connection == null) { if (this.connection == null) {
let options: any = this.getDriver(Config.Server.database); let options: any = this.getDriver(Config.Server.database);
options.name = "main"; options.name = 'main';
options.entities = [ options.entities = [
UserEntity, UserEntity,
PhotoEntity, PhotoEntity,
@ -46,11 +46,11 @@ export class SQLConnection {
public static async tryConnection(config: DataBaseConfig) { public static async tryConnection(config: DataBaseConfig) {
try { try {
await getConnection("test").close(); await getConnection('test').close();
} catch (err) { } catch (err) {
} }
const options: any = this.getDriver(config); const options: any = this.getDriver(config);
options.name = "test"; options.name = 'test';
options.entities = [ options.entities = [
UserEntity, UserEntity,
PhotoEntity, PhotoEntity,
@ -66,6 +66,20 @@ export class SQLConnection {
return true; 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) { private static async schemeSync(connection: Connection) {
let version = null; let version = null;
try { try {
@ -75,7 +89,7 @@ export class SQLConnection {
if (version && version.version == SQLConnection.VERSION) { if (version && version.version == SQLConnection.VERSION) {
return; return;
} }
Logger.info("Updating database scheme"); Logger.info('Updating database scheme');
if (!version) { if (!version) {
version = new VersionEntity(); version = new VersionEntity();
} }
@ -87,25 +101,11 @@ export class SQLConnection {
await connection.getRepository(VersionEntity).save(version); 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 { private static getDriver(config: DataBaseConfig): ConnectionOptions {
let driver: ConnectionOptions = null; let driver: ConnectionOptions = null;
if (config.type == DatabaseType.mysql) { if (config.type == DatabaseType.mysql) {
driver = { driver = {
type: "mysql", type: 'mysql',
host: config.mysql.host, host: config.mysql.host,
port: 3306, port: 3306,
username: config.mysql.username, username: config.mysql.username,
@ -114,7 +114,7 @@ export class SQLConnection {
}; };
} else if (config.type == DatabaseType.sqlite) { } else if (config.type == DatabaseType.sqlite) {
driver = { driver = {
type: "sqlite", type: 'sqlite',
database: ProjectPath.getAbsolutePath(config.sqlite.storage) database: ProjectPath.getAbsolutePath(config.sqlite.storage)
}; };
} }

View File

@ -1,9 +1,9 @@
import {AutoCompleteItem, SearchTypes} from "../../../common/entities/AutoCompleteItem"; import {AutoCompleteItem, SearchTypes} from '../../../common/entities/AutoCompleteItem';
import {ISearchManager} from "../interfaces/ISearchManager"; import {ISearchManager} from '../interfaces/ISearchManager';
import {SearchResultDTO} from "../../../common/entities/SearchResultDTO"; import {SearchResultDTO} from '../../../common/entities/SearchResultDTO';
import {SQLConnection} from "./SQLConnection"; import {SQLConnection} from './SQLConnection';
import {PhotoEntity} from "./enitites/PhotoEntity"; import {PhotoEntity} from './enitites/PhotoEntity';
import {DirectoryEntity} from "./enitites/DirectoryEntity"; import {DirectoryEntity} from './enitites/DirectoryEntity';
export class SearchManager implements ISearchManager { export class SearchManager implements ISearchManager {
@ -31,10 +31,10 @@ export class SearchManager implements ISearchManager {
(await photoRepository (await photoRepository
.createQueryBuilder('photo') .createQueryBuilder('photo')
.select('DISTINCT(photo.metadata.keywords)') .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) .limit(5)
.getRawMany()) .getRawMany())
.map(r => <Array<string>>r.metadataKeywords.split(",")) .map(r => <Array<string>>r.metadataKeywords.split(','))
.forEach(keywords => { .forEach(keywords => {
result = result.concat(this.encapsulateAutoComplete(keywords.filter(k => k.toLowerCase().indexOf(text.toLowerCase()) != -1), SearchTypes.keyword)); 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 (await photoRepository
.createQueryBuilder('photo') .createQueryBuilder('photo')
.select('photo.metadata.positionData.country as country, photo.metadata.positionData.state as state, photo.metadata.positionData.city as city') .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 + "%"}) .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.state LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'})
.orWhere('photo.metadata.positionData.city 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') .groupBy('photo.metadata.positionData.country, photo.metadata.positionData.state, photo.metadata.positionData.city')
.limit(5) .limit(5)
.getRawMany()) .getRawMany())
.filter(pm => !!pm) .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 => { .forEach(positions => {
result = result.concat(this.encapsulateAutoComplete(positions.filter(p => p.toLowerCase().indexOf(text.toLowerCase()) != -1), SearchTypes.position)); 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 result = result.concat(this.encapsulateAutoComplete((await photoRepository
.createQueryBuilder('photo') .createQueryBuilder('photo')
.select('DISTINCT(photo.name)') .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) .limit(5)
.getRawMany()) .getRawMany())
.map(r => r.name), SearchTypes.image)); .map(r => r.name), SearchTypes.image));
@ -66,7 +66,7 @@ export class SearchManager implements ISearchManager {
result = result.concat(this.encapsulateAutoComplete((await directoryRepository result = result.concat(this.encapsulateAutoComplete((await directoryRepository
.createQueryBuilder('dir') .createQueryBuilder('dir')
.select('DISTINCT(dir.name)') .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) .limit(5)
.getRawMany()) .getRawMany())
.map(r => r.name), SearchTypes.directory)); .map(r => r.name), SearchTypes.directory));
@ -88,27 +88,27 @@ export class SearchManager implements ISearchManager {
let query = connection let query = connection
.getRepository(PhotoEntity) .getRepository(PhotoEntity)
.createQueryBuilder("photo") .createQueryBuilder('photo')
.innerJoinAndSelect("photo.directory", "directory") .innerJoinAndSelect('photo.directory', 'directory')
.orderBy("photo.metadata.creationDate", "ASC"); .orderBy('photo.metadata.creationDate', 'ASC');
if (!searchType || searchType === SearchTypes.directory) { 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) { 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) { if (!searchType || searchType === SearchTypes.position) {
query.orWhere('photo.metadata.positionData.country 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.state LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'})
.orWhere('photo.metadata.positionData.city 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) { 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 result.photos = await query
@ -121,8 +121,8 @@ export class SearchManager implements ISearchManager {
result.directories = await connection result.directories = await connection
.getRepository(DirectoryEntity) .getRepository(DirectoryEntity)
.createQueryBuilder("dir") .createQueryBuilder('dir')
.where('dir.name LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"}) .where('dir.name LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'})
.limit(201) .limit(201)
.getMany(); .getMany();
@ -146,22 +146,22 @@ export class SearchManager implements ISearchManager {
result.photos = await connection result.photos = await connection
.getRepository(PhotoEntity) .getRepository(PhotoEntity)
.createQueryBuilder("photo") .createQueryBuilder('photo')
.orderBy("photo.metadata.creationDate", "ASC") .orderBy('photo.metadata.creationDate', 'ASC')
.where('photo.metadata.keywords LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"}) .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.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.state LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'})
.orWhere('photo.metadata.positionData.city 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 + "%"}) .orWhere('photo.name LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'})
.innerJoinAndSelect("photo.directory", "directory") .innerJoinAndSelect('photo.directory', 'directory')
.limit(10) .limit(10)
.getMany(); .getMany();
result.directories = await connection result.directories = await connection
.getRepository(DirectoryEntity) .getRepository(DirectoryEntity)
.createQueryBuilder("dir") .createQueryBuilder('dir')
.where('dir.name LIKE :text COLLATE utf8_general_ci', {text: "%" + text + "%"}) .where('dir.name LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'})
.limit(10) .limit(10)
.getMany(); .getMany();

View File

@ -1,9 +1,9 @@
import {ISharingManager} from "../interfaces/ISharingManager"; import {ISharingManager} from '../interfaces/ISharingManager';
import {SharingDTO} from "../../../common/entities/SharingDTO"; import {SharingDTO} from '../../../common/entities/SharingDTO';
import {SQLConnection} from "./SQLConnection"; import {SQLConnection} from './SQLConnection';
import {SharingEntity} from "./enitites/SharingEntity"; import {SharingEntity} from './enitites/SharingEntity';
import {Config} from "../../../common/config/private/Config"; import {Config} from '../../../common/config/private/Config';
import {PasswordHelper} from "../PasswordHelper"; import {PasswordHelper} from '../PasswordHelper';
export class SharingManager implements ISharingManager { export class SharingManager implements ISharingManager {
@ -11,8 +11,8 @@ export class SharingManager implements ISharingManager {
const connection = await SQLConnection.getConnection(); const connection = await SQLConnection.getConnection();
return connection return connection
.getRepository(SharingEntity) .getRepository(SharingEntity)
.createQueryBuilder("share") .createQueryBuilder('share')
.where("expires < :now", {now: Date.now()}) .where('expires < :now', {now: Date.now()})
.delete() .delete()
.execute(); .execute();
} }
@ -42,7 +42,7 @@ export class SharingManager implements ISharingManager {
}); });
if (sharing.timeStamp < Date.now() - Config.Server.sharing.updateTimeout) { 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) { if (inSharing.password == null) {
sharing.password = null; sharing.password = null;

View File

@ -1,8 +1,8 @@
import {UserDTO, UserRoles} from "../../../common/entities/UserDTO"; import {UserDTO, UserRoles} from '../../../common/entities/UserDTO';
import {IUserManager} from "../interfaces/IUserManager"; import {IUserManager} from '../interfaces/IUserManager';
import {UserEntity} from "./enitites/UserEntity"; import {UserEntity} from './enitites/UserEntity';
import {SQLConnection} from "./SQLConnection"; import {SQLConnection} from './SQLConnection';
import {PasswordHelper} from "../PasswordHelper"; import {PasswordHelper} from '../PasswordHelper';
export class UserManager implements IUserManager { export class UserManager implements IUserManager {
@ -22,7 +22,7 @@ export class UserManager implements IUserManager {
} }
if (pass && !PasswordHelper.comparePassword(pass, user.password)) { if (pass && !PasswordHelper.comparePassword(pass, user.password)) {
throw "No entry found"; throw 'No entry found';
} }
return user; return user;
@ -64,7 +64,7 @@ export class UserManager implements IUserManager {
} }
public async changePassword(request: any) { public async changePassword(request: any) {
throw new Error("not implemented"); //TODO: implement throw new Error('not implemented'); //TODO: implement
} }
} }

View File

@ -1,6 +1,6 @@
import {Column, Entity, ManyToOne, OneToMany, PrimaryGeneratedColumn} from "typeorm"; import {Column, Entity, ManyToOne, OneToMany, PrimaryGeneratedColumn} from 'typeorm';
import {DirectoryDTO} from "../../../../common/entities/DirectoryDTO"; import {DirectoryDTO} from '../../../../common/entities/DirectoryDTO';
import {PhotoEntity} from "./PhotoEntity"; import {PhotoEntity} from './PhotoEntity';
@Entity() @Entity()
export class DirectoryEntity implements DirectoryDTO { 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 * 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; public lastScanned: number;
isPartial?: boolean; isPartial?: boolean;
@ManyToOne(type => DirectoryEntity, directory => directory.directories, {onDelete: "CASCADE"}) @ManyToOne(type => DirectoryEntity, directory => directory.directories, {onDelete: 'CASCADE'})
public parent: DirectoryEntity; public parent: DirectoryEntity;
@OneToMany(type => DirectoryEntity, dir => dir.parent) @OneToMany(type => DirectoryEntity, dir => dir.parent)

View File

@ -1,37 +1,30 @@
import {Column, Entity, ManyToOne, PrimaryGeneratedColumn} from "typeorm"; import {Column, Entity, ManyToOne, PrimaryGeneratedColumn} from 'typeorm';
import { import {CameraMetadata, GPSMetadata, ImageSize, PhotoDTO, PhotoMetadata, PositionMetaData} from '../../../../common/entities/PhotoDTO';
CameraMetadata, import {DirectoryEntity} from './DirectoryEntity';
GPSMetadata,
ImageSize,
PhotoDTO,
PhotoMetadata,
PositionMetaData
} from "../../../../common/entities/PhotoDTO";
import {DirectoryEntity} from "./DirectoryEntity";
@Entity() @Entity()
export class CameraMetadataEntity implements CameraMetadata { export class CameraMetadataEntity implements CameraMetadata {
@Column("text", {nullable: true}) @Column('text', {nullable: true})
ISO: number; ISO: number;
@Column("text", {nullable: true}) @Column('text', {nullable: true})
model: string; model: string;
@Column("text", {nullable: true}) @Column('text', {nullable: true})
maker: string; maker: string;
@Column("int", {nullable: true}) @Column('int', {nullable: true})
fStop: number; fStop: number;
@Column("int", {nullable: true}) @Column('int', {nullable: true})
exposure: number; exposure: number;
@Column("int", {nullable: true}) @Column('int', {nullable: true})
focalLength: number; focalLength: number;
@Column("text", {nullable: true}) @Column('text', {nullable: true})
lens: string; lens: string;
} }
@ -39,21 +32,21 @@ export class CameraMetadataEntity implements CameraMetadata {
@Entity() @Entity()
export class GPSMetadataEntity implements GPSMetadata { export class GPSMetadataEntity implements GPSMetadata {
@Column("int", {nullable: true}) @Column('int', {nullable: true})
latitude: number; latitude: number;
@Column("int", {nullable: true}) @Column('int', {nullable: true})
longitude: number; longitude: number;
@Column("int", {nullable: true}) @Column('int', {nullable: true})
altitude: number; altitude: number;
} }
@Entity() @Entity()
export class ImageSizeEntity implements ImageSize { export class ImageSizeEntity implements ImageSize {
@Column("int") @Column('int')
width: number; width: number;
@Column("int") @Column('int')
height: number; height: number;
} }
@ -64,13 +57,13 @@ export class PositionMetaDataEntity implements PositionMetaData {
@Column(type => GPSMetadataEntity) @Column(type => GPSMetadataEntity)
GPSData: GPSMetadataEntity; GPSData: GPSMetadataEntity;
@Column("text", {nullable: true}) @Column('text', {nullable: true})
country: string; country: string;
@Column("text", {nullable: true}) @Column('text', {nullable: true})
state: string; state: string;
@Column("text", {nullable: true}) @Column('text', {nullable: true})
city: string; city: string;
} }
@ -78,7 +71,7 @@ export class PositionMetaDataEntity implements PositionMetaData {
@Entity() @Entity()
export class PhotoMetadataEntity implements PhotoMetadata { export class PhotoMetadataEntity implements PhotoMetadata {
@Column("simple-array") @Column('simple-array')
keywords: Array<string>; keywords: Array<string>;
@Column(type => CameraMetadataEntity) @Column(type => CameraMetadataEntity)
@ -90,10 +83,10 @@ export class PhotoMetadataEntity implements PhotoMetadata {
@Column(type => ImageSizeEntity) @Column(type => ImageSizeEntity)
size: ImageSizeEntity; size: ImageSizeEntity;
@Column("bigint") @Column('bigint')
creationDate: number; creationDate: number;
@Column("int") @Column('int')
fileSize: number; fileSize: number;
} }
@ -104,10 +97,10 @@ export class PhotoEntity implements PhotoDTO {
@PrimaryGeneratedColumn() @PrimaryGeneratedColumn()
id: number; id: number;
@Column("text") @Column('text')
name: string; name: string;
@ManyToOne(type => DirectoryEntity, directory => directory.photos, {onDelete: "CASCADE"}) @ManyToOne(type => DirectoryEntity, directory => directory.photos, {onDelete: 'CASCADE'})
directory: DirectoryEntity; directory: DirectoryEntity;
@Column(type => PhotoMetadataEntity) @Column(type => PhotoMetadataEntity)

View File

@ -1,7 +1,7 @@
import {Column, Entity, ManyToOne, PrimaryGeneratedColumn} from "typeorm"; import {Column, Entity, ManyToOne, PrimaryGeneratedColumn} from 'typeorm';
import {SharingDTO} from "../../../../common/entities/SharingDTO"; import {SharingDTO} from '../../../../common/entities/SharingDTO';
import {UserEntity} from "./UserEntity"; import {UserEntity} from './UserEntity';
import {UserDTO} from "../../../../common/entities/UserDTO"; import {UserDTO} from '../../../../common/entities/UserDTO';
@Entity() @Entity()
export class SharingEntity implements SharingDTO { export class SharingEntity implements SharingDTO {
@ -14,7 +14,7 @@ export class SharingEntity implements SharingDTO {
@Column() @Column()
path: string; path: string;
@Column({type: "text", nullable: true}) @Column({type: 'text', nullable: true})
password: string; password: string;
@Column() @Column()

View File

@ -1,5 +1,5 @@
import {UserDTO, UserRoles} from "../../../../common/entities/UserDTO"; import {UserDTO, UserRoles} from '../../../../common/entities/UserDTO';
import {Column, Entity, PrimaryGeneratedColumn} from "typeorm"; import {Column, Entity, PrimaryGeneratedColumn} from 'typeorm';
@Entity() @Entity()
export class UserEntity implements UserDTO { export class UserEntity implements UserDTO {
@ -13,10 +13,10 @@ export class UserEntity implements UserDTO {
@Column() @Column()
password: string; password: string;
@Column("smallint") @Column('smallint')
role: UserRoles; role: UserRoles;
@Column("text", {nullable: true}) @Column('text', {nullable: true})
permissions: string[]; permissions: string[];
} }

View File

@ -1,4 +1,4 @@
import {Column, Entity, PrimaryGeneratedColumn} from "typeorm"; import {Column, Entity, PrimaryGeneratedColumn} from 'typeorm';
@Entity() @Entity()
export class VersionEntity { export class VersionEntity {

View File

@ -1,14 +1,14 @@
import * as fs from "fs"; import * as fs from 'fs';
import * as path from "path"; import * as path from 'path';
import {DirectoryDTO} from "../../../common/entities/DirectoryDTO"; import {DirectoryDTO} from '../../../common/entities/DirectoryDTO';
import {CameraMetadata, GPSMetadata, ImageSize, PhotoDTO, PhotoMetadata} from "../../../common/entities/PhotoDTO"; import {CameraMetadata, GPSMetadata, ImageSize, PhotoDTO, PhotoMetadata} from '../../../common/entities/PhotoDTO';
import {Logger} from "../../Logger"; import {Logger} from '../../Logger';
import {IptcParser} from "ts-node-iptc"; import {IptcParser} from 'ts-node-iptc';
import {ExifParserFactory} from "ts-exif-parser"; import {ExifParserFactory} from 'ts-exif-parser';
import {ProjectPath} from "../../ProjectPath"; import {ProjectPath} from '../../ProjectPath';
import {Config} from "../../../common/config/private/Config"; import {Config} from '../../../common/config/private/Config';
const LOG_TAG = "[DiskManagerTask]"; const LOG_TAG = '[DiskManagerTask]';
export class DiskMangerWorker { export class DiskMangerWorker {
private static isImage(fullPath: string) { private static isImage(fullPath: string) {
@ -139,7 +139,7 @@ export class DiskMangerWorker {
metadata.size = <ImageSize> {width: 1, height: 1}; metadata.size = <ImageSize> {width: 1, height: 1};
} }
} catch (err) { } 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}; metadata.size = <ImageSize> {width: 1, height: 1};
} }

View File

@ -1,5 +1,5 @@
import {RendererInput, ThumbnailWoker} from "./ThumbnailWoker"; import {RendererInput, ThumbnailWoker} from './ThumbnailWoker';
import {Config} from "../../../common/config/private/Config"; import {Config} from '../../../common/config/private/Config';
interface QueTask { interface QueTask {

View File

@ -1,10 +1,10 @@
import * as cluster from "cluster"; import * as cluster from 'cluster';
import {Logger} from "../../Logger"; import {Logger} from '../../Logger';
import {DiskManagerTask, ThumbnailTask, WorkerMessage, WorkerTask, WorkerTaskTypes} from "./Worker"; import {DiskManagerTask, ThumbnailTask, WorkerMessage, WorkerTask, WorkerTaskTypes} from './Worker';
import {DirectoryDTO} from "../../../common/entities/DirectoryDTO"; import {DirectoryDTO} from '../../../common/entities/DirectoryDTO';
import {RendererInput} from "./ThumbnailWoker"; import {RendererInput} from './ThumbnailWoker';
import {Config} from "../../../common/config/private/Config"; import {Config} from '../../../common/config/private/Config';
import {ITaskQue} from "./TaskQue"; import {ITaskQue} from './TaskQue';
interface PoolTask { interface PoolTask {
@ -24,7 +24,7 @@ export class ThreadPool {
private tasks: PoolTask[] = []; private tasks: PoolTask[] = [];
constructor(private size: number) { 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++) { for (let i = 0; i < size; i++) {
this.startWorker(); this.startWorker();
} }
@ -39,14 +39,14 @@ export class ThreadPool {
}); });
worker.worker.on('exit', (code, signal) => { worker.worker.on('exit', (code, signal) => {
ThreadPool.WorkerCount--; 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'); Logger.debug('Starting a new worker');
this.startWorker(); this.startWorker();
}); });
worker.worker.on("message", (msg: WorkerMessage) => { worker.worker.on('message', (msg: WorkerMessage) => {
if (worker.poolTask == null) { 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) { if (msg.error) {
worker.poolTask.promise.reject(msg.error); worker.poolTask.promise.reject(msg.error);

View File

@ -1,7 +1,7 @@
import {Metadata, SharpInstance} from "sharp"; import {Metadata, SharpInstance} from 'sharp';
import {Dimensions, State} from "gm"; import {Dimensions, State} from 'gm';
import {Logger} from "../../Logger"; import {Logger} from '../../Logger';
import {ThumbnailProcessingLib} from "../../../common/config/private/IPrivateConfig"; import {ThumbnailProcessingLib} from '../../../common/config/private/IPrivateConfig';
export class ThumbnailWoker { export class ThumbnailWoker {
@ -39,14 +39,14 @@ export class RendererFactory {
case ThumbnailProcessingLib.sharp: case ThumbnailProcessingLib.sharp:
return RendererFactory.Sharp(); return RendererFactory.Sharp();
} }
throw "unknown renderer" throw 'unknown renderer';
} }
public static Jimp() { public static Jimp() {
const Jimp = require("jimp"); const Jimp = require('jimp');
return async (input: RendererInput): Promise<void> => { return async (input: RendererInput): Promise<void> => {
//generate thumbnail //generate thumbnail
Logger.silly("[JimpThRenderer] rendering thumbnail:", input.imagePath); Logger.silly('[JimpThRenderer] rendering thumbnail:', input.imagePath);
const image = await Jimp.read(input.imagePath); const image = await Jimp.read(input.imagePath);
/** /**
* newWidth * newHeight = size*size * newWidth * newHeight = size*size
@ -83,10 +83,10 @@ export class RendererFactory {
public static Sharp() { public static Sharp() {
const sharp = require("sharp"); const sharp = require('sharp');
return async (input: RendererInput): Promise<void> => { 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 image: SharpInstance = sharp(input.imagePath);
const metadata: Metadata = await image.metadata(); const metadata: Metadata = await image.metadata();
@ -120,10 +120,10 @@ export class RendererFactory {
public static Gm() { public static Gm() {
const gm = require("gm"); const gm = require('gm');
return (input: RendererInput): Promise<void> => { return (input: RendererInput): Promise<void> => {
return new Promise((resolve, reject) => { 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); let image: State = gm(input.imagePath);
image.size((err, value: Dimensions) => { image.size((err, value: Dimensions) => {
if (err) { if (err) {

View File

@ -1,13 +1,13 @@
import {DiskMangerWorker} from "./DiskMangerWorker"; import {DiskMangerWorker} from './DiskMangerWorker';
import {Logger} from "../../Logger"; import {Logger} from '../../Logger';
import {RendererInput, ThumbnailWoker} from "./ThumbnailWoker"; import {RendererInput, ThumbnailWoker} from './ThumbnailWoker';
import {ThumbnailProcessingLib} from "../../../common/config/private/IPrivateConfig"; import {ThumbnailProcessingLib} from '../../../common/config/private/IPrivateConfig';
export class Worker { export class Worker {
public static process() { public static process() {
Logger.debug("Worker is waiting for tasks"); Logger.debug('Worker is waiting for tasks');
process.on('message', async (task: WorkerTask) => { process.on('message', async (task: WorkerTask) => {
try { try {
let result = null; let result = null;
@ -22,8 +22,8 @@ export class Worker {
result = await ThumbnailWoker.render((<ThumbnailTask>task).input, (<ThumbnailTask>task).renderer); result = await ThumbnailWoker.render((<ThumbnailTask>task).input, (<ThumbnailTask>task).renderer);
break; break;
default: default:
Logger.error("Unknown worker task type"); Logger.error('Unknown worker task type');
throw "Unknown worker task type"; throw 'Unknown worker task type';
} }
process.send(<WorkerMessage>{ process.send(<WorkerMessage>{
error: null, error: null,

View File

@ -1,7 +1,7 @@
import {AuthenticationMWs} from "../middlewares/user/AuthenticationMWs"; import {AuthenticationMWs} from '../middlewares/user/AuthenticationMWs';
import {UserRoles} from "../../common/entities/UserDTO"; import {UserRoles} from '../../common/entities/UserDTO';
import {RenderingMWs} from "../middlewares/RenderingMWs"; import {RenderingMWs} from '../middlewares/RenderingMWs';
import {AdminMWs} from "../middlewares/AdminMWs"; import {AdminMWs} from '../middlewares/AdminMWs';
export class AdminRouter { export class AdminRouter {
public static route(app: any) { public static route(app: any) {
@ -12,98 +12,97 @@ export class AdminRouter {
private static addIndexGallery(app) { private static addIndexGallery(app) {
app.get("/api/admin/indexes/job/progress", app.get('/api/admin/indexes/job/progress',
AuthenticationMWs.authenticate, AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.Admin), AuthenticationMWs.authorise(UserRoles.Admin),
AdminMWs.getIndexingProgress, AdminMWs.getIndexingProgress,
RenderingMWs.renderResult RenderingMWs.renderResult
); );
app.put("/api/admin/indexes/job", app.put('/api/admin/indexes/job',
AuthenticationMWs.authenticate, AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.Admin), AuthenticationMWs.authorise(UserRoles.Admin),
AdminMWs.startIndexing, AdminMWs.startIndexing,
RenderingMWs.renderResult RenderingMWs.renderResult
); );
app.delete("/api/admin/indexes/job", app.delete('/api/admin/indexes/job',
AuthenticationMWs.authenticate, AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.Admin), AuthenticationMWs.authorise(UserRoles.Admin),
AdminMWs.cancelIndexing, AdminMWs.cancelIndexing,
RenderingMWs.renderResult RenderingMWs.renderResult
); );
app.delete("/api/admin/indexes", app.delete('/api/admin/indexes',
AuthenticationMWs.authenticate, AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.Admin), AuthenticationMWs.authorise(UserRoles.Admin),
AdminMWs.resetIndexes, AdminMWs.resetIndexes,
RenderingMWs.renderResult RenderingMWs.renderResult
); );
}; }
private static addSettings(app) { private static addSettings(app) {
app.get("/api/settings", app.get('/api/settings',
AuthenticationMWs.authenticate, AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.Admin), AuthenticationMWs.authorise(UserRoles.Admin),
RenderingMWs.renderConfig RenderingMWs.renderConfig
); );
app.put("/api/settings/database", app.put('/api/settings/database',
AuthenticationMWs.authenticate, AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.Admin), AuthenticationMWs.authorise(UserRoles.Admin),
AdminMWs.updateDatabaseSettings, AdminMWs.updateDatabaseSettings,
RenderingMWs.renderOK RenderingMWs.renderOK
); );
app.put("/api/settings/map", app.put('/api/settings/map',
AuthenticationMWs.authenticate, AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.Admin), AuthenticationMWs.authorise(UserRoles.Admin),
AdminMWs.updateMapSettings, AdminMWs.updateMapSettings,
RenderingMWs.renderOK RenderingMWs.renderOK
); );
app.put("/api/settings/authentication", app.put('/api/settings/authentication',
AuthenticationMWs.authenticate, AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.Admin), AuthenticationMWs.authorise(UserRoles.Admin),
AdminMWs.updateAuthenticationSettings, AdminMWs.updateAuthenticationSettings,
RenderingMWs.renderOK RenderingMWs.renderOK
); );
app.put("/api/settings/thumbnail", app.put('/api/settings/thumbnail',
AuthenticationMWs.authenticate, AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.Admin), AuthenticationMWs.authorise(UserRoles.Admin),
AdminMWs.updateThumbnailSettings, AdminMWs.updateThumbnailSettings,
RenderingMWs.renderOK RenderingMWs.renderOK
); );
app.put("/api/settings/search", app.put('/api/settings/search',
AuthenticationMWs.authenticate, AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.Admin), AuthenticationMWs.authorise(UserRoles.Admin),
AdminMWs.updateSearchSettings, AdminMWs.updateSearchSettings,
RenderingMWs.renderOK RenderingMWs.renderOK
); );
app.put("/api/settings/share", app.put('/api/settings/share',
AuthenticationMWs.authenticate, AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.Admin), AuthenticationMWs.authorise(UserRoles.Admin),
AdminMWs.updateShareSettings, AdminMWs.updateShareSettings,
RenderingMWs.renderOK RenderingMWs.renderOK
); );
app.put("/api/settings/basic", app.put('/api/settings/basic',
AuthenticationMWs.authenticate, AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.Admin), AuthenticationMWs.authorise(UserRoles.Admin),
AdminMWs.updateBasicSettings, AdminMWs.updateBasicSettings,
RenderingMWs.renderOK RenderingMWs.renderOK
); );
app.put("/api/settings/other", app.put('/api/settings/other',
AuthenticationMWs.authenticate, AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.Admin), AuthenticationMWs.authorise(UserRoles.Admin),
AdminMWs.updateOtherSettings, AdminMWs.updateOtherSettings,
RenderingMWs.renderOK RenderingMWs.renderOK
); );
app.put("/api/settings/indexing", app.put('/api/settings/indexing',
AuthenticationMWs.authenticate, AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.Admin), AuthenticationMWs.authorise(UserRoles.Admin),
AdminMWs.updateIndexingSettings, AdminMWs.updateIndexingSettings,
RenderingMWs.renderOK RenderingMWs.renderOK
); );
}
};
} }

View File

@ -1,6 +1,6 @@
import {RenderingMWs} from "../middlewares/RenderingMWs"; import {RenderingMWs} from '../middlewares/RenderingMWs';
import {ErrorCodes, ErrorDTO} from "../../common/entities/Error"; import {ErrorCodes, ErrorDTO} from '../../common/entities/Error';
import {Logger} from "../Logger"; import {Logger} from '../Logger';
import Request = Express.Request; import Request = Express.Request;
import Response = Express.Response; import Response = Express.Response;
@ -12,17 +12,17 @@ export class ErrorRouter {
} }
private static addApiErrorHandler(app) { private static addApiErrorHandler(app) {
app.use("/api/*", app.use('/api/*',
RenderingMWs.renderError RenderingMWs.renderError
); );
}; }
private static addGenericHandler(app) { private static addGenericHandler(app) {
app.use((err: any, req: Request, res: Response, next: Function) => { app.use((err: any, req: Request, res: Response, next: Function) => {
//Flush out the stack to the console // Flush out the stack to the console
Logger.error("Unexpected error:"); Logger.error('Unexpected error:');
console.error(err); 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 RenderingMWs.renderError
); );

View File

@ -1,8 +1,8 @@
import {AuthenticationMWs} from "../middlewares/user/AuthenticationMWs"; import {AuthenticationMWs} from '../middlewares/user/AuthenticationMWs';
import {GalleryMWs} from "../middlewares/GalleryMWs"; import {GalleryMWs} from '../middlewares/GalleryMWs';
import {RenderingMWs} from "../middlewares/RenderingMWs"; import {RenderingMWs} from '../middlewares/RenderingMWs';
import {ThumbnailGeneratorMWs} from "../middlewares/thumbnail/ThumbnailGeneratorMWs"; import {ThumbnailGeneratorMWs} from '../middlewares/thumbnail/ThumbnailGeneratorMWs';
import {UserRoles} from "../../common/entities/UserDTO"; import {UserRoles} from '../../common/entities/UserDTO';
export class GalleryRouter { export class GalleryRouter {
public static route(app: any) { public static route(app: any) {
@ -18,7 +18,7 @@ export class GalleryRouter {
} }
private static addDirectoryList(app) { 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.authenticate,
AuthenticationMWs.authoriseDirectory, AuthenticationMWs.authoriseDirectory,
GalleryMWs.listDirectory, GalleryMWs.listDirectory,
@ -26,40 +26,40 @@ export class GalleryRouter {
GalleryMWs.removeCyclicDirectoryReferences, GalleryMWs.removeCyclicDirectoryReferences,
RenderingMWs.renderResult RenderingMWs.renderResult
); );
}; }
private static addGetImage(app) { 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, AuthenticationMWs.authenticate,
//TODO: authorize path // TODO: authorize path
GalleryMWs.loadImage, GalleryMWs.loadImage,
RenderingMWs.renderFile RenderingMWs.renderFile
); );
}; }
private static addGetImageThumbnail(app) { 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, AuthenticationMWs.authenticate,
//TODO: authorize path // TODO: authorize path
GalleryMWs.loadImage, GalleryMWs.loadImage,
ThumbnailGeneratorMWs.generateThumbnail, ThumbnailGeneratorMWs.generateThumbnail,
RenderingMWs.renderFile RenderingMWs.renderFile
); );
}; }
private static addGetImageIcon(app) { 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, AuthenticationMWs.authenticate,
//TODO: authorize path // TODO: authorize path
GalleryMWs.loadImage, GalleryMWs.loadImage,
ThumbnailGeneratorMWs.generateIcon, ThumbnailGeneratorMWs.generateIcon,
RenderingMWs.renderFile RenderingMWs.renderFile
); );
}; }
private static addSearch(app) { private static addSearch(app) {
app.get("/api/search/:text", app.get('/api/search/:text',
AuthenticationMWs.authenticate, AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.Guest), AuthenticationMWs.authorise(UserRoles.Guest),
GalleryMWs.search, GalleryMWs.search,
@ -67,10 +67,10 @@ export class GalleryRouter {
GalleryMWs.removeCyclicDirectoryReferences, GalleryMWs.removeCyclicDirectoryReferences,
RenderingMWs.renderResult RenderingMWs.renderResult
); );
}; }
private static addInstantSearch(app) { private static addInstantSearch(app) {
app.get("/api/instant-search/:text", app.get('/api/instant-search/:text',
AuthenticationMWs.authenticate, AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.Guest), AuthenticationMWs.authorise(UserRoles.Guest),
GalleryMWs.instantSearch, GalleryMWs.instantSearch,
@ -78,16 +78,15 @@ export class GalleryRouter {
GalleryMWs.removeCyclicDirectoryReferences, GalleryMWs.removeCyclicDirectoryReferences,
RenderingMWs.renderResult RenderingMWs.renderResult
); );
}; }
private static addAutoComplete(app) { private static addAutoComplete(app) {
app.get("/api/autocomplete/:text", app.get('/api/autocomplete/:text',
AuthenticationMWs.authenticate, AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.Guest), AuthenticationMWs.authorise(UserRoles.Guest),
GalleryMWs.autocomplete, GalleryMWs.autocomplete,
RenderingMWs.renderResult RenderingMWs.renderResult
); );
}; }
} }

View File

@ -1,5 +1,5 @@
import {NextFunction, Request, Response} from "express"; import {NextFunction, Request, Response} from 'express';
import {Logger} from "../Logger"; import {Logger} from '../Logger';
/** /**
* Adds logging to express * Adds logging to express
@ -7,32 +7,32 @@ import {Logger} from "../Logger";
export class LoggerRouter { export class LoggerRouter {
public static route(app: any) { 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['_startTime'] = Date.now();
req['logged'] = true; req['logged'] = true;
const end = res.end; const end = res.end;
res.end = (a?: any, b?: any, c?: any) => { res.end = (a?: any, b?: any, c?: any) => {
res.end = end; res.end = end;
res.end(a, b, c); 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(); 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['_startTime'] = Date.now();
req['logged'] = true; req['logged'] = true;
const end = res.end; const end = res.end;
res.end = (a?: any, b?: any, c?: any) => { res.end = (a?: any, b?: any, c?: any) => {
res.end = end; res.end = end;
res.end(a, b, c); 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(); return next();
}); });
app.use((req: Request, res: Response, next: NextFunction) => { app.use((req: Request, res: Response, next: NextFunction) => {
if (req['logged'] == true) { if (req['logged'] === true) {
return next(); return next();
} }
req['_startTime'] = Date.now(); req['_startTime'] = Date.now();
@ -40,7 +40,7 @@ export class LoggerRouter {
res.end = (a?: any, b?: any, c?: any) => { res.end = (a?: any, b?: any, c?: any) => {
res.end = end; res.end = end;
res.end(a, b, c); 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(); return next();
}); });

View File

@ -1,9 +1,7 @@
import {UserRoles} from "../../common/entities/UserDTO"; import {UserRoles} from '../../common/entities/UserDTO';
import {AuthenticationMWs} from "../middlewares/user/AuthenticationMWs"; import {AuthenticationMWs} from '../middlewares/user/AuthenticationMWs';
import {RenderingMWs} from "../middlewares/RenderingMWs"; import {RenderingMWs} from '../middlewares/RenderingMWs';
import {NotificationMWs} from "../middlewares/NotificationMWs"; import {NotificationMWs} from '../middlewares/NotificationMWs';
import Request = Express.Request;
import Response = Express.Response;
export class NotificationRouter { export class NotificationRouter {
public static route(app: any) { public static route(app: any) {
@ -12,13 +10,12 @@ export class NotificationRouter {
} }
private static addGetNotifications(app) { private static addGetNotifications(app) {
app.get("/api/notifications", app.get('/api/notifications',
AuthenticationMWs.authenticate, AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.Guest), AuthenticationMWs.authorise(UserRoles.Guest),
NotificationMWs.list, NotificationMWs.list,
RenderingMWs.renderResult RenderingMWs.renderResult
); );
}; }
} }

View File

@ -1,18 +1,18 @@
import {NextFunction, Request, Response} from "express"; import {NextFunction, Request, Response} from 'express';
import * as path from "path"; import * as path from 'path';
import * as fs from "fs"; import * as fs from 'fs';
import {Utils} from "../../common/Utils"; import {Utils} from '../../common/Utils';
import {Config} from "../../common/config/private/Config"; import {Config} from '../../common/config/private/Config';
import {ProjectPath} from "../ProjectPath"; import {ProjectPath} from '../ProjectPath';
import {AuthenticationMWs} from "../middlewares/user/AuthenticationMWs"; import {AuthenticationMWs} from '../middlewares/user/AuthenticationMWs';
import {CookieNames} from "../../common/CookieNames"; import {CookieNames} from '../../common/CookieNames';
export class PublicRouter { export class PublicRouter {
public static route(app) { public static route(app) {
const setLocale = (req: Request, res: Response, next: Function) => { const setLocale = (req: Request, res: Response, next: Function) => {
let localePath = ""; let localePath = '';
let selectedLocale = req['locale']; let selectedLocale = req['locale'];
if (req.cookies && req.cookies[CookieNames.lang]) { if (req.cookies && req.cookies[CookieNames.lang]) {
if (Config.Client.languages.indexOf(req.cookies[CookieNames.lang]) !== -1) { if (Config.Client.languages.indexOf(req.cookies[CookieNames.lang]) !== -1) {
@ -37,7 +37,7 @@ export class PublicRouter {
if (Config.Client.languages.indexOf(locale) !== -1) { if (Config.Client.languages.indexOf(locale) !== -1) {
res.cookie(CookieNames.lang, locale); res.cookie(CookieNames.lang, locale);
} }
res.redirect("/?ln=" + locale); res.redirect('/?ln=' + locale);
}; };
}; };
@ -47,7 +47,7 @@ export class PublicRouter {
res.tpl.user = null; res.tpl.user = null;
if (req.session.user) { if (req.session.user) {
let user = Utils.clone(req.session.user); const user = Utils.clone(req.session.user);
delete user.password; delete user.password;
res.tpl.user = user; res.tpl.user = user;
} }
@ -60,13 +60,13 @@ export class PublicRouter {
res.render(path.resolve(ProjectPath.FrontendFolder, 'config_inject.ejs'), res.tpl); 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, AuthenticationMWs.tryAuthenticate,
setLocale, setLocale,
renderIndex renderIndex
); );
Config.Client.languages.forEach(l => { 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) redirectToBase(l)
); );
}); });

View File

@ -1,7 +1,7 @@
import {AuthenticationMWs} from "../middlewares/user/AuthenticationMWs"; import {AuthenticationMWs} from '../middlewares/user/AuthenticationMWs';
import {UserRoles} from "../../common/entities/UserDTO"; import {UserRoles} from '../../common/entities/UserDTO';
import {RenderingMWs} from "../middlewares/RenderingMWs"; import {RenderingMWs} from '../middlewares/RenderingMWs';
import {SharingMWs} from "../middlewares/SharingMWs"; import {SharingMWs} from '../middlewares/SharingMWs';
export class SharingRouter { export class SharingRouter {
public static route(app: any) { public static route(app: any) {
@ -13,7 +13,7 @@ export class SharingRouter {
} }
private static addShareLogin(app) { private static addShareLogin(app) {
app.post("/api/share/login", app.post('/api/share/login',
AuthenticationMWs.inverseAuthenticate, AuthenticationMWs.inverseAuthenticate,
AuthenticationMWs.shareLogin, AuthenticationMWs.shareLogin,
RenderingMWs.renderSessionUser RenderingMWs.renderSessionUser
@ -21,7 +21,7 @@ export class SharingRouter {
}; };
private static addGetSharing(app) { private static addGetSharing(app) {
app.get("/api/share/:sharingKey", app.get('/api/share/:sharingKey',
AuthenticationMWs.authenticate, AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.LimitedGuest), AuthenticationMWs.authorise(UserRoles.LimitedGuest),
SharingMWs.getSharing, SharingMWs.getSharing,
@ -30,7 +30,7 @@ export class SharingRouter {
}; };
private static addCreateSharing(app) { 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.authenticate,
AuthenticationMWs.authorise(UserRoles.User), AuthenticationMWs.authorise(UserRoles.User),
SharingMWs.createSharing, SharingMWs.createSharing,
@ -39,7 +39,7 @@ export class SharingRouter {
}; };
private static addUpdateSharing(app) { 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.authenticate,
AuthenticationMWs.authorise(UserRoles.User), AuthenticationMWs.authorise(UserRoles.User),
SharingMWs.updateSharing, SharingMWs.updateSharing,

View File

@ -1,8 +1,8 @@
import {UserMWs} from "../middlewares/user/UserMWs"; import {UserMWs} from '../middlewares/user/UserMWs';
import {UserRoles} from "../../common/entities/UserDTO"; import {UserRoles} from '../../common/entities/UserDTO';
import {AuthenticationMWs} from "../middlewares/user/AuthenticationMWs"; import {AuthenticationMWs} from '../middlewares/user/AuthenticationMWs';
import {UserRequestConstrainsMWs} from "../middlewares/user/UserRequestConstrainsMWs"; import {UserRequestConstrainsMWs} from '../middlewares/user/UserRequestConstrainsMWs';
import {RenderingMWs} from "../middlewares/RenderingMWs"; import {RenderingMWs} from '../middlewares/RenderingMWs';
export class UserRouter { export class UserRouter {
public static route(app) { public static route(app) {
@ -19,77 +19,77 @@ export class UserRouter {
} }
private static addLogin(app) { private static addLogin(app) {
app.post("/api/user/login", app.post('/api/user/login',
AuthenticationMWs.inverseAuthenticate, AuthenticationMWs.inverseAuthenticate,
AuthenticationMWs.login, AuthenticationMWs.login,
RenderingMWs.renderSessionUser RenderingMWs.renderSessionUser
); );
}; }
private static addLogout(app) { private static addLogout(app) {
app.post("/api/user/logout", app.post('/api/user/logout',
AuthenticationMWs.logout, AuthenticationMWs.logout,
RenderingMWs.renderOK RenderingMWs.renderOK
); );
}; }
private static addGetSessionUser(app) { private static addGetSessionUser(app) {
app.get("/api/user/login", app.get('/api/user/login',
AuthenticationMWs.authenticate, AuthenticationMWs.authenticate,
RenderingMWs.renderSessionUser RenderingMWs.renderSessionUser
); );
}; }
private static addChangePassword(app) { private static addChangePassword(app) {
app.post("/api/user/:id/password", app.post('/api/user/:id/password',
AuthenticationMWs.authenticate, AuthenticationMWs.authenticate,
UserRequestConstrainsMWs.forceSelfRequest, UserRequestConstrainsMWs.forceSelfRequest,
UserMWs.changePassword, UserMWs.changePassword,
RenderingMWs.renderOK RenderingMWs.renderOK
); );
}; }
private static addCreateUser(app) { private static addCreateUser(app) {
app.put("/api/user", app.put('/api/user',
AuthenticationMWs.authenticate, AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.Admin), AuthenticationMWs.authorise(UserRoles.Admin),
UserMWs.createUser, UserMWs.createUser,
RenderingMWs.renderOK RenderingMWs.renderOK
); );
}; }
private static addDeleteUser(app) { private static addDeleteUser(app) {
app.delete("/api/user/:id", app.delete('/api/user/:id',
AuthenticationMWs.authenticate, AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.Admin), AuthenticationMWs.authorise(UserRoles.Admin),
UserRequestConstrainsMWs.notSelfRequest, UserRequestConstrainsMWs.notSelfRequest,
UserMWs.deleteUser, UserMWs.deleteUser,
RenderingMWs.renderOK RenderingMWs.renderOK
); );
}; }
private static addListUsers(app) { private static addListUsers(app) {
app.get("/api/user/list", app.get('/api/user/list',
AuthenticationMWs.authenticate, AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.Admin), AuthenticationMWs.authorise(UserRoles.Admin),
UserMWs.listUsers, UserMWs.listUsers,
RenderingMWs.renderResult RenderingMWs.renderResult
); );
}; }
private static addChangeRole(app) { private static addChangeRole(app) {
app.post("/api/user/:id/role", app.post('/api/user/:id/role',
AuthenticationMWs.authenticate, AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.Admin), AuthenticationMWs.authorise(UserRoles.Admin),
UserRequestConstrainsMWs.notSelfRequestOr2Admins, UserRequestConstrainsMWs.notSelfRequestOr2Admins,
UserMWs.changeRole, UserMWs.changeRole,
RenderingMWs.renderOK RenderingMWs.renderOK
); );
}; }
} }

View File

@ -1,29 +1,29 @@
import * as _express from "express"; import * as _express from 'express';
import * as _bodyParser from "body-parser"; import * as _bodyParser from 'body-parser';
import * as cookieParser from "cookie-parser"; import * as cookieParser from 'cookie-parser';
import * as _http from "http"; import * as _http from 'http';
import * as locale from "locale"; import * as locale from 'locale';
import {PublicRouter} from "./routes/PublicRouter"; import {PublicRouter} from './routes/PublicRouter';
import {UserRouter} from "./routes/UserRouter"; import {UserRouter} from './routes/UserRouter';
import {GalleryRouter} from "./routes/GalleryRouter"; import {GalleryRouter} from './routes/GalleryRouter';
import {AdminRouter} from "./routes/AdminRouter"; import {AdminRouter} from './routes/AdminRouter';
import {ErrorRouter} from "./routes/ErrorRouter"; import {ErrorRouter} from './routes/ErrorRouter';
import {SharingRouter} from "./routes/SharingRouter"; import {SharingRouter} from './routes/SharingRouter';
import {ObjectManagerRepository} from "./model/ObjectManagerRepository"; import {ObjectManagerRepository} from './model/ObjectManagerRepository';
import {Logger} from "./Logger"; import {Logger} from './Logger';
import {Config} from "../common/config/private/Config"; import {Config} from '../common/config/private/Config';
import {DatabaseType} from "../common/config/private/IPrivateConfig"; import {DatabaseType} from '../common/config/private/IPrivateConfig';
import {LoggerRouter} from "./routes/LoggerRouter"; import {LoggerRouter} from './routes/LoggerRouter';
import {ThumbnailGeneratorMWs} from "./middlewares/thumbnail/ThumbnailGeneratorMWs"; import {ThumbnailGeneratorMWs} from './middlewares/thumbnail/ThumbnailGeneratorMWs';
import {DiskManager} from "./model/DiskManger"; import {DiskManager} from './model/DiskManger';
import {NotificationRouter} from "./routes/NotificationRouter"; import {NotificationRouter} from './routes/NotificationRouter';
import {ConfigDiagnostics} from "./model/ConfigDiagnostics"; import {ConfigDiagnostics} from './model/ConfigDiagnostics';
import {Localizations} from "./model/Localizations"; import {Localizations} from './model/Localizations';
import {CookieNames} from "../common/CookieNames"; import {CookieNames} from '../common/CookieNames';
const _session = require('cookie-session'); const _session = require('cookie-session');
const LOG_TAG = "[server]"; const LOG_TAG = '[server]';
export class Server { export class Server {
@ -31,16 +31,16 @@ export class Server {
private server: any; private server: any;
constructor() { constructor() {
if (!(process.env.NODE_ENV == "production")) { if (!(process.env.NODE_ENV == 'production')) {
Logger.debug(LOG_TAG, "Running in DEBUG mode"); Logger.debug(LOG_TAG, 'Running in DEBUG mode');
} }
this.init(); this.init();
} }
async init() { async init() {
Logger.info(LOG_TAG, "running diagnostics..."); Logger.info(LOG_TAG, 'running diagnostics...');
await ConfigDiagnostics.runDiagnostics(); await ConfigDiagnostics.runDiagnostics();
Logger.info(LOG_TAG, "using config:"); Logger.info(LOG_TAG, 'using config:');
Logger.info(LOG_TAG, JSON.stringify(Config, null, '\t')); Logger.info(LOG_TAG, JSON.stringify(Config, null, '\t'));
this.app = _express(); this.app = _express();
@ -61,7 +61,7 @@ export class Server {
this.app.use(_session({ this.app.use(_session({
name: CookieNames.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) => { /* this.app.use((req: Request, res: Response, next: NextFunction) => {
@ -81,7 +81,7 @@ export class Server {
ThumbnailGeneratorMWs.init(); ThumbnailGeneratorMWs.init();
Localizations.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) { if (Config.Server.database.type != DatabaseType.memory) {
await ObjectManagerRepository.InitSQLManagers(); await ObjectManagerRepository.InitSQLManagers();
} else { } else {

View File

@ -1,10 +1,10 @@
import {Component, OnInit} from "@angular/core"; import {Component, OnInit} from '@angular/core';
import {AuthenticationService} from "../model/network/authentication.service"; import {AuthenticationService} from '../model/network/authentication.service';
import {UserRoles} from "../../../common/entities/UserDTO"; import {UserRoles} from '../../../common/entities/UserDTO';
import {NotificationService} from "../model/notification.service"; import {NotificationService} from '../model/notification.service';
import {NotificationType} from "../../../common/entities/NotificationDTO"; import {NotificationType} from '../../../common/entities/NotificationDTO';
import {NavigationService} from "../model/navigation.service"; import {NavigationService} from '../model/navigation.service';
import {I18n} from "@ngx-translate/i18n-polyfill"; import {I18n} from '@ngx-translate/i18n-polyfill';
@Component({ @Component({
selector: 'admin', selector: 'admin',
@ -15,16 +15,16 @@ export class AdminComponent implements OnInit {
simplifiedMode = true; simplifiedMode = true;
text = { text = {
Advanced: "Advanced", Advanced: 'Advanced',
Simplified: "Simplified" Simplified: 'Simplified'
}; };
constructor(private _authService: AuthenticationService, constructor(private _authService: AuthenticationService,
private _navigation: NavigationService, private _navigation: NavigationService,
public notificationService: NotificationService, public notificationService: NotificationService,
public i18n: I18n) { public i18n: I18n) {
this.text.Advanced = i18n("Advanced"); this.text.Advanced = i18n('Advanced');
this.text.Simplified = i18n("Simplified"); this.text.Simplified = i18n('Simplified');
} }
ngOnInit() { ngOnInit() {
@ -38,13 +38,13 @@ export class AdminComponent implements OnInit {
public getCss(type: NotificationType) { public getCss(type: NotificationType) {
switch (type) { switch (type) {
case NotificationType.error: case NotificationType.error:
return "danger"; return 'danger';
case NotificationType.warning: case NotificationType.warning:
return "warning"; return 'warning';
case NotificationType.info: case NotificationType.info:
return "info"; return 'info';
} }
return "info"; return 'info';
} }
} }

View File

@ -1,15 +1,15 @@
import {Component, OnDestroy, OnInit, ViewContainerRef} from "@angular/core"; import {Component, OnDestroy, OnInit, ViewContainerRef} from '@angular/core';
import {AuthenticationService} from "./model/network/authentication.service"; import {AuthenticationService} from './model/network/authentication.service';
import {UserDTO} from "../../common/entities/UserDTO"; import {UserDTO} from '../../common/entities/UserDTO';
import {Router} from "@angular/router"; import {Router} from '@angular/router';
import {Config} from "../../common/config/public/Config"; import {Config} from '../../common/config/public/Config';
import {Title} from "@angular/platform-browser"; import {Title} from '@angular/platform-browser';
import {NotificationService} from "./model/notification.service"; import {NotificationService} from './model/notification.service';
import {ShareService} from "./gallery/share.service"; import {ShareService} from './gallery/share.service';
import "hammerjs"; import 'hammerjs';
@Component({ @Component({
selector: 'pi-gallery2-app', selector: 'app-pi-gallery2',
template: `<router-outlet></router-outlet>`, template: `<router-outlet></router-outlet>`,
}) })
@ -55,17 +55,17 @@ export class AppComponent implements OnInit, OnDestroy {
private toLogin() { private toLogin() {
if (this._shareService.isSharing()) { 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 { } else {
return this._router.navigate(["login"]); return this._router.navigate(['login']);
} }
} }
private toGallery() { private toGallery() {
if (this._shareService.isSharing()) { if (this._shareService.isSharing()) {
return this._router.navigate(["share", this._shareService.getSharingKey()]); return this._router.navigate(['share', this._shareService.getSharingKey()]);
} else { } else {
return this._router.navigate(["gallery", ""]); return this._router.navigate(['gallery', '']);
} }
} }
} }

View File

@ -1,62 +1,62 @@
import {Injectable, LOCALE_ID, NgModule, TRANSLATIONS} from "@angular/core"; import {Injectable, LOCALE_ID, NgModule, TRANSLATIONS} from '@angular/core';
import {BrowserModule, HAMMER_GESTURE_CONFIG, HammerGestureConfig} from "@angular/platform-browser"; import {BrowserModule, HAMMER_GESTURE_CONFIG, HammerGestureConfig} from '@angular/platform-browser';
import {FormsModule} from "@angular/forms"; import {FormsModule} from '@angular/forms';
import {HttpModule} from "@angular/http"; import {AgmCoreModule} from '@agm/core';
import {AgmCoreModule} from "@agm/core"; import {AppComponent} from './app.component';
import {AppComponent} from "./app.component"; import {appRoutes} from './app.routing';
import {appRoutes} from "./app.routing"; import {UserService} from './model/network/user.service';
import {UserService} from "./model/network/user.service"; import {GalleryService} from './gallery/gallery.service';
import {GalleryService} from "./gallery/gallery.service"; import {NetworkService} from './model/network/network.service';
import {NetworkService} from "./model/network/network.service"; import {ThumbnailLoaderService} from './gallery/thumnailLoader.service';
import {ThumbnailLoaderService} from "./gallery/thumnailLoader.service"; import {GalleryCacheService} from './gallery/cache.gallery.service';
import {GalleryCacheService} from "./gallery/cache.gallery.service"; import {FullScreenService} from './gallery/fullscreen.service';
import {FullScreenService} from "./gallery/fullscreen.service"; import {AuthenticationService} from './model/network/authentication.service';
import {AuthenticationService} from "./model/network/authentication.service"; import {UserMangerSettingsComponent} from './settings/usermanager/usermanager.settings.component';
import {UserMangerSettingsComponent} from "./settings/usermanager/usermanager.settings.component"; import {FrameComponent} from './frame/frame.component';
import {FrameComponent} from "./frame/frame.component"; import {GalleryLightboxPhotoComponent} from './gallery/lightbox/photo/photo.lightbox.gallery.component';
import {GalleryLightboxPhotoComponent} from "./gallery/lightbox/photo/photo.lightbox.gallery.component"; import {GalleryPhotoLoadingComponent} from './gallery/grid/photo/loading/loading.photo.grid.gallery.component';
import {GalleryPhotoLoadingComponent} from "./gallery/grid/photo/loading/loading.photo.grid.gallery.component"; import {GalleryNavigatorComponent} from './gallery/navigator/navigator.gallery.component';
import {GalleryNavigatorComponent} from "./gallery/navigator/navigator.gallery.component"; import {GallerySearchComponent} from './gallery/search/search.gallery.component';
import {GallerySearchComponent} from "./gallery/search/search.gallery.component"; import {GalleryLightboxComponent} from './gallery/lightbox/lightbox.gallery.component';
import {GalleryLightboxComponent} from "./gallery/lightbox/lightbox.gallery.component"; import {GalleryDirectoryComponent} from './gallery/directory/directory.gallery.component';
import {GalleryDirectoryComponent} from "./gallery/directory/directory.gallery.component"; import {GalleryGridComponent} from './gallery/grid/grid.gallery.component';
import {GalleryGridComponent} from "./gallery/grid/grid.gallery.component"; import {GalleryPhotoComponent} from './gallery/grid/photo/photo.grid.gallery.component';
import {GalleryPhotoComponent} from "./gallery/grid/photo/photo.grid.gallery.component"; import {LoginComponent} from './login/login.component';
import {LoginComponent} from "./login/login.component"; import {AdminComponent} from './admin/admin.component';
import {AdminComponent} from "./admin/admin.component"; import {GalleryComponent} from './gallery/gallery.component';
import {GalleryComponent} from "./gallery/gallery.component"; import {StringifyRole} from './pipes/StringifyRolePipe';
import {StringifyRole} from "./pipes/StringifyRolePipe"; import {GalleryMapComponent} from './gallery/map/map.gallery.component';
import {GalleryMapComponent} from "./gallery/map/map.gallery.component"; import {GalleryMapLightboxComponent} from './gallery/map/lightbox/lightbox.map.gallery.component';
import {GalleryMapLightboxComponent} from "./gallery/map/lightbox/lightbox.map.gallery.component"; import {ThumbnailManagerService} from './gallery/thumnailManager.service';
import {ThumbnailManagerService} from "./gallery/thumnailManager.service"; import {OverlayService} from './gallery/overlay.service';
import {OverlayService} from "./gallery/overlay.service"; import {Config} from '../../common/config/public/Config';
import {Config} from "../../common/config/public/Config"; import {LAZY_MAPS_API_CONFIG} from '@agm/core/services';
import {LAZY_MAPS_API_CONFIG} from "@agm/core/services"; import {SlimLoadingBarModule} from 'ng2-slim-loading-bar';
import {SlimLoadingBarModule} from "ng2-slim-loading-bar"; import {GalleryShareComponent} from './gallery/share/share.gallery.component';
import {GalleryShareComponent} from "./gallery/share/share.gallery.component"; import {ShareLoginComponent} from './sharelogin/share-login.component';
import {ShareLoginComponent} from "./sharelogin/share-login.component"; import {ShareService} from './gallery/share.service';
import {ShareService} from "./gallery/share.service"; import {ModalModule} from 'ngx-bootstrap/modal';
import {ModalModule} from "ngx-bootstrap/modal"; import {DatabaseSettingsComponent} from './settings/database/database.settings.component';
import {DatabaseSettingsComponent} from "./settings/database/database.settings.component"; import {ToastModule} from 'ng2-toastr/ng2-toastr';
import {ToastModule} from "ng2-toastr/ng2-toastr"; import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
import {BrowserAnimationsModule} from "@angular/platform-browser/animations"; import {NotificationService} from './model/notification.service';
import {NotificationService} from "./model/notification.service"; import {JWBootstrapSwitchModule} from 'jw-bootstrap-switch-ng2';
import {JWBootstrapSwitchModule} from "jw-bootstrap-switch-ng2"; import {ClipboardModule} from 'ngx-clipboard';
import {ClipboardModule} from "ngx-clipboard"; import {NavigationService} from './model/navigation.service';
import {NavigationService} from "./model/navigation.service"; import {InfoPanelLightboxComponent} from './gallery/lightbox/infopanel/info-panel.lightbox.gallery.component';
import {InfoPanelLightboxComponent} from "./gallery/lightbox/infopanel/info-panel.lightbox.gallery.component"; import {MapSettingsComponent} from './settings/map/map.settings.component';
import {MapSettingsComponent} from "./settings/map/map.settings.component"; import {TooltipModule} from 'ngx-bootstrap/tooltip';
import {TooltipModule} from "ngx-bootstrap/tooltip"; import {BsDropdownModule} from 'ngx-bootstrap/dropdown';
import {BsDropdownModule} from "ngx-bootstrap/dropdown"; import {ThumbnailSettingsComponent} from './settings/thumbnail/thumbanil.settings.component';
import {ThumbnailSettingsComponent} from "./settings/thumbnail/thumbanil.settings.component"; import {SearchSettingsComponent} from './settings/search/search.settings.component';
import {SearchSettingsComponent} from "./settings/search/search.settings.component"; import {SettingsService} from './settings/settings.service';
import {SettingsService} from "./settings/settings.service"; import {ShareSettingsComponent} from './settings/share/share.settings.component';
import {ShareSettingsComponent} from "./settings/share/share.settings.component"; import {BasicSettingsComponent} from './settings/basic/basic.settings.component';
import {BasicSettingsComponent} from "./settings/basic/basic.settings.component"; import {OtherSettingsComponent} from './settings/other/other.settings.component';
import {OtherSettingsComponent} from "./settings/other/other.settings.component"; import {HttpClientModule} from '@angular/common/http';
import {DefaultUrlSerializer, UrlSerializer, UrlTree} from '@angular/router'; import {DefaultUrlSerializer, UrlSerializer, UrlTree} from '@angular/router';
import {IndexingSettingsComponent} from "./settings/indexing/indexing.settings.component"; import {IndexingSettingsComponent} from './settings/indexing/indexing.settings.component';
import {LanguageComponent} from "./language/language.component"; import {LanguageComponent} from './language/language.component';
import {I18n} from '@ngx-translate/i18n-polyfill'; import {I18n} from '@ngx-translate/i18n-polyfill';
@Injectable() @Injectable()
@ -71,7 +71,7 @@ export class GoogleMapsConfig {
export class MyHammerConfig extends HammerGestureConfig { export class MyHammerConfig extends HammerGestureConfig {
overrides = <any>{ overrides = <any>{
'swipe': {direction: 31} // enable swipe up 'swipe': {direction: 31} // enable swipe up
} };
} }
export class CustomUrlSerializer implements UrlSerializer { export class CustomUrlSerializer implements UrlSerializer {
@ -81,7 +81,7 @@ export class CustomUrlSerializer implements UrlSerializer {
// Encode parentheses // Encode parentheses
url = url.replace(/\(/g, '%28').replace(/\)/g, '%29'); url = url.replace(/\(/g, '%28').replace(/\)/g, '%29');
// Use the default serializer. // Use the default serializer.
return this._defaultUrlSerializer.parse(url) return this._defaultUrlSerializer.parse(url);
} }
serialize(tree: UrlTree): string { serialize(tree: UrlTree): string {
@ -93,7 +93,7 @@ declare const require;
export function translationsFactory(locale: string) { export function translationsFactory(locale: string) {
locale = locale || 'en'; // default to english if no locale 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`); return require(`raw-loader!../translate/messages.${locale}.xlf`);
} }
@ -101,7 +101,7 @@ export function translationsFactory(locale: string) {
imports: [ imports: [
BrowserModule, BrowserModule,
FormsModule, FormsModule,
HttpModule, HttpClientModule,
BrowserAnimationsModule, BrowserAnimationsModule,
appRoutes, appRoutes,
ClipboardModule, ClipboardModule,
@ -117,10 +117,10 @@ export function translationsFactory(locale: string) {
LoginComponent, LoginComponent,
ShareLoginComponent, ShareLoginComponent,
GalleryComponent, GalleryComponent,
//misc // misc
FrameComponent, FrameComponent,
LanguageComponent, LanguageComponent,
//Gallery // Gallery
GalleryLightboxPhotoComponent, GalleryLightboxPhotoComponent,
GalleryPhotoLoadingComponent, GalleryPhotoLoadingComponent,
GalleryGridComponent, GalleryGridComponent,
@ -135,7 +135,7 @@ export function translationsFactory(locale: string) {
GalleryPhotoComponent, GalleryPhotoComponent,
AdminComponent, AdminComponent,
InfoPanelLightboxComponent, InfoPanelLightboxComponent,
//Settings // Settings
UserMangerSettingsComponent, UserMangerSettingsComponent,
DatabaseSettingsComponent, DatabaseSettingsComponent,
MapSettingsComponent, MapSettingsComponent,

View File

@ -1,9 +1,9 @@
import {ModuleWithProviders} from "@angular/core"; import {ModuleWithProviders} from '@angular/core';
import {RouterModule, Routes} from "@angular/router"; import {RouterModule, Routes} from '@angular/router';
import {LoginComponent} from "./login/login.component"; import {LoginComponent} from './login/login.component';
import {GalleryComponent} from "./gallery/gallery.component"; import {GalleryComponent} from './gallery/gallery.component';
import {AdminComponent} from "./admin/admin.component"; import {AdminComponent} from './admin/admin.component';
import {ShareLoginComponent} from "./sharelogin/share-login.component"; import {ShareLoginComponent} from './sharelogin/share-login.component';
const ROUTES: Routes = [ const ROUTES: Routes = [
{ {

View File

@ -53,7 +53,6 @@ ng2-slim-loading-bar {
} }
} }
.badge { .badge {
margin-left: -5px; margin-left: -5px;
padding: 0; padding: 0;

View File

@ -1,10 +1,10 @@
import {Component, ViewEncapsulation} from "@angular/core"; import {Component, ViewEncapsulation} from '@angular/core';
import {RouterLink} from "@angular/router"; import {RouterLink} from '@angular/router';
import {AuthenticationService} from "../model/network/authentication.service"; import {AuthenticationService} from '../model/network/authentication.service';
import {UserDTO, UserRoles} from "../../../common/entities/UserDTO"; import {UserDTO, UserRoles} from '../../../common/entities/UserDTO';
import {Config} from "../../../common/config/public/Config"; import {Config} from '../../../common/config/public/Config';
import {BehaviorSubject} from "rxjs/BehaviorSubject"; import {BehaviorSubject} from 'rxjs/BehaviorSubject';
import {NotificationService} from "../model/notification.service"; import {NotificationService} from '../model/notification.service';
@Component({ @Component({
selector: 'app-frame', selector: 'app-frame',

View File

@ -1,5 +1,6 @@
import {PhotoDTO} from "../../../common/entities/PhotoDTO"; import {PhotoDTO} from '../../../common/entities/PhotoDTO';
import {Utils} from "../../../common/Utils"; import {Utils} from '../../../common/Utils';
export class IconPhoto { export class IconPhoto {
@ -18,23 +19,23 @@ export class IconPhoto {
} }
getIconPath() { 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() { 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 { equals(other: PhotoDTO | IconPhoto): boolean {
//is gridphoto //is gridphoto
if (other instanceof IconPhoto) { 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 //is photo
if (other.directory) { 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; return false;

View File

@ -1,7 +1,8 @@
import {PhotoDTO} from "../../../common/entities/PhotoDTO"; import {PhotoDTO} from '../../../common/entities/PhotoDTO';
import {Utils} from "../../../common/Utils"; import {Utils} from '../../../common/Utils';
import {IconPhoto} from "./IconPhoto"; import {IconPhoto} from './IconPhoto';
import {Config} from "../../../common/config/public/Config"; import {Config} from '../../../common/config/public/Config';
export class Photo extends IconPhoto { export class Photo extends IconPhoto {
@ -50,13 +51,13 @@ export class Photo extends IconPhoto {
getReplacementThumbnailPath() { getReplacementThumbnailPath() {
let size = this.getReplacementThumbnailSize(); 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() { getThumbnailPath() {
let size = this.getThumbnailSize(); 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());
} }

View File

@ -1,10 +1,10 @@
import {Injectable} from "@angular/core"; import {Injectable} from '@angular/core';
import {PhotoDTO} from "../../../common/entities/PhotoDTO"; import {PhotoDTO} from '../../../common/entities/PhotoDTO';
import {DirectoryDTO} from "../../../common/entities/DirectoryDTO"; import {DirectoryDTO} from '../../../common/entities/DirectoryDTO';
import {Utils} from "../../../common/Utils"; import {Utils} from '../../../common/Utils';
import {Config} from "../../../common/config/public/Config"; import {Config} from '../../../common/config/public/Config';
import {AutoCompleteItem, SearchTypes} from "../../../common/entities/AutoCompleteItem"; import {AutoCompleteItem, SearchTypes} from '../../../common/entities/AutoCompleteItem';
import {SearchResultDTO} from "../../../common/entities/SearchResultDTO"; import {SearchResultDTO} from '../../../common/entities/SearchResultDTO';
interface CacheItem<T> { interface CacheItem<T> {
timestamp: number; timestamp: number;
@ -14,11 +14,11 @@ interface CacheItem<T> {
@Injectable() @Injectable()
export class GalleryCacheService { export class GalleryCacheService {
private static CONTENT_PREFIX = "content:"; private static CONTENT_PREFIX = 'content:';
private static AUTO_COMPLETE_PREFIX = "autocomplete:"; private static AUTO_COMPLETE_PREFIX = 'autocomplete:';
private static INSTANT_SEARCH_PREFIX = "instant_search:"; private static INSTANT_SEARCH_PREFIX = 'instant_search:';
private static SEARCH_PREFIX = "search:"; private static SEARCH_PREFIX = 'search:';
private static SEARCH_TYPE_PREFIX = ":type:"; private static SEARCH_TYPE_PREFIX = ':type:';
public getAutoComplete(text: string): Array<AutoCompleteItem> { public getAutoComplete(text: string): Array<AutoCompleteItem> {
@ -68,7 +68,7 @@ export class GalleryCacheService {
public getSearch(text: string, type?: SearchTypes): SearchResultDTO { public getSearch(text: string, type?: SearchTypes): SearchResultDTO {
let key = GalleryCacheService.SEARCH_PREFIX + text; let key = GalleryCacheService.SEARCH_PREFIX + text;
if (typeof type != "undefined") { if (typeof type != 'undefined') {
key += GalleryCacheService.SEARCH_TYPE_PREFIX + type; key += GalleryCacheService.SEARCH_TYPE_PREFIX + type;
} }
const tmp = localStorage.getItem(key); const tmp = localStorage.getItem(key);
@ -89,7 +89,7 @@ export class GalleryCacheService {
item: searchResult item: searchResult
}; };
let key = GalleryCacheService.SEARCH_PREFIX + text; let key = GalleryCacheService.SEARCH_PREFIX + text;
if (typeof type != "undefined") { if (typeof type != 'undefined') {
key += GalleryCacheService.SEARCH_TYPE_PREFIX + type; key += GalleryCacheService.SEARCH_TYPE_PREFIX + type;
} }
localStorage.setItem(key, JSON.stringify(tmp)); localStorage.setItem(key, JSON.stringify(tmp));

View File

@ -1,11 +1,11 @@
import {Component, ElementRef, Input, OnDestroy, OnInit, ViewChild} from "@angular/core"; import {Component, ElementRef, Input, OnDestroy, OnInit, ViewChild} from '@angular/core';
import {DomSanitizer} from "@angular/platform-browser"; import {DomSanitizer} from '@angular/platform-browser';
import {DirectoryDTO} from "../../../../common/entities/DirectoryDTO"; import {DirectoryDTO} from '../../../../common/entities/DirectoryDTO';
import {RouterLink} from "@angular/router"; import {RouterLink} from '@angular/router';
import {Utils} from "../../../../common/Utils"; import {Utils} from '../../../../common/Utils';
import {Photo} from "../Photo"; import {Photo} from '../Photo';
import {Thumbnail, ThumbnailManagerService} from "../thumnailManager.service"; import {Thumbnail, ThumbnailManagerService} from '../thumnailManager.service';
import {ShareService} from "../share.service"; import {ShareService} from '../share.service';
@Component({ @Component({
selector: 'gallery-directory', selector: 'gallery-directory',
@ -15,7 +15,7 @@ import {ShareService} from "../share.service";
}) })
export class GalleryDirectoryComponent implements OnInit, OnDestroy { export class GalleryDirectoryComponent implements OnInit, OnDestroy {
@Input() directory: DirectoryDTO; @Input() directory: DirectoryDTO;
@ViewChild("dirContainer") container: ElementRef; @ViewChild('dirContainer') container: ElementRef;
thumbnail: Thumbnail = null; thumbnail: Thumbnail = null;
constructor(private thumbnailService: ThumbnailManagerService, constructor(private thumbnailService: ThumbnailManagerService,
@ -27,7 +27,7 @@ export class GalleryDirectoryComponent implements OnInit, OnDestroy {
size: number = null; size: number = null;
getSanitizedThUrl() { 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 //TODO: implement scroll

View File

@ -1,5 +1,5 @@
import {Injectable} from "@angular/core"; import {Injectable} from '@angular/core';
import {Event} from "../../../common/event/Event"; import {Event} from '../../../common/event/Event';
@Injectable() @Injectable()
export class FullScreenService { export class FullScreenService {

View File

@ -1,9 +1,9 @@
gallery-map { gallery-map {
margin-right: 0; margin-right: 0;
margin-left: auto; margin-left: auto;
display: block; display: block;
height: 80px; height: 80px;
width: 100px; width: 100px;
} }
.directories { .directories {

View File

@ -1,18 +1,18 @@
import {Component, OnDestroy, OnInit, ViewChild} from "@angular/core"; import {Component, OnDestroy, OnInit, ViewChild} from '@angular/core';
import {AuthenticationService} from "../model/network/authentication.service"; import {AuthenticationService} from '../model/network/authentication.service';
import {ActivatedRoute, Params, Router} from "@angular/router"; import {ActivatedRoute, Params, Router} from '@angular/router';
import {GalleryService} from "./gallery.service"; import {GalleryService} from './gallery.service';
import {GalleryGridComponent} from "./grid/grid.gallery.component"; import {GalleryGridComponent} from './grid/grid.gallery.component';
import {GallerySearchComponent} from "./search/search.gallery.component"; import {GallerySearchComponent} from './search/search.gallery.component';
import {SearchTypes} from "../../../common/entities/AutoCompleteItem"; import {SearchTypes} from '../../../common/entities/AutoCompleteItem';
import {Config} from "../../../common/config/public/Config"; import {Config} from '../../../common/config/public/Config';
import {DirectoryDTO} from "../../../common/entities/DirectoryDTO"; import {DirectoryDTO} from '../../../common/entities/DirectoryDTO';
import {SearchResultDTO} from "../../../common/entities/SearchResultDTO"; import {SearchResultDTO} from '../../../common/entities/SearchResultDTO';
import {ShareService} from "./share.service"; import {ShareService} from './share.service';
import {NavigationService} from "../model/navigation.service"; import {NavigationService} from '../model/navigation.service';
import {UserRoles} from "../../../common/entities/UserDTO"; import {UserRoles} from '../../../common/entities/UserDTO';
import {Observable} from "rxjs/Rx"; import {Observable} from 'rxjs/Rx';
import {ContentWrapper} from "../../../common/entities/ConentWrapper"; import {ContentWrapper} from '../../../common/entities/ConentWrapper';
@Component({ @Component({
selector: 'gallery', selector: 'gallery',
@ -62,26 +62,33 @@ export class GalleryComponent implements OnInit, OnDestroy {
this.countDown.second = t % 60; this.countDown.second = t % 60;
} }
async ngOnInit() { private onRoute = async (params: Params) => {
await this.shareService.wait(); const searchText = params['searchText'];
if (!this._authService.isAuthenticated() && if (searchText && searchText != '') {
(!this.shareService.isSharing() || let typeString = params['type'];
(this.shareService.isSharing() && Config.Client.Sharing.passwordProtected == true))) {
return this._navigation.toLogin(); if (typeString && typeString != '') {
} let type: SearchTypes = <any>SearchTypes[typeString];
this.showSearchBar = Config.Client.Search.enabled && this._authService.isAuthorized(UserRoles.Guest); this._galleryService.search(searchText, type);
this.showShare = Config.Client.Sharing.enabled && this._authService.isAuthorized(UserRoles.User); return;
}
this.subscription.content = this._galleryService.content.subscribe(this.onContentChange); this._galleryService.search(searchText);
this.subscription.route = this._route.params.subscribe(this.onRoute); return;
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);
};
ngOnDestroy() { ngOnDestroy() {
if (this.subscription.content !== null) { if (this.subscription.content !== null) {
@ -118,33 +125,26 @@ export class GalleryComponent implements OnInit, OnDestroy {
} }
}; };
private onRoute = async (params: Params) => { async ngOnInit() {
const searchText = params['searchText']; await this.shareService.wait();
if (searchText && searchText != "") { if (!this._authService.isAuthenticated() &&
let typeString = params['type']; (!this.shareService.isSharing() ||
(this.shareService.isSharing() && Config.Client.Sharing.passwordProtected == true))) {
if (typeString && typeString != "") { return this._navigation.toLogin();
let type: SearchTypes = <any>SearchTypes[typeString]; }
this._galleryService.search(searchText, type); this.showSearchBar = Config.Client.Search.enabled && this._authService.isAuthorized(UserRoles.Guest);
return; this.showShare = Config.Client.Sharing.enabled && this._authService.isAuthorized(UserRoles.User);
}
this._galleryService.search(searchText); this.subscription.content = this._galleryService.content.subscribe(this.onContentChange);
return; 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() { onLightboxLastElement() {

View File

@ -1,13 +1,13 @@
import {Injectable} from "@angular/core"; import {Injectable} from '@angular/core';
import {NetworkService} from "../model/network/network.service"; import {NetworkService} from '../model/network/network.service';
import {ContentWrapper} from "../../../common/entities/ConentWrapper"; import {ContentWrapper} from '../../../common/entities/ConentWrapper';
import {DirectoryDTO} from "../../../common/entities/DirectoryDTO"; import {DirectoryDTO} from '../../../common/entities/DirectoryDTO';
import {SearchTypes} from "../../../common/entities/AutoCompleteItem"; import {SearchTypes} from '../../../common/entities/AutoCompleteItem';
import {GalleryCacheService} from "./cache.gallery.service"; import {GalleryCacheService} from './cache.gallery.service';
import {BehaviorSubject} from "rxjs/BehaviorSubject"; import {BehaviorSubject} from 'rxjs/BehaviorSubject';
import {SharingDTO} from "../../../common/entities/SharingDTO"; import {SharingDTO} from '../../../common/entities/SharingDTO';
import {Config} from "../../../common/config/public/Config"; import {Config} from '../../../common/config/public/Config';
import {ShareService} from "./share.service"; import {ShareService} from './share.service';
@Injectable() @Injectable()
export class GalleryService { 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) { if (!cw || cw.notModified == true) {
@ -78,8 +78,8 @@ export class GalleryService {
if (this.searchId != null) { if (this.searchId != null) {
clearTimeout(this.searchId); clearTimeout(this.searchId);
} }
if (text === null || text === '' || text.trim() == ".") { if (text === null || text === '' || text.trim() == '.') {
return null return null;
} }
this.content.next(new ContentWrapper()); this.content.next(new ContentWrapper());
@ -87,10 +87,10 @@ export class GalleryService {
cw.searchResult = this.galleryCacheService.getSearch(text, type); cw.searchResult = this.galleryCacheService.getSearch(text, type);
if (cw.searchResult == null) { if (cw.searchResult == null) {
const params = {}; const params = {};
if (typeof type != "undefined") { if (typeof type != 'undefined') {
params['type'] = type; 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.galleryCacheService.setSearch(text, type, cw.searchResult);
} }
this.content.next(cw); this.content.next(cw);
@ -98,16 +98,16 @@ export class GalleryService {
} }
public async instantSearch(text: string): Promise<ContentWrapper> { 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); const content = new ContentWrapper(this.lastDirectory);
this.content.next(content); this.content.next(content);
if (this.searchId != null) { if (this.searchId != null) {
clearTimeout(this.searchId); clearTimeout(this.searchId);
} }
if (!this.lastDirectory) { if (!this.lastDirectory) {
this.getDirectory("/"); this.getDirectory('/');
} }
return null return null;
} }
if (this.searchId != null) { if (this.searchId != null) {
@ -128,7 +128,7 @@ export class GalleryService {
cw.searchResult = this.galleryCacheService.getInstantSearch(text); cw.searchResult = this.galleryCacheService.getInstantSearch(text);
if (cw.searchResult == null) { 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); this.galleryCacheService.setInstantSearch(text, cw.searchResult);
} }
} }
@ -145,7 +145,7 @@ export class GalleryService {
} }
public async getSharing(sharingKey: string): Promise<SharingDTO> { public async getSharing(sharingKey: string): Promise<SharingDTO> {
return this.networkService.getJson<SharingDTO>("/share/" + sharingKey); return this.networkService.getJson<SharingDTO>('/share/' + sharingKey);
} }
} }

View File

@ -1,5 +1,6 @@
import {PhotoDTO} from "../../../../common/entities/PhotoDTO"; import {PhotoDTO} from '../../../../common/entities/PhotoDTO';
import {Photo} from "../Photo"; import {Photo} from '../Photo';
export class GridPhoto extends Photo { export class GridPhoto extends Photo {

View File

@ -1,4 +1,4 @@
import {PhotoDTO} from "../../../../common/entities/PhotoDTO"; import {PhotoDTO} from '../../../../common/entities/PhotoDTO';
export class GridRowBuilder { export class GridRowBuilder {

View File

@ -1,12 +1,12 @@
div { div {
/*display: block;*/ /*display: block;*/
line-height: normal; line-height: normal;
font-size: 0; font-size: 0;
} }
gallery-grid-photo { gallery-grid-photo {
display: inline-block; display: inline-block;
cursor: pointer; cursor: pointer;
margin: 2px; margin: 2px;
} }

View File

@ -1,12 +1,12 @@
<div #gridContainer> <div #gridContainer>
<gallery-grid-photo <gallery-grid-photo
*ngFor="let gridPhoto of photosToRender" *ngFor="let gridPhoto of photosToRender"
(click)="lightbox.show(gridPhoto.photo)" (click)="lightbox.show(gridPhoto.photo)"
[gridPhoto]="gridPhoto" [gridPhoto]="gridPhoto"
[style.width.px]="gridPhoto.renderWidth" [style.width.px]="gridPhoto.renderWidth"
[style.height.px]="gridPhoto.renderHeight" [style.height.px]="gridPhoto.renderHeight"
[style.marginLeft.px]="IMAGE_MARGIN" [style.marginLeft.px]="IMAGE_MARGIN"
[style.marginRight.px]="IMAGE_MARGIN"> [style.marginRight.px]="IMAGE_MARGIN">
</gallery-grid-photo> </gallery-grid-photo>
</div> </div>

View File

@ -10,14 +10,14 @@ import {
QueryList, QueryList,
ViewChild, ViewChild,
ViewChildren ViewChildren
} from "@angular/core"; } from '@angular/core';
import {PhotoDTO} from "../../../../common/entities/PhotoDTO"; import {PhotoDTO} from '../../../../common/entities/PhotoDTO';
import {GridRowBuilder} from "./GridRowBuilder"; import {GridRowBuilder} from './GridRowBuilder';
import {GalleryLightboxComponent} from "../lightbox/lightbox.gallery.component"; import {GalleryLightboxComponent} from '../lightbox/lightbox.gallery.component';
import {GridPhoto} from "./GridPhoto"; import {GridPhoto} from './GridPhoto';
import {GalleryPhotoComponent} from "./photo/photo.grid.gallery.component"; import {GalleryPhotoComponent} from './photo/photo.grid.gallery.component';
import {OverlayService} from "../overlay.service"; import {OverlayService} from '../overlay.service';
import {Config} from "../../../../common/config/public/Config"; import {Config} from '../../../../common/config/public/Config';
@Component({ @Component({
selector: 'gallery-grid', selector: 'gallery-grid',
@ -154,7 +154,7 @@ export class GalleryGridComponent implements OnChanges, AfterViewInit, OnDestroy
this.renderedPhotoIndex < numberOfPhotos)) { this.renderedPhotoIndex < numberOfPhotos)) {
let ret = this.renderARow(); let ret = this.renderARow();
if (ret === null) { if (ret === null) {
throw new Error("Grid photos rendering failed"); throw new Error('Grid photos rendering failed');
} }
renderedContentHeight += ret; renderedContentHeight += ret;
} }

View File

@ -1,97 +1,97 @@
.static { .static {
width: 100%; width: 100%;
height: 100%; height: 100%;
background-color: #bbbbbb; background-color: #bbbbbb;
color: #7f7f7f; color: #7f7f7f;
font-size: 50px; font-size: 50px;
} }
.static span { .static span {
top: calc(50% - 25px); top: calc(50% - 25px);
left: calc(50% - 25px); left: calc(50% - 25px);
} }
.sk-cube-grid { .sk-cube-grid {
width: 100%; width: 100%;
height: 100%; height: 100%;
} }
.sk-cube-grid .sk-cube { .sk-cube-grid .sk-cube {
width: calc(100% / 3); width: calc(100% / 3);
height: calc(100% / 3); height: calc(100% / 3);
background-color: #bbbbbb; background-color: #bbbbbb;
float: left; float: left;
} }
.sk-cube-grid.animate .sk-cube { .sk-cube-grid.animate .sk-cube {
-webkit-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; animation: sk-cubeGridScaleDelay 4.6s infinite ease-in-out;
} }
.sk-cube-grid.animate .sk-cube1 { .sk-cube-grid.animate .sk-cube1 {
-webkit-animation-delay: 0.4s; -webkit-animation-delay: 0.4s;
animation-delay: 0.4s; animation-delay: 0.4s;
} }
.sk-cube-grid.animate .sk-cube2 { .sk-cube-grid.animate .sk-cube2 {
-webkit-animation-delay: 0.6s; -webkit-animation-delay: 0.6s;
animation-delay: 0.6s; animation-delay: 0.6s;
} }
.sk-cube-grid.animate .sk-cube3 { .sk-cube-grid.animate .sk-cube3 {
-webkit-animation-delay: 0.8s; -webkit-animation-delay: 0.8s;
animation-delay: 0.8s; animation-delay: 0.8s;
} }
.sk-cube-grid.animate .sk-cube4 { .sk-cube-grid.animate .sk-cube4 {
-webkit-animation-delay: 0.2s; -webkit-animation-delay: 0.2s;
animation-delay: 0.2s; animation-delay: 0.2s;
} }
.sk-cube-grid.animate .sk-cube5 { .sk-cube-grid.animate .sk-cube5 {
-webkit-animation-delay: 0.4s; -webkit-animation-delay: 0.4s;
animation-delay: 0.4s; animation-delay: 0.4s;
} }
.sk-cube-grid.animate .sk-cube6 { .sk-cube-grid.animate .sk-cube6 {
-webkit-animation-delay: 0.6s; -webkit-animation-delay: 0.6s;
animation-delay: 0.6s; animation-delay: 0.6s;
} }
.sk-cube-grid.animate .sk-cube7 { .sk-cube-grid.animate .sk-cube7 {
-webkit-animation-delay: 0s; -webkit-animation-delay: 0s;
animation-delay: 0s; animation-delay: 0s;
} }
.sk-cube-grid.animate .sk-cube8 { .sk-cube-grid.animate .sk-cube8 {
-webkit-animation-delay: 0.2s; -webkit-animation-delay: 0.2s;
animation-delay: 0.2s; animation-delay: 0.2s;
} }
.sk-cube-grid.animate .sk-cube9 { .sk-cube-grid.animate .sk-cube9 {
-webkit-animation-delay: 0.4s; -webkit-animation-delay: 0.4s;
animation-delay: 0.4s; animation-delay: 0.4s;
} }
@-webkit-keyframes sk-cubeGridScaleDelay { @-webkit-keyframes sk-cubeGridScaleDelay {
0%, 70%, 100% { 0%, 70%, 100% {
-webkit-transform: scale3D(1, 1, 1); -webkit-transform: scale3D(1, 1, 1);
transform: scale3D(1, 1, 1); transform: scale3D(1, 1, 1);
} }
35% { 35% {
-webkit-transform: scale3D(0, 0, 1); -webkit-transform: scale3D(0, 0, 1);
transform: scale3D(0, 0, 1); transform: scale3D(0, 0, 1);
} }
} }
@keyframes sk-cubeGridScaleDelay { @keyframes sk-cubeGridScaleDelay {
0%, 70%, 100% { 0%, 70%, 100% {
-webkit-transform: scale3D(1, 1, 1); -webkit-transform: scale3D(1, 1, 1);
transform: scale3D(1, 1, 1); transform: scale3D(1, 1, 1);
} }
35% { 35% {
-webkit-transform: scale3D(0, 0, 1); -webkit-transform: scale3D(0, 0, 1);
transform: scale3D(0, 0, 1); transform: scale3D(0, 0, 1);
} }
} }

View File

@ -4,13 +4,13 @@
</span> </span>
</div> </div>
<div class="sk-cube-grid animate" *ngIf="animate == true"> <div class="sk-cube-grid animate" *ngIf="animate == true">
<div class="sk-cube sk-cube1"></div> <div class="sk-cube sk-cube1"></div>
<div class="sk-cube sk-cube2"></div> <div class="sk-cube sk-cube2"></div>
<div class="sk-cube sk-cube3"></div> <div class="sk-cube sk-cube3"></div>
<div class="sk-cube sk-cube4"></div> <div class="sk-cube sk-cube4"></div>
<div class="sk-cube sk-cube5"></div> <div class="sk-cube sk-cube5"></div>
<div class="sk-cube sk-cube6"></div> <div class="sk-cube sk-cube6"></div>
<div class="sk-cube sk-cube7"></div> <div class="sk-cube sk-cube7"></div>
<div class="sk-cube sk-cube8"></div> <div class="sk-cube sk-cube8"></div>
<div class="sk-cube sk-cube9"></div> <div class="sk-cube sk-cube9"></div>
</div> </div>

View File

@ -1,4 +1,4 @@
import {Component, Input} from "@angular/core"; import {Component, Input} from '@angular/core';
@Component({ @Component({
selector: 'gallery-grid-photo-loading', selector: 'gallery-grid-photo-loading',

View File

@ -49,11 +49,11 @@ img {
} }
.info { .info {
background-color: transparent; background-color: transparent;
color: white; color: white;
font-size: medium; font-size: medium;
position: relative; position: relative;
padding: 5px; padding: 5px;
margin-top: 0; margin-top: 0;
transition: margin .3s ease-out, background-color .3s ease-out; transition: margin .3s ease-out, background-color .3s ease-out;

View File

@ -1,11 +1,11 @@
import {Component, ElementRef, Input, OnDestroy, OnInit, ViewChild} from "@angular/core"; import {Component, ElementRef, Input, OnDestroy, OnInit, ViewChild} from '@angular/core';
import {Dimension, IRenderable} from "../../../model/IRenderable"; import {Dimension, IRenderable} from '../../../model/IRenderable';
import {GridPhoto} from "../GridPhoto"; import {GridPhoto} from '../GridPhoto';
import {SearchTypes} from "../../../../../common/entities/AutoCompleteItem"; import {SearchTypes} from '../../../../../common/entities/AutoCompleteItem';
import {RouterLink} from "@angular/router"; import {RouterLink} from '@angular/router';
import {Thumbnail, ThumbnailManagerService} from "../../thumnailManager.service"; import {Thumbnail, ThumbnailManagerService} from '../../thumnailManager.service';
import {Config} from "../../../../../common/config/public/Config"; import {Config} from '../../../../../common/config/public/Config';
import {AnimationBuilder} from "@angular/animations"; import {AnimationBuilder} from '@angular/animations';
@Component({ @Component({
selector: 'gallery-grid-photo', selector: 'gallery-grid-photo',
@ -15,9 +15,9 @@ import {AnimationBuilder} from "@angular/animations";
}) })
export class GalleryPhotoComponent implements IRenderable, OnInit, OnDestroy { export class GalleryPhotoComponent implements IRenderable, OnInit, OnDestroy {
@Input() gridPhoto: GridPhoto; @Input() gridPhoto: GridPhoto;
@ViewChild("img") imageRef: ElementRef; @ViewChild('img') imageRef: ElementRef;
@ViewChild("info") infoDiv: ElementRef; @ViewChild('info') infoDiv: ElementRef;
@ViewChild("photoContainer") container: ElementRef; @ViewChild('photoContainer') container: ElementRef;
thumbnail: Thumbnail; thumbnail: Thumbnail;
/* /*
@ -35,7 +35,7 @@ export class GalleryPhotoComponent implements IRenderable, OnInit, OnDestroy {
infoBar = { infoBar = {
marginTop: 0, marginTop: 0,
visible: false, visible: false,
background: "rgba(0,0,0,0.0)" background: 'rgba(0,0,0,0.0)'
}; };
animationTimer = null; animationTimer = null;
@ -83,7 +83,7 @@ export class GalleryPhotoComponent implements IRenderable, OnInit, OnDestroy {
getPositionText(): string { getPositionText(): string {
if (!this.gridPhoto) { if (!this.gridPhoto) {
return "" return '';
} }
return this.gridPhoto.photo.metadata.positionData.city || return this.gridPhoto.photo.metadata.positionData.city ||
this.gridPhoto.photo.metadata.positionData.state || this.gridPhoto.photo.metadata.positionData.state ||
@ -97,7 +97,7 @@ export class GalleryPhotoComponent implements IRenderable, OnInit, OnDestroy {
clearTimeout(this.animationTimer); clearTimeout(this.animationTimer);
} }
this.animationTimer = setTimeout(() => { this.animationTimer = setTimeout(() => {
this.infoBar.background = "rgba(0,0,0,0.8)"; this.infoBar.background = 'rgba(0,0,0,0.8)';
if (!this.infoDiv) { if (!this.infoDiv) {
this.animationTimer = setTimeout(() => { this.animationTimer = setTimeout(() => {
if (!this.infoDiv) { if (!this.infoDiv) {
@ -115,7 +115,7 @@ export class GalleryPhotoComponent implements IRenderable, OnInit, OnDestroy {
mouseOut() { mouseOut() {
this.infoBar.marginTop = 0; 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) { if (this.animationTimer != null) {
clearTimeout(this.animationTimer); clearTimeout(this.animationTimer);
} }

View File

@ -1,6 +1,6 @@
import {Component, ElementRef, EventEmitter, Input, Output} from "@angular/core"; import {Component, ElementRef, EventEmitter, Input, Output} from '@angular/core';
import {PhotoDTO} from "../../../../../common/entities/PhotoDTO"; import {PhotoDTO} from '../../../../../common/entities/PhotoDTO';
import {Config} from "../../../../../common/config/public/Config"; import {Config} from '../../../../../common/config/public/Config';
@Component({ @Component({
selector: 'info-panel', selector: 'info-panel',
@ -21,7 +21,7 @@ export class InfoPanelLightboxComponent {
} }
calcFileSize() { calcFileSize() {
let postFixes = ["B", "KB", "MB", "GB", "TB"]; let postFixes = ['B', 'KB', 'MB', 'GB', 'TB'];
let index = 0; let index = 0;
let size = this.photo.metadata.fileSize; let size = this.photo.metadata.fileSize;
while (size > 1000 && index < postFixes.length - 1) { while (size > 1000 && index < postFixes.length - 1) {
@ -42,8 +42,8 @@ export class InfoPanelLightboxComponent {
getDate() { getDate() {
const date = new Date(this.photo.metadata.creationDate); const date = new Date(this.photo.metadata.creationDate);
let locale = "en-us"; let locale = 'en-us';
return date.toLocaleString(locale, {month: "long"}) + " " + date.getDate(); return date.toLocaleString(locale, {month: 'long'}) + ' ' + date.getDate();
} }
getTime() { getTime() {
@ -53,31 +53,31 @@ export class InfoPanelLightboxComponent {
getDay() { getDay() {
const date = new Date(this.photo.metadata.creationDate); const date = new Date(this.photo.metadata.creationDate);
let locale = "en-us"; let locale = 'en-us';
return date.toLocaleString(locale, {weekday: "long"}); return date.toLocaleString(locale, {weekday: 'long'});
} }
toFraction(f) { toFraction(f) {
if (f > 1) { if (f > 1) {
return f; return f;
} }
return "1/" + (1 / f); return '1/' + (1 / f);
} }
hasGPS() { hasGPS() {
return this.photo.metadata.positionData && this.photo.metadata.positionData.GPSData && 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 { getPositionText(): string {
if (!this.photo.metadata.positionData) { if (!this.photo.metadata.positionData) {
return ""; return '';
} }
let str = this.photo.metadata.positionData.city || let str = this.photo.metadata.positionData.city ||
this.photo.metadata.positionData.state; this.photo.metadata.positionData.state;
if (str.length != 0) { if (str.length != 0) {
str += ", "; str += ', ';
} }
str += this.photo.metadata.positionData.country; str += this.photo.metadata.positionData.country;

View File

@ -1,23 +1,13 @@
import { import {ChangeDetectorRef, Component, ElementRef, EventEmitter, HostListener, OnDestroy, Output, QueryList, ViewChild} from '@angular/core';
ChangeDetectorRef, import {PhotoDTO} from '../../../../common/entities/PhotoDTO';
Component, import {GalleryPhotoComponent} from '../grid/photo/photo.grid.gallery.component';
ElementRef, import {Dimension} from '../../model/IRenderable';
EventEmitter, import {FullScreenService} from '../fullscreen.service';
HostListener, import {OverlayService} from '../overlay.service';
OnDestroy, import {Subscription} from 'rxjs';
Output, import {animate, AnimationBuilder, AnimationPlayer, style} from '@angular/animations';
QueryList, import {GalleryLightboxPhotoComponent} from './photo/photo.lightbox.gallery.component';
ViewChild import {Observable} from 'rxjs/Observable';
} 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({ @Component({
selector: 'gallery-lightbox', selector: 'gallery-lightbox',
@ -28,8 +18,8 @@ export class GalleryLightboxComponent implements OnDestroy {
@Output('onLastElement') onLastElement = new EventEmitter(); @Output('onLastElement') onLastElement = new EventEmitter();
@ViewChild("photo") photoElement: GalleryLightboxPhotoComponent; @ViewChild('photo') photoElement: GalleryLightboxPhotoComponent;
@ViewChild("lightbox") lightboxElement: ElementRef; @ViewChild('lightbox') lightboxElement: ElementRef;
public navigation = {hasPrev: true, hasNext: true}; public navigation = {hasPrev: true, hasNext: true};
public blackCanvasOpacity: any = 0; public blackCanvasOpacity: any = 0;
@ -108,40 +98,13 @@ export class GalleryLightboxComponent implements OnDestroy {
this.updateActivePhoto(photoIndex, resize); 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) { public show(photo: PhotoDTO) {
this.controllersVisible = true; this.controllersVisible = true;
this.showControls(); this.showControls();
this.visible = true; this.visible = true;
let selectedPhoto = this.findPhotoComponent(photo); let selectedPhoto = this.findPhotoComponent(photo);
if (selectedPhoto === null) { if (selectedPhoto === null) {
throw new Error("Can't find Photo"); throw new Error('Can\'t find Photo');
} }
const lightboxDimension = selectedPhoto.getDimension(); const lightboxDimension = selectedPhoto.getDimension();
@ -168,6 +131,33 @@ export class GalleryLightboxComponent implements OnDestroy {
this.showPhoto(this.gridPhotoQL.toArray().indexOf(selectedPhoto), false); 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() { public hide() {
this.controllersVisible = false; this.controllersVisible = false;
this.fullScreenService.exitFullScreen(); this.fullScreenService.exitFullScreen();

View File

@ -1,9 +1,9 @@
.imgContainer img { .imgContainer img {
position: absolute; position: absolute;
} }
.imgContainer { .imgContainer {
justify-content: center; /* add to align horizontal */ justify-content: center; /* add to align horizontal */
align-items: center; /* add to align vertical */ align-items: center; /* add to align vertical */
} }

View File

@ -1,8 +1,8 @@
<div class="imgContainer" #imgContainer> <div class="imgContainer" #imgContainer>
<img *ngIf="showThumbnail()" <img *ngIf="showThumbnail()"
[style.width.%]="imageSize.width" [style.width.%]="imageSize.width"
[style.height.%]="imageSize.height" [style.height.%]="imageSize.height"
[src]="thumbnailPath()"/> [src]="thumbnailPath()"/>
<img *ngIf="gridPhoto !== null && loadImage" <img *ngIf="gridPhoto !== null && loadImage"
[style.width.%]="imageSize.width" [style.width.%]="imageSize.width"

View File

@ -1,5 +1,5 @@
import {Component, ElementRef, Input, OnChanges} from "@angular/core"; import {Component, ElementRef, Input, OnChanges} from '@angular/core';
import {GridPhoto} from "../../grid/GridPhoto"; import {GridPhoto} from '../../grid/GridPhoto';
@Component({ @Component({
selector: 'gallery-lightbox-photo', selector: 'gallery-lightbox-photo',
@ -12,7 +12,7 @@ export class GalleryLightboxPhotoComponent implements OnChanges {
@Input() loadImage: boolean = false; @Input() loadImage: boolean = false;
@Input() windowAspect: number = 1; @Input() windowAspect: number = 1;
public imageSize = {width: "auto", height: "100"}; public imageSize = {width: 'auto', height: '100'};
imageLoaded: boolean = false; imageLoaded: boolean = false;
public imageLoadFinished: boolean = false; public imageLoadFinished: boolean = false;
@ -27,6 +27,32 @@ export class GalleryLightboxPhotoComponent implements OnChanges {
this.setImageSize(); 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() { private setImageSize() {
if (!this.gridPhoto) { if (!this.gridPhoto) {
return; return;
@ -36,39 +62,13 @@ export class GalleryLightboxPhotoComponent implements OnChanges {
const photoAspect = this.gridPhoto.photo.metadata.size.width / this.gridPhoto.photo.metadata.size.height; const photoAspect = this.gridPhoto.photo.metadata.size.width / this.gridPhoto.photo.metadata.size.height;
if (photoAspect < this.windowAspect) { if (photoAspect < this.windowAspect) {
this.imageSize.height = "100"; this.imageSize.height = '100';
this.imageSize.width = null; this.imageSize.width = null;
} else { } else {
this.imageSize.height = null; 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
}
} }

View File

@ -1,67 +1,67 @@
.lightbox { .lightbox {
position: fixed; /* Stay in place */ position: fixed; /* Stay in place */
z-index: 1100; /* Sit on top */ z-index: 1100; /* Sit on top */
left: 0; left: 0;
top: 0; top: 0;
width: 100%; /* Full width */ width: 100%; /* Full width */
height: 100%; /* Full height */ height: 100%; /* Full height */
overflow: hidden; overflow: hidden;
display: flex; /* add */ display: flex; /* add */
justify-content: center; /* add to align horizontal */ justify-content: center; /* add to align horizontal */
align-items: center; /* add to align vertical */ align-items: center; /* add to align vertical */
cursor: pointer; cursor: pointer;
transition: all 0.3s ease-in-out; transition: all 0.3s ease-in-out;
} }
.sebm-google-map-container { .sebm-google-map-container {
width: 100%; width: 100%;
height: 100%; height: 100%;
} }
.blackCanvas { .blackCanvas {
position: fixed; /* Stay in place */ position: fixed; /* Stay in place */
z-index: 1099; /* Sit on top */ z-index: 1099; /* Sit on top */
left: 0; left: 0;
top: 0; top: 0;
width: 100%; /* Full width */ width: 100%; /* Full width */
height: 100%; /* Full height */ height: 100%; /* Full height */
background-color: black; background-color: black;
transition: all 0.3s ease-in-out; transition: all 0.3s ease-in-out;
} }
#controllers-container { #controllers-container {
z-index: 1100; z-index: 1100;
right: 0; right: 0;
top: 0; top: 0;
position: fixed; position: fixed;
} }
#controls { #controls {
top: 0; top: 0;
height: initial; height: initial;
text-align: right; text-align: right;
width: 100%; width: 100%;
padding: 5px; padding: 5px;
font-size: large; font-size: large;
} }
#controls span { #controls span {
margin-left: 6px; margin-left: 6px;
margin-right: 6px; margin-right: 6px;
color: black; color: black;
cursor: pointer; cursor: pointer;
} }
.highlight { .highlight {
opacity: 0.4; opacity: 0.4;
transition: opacity .2s ease-out; transition: opacity .2s ease-out;
-moz-transition: opacity .2s ease-out; -moz-transition: opacity .2s ease-out;
-webkit-transition: opacity .2s ease-out; -webkit-transition: opacity .2s ease-out;
-o-transition: opacity .2s ease-out; -o-transition: opacity .2s ease-out;
} }
.highlight:hover { .highlight:hover {
opacity: 1.0; opacity: 1.0;
} }
.preview-loading { .preview-loading {

View File

@ -1,11 +1,11 @@
import {Component, ElementRef, HostListener, Input, OnChanges, ViewChild} from "@angular/core"; import {Component, ElementRef, HostListener, Input, OnChanges, ViewChild} from '@angular/core';
import {PhotoDTO} from "../../../../../common/entities/PhotoDTO"; import {PhotoDTO} from '../../../../../common/entities/PhotoDTO';
import {Dimension} from "../../../model/IRenderable"; import {Dimension} from '../../../model/IRenderable';
import {FullScreenService} from "../../fullscreen.service"; import {FullScreenService} from '../../fullscreen.service';
import {AgmMap} from "@agm/core"; import {AgmMap} from '@agm/core';
import {IconThumbnail, Thumbnail, ThumbnailManagerService} from "../../thumnailManager.service"; import {IconThumbnail, Thumbnail, ThumbnailManagerService} from '../../thumnailManager.service';
import {IconPhoto} from "../../IconPhoto"; import {IconPhoto} from '../../IconPhoto';
import {Photo} from "../../Photo"; import {Photo} from '../../Photo';
@Component({ @Component({
selector: 'gallery-map-lightbox', selector: 'gallery-map-lightbox',
@ -23,7 +23,7 @@ export class GalleryMapLightboxComponent implements OnChanges {
mapPhotos: MapPhoto[] = []; mapPhotos: MapPhoto[] = [];
mapCenter = {latitude: 0, longitude: 0}; mapCenter = {latitude: 0, longitude: 0};
@ViewChild("root") elementRef: ElementRef; @ViewChild('root') elementRef: ElementRef;
@ViewChild(AgmMap) map: AgmMap; @ViewChild(AgmMap) map: AgmMap;

View File

@ -1,10 +1,10 @@
.sebm-google-map-container { .sebm-google-map-container {
width: 100%; width: 100%;
height: 100%; height: 100%;
} }
#map { #map {
width: 100%; width: 100%;
height: 100%; height: 100%;
} }

View File

@ -1,7 +1,8 @@
import {Component, ElementRef, Input, OnChanges, ViewChild} from "@angular/core"; import {Component, ElementRef, Input, OnChanges, ViewChild} from '@angular/core';
import {PhotoDTO} from "../../../../common/entities/PhotoDTO"; import {PhotoDTO} from '../../../../common/entities/PhotoDTO';
import {Dimension, IRenderable} from "../../model/IRenderable"; import {Dimension, IRenderable} from '../../model/IRenderable';
import {GalleryMapLightboxComponent} from "./lightbox/lightbox.map.gallery.component"; import {GalleryMapLightboxComponent} from './lightbox/lightbox.map.gallery.component';
@Component({ @Component({
selector: 'gallery-map', selector: 'gallery-map',
templateUrl: './map.gallery.component.html', templateUrl: './map.gallery.component.html',
@ -14,7 +15,7 @@ export class GalleryMapComponent implements OnChanges, IRenderable {
mapPhotos: Array<{ latitude: number, longitude: number }> = []; mapPhotos: Array<{ latitude: number, longitude: number }> = [];
mapCenter = {latitude: 0, longitude: 0}; mapCenter = {latitude: 0, longitude: 0};
@ViewChild("map") map: ElementRef; @ViewChild('map') map: ElementRef;
//TODO: fix zooming //TODO: fix zooming
ngOnChanges() { ngOnChanges() {

View File

@ -1,10 +1,10 @@
import {Component, Input, OnChanges} from "@angular/core"; import {Component, Input, OnChanges} from '@angular/core';
import {DirectoryDTO} from "../../../../common/entities/DirectoryDTO"; import {DirectoryDTO} from '../../../../common/entities/DirectoryDTO';
import {RouterLink} from "@angular/router"; import {RouterLink} from '@angular/router';
import {UserDTO} from "../../../../common/entities/UserDTO"; import {UserDTO} from '../../../../common/entities/UserDTO';
import {AuthenticationService} from "../../model/network/authentication.service"; import {AuthenticationService} from '../../model/network/authentication.service';
import {ShareService} from "../share.service"; import {ShareService} from '../share.service';
import {I18n} from "@ngx-translate/i18n-polyfill"; import {I18n} from '@ngx-translate/i18n-polyfill';
@Component({ @Component({
selector: 'gallery-navbar', selector: 'gallery-navbar',
@ -31,14 +31,14 @@ export class GalleryNavigatorComponent implements OnChanges {
return []; 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); dirs.push(this.directory.name);
//removing empty strings //removing empty strings
for (let i = 0; i < dirs.length; i++) { 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); dirs.splice(i, 1);
i--; i--;
} }
@ -49,14 +49,14 @@ export class GalleryNavigatorComponent implements OnChanges {
//create root link //create root link
if (dirs.length == 0) { if (dirs.length == 0) {
arr.push({name: this.i18n("Images"), route: null}); arr.push({name: this.i18n('Images'), route: null});
} else { } 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 //create rest navigation
dirs.forEach((name, index) => { 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) { if (dirs.length - 1 == index) {
arr.push({name: name, route: null}); arr.push({name: name, route: null});
} else { } else {

View File

@ -1,5 +1,5 @@
import {Injectable} from "@angular/core"; import {Injectable} from '@angular/core';
import {Event} from "../../../common/event/Event"; import {Event} from '../../../common/event/Event';
@Injectable() @Injectable()
export class OverlayService { export class OverlayService {
@ -24,20 +24,20 @@ export class OverlayService {
if (this.scrollWidth == null) { if (this.scrollWidth == null) {
let outer = document.createElement("div"); let outer = document.createElement('div');
outer.style.visibility = "hidden"; outer.style.visibility = 'hidden';
outer.style.width = "100px"; outer.style.width = '100px';
outer.style.msOverflowStyle = "scrollbar"; // needed for WinJS apps outer.style.msOverflowStyle = 'scrollbar'; // needed for WinJS apps
document.body.appendChild(outer); document.body.appendChild(outer);
let widthNoScroll = outer.offsetWidth; let widthNoScroll = outer.offsetWidth;
// force scrollbars // force scrollbars
outer.style.overflowY = "scroll"; outer.style.overflowY = 'scroll';
// add innerdiv // add innerdiv
let inner = document.createElement("div"); let inner = document.createElement('div');
inner.style.width = "100%"; inner.style.width = '100%';
outer.appendChild(inner); outer.appendChild(inner);
let widthWithScroll = inner.offsetWidth; let widthWithScroll = inner.offsetWidth;

View File

@ -1,7 +1,7 @@
import {Injectable} from "@angular/core"; import {Injectable} from '@angular/core';
import {NetworkService} from "../../model/network/network.service"; import {NetworkService} from '../../model/network/network.service';
import {AutoCompleteItem} from "../../../../common/entities/AutoCompleteItem"; import {AutoCompleteItem} from '../../../../common/entities/AutoCompleteItem';
import {GalleryCacheService} from "../cache.gallery.service"; import {GalleryCacheService} from '../cache.gallery.service';
@Injectable() @Injectable()
export class AutoCompleteService { export class AutoCompleteService {
@ -14,7 +14,7 @@ export class AutoCompleteService {
public async autoComplete(text: string): Promise<Array<AutoCompleteItem>> { public async autoComplete(text: string): Promise<Array<AutoCompleteItem>> {
let items: Array<AutoCompleteItem> = this.galleryCacheService.getAutoComplete(text); let items: Array<AutoCompleteItem> = this.galleryCacheService.getAutoComplete(text);
if (items == null) { 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); this.galleryCacheService.setAutoComplete(text, items);
} }
return items; return items;

View File

@ -1,9 +1,9 @@
import {Component} from "@angular/core"; import {Component} from '@angular/core';
import {AutoCompleteService} from "./autocomplete.service"; import {AutoCompleteService} from './autocomplete.service';
import {AutoCompleteItem, SearchTypes} from "../../../../common/entities/AutoCompleteItem"; import {AutoCompleteItem, SearchTypes} from '../../../../common/entities/AutoCompleteItem';
import {ActivatedRoute, Params, RouterLink} from "@angular/router"; import {ActivatedRoute, Params, RouterLink} from '@angular/router';
import {GalleryService} from "../gallery.service"; import {GalleryService} from '../gallery.service';
import {Config} from "../../../../common/config/public/Config"; import {Config} from '../../../../common/config/public/Config';
@Component({ @Component({
selector: 'gallery-search', selector: 'gallery-search',
@ -14,10 +14,10 @@ import {Config} from "../../../../common/config/public/Config";
export class GallerySearchComponent { export class GallerySearchComponent {
autoCompleteItems: Array<AutoCompleteRenderItem> = []; autoCompleteItems: Array<AutoCompleteRenderItem> = [];
public searchText: string = ""; public searchText: string = '';
private cache = { private cache = {
lastAutocomplete: "", lastAutocomplete: '',
lastInstantSearch: "" lastInstantSearch: ''
}; };
SearchTypes: any = []; SearchTypes: any = [];
@ -32,7 +32,7 @@ export class GallerySearchComponent {
this.subscription = this._route.params.subscribe((params: Params) => { this.subscription = this._route.params.subscribe((params: Params) => {
let searchText = params['searchText']; let searchText = params['searchText'];
if (searchText && searchText != "") { if (searchText && searchText != '') {
this.searchText = searchText; this.searchText = searchText;
} }
}); });
@ -41,7 +41,7 @@ export class GallerySearchComponent {
ngOnDestroy() { ngOnDestroy() {
if (this.subscription !== null) { if (this.subscription !== null) {
this.subscription.unsubscribe() this.subscription.unsubscribe();
} }
} }
@ -94,9 +94,9 @@ export class GallerySearchComponent {
private async autocomplete(searchText: string) { private async autocomplete(searchText: string) {
if (!Config.Client.Search.autocompleteEnabled) { if (!Config.Client.Search.autocompleteEnabled) {
return return;
} }
if (searchText.trim() == ".") { if (searchText.trim() == '.') {
return; return;
} }
@ -129,9 +129,9 @@ export class GallerySearchComponent {
} }
class AutoCompleteRenderItem { class AutoCompleteRenderItem {
public preText: string = ""; public preText: string = '';
public highLightText: string = ""; public highLightText: string = '';
public postText: string = ""; public postText: string = '';
public type: SearchTypes; public type: SearchTypes;
constructor(public text: string, searchText: string, type: SearchTypes) { constructor(public text: string, searchText: string, type: SearchTypes) {

View File

@ -1,8 +1,8 @@
import {Injectable} from "@angular/core"; import {Injectable} from '@angular/core';
import {NetworkService} from "../model/network/network.service"; import {NetworkService} from '../model/network/network.service';
import {CreateSharingDTO, SharingDTO} from "../../../common/entities/SharingDTO"; import {CreateSharingDTO, SharingDTO} from '../../../common/entities/SharingDTO';
import {Router, RoutesRecognized} from "@angular/router"; import {Router, RoutesRecognized} from '@angular/router';
import {BehaviorSubject} from "rxjs/BehaviorSubject"; import {BehaviorSubject} from 'rxjs/BehaviorSubject';
@Injectable() @Injectable()
export class ShareService { export class ShareService {
@ -27,8 +27,8 @@ export class ShareService {
this.router.events.subscribe(val => { this.router.events.subscribe(val => {
if (val instanceof RoutesRecognized) { if (val instanceof RoutesRecognized) {
this.param = val.state.root.firstChild.params["sharingKey"] || null; this.param = val.state.root.firstChild.params['sharingKey'] || null;
this.queryParam = val.state.root.firstChild.queryParams["sk"] || null; this.queryParam = val.state.root.firstChild.queryParams['sk'] || null;
const changed = this.sharingKey != this.param || this.queryParam; const changed = this.sharingKey != this.param || this.queryParam;
if (changed) { if (changed) {
this.sharingKey = this.param || this.queryParam; this.sharingKey = this.param || this.queryParam;
@ -50,7 +50,7 @@ export class ShareService {
} }
public createSharing(dir: string, includeSubfolders: boolean, valid: number): Promise<SharingDTO> { public createSharing(dir: string, includeSubfolders: boolean, valid: number): Promise<SharingDTO> {
return this._networkService.postJson("/share/" + dir, { return this._networkService.postJson('/share/' + dir, {
createSharing: <CreateSharingDTO>{ createSharing: <CreateSharingDTO>{
includeSubfolders: includeSubfolders, includeSubfolders: includeSubfolders,
valid: valid valid: valid
@ -59,7 +59,7 @@ export class ShareService {
} }
public updateSharing(dir: string, sharingId: number, includeSubfolders: boolean, password: string, valid: number): Promise<SharingDTO> { 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>{ updateSharing: <CreateSharingDTO>{
id: sharingId, id: sharingId,
includeSubfolders: includeSubfolders, includeSubfolders: includeSubfolders,
@ -79,7 +79,7 @@ export class ShareService {
} }
public async getSharing(): Promise<SharingDTO> { 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); this.sharing.next(sharing);
return sharing; return sharing;
} }

View File

@ -1,14 +1,14 @@
import {Component, OnDestroy, OnInit, ViewChild} from "@angular/core"; import {Component, OnDestroy, OnInit, ViewChild} from '@angular/core';
import {Utils} from "../../../../common/Utils"; import {Utils} from '../../../../common/Utils';
import {ShareService} from "../share.service"; import {ShareService} from '../share.service';
import {GalleryService} from "../gallery.service"; import {GalleryService} from '../gallery.service';
import {ContentWrapper} from "../../../../common/entities/ConentWrapper"; import {ContentWrapper} from '../../../../common/entities/ConentWrapper';
import {SharingDTO} from "../../../../common/entities/SharingDTO"; import {SharingDTO} from '../../../../common/entities/SharingDTO';
import {ModalDirective} from "ngx-bootstrap/modal"; import {ModalDirective} from 'ngx-bootstrap/modal';
import {Config} from "../../../../common/config/public/Config"; import {Config} from '../../../../common/config/public/Config';
import {NotificationService} from "../../model/notification.service"; import {NotificationService} from '../../model/notification.service';
import {DirectoryDTO} from "../../../../common/entities/DirectoryDTO"; import {DirectoryDTO} from '../../../../common/entities/DirectoryDTO';
import {I18n} from "@ngx-translate/i18n-polyfill"; import {I18n} from '@ngx-translate/i18n-polyfill';
@Component({ @Component({
@ -20,7 +20,7 @@ export class GalleryShareComponent implements OnInit, OnDestroy {
@ViewChild('shareModal') public childModal: ModalDirective; @ViewChild('shareModal') public childModal: ModalDirective;
enabled: boolean = true; enabled: boolean = true;
url: string = ""; url: string = '';
input = { input = {
includeSubfolders: true, includeSubfolders: true,
@ -28,9 +28,9 @@ export class GalleryShareComponent implements OnInit, OnDestroy {
amount: 30, amount: 30,
type: ValidityTypes.Days type: ValidityTypes.Days
}, },
password: "" password: ''
}; };
currentDir: string = ""; currentDir: string = '';
sharing: SharingDTO = null; sharing: SharingDTO = null;
contentSubscription = null; contentSubscription = null;
passwordProtection = false; passwordProtection = false;
@ -72,33 +72,33 @@ export class GalleryShareComponent implements OnInit, OnDestroy {
case ValidityTypes.Months: case ValidityTypes.Months:
return this.input.valid.amount * 1000 * 60 * 60 * 24 * 30; 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() { async update() {
if (this.sharing == null) { if (this.sharing == null) {
return; 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.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() { async get() {
this.url = "loading.."; this.url = 'loading..';
this.sharing = await this._sharingService.createSharing(this.currentDir, this.input.includeSubfolders, this.calcValidity()); 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() { async showModal() {
await this.get(); await this.get();
this.input.password = ""; this.input.password = '';
this.childModal.show(); this.childModal.show();
document.body.style.paddingRight = "0px"; document.body.style.paddingRight = '0px';
} }
onCopy() { 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() { public hideModal() {

View File

@ -1,9 +1,9 @@
import {Injectable} from "@angular/core"; import {Injectable} from '@angular/core';
import {GalleryCacheService} from "./cache.gallery.service"; import {GalleryCacheService} from './cache.gallery.service';
import {Photo} from "./Photo"; import {Photo} from './Photo';
import {IconPhoto} from "./IconPhoto"; import {IconPhoto} from './IconPhoto';
import {PhotoDTO} from "../../../common/entities/PhotoDTO"; import {PhotoDTO} from '../../../common/entities/PhotoDTO';
import {Config} from "../../../common/config/public/Config"; import {Config} from '../../../common/config/public/Config';
export enum ThumbnailLoadingPriority { export enum ThumbnailLoadingPriority {
extraHigh = 4, high = 3, medium = 2, low = 1 extraHigh = 4, high = 3, medium = 2, low = 1
@ -23,7 +23,7 @@ export class ThumbnailLoaderService {
let index = taskEntry.parentTask.taskEntities.indexOf(taskEntry); let index = taskEntry.parentTask.taskEntities.indexOf(taskEntry);
if (index == -1) { 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); taskEntry.parentTask.taskEntities.splice(index, 1);
@ -31,7 +31,7 @@ export class ThumbnailLoaderService {
&& taskEntry.parentTask.inProgress == false) { && taskEntry.parentTask.inProgress == false) {
let i = this.que.indexOf(taskEntry.parentTask); let i = this.que.indexOf(taskEntry.parentTask);
if (i == -1) { if (i == -1) {
throw new Error("ThumbnailTask not exist"); throw new Error('ThumbnailTask not exist');
} }
this.que.splice(i, 1); this.que.splice(i, 1);
} }
@ -136,7 +136,7 @@ export class ThumbnailLoaderService {
let i = this.que.indexOf(task); let i = this.que.indexOf(task);
if (i == -1) { if (i == -1) {
if (task.taskEntities.length !== 0) { if (task.taskEntities.length !== 0) {
console.error("ThumbnailLoader: can't find poolTask to remove"); console.error('ThumbnailLoader: can\'t find poolTask to remove');
} }
return; return;
} }

View File

@ -1,12 +1,7 @@
import {Injectable} from "@angular/core"; import {Injectable} from '@angular/core';
import { import {ThumbnailLoaderService, ThumbnailLoadingListener, ThumbnailLoadingPriority, ThumbnailTaskEntity} from './thumnailLoader.service';
ThumbnailLoaderService, import {Photo} from './Photo';
ThumbnailLoadingListener, import {IconPhoto} from './IconPhoto';
ThumbnailLoadingPriority,
ThumbnailTaskEntity
} from "./thumnailLoader.service";
import {Photo} from "./Photo";
import {IconPhoto} from "./IconPhoto";
@Injectable() @Injectable()
@ -80,7 +75,7 @@ export class IconThumbnail extends ThumbnailBase {
constructor(private photo: IconPhoto, thumbnailService: ThumbnailLoaderService) { constructor(private photo: IconPhoto, thumbnailService: ThumbnailLoaderService) {
super(thumbnailService); super(thumbnailService);
this.src = ""; this.src = '';
this.error = false; this.error = false;
if (this.photo.isIconAvailable()) { if (this.photo.isIconAvailable()) {
this.src = this.photo.getIconPath(); this.src = this.photo.getIconPath();
@ -166,28 +161,28 @@ export class Thumbnail extends ThumbnailBase {
public load() { public load() {
if (!this.photo.isThumbnailAvailable() && this.thumbnailTask == null) { if (!this.photo.isThumbnailAvailable() && this.thumbnailTask == null) {
// setTimeout(() => { // setTimeout(() => {
let listener: ThumbnailLoadingListener = { let listener: ThumbnailLoadingListener = {
onStartedLoading: () => { //onLoadStarted onStartedLoading: () => { //onLoadStarted
this.loading = true; this.loading = true;
}, },
onLoad: () => {//onLoaded onLoad: () => {//onLoaded
this.src = this.photo.getThumbnailPath(); this.src = this.photo.getThumbnailPath();
if (this.onLoad) this.onLoad(); if (this.onLoad) this.onLoad();
this.available = true; this.available = true;
this.loading = false; this.loading = false;
this.thumbnailTask = null; this.thumbnailTask = null;
}, },
onError: (error) => {//onError onError: (error) => {//onError
this.thumbnailTask = null; this.thumbnailTask = null;
this.loading = false; this.loading = false;
this.error = true; 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);
} }
};
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); // }, 0);
} }
} }

View File

@ -1,7 +1,7 @@
import {Component, Input} from "@angular/core"; import {Component, Input} from '@angular/core';
import {Config} from "../../../common/config/public/Config"; import {Config} from '../../../common/config/public/Config';
import {Cookie} from "ng2-cookies"; import {Cookie} from 'ng2-cookies';
import {CookieNames} from "../../../common/CookieNames"; import {CookieNames} from '../../../common/CookieNames';
@Component({ @Component({
selector: 'language', selector: 'language',

View File

@ -1,9 +1,9 @@
import {Component, OnInit} from "@angular/core"; import {Component, OnInit} from '@angular/core';
import {LoginCredential} from "../../../common/entities/LoginCredential"; import {LoginCredential} from '../../../common/entities/LoginCredential';
import {AuthenticationService} from "../model/network/authentication.service"; import {AuthenticationService} from '../model/network/authentication.service';
import {ErrorCodes} from "../../../common/entities/Error"; import {ErrorCodes} from '../../../common/entities/Error';
import {Config} from "../../../common/config/public/Config"; import {Config} from '../../../common/config/public/Config';
import {NavigationService} from "../model/navigation.service"; import {NavigationService} from '../model/navigation.service';
@Component({ @Component({
selector: 'login', selector: 'login',

View File

@ -11,6 +11,6 @@ export interface Dimension {
export module Dimension { export module Dimension {
export const toString = (dim: 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'};
} };
} }

View File

@ -1,7 +1,7 @@
import {Injectable} from "@angular/core"; import {Injectable} from '@angular/core';
import {Router} from "@angular/router"; import {Router} from '@angular/router';
import {ShareService} from "../gallery/share.service"; import {ShareService} from '../gallery/share.service';
@Injectable() @Injectable()
export class NavigationService { export class NavigationService {
@ -17,22 +17,22 @@ export class NavigationService {
} }
public async toLogin() { public async toLogin() {
console.log("toLogin"); console.log('toLogin');
await this._shareService.wait(); await this._shareService.wait();
if (this._shareService.isSharing()) { 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 { } else {
return this._router.navigate(["login"]); return this._router.navigate(['login']);
} }
} }
public async toGallery() { public async toGallery() {
console.log("toGallery"); console.log('toGallery');
await this._shareService.wait(); await this._shareService.wait();
if (this._shareService.isSharing()) { 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 { } 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