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