1
0
mirror of https://github.com/bpatrik/pigallery2.git synced 2025-10-30 23:57:43 +02:00

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
node_js:
- '9'
@@ -14,3 +15,9 @@ deploy:
cache:
directories:
- node_modules
addons:
chrome: stable
before_install:
- # start your web application and listen on `localhost`
- google-chrome-stable --headless --disable-gpu --remote-debugging-port=9222 http://localhost &

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,11 +1,12 @@
import {NotificationDTO, NotificationType} from "../../common/entities/NotificationDTO";
import {NotificationDTO, NotificationType} from '../../common/entities/NotificationDTO';
export class NotificationManager {
public static notifications: NotificationDTO[] = [];
public static HasNotification: NotificationDTO[] =
[
{
type: NotificationType.info,
message: "There are unhandled server notification. Login as Administrator to handle them."
message: 'There are unhandled server notification. Login as Administrator to handle them.'
}
];

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,6 +1,6 @@
import {Column, Entity, ManyToOne, OneToMany, PrimaryGeneratedColumn} from "typeorm";
import {DirectoryDTO} from "../../../../common/entities/DirectoryDTO";
import {PhotoEntity} from "./PhotoEntity";
import {Column, Entity, ManyToOne, OneToMany, PrimaryGeneratedColumn} from 'typeorm';
import {DirectoryDTO} from '../../../../common/entities/DirectoryDTO';
import {PhotoEntity} from './PhotoEntity';
@Entity()
export class DirectoryEntity implements DirectoryDTO {
@@ -23,12 +23,12 @@ export class DirectoryEntity implements DirectoryDTO {
/**
* Last time the directory was fully scanned, not only for a few photos to create a preview
*/
@Column({type: "bigint", nullable: true})
@Column({type: 'bigint', nullable: true})
public lastScanned: number;
isPartial?: boolean;
@ManyToOne(type => DirectoryEntity, directory => directory.directories, {onDelete: "CASCADE"})
@ManyToOne(type => DirectoryEntity, directory => directory.directories, {onDelete: 'CASCADE'})
public parent: DirectoryEntity;
@OneToMany(type => DirectoryEntity, dir => dir.parent)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,10 +1,10 @@
import * as cluster from "cluster";
import {Logger} from "../../Logger";
import {DiskManagerTask, ThumbnailTask, WorkerMessage, WorkerTask, WorkerTaskTypes} from "./Worker";
import {DirectoryDTO} from "../../../common/entities/DirectoryDTO";
import {RendererInput} from "./ThumbnailWoker";
import {Config} from "../../../common/config/private/Config";
import {ITaskQue} from "./TaskQue";
import * as cluster from 'cluster';
import {Logger} from '../../Logger';
import {DiskManagerTask, ThumbnailTask, WorkerMessage, WorkerTask, WorkerTaskTypes} from './Worker';
import {DirectoryDTO} from '../../../common/entities/DirectoryDTO';
import {RendererInput} from './ThumbnailWoker';
import {Config} from '../../../common/config/private/Config';
import {ITaskQue} from './TaskQue';
interface PoolTask {
@@ -24,7 +24,7 @@ export class ThreadPool {
private tasks: PoolTask[] = [];
constructor(private size: number) {
Logger.silly("Creating thread pool with", size, "workers");
Logger.silly('Creating thread pool with', size, 'workers');
for (let i = 0; i < size; i++) {
this.startWorker();
}
@@ -39,14 +39,14 @@ export class ThreadPool {
});
worker.worker.on('exit', (code, signal) => {
ThreadPool.WorkerCount--;
Logger.warn('Worker ' + worker.worker.process.pid + ' died with code: ' + code + ', and signal: ' + signal + ", worker count:", ThreadPool.WorkerCount);
Logger.warn('Worker ' + worker.worker.process.pid + ' died with code: ' + code + ', and signal: ' + signal + ', worker count:', ThreadPool.WorkerCount);
Logger.debug('Starting a new worker');
this.startWorker();
});
worker.worker.on("message", (msg: WorkerMessage) => {
worker.worker.on('message', (msg: WorkerMessage) => {
if (worker.poolTask == null) {
throw "No worker task after worker task is completed"
throw 'No worker task after worker task is completed';
}
if (msg.error) {
worker.poolTask.promise.reject(msg.error);

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,8 +1,8 @@
import {AuthenticationMWs} from "../middlewares/user/AuthenticationMWs";
import {GalleryMWs} from "../middlewares/GalleryMWs";
import {RenderingMWs} from "../middlewares/RenderingMWs";
import {ThumbnailGeneratorMWs} from "../middlewares/thumbnail/ThumbnailGeneratorMWs";
import {UserRoles} from "../../common/entities/UserDTO";
import {AuthenticationMWs} from '../middlewares/user/AuthenticationMWs';
import {GalleryMWs} from '../middlewares/GalleryMWs';
import {RenderingMWs} from '../middlewares/RenderingMWs';
import {ThumbnailGeneratorMWs} from '../middlewares/thumbnail/ThumbnailGeneratorMWs';
import {UserRoles} from '../../common/entities/UserDTO';
export class GalleryRouter {
public static route(app: any) {
@@ -18,7 +18,7 @@ export class GalleryRouter {
}
private static addDirectoryList(app) {
app.get(["/api/gallery/content/:directory(*)", "/api/gallery/", "/api/gallery//"],
app.get(['/api/gallery/content/:directory(*)', '/api/gallery/', '/api/gallery//'],
AuthenticationMWs.authenticate,
AuthenticationMWs.authoriseDirectory,
GalleryMWs.listDirectory,
@@ -26,40 +26,40 @@ export class GalleryRouter {
GalleryMWs.removeCyclicDirectoryReferences,
RenderingMWs.renderResult
);
};
}
private static addGetImage(app) {
app.get(["/api/gallery/content/:imagePath(*\.(jpg|bmp|png|gif|jpeg))"],
app.get(['/api/gallery/content/:imagePath(*\.(jpg|bmp|png|gif|jpeg))'],
AuthenticationMWs.authenticate,
//TODO: authorize path
// TODO: authorize path
GalleryMWs.loadImage,
RenderingMWs.renderFile
);
};
}
private static addGetImageThumbnail(app) {
app.get("/api/gallery/content/:imagePath(*\.(jpg|bmp|png|gif|jpeg))/thumbnail/:size?",
app.get('/api/gallery/content/:imagePath(*\.(jpg|bmp|png|gif|jpeg))/thumbnail/:size?',
AuthenticationMWs.authenticate,
//TODO: authorize path
// TODO: authorize path
GalleryMWs.loadImage,
ThumbnailGeneratorMWs.generateThumbnail,
RenderingMWs.renderFile
);
};
}
private static addGetImageIcon(app) {
app.get("/api/gallery/content/:imagePath(*\.(jpg|bmp|png|gif|jpeg))/icon",
app.get('/api/gallery/content/:imagePath(*\.(jpg|bmp|png|gif|jpeg))/icon',
AuthenticationMWs.authenticate,
//TODO: authorize path
// TODO: authorize path
GalleryMWs.loadImage,
ThumbnailGeneratorMWs.generateIcon,
RenderingMWs.renderFile
);
};
}
private static addSearch(app) {
app.get("/api/search/:text",
app.get('/api/search/:text',
AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.Guest),
GalleryMWs.search,
@@ -67,10 +67,10 @@ export class GalleryRouter {
GalleryMWs.removeCyclicDirectoryReferences,
RenderingMWs.renderResult
);
};
}
private static addInstantSearch(app) {
app.get("/api/instant-search/:text",
app.get('/api/instant-search/:text',
AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.Guest),
GalleryMWs.instantSearch,
@@ -78,16 +78,15 @@ export class GalleryRouter {
GalleryMWs.removeCyclicDirectoryReferences,
RenderingMWs.renderResult
);
};
}
private static addAutoComplete(app) {
app.get("/api/autocomplete/:text",
app.get('/api/autocomplete/:text',
AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.Guest),
GalleryMWs.autocomplete,
RenderingMWs.renderResult
);
};
}
}

View File

@@ -1,5 +1,5 @@
import {NextFunction, Request, Response} from "express";
import {Logger} from "../Logger";
import {NextFunction, Request, Response} from 'express';
import {Logger} from '../Logger';
/**
* Adds logging to express
@@ -7,32 +7,32 @@ import {Logger} from "../Logger";
export class LoggerRouter {
public static route(app: any) {
app.get("/api*", (req: Request, res: Response, next: NextFunction) => {
app.get('/api*', (req: Request, res: Response, next: NextFunction) => {
req['_startTime'] = Date.now();
req['logged'] = true;
const end = res.end;
res.end = (a?: any, b?: any, c?: any) => {
res.end = end;
res.end(a, b, c);
Logger.verbose(req.method, req.url, res.statusCode, (Date.now() - req['_startTime']) + "ms");
Logger.verbose(req.method, req.url, res.statusCode, (Date.now() - req['_startTime']) + 'ms');
};
return next();
});
app.get("/node_modules*", (req: Request, res: Response, next: NextFunction) => {
app.get('/node_modules*', (req: Request, res: Response, next: NextFunction) => {
req['_startTime'] = Date.now();
req['logged'] = true;
const end = res.end;
res.end = (a?: any, b?: any, c?: any) => {
res.end = end;
res.end(a, b, c);
Logger.silly(req.method, req.url, res.statusCode, (Date.now() - req['_startTime']) + "ms");
Logger.silly(req.method, req.url, res.statusCode, (Date.now() - req['_startTime']) + 'ms');
};
return next();
});
app.use((req: Request, res: Response, next: NextFunction) => {
if (req['logged'] == true) {
if (req['logged'] === true) {
return next();
}
req['_startTime'] = Date.now();
@@ -40,7 +40,7 @@ export class LoggerRouter {
res.end = (a?: any, b?: any, c?: any) => {
res.end = end;
res.end(a, b, c);
Logger.debug(req.method, req.url, res.statusCode, (Date.now() - req['_startTime']) + "ms");
Logger.debug(req.method, req.url, res.statusCode, (Date.now() - req['_startTime']) + 'ms');
};
return next();
});

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,5 +1,6 @@
import {PhotoDTO} from "../../../common/entities/PhotoDTO";
import {Utils} from "../../../common/Utils";
import {PhotoDTO} from '../../../common/entities/PhotoDTO';
import {Utils} from '../../../common/Utils';
export class IconPhoto {
@@ -18,23 +19,23 @@ export class IconPhoto {
}
getIconPath() {
return Utils.concatUrls("/api/gallery/content/", this.photo.directory.path, this.photo.directory.name, this.photo.name, "icon");
return Utils.concatUrls('/api/gallery/content/', this.photo.directory.path, this.photo.directory.name, this.photo.name, 'icon');
}
getPhotoPath() {
return Utils.concatUrls("/api/gallery/content/", this.photo.directory.path, this.photo.directory.name, this.photo.name);
return Utils.concatUrls('/api/gallery/content/', this.photo.directory.path, this.photo.directory.name, this.photo.name);
}
equals(other: PhotoDTO | IconPhoto): boolean {
//is gridphoto
if (other instanceof IconPhoto) {
return this.photo.directory.path === other.photo.directory.path && this.photo.directory.name === other.photo.directory.name && this.photo.name === other.photo.name
return this.photo.directory.path === other.photo.directory.path && this.photo.directory.name === other.photo.directory.name && this.photo.name === other.photo.name;
}
//is photo
if (other.directory) {
return this.photo.directory.path === other.directory.path && this.photo.directory.name === other.directory.name && this.photo.name === other.name
return this.photo.directory.path === other.directory.path && this.photo.directory.name === other.directory.name && this.photo.name === other.name;
}
return false;

View File

@@ -1,7 +1,8 @@
import {PhotoDTO} from "../../../common/entities/PhotoDTO";
import {Utils} from "../../../common/Utils";
import {IconPhoto} from "./IconPhoto";
import {Config} from "../../../common/config/public/Config";
import {PhotoDTO} from '../../../common/entities/PhotoDTO';
import {Utils} from '../../../common/Utils';
import {IconPhoto} from './IconPhoto';
import {Config} from '../../../common/config/public/Config';
export class Photo extends IconPhoto {
@@ -50,13 +51,13 @@ export class Photo extends IconPhoto {
getReplacementThumbnailPath() {
let size = this.getReplacementThumbnailSize();
return Utils.concatUrls("/api/gallery/content/", this.photo.directory.path, this.photo.directory.name, this.photo.name, "thumbnail", size.toString());
return Utils.concatUrls('/api/gallery/content/', this.photo.directory.path, this.photo.directory.name, this.photo.name, 'thumbnail', size.toString());
}
getThumbnailPath() {
let size = this.getThumbnailSize();
return Utils.concatUrls("/api/gallery/content/", this.photo.directory.path, this.photo.directory.name, this.photo.name, "thumbnail", size.toString());
return Utils.concatUrls('/api/gallery/content/', this.photo.directory.path, this.photo.directory.name, this.photo.name, 'thumbnail', size.toString());
}

View File

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

View File

@@ -1,11 +1,11 @@
import {Component, ElementRef, Input, OnDestroy, OnInit, ViewChild} from "@angular/core";
import {DomSanitizer} from "@angular/platform-browser";
import {DirectoryDTO} from "../../../../common/entities/DirectoryDTO";
import {RouterLink} from "@angular/router";
import {Utils} from "../../../../common/Utils";
import {Photo} from "../Photo";
import {Thumbnail, ThumbnailManagerService} from "../thumnailManager.service";
import {ShareService} from "../share.service";
import {Component, ElementRef, Input, OnDestroy, OnInit, ViewChild} from '@angular/core';
import {DomSanitizer} from '@angular/platform-browser';
import {DirectoryDTO} from '../../../../common/entities/DirectoryDTO';
import {RouterLink} from '@angular/router';
import {Utils} from '../../../../common/Utils';
import {Photo} from '../Photo';
import {Thumbnail, ThumbnailManagerService} from '../thumnailManager.service';
import {ShareService} from '../share.service';
@Component({
selector: 'gallery-directory',
@@ -15,7 +15,7 @@ import {ShareService} from "../share.service";
})
export class GalleryDirectoryComponent implements OnInit, OnDestroy {
@Input() directory: DirectoryDTO;
@ViewChild("dirContainer") container: ElementRef;
@ViewChild('dirContainer') container: ElementRef;
thumbnail: Thumbnail = null;
constructor(private thumbnailService: ThumbnailManagerService,
@@ -27,7 +27,7 @@ export class GalleryDirectoryComponent implements OnInit, OnDestroy {
size: number = null;
getSanitizedThUrl() {
return this._sanitizer.bypassSecurityTrustStyle('url(' + encodeURI(this.thumbnail.Src).replace(/\(/g, "%28").replace(/\)/g, "%29") + ')');
return this._sanitizer.bypassSecurityTrustStyle('url(' + encodeURI(this.thumbnail.Src).replace(/\(/g, '%28').replace(/\)/g, '%29') + ')');
}
//TODO: implement scroll

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,23 +1,13 @@
import {
ChangeDetectorRef,
Component,
ElementRef,
EventEmitter,
HostListener,
OnDestroy,
Output,
QueryList,
ViewChild
} from "@angular/core";
import {PhotoDTO} from "../../../../common/entities/PhotoDTO";
import {GalleryPhotoComponent} from "../grid/photo/photo.grid.gallery.component";
import {Dimension} from "../../model/IRenderable";
import {FullScreenService} from "../fullscreen.service";
import {OverlayService} from "../overlay.service";
import {Subscription} from "rxjs";
import {animate, AnimationBuilder, AnimationPlayer, style} from "@angular/animations";
import {GalleryLightboxPhotoComponent} from "./photo/photo.lightbox.gallery.component";
import {Observable} from "rxjs/Observable";
import {ChangeDetectorRef, Component, ElementRef, EventEmitter, HostListener, OnDestroy, Output, QueryList, ViewChild} from '@angular/core';
import {PhotoDTO} from '../../../../common/entities/PhotoDTO';
import {GalleryPhotoComponent} from '../grid/photo/photo.grid.gallery.component';
import {Dimension} from '../../model/IRenderable';
import {FullScreenService} from '../fullscreen.service';
import {OverlayService} from '../overlay.service';
import {Subscription} from 'rxjs';
import {animate, AnimationBuilder, AnimationPlayer, style} from '@angular/animations';
import {GalleryLightboxPhotoComponent} from './photo/photo.lightbox.gallery.component';
import {Observable} from 'rxjs/Observable';
@Component({
selector: 'gallery-lightbox',
@@ -28,8 +18,8 @@ export class GalleryLightboxComponent implements OnDestroy {
@Output('onLastElement') onLastElement = new EventEmitter();
@ViewChild("photo") photoElement: GalleryLightboxPhotoComponent;
@ViewChild("lightbox") lightboxElement: ElementRef;
@ViewChild('photo') photoElement: GalleryLightboxPhotoComponent;
@ViewChild('lightbox') lightboxElement: ElementRef;
public navigation = {hasPrev: true, hasNext: true};
public blackCanvasOpacity: any = 0;
@@ -108,40 +98,13 @@ export class GalleryLightboxComponent implements OnDestroy {
this.updateActivePhoto(photoIndex, resize);
}
private updateActivePhoto(photoIndex: number, resize: boolean = true) {
let pcList = this.gridPhotoQL.toArray();
if (photoIndex < 0 || photoIndex > this.gridPhotoQL.length) {
throw new Error("Can't find the photo");
}
this.activePhotoId = photoIndex;
this.activePhoto = pcList[photoIndex];
if (resize) {
this.animatePhoto(this.calcLightBoxPhotoDimension(this.activePhoto.gridPhoto.photo));
}
this.navigation.hasPrev = photoIndex > 0;
this.navigation.hasNext = photoIndex + 1 < pcList.length;
let to = this.activePhoto.getDimension();
//if target image out of screen -> scroll to there
if (this.getBodyScrollTop() > to.top || this.getBodyScrollTop() + this.getPhotoFrameHeight() < to.top) {
this.setBodyScrollTop(to.top);
}
}
startPhotoDimension: Dimension = <Dimension>{top: 0, left: 0, width: 0, height: 0};
public show(photo: PhotoDTO) {
this.controllersVisible = true;
this.showControls();
this.visible = true;
let selectedPhoto = this.findPhotoComponent(photo);
if (selectedPhoto === null) {
throw new Error("Can't find Photo");
throw new Error('Can\'t find Photo');
}
const lightboxDimension = selectedPhoto.getDimension();
@@ -168,6 +131,33 @@ export class GalleryLightboxComponent implements OnDestroy {
this.showPhoto(this.gridPhotoQL.toArray().indexOf(selectedPhoto), false);
}
startPhotoDimension: Dimension = <Dimension>{top: 0, left: 0, width: 0, height: 0};
private updateActivePhoto(photoIndex: number, resize: boolean = true) {
let pcList = this.gridPhotoQL.toArray();
if (photoIndex < 0 || photoIndex > this.gridPhotoQL.length) {
throw new Error('Can\'t find the photo');
}
this.activePhotoId = photoIndex;
this.activePhoto = pcList[photoIndex];
if (resize) {
this.animatePhoto(this.calcLightBoxPhotoDimension(this.activePhoto.gridPhoto.photo));
}
this.navigation.hasPrev = photoIndex > 0;
this.navigation.hasNext = photoIndex + 1 < pcList.length;
let to = this.activePhoto.getDimension();
//if target image out of screen -> scroll to there
if (this.getBodyScrollTop() > to.top || this.getBodyScrollTop() + this.getPhotoFrameHeight() < to.top) {
this.setBodyScrollTop(to.top);
}
}
public hide() {
this.controllersVisible = false;
this.fullScreenService.exitFullScreen();

View File

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

View File

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

View File

@@ -1,5 +1,5 @@
import {Component, ElementRef, Input, OnChanges} from "@angular/core";
import {GridPhoto} from "../../grid/GridPhoto";
import {Component, ElementRef, Input, OnChanges} from '@angular/core';
import {GridPhoto} from '../../grid/GridPhoto';
@Component({
selector: 'gallery-lightbox-photo',
@@ -12,7 +12,7 @@ export class GalleryLightboxPhotoComponent implements OnChanges {
@Input() loadImage: boolean = false;
@Input() windowAspect: number = 1;
public imageSize = {width: "auto", height: "100"};
public imageSize = {width: 'auto', height: '100'};
imageLoaded: boolean = false;
public imageLoadFinished: boolean = false;
@@ -27,6 +27,32 @@ export class GalleryLightboxPhotoComponent implements OnChanges {
this.setImageSize();
}
onImageError() {
//TODO:handle error
this.imageLoadFinished = true;
console.error('cant load image');
}
onImageLoad() {
this.imageLoadFinished = true;
this.imageLoaded = true;
}
public thumbnailPath(): string {
if (this.gridPhoto.isThumbnailAvailable() === true)
return this.gridPhoto.getThumbnailPath();
if (this.gridPhoto.isReplacementThumbnailAvailable() === true)
return this.gridPhoto.getReplacementThumbnailPath();
return null;
}
public showThumbnail(): boolean {
return this.gridPhoto && !this.imageLoaded &&
(this.gridPhoto.isThumbnailAvailable() || this.gridPhoto.isReplacementThumbnailAvailable());
}
private setImageSize() {
if (!this.gridPhoto) {
return;
@@ -36,39 +62,13 @@ export class GalleryLightboxPhotoComponent implements OnChanges {
const photoAspect = this.gridPhoto.photo.metadata.size.width / this.gridPhoto.photo.metadata.size.height;
if (photoAspect < this.windowAspect) {
this.imageSize.height = "100";
this.imageSize.height = '100';
this.imageSize.width = null;
} else {
this.imageSize.height = null;
this.imageSize.width = "100";
this.imageSize.width = '100';
}
}
onImageLoad() {
this.imageLoadFinished = true;
this.imageLoaded = true;
}
onImageError() {
//TODO:handle error
this.imageLoadFinished = true;
console.error("cant load image");
}
public showThumbnail(): boolean {
return this.gridPhoto && !this.imageLoaded &&
(this.gridPhoto.isThumbnailAvailable() || this.gridPhoto.isReplacementThumbnailAvailable());
}
public thumbnailPath(): string {
if (this.gridPhoto.isThumbnailAvailable() === true)
return this.gridPhoto.getThumbnailPath();
if (this.gridPhoto.isReplacementThumbnailAvailable() === true)
return this.gridPhoto.getReplacementThumbnailPath();
return null
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -11,6 +11,6 @@ export interface Dimension {
export module Dimension {
export const toString = (dim: Dimension) => {
return {top: dim.top + "px", left: dim.left + "px", width: dim.width + "px", height: dim.height + "px"};
}
return {top: dim.top + 'px', left: dim.left + 'px', width: dim.width + 'px', height: dim.height + 'px'};
};
}

View File

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

Some files were not shown because too many files have changed in this diff Show More