1
0
mirror of https://github.com/xuthus83/pigallery2.git synced 2024-11-03 21:04:03 +08:00

refactoring random photo. Fixing tests

This commit is contained in:
Patrik J. Braun 2021-01-17 15:56:15 +01:00
parent a8bbefe0f8
commit de9c58fd90
11 changed files with 171 additions and 428 deletions

View File

@ -4,19 +4,17 @@ import {NextFunction, Request, Response} from 'express';
import {ErrorCodes, ErrorDTO} from '../../common/entities/Error';
import {DirectoryDTO} from '../../common/entities/DirectoryDTO';
import {ObjectManagers} from '../model/ObjectManagers';
import {SearchTypes} from '../../common/entities/AutoCompleteItem';
import {ContentWrapper} from '../../common/entities/ConentWrapper';
import {PhotoDTO} from '../../common/entities/PhotoDTO';
import {ProjectPath} from '../ProjectPath';
import {Config} from '../../common/config/private/Config';
import {UserDTO} from '../../common/entities/UserDTO';
import {RandomQuery} from '../model/database/interfaces/IGalleryManager';
import {MediaDTO} from '../../common/entities/MediaDTO';
import {VideoDTO} from '../../common/entities/VideoDTO';
import {Utils} from '../../common/Utils';
import {QueryParams} from '../../common/QueryParams';
import {VideoProcessing} from '../model/fileprocessing/VideoProcessing';
import {DiskMangerWorker} from '../model/threading/DiskMangerWorker';
import {SearchQueryDTO, SearchQueryTypes} from '../../common/entities/SearchQueryDTO';
export class GalleryMWs {
@ -115,53 +113,6 @@ export class GalleryMWs {
}
public static async getRandomImage(req: Request, res: Response, next: NextFunction) {
if (Config.Client.RandomPhoto.enabled === false) {
return next();
}
try {
const query: RandomQuery = {};
if (req.query.directory) {
query.directory = DiskMangerWorker.normalizeDirPath(<string>req.query.directory);
}
if (req.query.recursive === 'true') {
query.recursive = true;
}
if (req.query.orientation) {
query.orientation = parseInt(req.query.orientation.toString(), 10);
}
if (req.query.maxResolution) {
query.maxResolution = parseFloat(req.query.maxResolution.toString());
}
if (req.query.minResolution) {
query.minResolution = parseFloat(req.query.minResolution.toString());
}
if (req.query.fromDate) {
query.fromDate = new Date(<string>req.query.fromDate);
}
if (req.query.toDate) {
query.toDate = new Date(<string>req.query.toDate);
}
if (query.minResolution && query.maxResolution && query.maxResolution < query.minResolution) {
return next(new ErrorDTO(ErrorCodes.INPUT_ERROR, 'Input error: min resolution is greater than the max resolution'));
}
if (query.toDate && query.fromDate && query.toDate.getTime() < query.fromDate.getTime()) {
return next(new ErrorDTO(ErrorCodes.INPUT_ERROR, 'Input error: to date is earlier than from date'));
}
const photo = await ObjectManagers.getInstance()
.GalleryManager.getRandomPhoto(query);
if (!photo) {
return next(new ErrorDTO(ErrorCodes.INPUT_ERROR, 'No photo found'));
}
req.params.mediaPath = path.join(photo.directory.path, photo.directory.name, photo.name);
return next();
} catch (e) {
return next(new ErrorDTO(ErrorCodes.GENERAL_ERROR, 'Can\'t get random photo: ' + e.toString()));
}
}
public static async loadFile(req: Request, res: Response, next: NextFunction) {
if (!(req.params.mediaPath)) {
return next();
@ -203,7 +154,7 @@ export class GalleryMWs {
public static async search(req: Request, res: Response, next: NextFunction) {
if (Config.Client.Search.enabled === false) {
if (Config.Client.Search.enabled === false || !req.query[QueryParams.gallery.search.query]) {
return next();
}
@ -211,12 +162,10 @@ export class GalleryMWs {
return next();
}
let type: SearchTypes;
if (req.query[QueryParams.gallery.search.type]) {
type = parseInt(<string>req.query[QueryParams.gallery.search.type], 10);
}
const query: SearchQueryDTO = <any>req.query[QueryParams.gallery.search.type];
try {
const result = await ObjectManagers.getInstance().SearchManager.search(req.params.text, type);
const result = await ObjectManagers.getInstance().SearchManager.search(query);
result.directories.forEach(dir => dir.media = dir.media || []);
req.resultPipe = new ContentWrapper(null, result);
@ -226,25 +175,6 @@ export class GalleryMWs {
}
}
public static async instantSearch(req: Request, res: Response, next: NextFunction) {
if (Config.Client.Search.instantSearchEnabled === false) {
return next();
}
if (!(req.params.text)) {
return next();
}
try {
const result = await ObjectManagers.getInstance().SearchManager.instantSearch(req.params.text);
result.directories.forEach(dir => dir.media = dir.media || []);
req.resultPipe = new ContentWrapper(null, result);
return next();
} catch (err) {
return next(new ErrorDTO(ErrorCodes.GENERAL_ERROR, 'Error during searching', err));
}
}
public static async autocomplete(req: Request, res: Response, next: NextFunction) {
if (Config.Client.Search.AutoComplete.enabled === false) {
@ -254,8 +184,12 @@ export class GalleryMWs {
return next();
}
let type: SearchQueryTypes = SearchQueryTypes.any_text;
if (req.query[QueryParams.gallery.search.type]) {
type = parseInt(<string>req.query[QueryParams.gallery.search.type], 10);
}
try {
req.resultPipe = await ObjectManagers.getInstance().SearchManager.autocomplete(req.params.text);
req.resultPipe = await ObjectManagers.getInstance().SearchManager.autocomplete(req.params.text, type);
return next();
} catch (err) {
return next(new ErrorDTO(ErrorCodes.GENERAL_ERROR, 'Error during searching', err));
@ -264,4 +198,25 @@ export class GalleryMWs {
}
public static async getRandomImage(req: Request, res: Response, next: NextFunction) {
if (Config.Client.RandomPhoto.enabled === false) {
return next();
}
try {
const query: SearchQueryDTO = <any>req.query[QueryParams.gallery.search.type];
const photo = await ObjectManagers.getInstance()
.SearchManager.getRandomPhoto(query);
if (!photo) {
return next(new ErrorDTO(ErrorCodes.INPUT_ERROR, 'No photo found'));
}
req.params.mediaPath = path.join(photo.directory.path, photo.directory.name, photo.name);
return next();
} catch (e) {
return next(new ErrorDTO(ErrorCodes.GENERAL_ERROR, 'Can\'t get random photo: ' + e.toString()));
}
}
}

View File

@ -17,6 +17,5 @@ export interface IGalleryManager {
knownLastModified?: number,
knownLastScanned?: number): Promise<DirectoryDTO>;
getRandomPhoto(queryFilter: RandomQuery): Promise<PhotoDTO>;
}

View File

@ -1,11 +1,13 @@
import {AutoCompleteItem} from '../../../../common/entities/AutoCompleteItem';
import {SearchResultDTO} from '../../../../common/entities/SearchResultDTO';
import {SearchQueryDTO, SearchQueryTypes} from '../../../../common/entities/SearchQueryDTO';
import {PhotoDTO} from '../../../../common/entities/PhotoDTO';
import {RandomQuery} from './IGalleryManager';
export interface ISearchManager {
autocomplete(text: string): Promise<AutoCompleteItem[]>;
autocomplete(text: string, type: SearchQueryTypes): Promise<AutoCompleteItem[]>;
search(query: SearchQueryDTO): Promise<SearchResultDTO>;
instantSearch(text: string): Promise<SearchResultDTO>;
getRandomPhoto(queryFilter: SearchQueryDTO): Promise<PhotoDTO>;
}

View File

@ -4,16 +4,11 @@ import {SearchResultDTO} from '../../../../common/entities/SearchResultDTO';
import {SearchQueryDTO, SearchQueryTypes} from '../../../../common/entities/SearchQueryDTO';
export class SearchManager implements ISearchManager {
autocomplete(text: string): Promise<AutoCompleteItem[]> {
autocomplete(text: string, type: SearchQueryTypes): Promise<AutoCompleteItem[]> {
throw new Error('Method not implemented.');
}
search(query: SearchQueryDTO): Promise<SearchResultDTO> {
throw new Error('Method not implemented.');
}
instantSearch(text: string): Promise<SearchResultDTO> {
throw new Error('Method not implemented.');
}
}

View File

@ -19,6 +19,7 @@ import {FaceRegionEntry} from './enitites/FaceRegionEntry';
import {ObjectManagers} from '../../ObjectManagers';
import {DuplicatesDTO} from '../../../../common/entities/DuplicatesDTO';
import {ServerConfig} from '../../../../common/config/private/PrivateConfig';
import {SearchQueryDTO} from '../../../../common/entities/SearchQueryDTO';
const LOG_TAG = '[GalleryManager]';
@ -87,62 +88,6 @@ export class GalleryManager implements IGalleryManager, ISQLGalleryManager {
}
public async getRandomPhoto(queryFilter: RandomQuery): Promise<PhotoDTO> {
const connection = await SQLConnection.getConnection();
const photosRepository = connection.getRepository(PhotoEntity);
const query: SelectQueryBuilder<PhotoEntity> = photosRepository.createQueryBuilder('photo');
query.innerJoinAndSelect('photo.directory', 'directory');
if (queryFilter.directory) {
const directoryName = path.basename(queryFilter.directory);
const directoryParent = path.join(path.dirname(queryFilter.directory), path.sep);
query.where(new Brackets(qb => {
qb.where('directory.name = :name AND directory.path = :path', {
name: directoryName,
path: directoryParent
});
if (queryFilter.recursive) {
qb.orWhere('directory.path LIKE :text COLLATE utf8_general_ci', {text: queryFilter.directory + '%'});
}
}));
}
if (queryFilter.fromDate) {
query.andWhere('photo.metadata.creationDate >= :fromDate', {
fromDate: queryFilter.fromDate.getTime()
});
}
if (queryFilter.toDate) {
query.andWhere('photo.metadata.creationDate <= :toDate', {
toDate: queryFilter.toDate.getTime()
});
}
if (queryFilter.minResolution) {
query.andWhere('photo.metadata.size.width * photo.metadata.size.height >= :minRes', {
minRes: queryFilter.minResolution * 1000 * 1000
});
}
if (queryFilter.maxResolution) {
query.andWhere('photo.metadata.size.width * photo.metadata.size.height <= :maxRes', {
maxRes: queryFilter.maxResolution * 1000 * 1000
});
}
if (queryFilter.orientation === OrientationType.landscape) {
query.andWhere('photo.metadata.size.width >= photo.metadata.size.height');
}
if (queryFilter.orientation === OrientationType.portrait) {
query.andWhere('photo.metadata.size.width <= photo.metadata.size.height');
}
if (Config.Server.Database.type === ServerConfig.DatabaseType.mysql) {
return await query.groupBy('RAND(), photo.id').limit(1).getOne();
}
return await query.groupBy('RANDOM()').limit(1).getOne();
}
async countDirectories(): Promise<number> {
const connection = await SQLConnection.getConnection();

View File

@ -27,6 +27,8 @@ import {
import {GalleryManager} from './GalleryManager';
import {ObjectManagers} from '../../ObjectManagers';
import {Utils} from '../../../../common/Utils';
import {PhotoDTO} from '../../../../common/entities/PhotoDTO';
import {ServerConfig} from '../../../../common/config/private/PrivateConfig';
export class SearchManager implements ISearchManager {
@ -43,7 +45,7 @@ export class SearchManager implements ISearchManager {
return a;
}
async autocomplete(text: string): Promise<AutoCompleteItem[]> {
async autocomplete(text: string, type: SearchQueryTypes): Promise<AutoCompleteItem[]> {
const connection = await SQLConnection.getConnection();
@ -54,88 +56,83 @@ export class SearchManager implements ISearchManager {
const directoryRepository = connection.getRepository(DirectoryEntity);
(await photoRepository
.createQueryBuilder('photo')
.select('DISTINCT(photo.metadata.keywords)')
.where('photo.metadata.keywords LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'})
.limit(Config.Client.Search.AutoComplete.maxItemsPerCategory)
.getRawMany())
.map(r => <Array<string>>(<string>r.metadataKeywords).split(','))
.forEach(keywords => {
result = result.concat(this.encapsulateAutoComplete(keywords
.filter(k => k.toLowerCase().indexOf(text.toLowerCase()) !== -1), SearchQueryTypes.keyword));
});
if (type === SearchQueryTypes.any_text || type === SearchQueryTypes.keyword) {
(await photoRepository
.createQueryBuilder('photo')
.select('DISTINCT(photo.metadata.keywords)')
.where('photo.metadata.keywords LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'})
.limit(Config.Client.Search.AutoComplete.maxItemsPerCategory)
.getRawMany())
.map(r => <Array<string>>(<string>r.metadataKeywords).split(','))
.forEach(keywords => {
result = result.concat(this.encapsulateAutoComplete(keywords
.filter(k => k.toLowerCase().indexOf(text.toLowerCase()) !== -1), SearchQueryTypes.keyword));
});
}
result = result.concat(this.encapsulateAutoComplete((await personRepository
.createQueryBuilder('person')
.select('DISTINCT(person.name)')
.where('person.name LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'})
.limit(Config.Client.Search.AutoComplete.maxItemsPerCategory)
.orderBy('person.name')
.getRawMany())
.map(r => r.name), SearchQueryTypes.person));
if (type === SearchQueryTypes.any_text || type === SearchQueryTypes.person) {
result = result.concat(this.encapsulateAutoComplete((await personRepository
.createQueryBuilder('person')
.select('DISTINCT(person.name)')
.where('person.name LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'})
.limit(Config.Client.Search.AutoComplete.maxItemsPerCategory)
.orderBy('person.name')
.getRawMany())
.map(r => r.name), SearchQueryTypes.person));
}
(await photoRepository
.createQueryBuilder('photo')
.select('photo.metadata.positionData.country as country, ' +
'photo.metadata.positionData.state as state, photo.metadata.positionData.city as city')
.where('photo.metadata.positionData.country LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'})
.orWhere('photo.metadata.positionData.state LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'})
.orWhere('photo.metadata.positionData.city LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'})
.groupBy('photo.metadata.positionData.country, photo.metadata.positionData.state, photo.metadata.positionData.city')
.limit(Config.Client.Search.AutoComplete.maxItemsPerCategory)
.getRawMany())
.filter(pm => !!pm)
.map(pm => <Array<string>>[pm.city || '', pm.country || '', pm.state || ''])
.forEach(positions => {
result = result.concat(this.encapsulateAutoComplete(positions
.filter(p => p.toLowerCase().indexOf(text.toLowerCase()) !== -1), SearchQueryTypes.position));
});
if (type === SearchQueryTypes.any_text || type === SearchQueryTypes.position) {
(await photoRepository
.createQueryBuilder('photo')
.select('photo.metadata.positionData.country as country, ' +
'photo.metadata.positionData.state as state, photo.metadata.positionData.city as city')
.where('photo.metadata.positionData.country LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'})
.orWhere('photo.metadata.positionData.state LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'})
.orWhere('photo.metadata.positionData.city LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'})
.groupBy('photo.metadata.positionData.country, photo.metadata.positionData.state, photo.metadata.positionData.city')
.limit(Config.Client.Search.AutoComplete.maxItemsPerCategory)
.getRawMany())
.filter(pm => !!pm)
.map(pm => <Array<string>>[pm.city || '', pm.country || '', pm.state || ''])
.forEach(positions => {
result = result.concat(this.encapsulateAutoComplete(positions
.filter(p => p.toLowerCase().indexOf(text.toLowerCase()) !== -1), SearchQueryTypes.position));
});
}
result = result.concat(this.encapsulateAutoComplete((await mediaRepository
.createQueryBuilder('media')
.select('DISTINCT(media.name)')
.where('media.name LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'})
.limit(Config.Client.Search.AutoComplete.maxItemsPerCategory)
.getRawMany())
.map(r => r.name), SearchQueryTypes.file_name));
if (type === SearchQueryTypes.any_text || type === SearchQueryTypes.file_name) {
result = result.concat(this.encapsulateAutoComplete((await mediaRepository
.createQueryBuilder('media')
.select('DISTINCT(media.name)')
.where('media.name LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'})
.limit(Config.Client.Search.AutoComplete.maxItemsPerCategory)
.getRawMany())
.map(r => r.name), SearchQueryTypes.file_name));
}
if (type === SearchQueryTypes.any_text || type === SearchQueryTypes.caption) {
result = result.concat(this.encapsulateAutoComplete((await photoRepository
.createQueryBuilder('media')
.select('DISTINCT(media.metadata.caption) as caption')
.where('media.metadata.caption LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'})
.limit(Config.Client.Search.AutoComplete.maxItemsPerCategory)
.getRawMany())
.map(r => r.caption), SearchQueryTypes.caption));
}
result = result.concat(this.encapsulateAutoComplete((await photoRepository
.createQueryBuilder('media')
.select('DISTINCT(media.metadata.caption) as caption')
.where('media.metadata.caption LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'})
.limit(Config.Client.Search.AutoComplete.maxItemsPerCategory)
.getRawMany())
.map(r => r.caption), SearchQueryTypes.caption));
result = result.concat(this.encapsulateAutoComplete((await directoryRepository
.createQueryBuilder('dir')
.select('DISTINCT(dir.name)')
.where('dir.name LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'})
.limit(Config.Client.Search.AutoComplete.maxItemsPerCategory)
.getRawMany())
.map(r => r.name), SearchQueryTypes.directory));
if (type === SearchQueryTypes.any_text || type === SearchQueryTypes.directory) {
result = result.concat(this.encapsulateAutoComplete((await directoryRepository
.createQueryBuilder('dir')
.select('DISTINCT(dir.name)')
.where('dir.name LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'})
.limit(Config.Client.Search.AutoComplete.maxItemsPerCategory)
.getRawMany())
.map(r => r.name), SearchQueryTypes.directory));
}
return SearchManager.autoCompleteItemsUnique(result);
}
async getGPSData(query: SearchQueryDTO) {
if ((query as ANDSearchQuery | ORSearchQuery).list) {
for (let i = 0; i < (query as ANDSearchQuery | ORSearchQuery).list.length; ++i) {
(query as ANDSearchQuery | ORSearchQuery).list[i] =
await this.getGPSData((query as ANDSearchQuery | ORSearchQuery).list[i]);
}
}
if (query.type === SearchQueryTypes.distance && (<DistanceSearch>query).from.text) {
(<DistanceSearch>query).from.GPSData =
await ObjectManagers.getInstance().LocationManager.getGPSData((<DistanceSearch>query).from.text);
}
return query;
}
async search(queryIN: SearchQueryDTO) {
let query = this.flattenSameOfQueries(queryIN);
query = await this.getGPSData(query);
@ -188,51 +185,34 @@ export class SearchManager implements ISearchManager {
return result;
}
async instantSearch(text: string): Promise<SearchResultDTO> {
public async getRandomPhoto(query: SearchQueryDTO): Promise<PhotoDTO> {
const connection = await SQLConnection.getConnection();
const result: SearchResultDTO = {
searchQuery: <TextSearch>{type: SearchQueryTypes.any_text, text: text},
// searchType:undefined, not adding this
directories: [],
media: [],
metaFile: [],
resultOverflow: false
};
const query = await connection.getRepository(MediaEntity).createQueryBuilder('media')
.innerJoin(q => q.from(MediaEntity, 'media')
.select('distinct media.id')
.limit(10)
.leftJoin('media.directory', 'directory')
.leftJoin('media.metadata.faces', 'faces')
.leftJoin('faces.person', 'person')
.where('media.metadata.keywords LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'})
.orWhere('media.metadata.positionData.country LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'})
.orWhere('media.metadata.positionData.state LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'})
.orWhere('media.metadata.positionData.city LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'})
.orWhere('media.name LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'})
.orWhere('media.metadata.caption LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'})
.orWhere('person.name LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'})
,
'innerMedia',
'media.id=innerMedia.id')
.leftJoinAndSelect('media.directory', 'directory')
.leftJoinAndSelect('media.metadata.faces', 'faces')
.leftJoinAndSelect('faces.person', 'person');
const sqlQuery: SelectQueryBuilder<PhotoEntity> = connection
.getRepository(PhotoEntity)
.createQueryBuilder('media')
.innerJoinAndSelect('media.directory', 'directory')
.where(this.buildWhereQuery(query));
result.media = await this.loadMediaWithFaces(query);
if (Config.Server.Database.type === ServerConfig.DatabaseType.mysql) {
return await sqlQuery.groupBy('RAND(), media.id').limit(1).getOne();
}
return await sqlQuery.groupBy('RANDOM()').limit(1).getOne();
}
result.directories = await connection
.getRepository(DirectoryEntity)
.createQueryBuilder('dir')
.where('dir.name LIKE :text COLLATE utf8_general_ci', {text: '%' + text + '%'})
.limit(10)
.getMany();
return result;
private async getGPSData(query: SearchQueryDTO) {
if ((query as ANDSearchQuery | ORSearchQuery).list) {
for (let i = 0; i < (query as ANDSearchQuery | ORSearchQuery).list.length; ++i) {
(query as ANDSearchQuery | ORSearchQuery).list[i] =
await this.getGPSData((query as ANDSearchQuery | ORSearchQuery).list[i]);
}
}
if (query.type === SearchQueryTypes.distance && (<DistanceSearch>query).from.text) {
(<DistanceSearch>query).from.GPSData =
await ObjectManagers.getInstance().LocationManager.getGPSData((<DistanceSearch>query).from.text);
}
return query;
}
private buildWhereQuery(query: SearchQueryDTO, paramCounter = {value: 0}): Brackets {

View File

@ -25,7 +25,6 @@ export class GalleryRouter {
this.addDirectoryList(app);
this.addSearch(app);
this.addInstantSearch(app);
this.addAutoComplete(app);
}
@ -199,20 +198,6 @@ export class GalleryRouter {
);
}
protected static addInstantSearch(app: Express) {
app.get('/api/instant-search/:text',
// common part
AuthenticationMWs.authenticate,
AuthenticationMWs.authorise(UserRoles.Guest),
VersionMWs.injectGalleryVersion,
// specific part
GalleryMWs.instantSearch,
ThumbnailGeneratorMWs.addThumbnailInformation,
GalleryMWs.cleanUpGalleryResults,
RenderingMWs.renderResult
);
}
protected static addAutoComplete(app: Express) {
app.get('/api/autocomplete/:text',

View File

@ -10,7 +10,8 @@ export const QueryParams = {
maxResolution: 'toRes'
},
search: {
type: 'type'
type: 'type',
query: 'qs'
},
photo: 'p',
sharingKey_query: 'sk',

View File

@ -25,12 +25,6 @@ export module ClientConfig {
export class SearchConfig {
@ConfigProperty()
enabled: boolean = true;
@ConfigProperty()
instantSearchEnabled: boolean = true;
@ConfigProperty({type: 'unsignedInt'})
InstantSearchTimeout: number = 3000;
@ConfigProperty({type: 'unsignedInt'})
instantSearchCacheTimeout: number = 1000 * 60 * 60;
@ConfigProperty({type: 'unsignedInt'})
searchCacheTimeout: number = 1000 * 60 * 60;
@ConfigProperty()

View File

@ -1,21 +1,6 @@
import {expect} from 'chai';
import {TestHelper} from './TestHelper';
import {SQLTestHelper} from '../../../SQLTestHelper';
import {GalleryManager} from '../../../../../src/backend/model/database/sql/GalleryManager';
import {IndexingManager} from '../../../../../src/backend/model/database/sql/IndexingManager';
import {DirectoryDTO} from '../../../../../src/common/entities/DirectoryDTO';
import {Utils} from '../../../../../src/common/Utils';
import {ObjectManagers} from '../../../../../src/backend/model/ObjectManagers';
import {PersonManager} from '../../../../../src/backend/model/database/sql/PersonManager';
import {MediaEntity} from '../../../../../src/backend/model/database/sql/enitites/MediaEntity';
import {VersionManager} from '../../../../../src/backend/model/database/sql/VersionManager';
class IndexingManagerTest extends IndexingManager {
public async saveToDB(scannedDirectory: DirectoryDTO): Promise<void> {
return super.saveToDB(scannedDirectory);
}
}
// to help WebStorm to handle the test cases
declare let describe: any;
@ -25,36 +10,4 @@ describe = SQLTestHelper.describe;
describe('GalleryManager', (sqlHelper: SQLTestHelper) => {
beforeEach(async () => {
await sqlHelper.initDB();
ObjectManagers.getInstance().PersonManager = new PersonManager();
ObjectManagers.getInstance().VersionManager = new VersionManager();
});
after(async () => {
await sqlHelper.clearDB();
});
it('should get random photo', async () => {
const gm = new GalleryManager();
const im = new IndexingManagerTest();
const parent = TestHelper.getRandomizedDirectoryEntry();
const p1 = TestHelper.getRandomizedPhotoEntry(parent, 'Photo1');
expect(await gm.getRandomPhoto({})).to.not.exist;
DirectoryDTO.removeReferences(parent);
await im.saveToDB(Utils.clone(parent));
delete p1.metadata.faces;
delete p1.directory;
delete p1.id;
const found: MediaEntity = <any>await gm.getRandomPhoto({});
delete found.metadata.bitRate;
delete found.metadata.duration;
delete found.directory;
delete found.id;
expect(Utils.clone(found)).to.be.deep.equal(Utils.clone(p1));
});
});

View File

@ -105,30 +105,6 @@ describe('SearchManager', (sqlHelper: SQLTestHelper) => {
const setUpSqlDB = async () => {
await sqlHelper.initDB();
await setUpTestGallery();
/*
const savePhoto = async (photo: PhotoDTO) => {
const savedPhoto = await pr.save(photo);
if (!photo.metadata.faces) {
return;
}
for (let i = 0; i < photo.metadata.faces.length; i++) {
const face = photo.metadata.faces[i];
const person = await conn.getRepository(PersonEntry).save({name: face.name});
await conn.getRepository(FaceRegionEntry).save({box: face.box, person: person, media: savedPhoto});
}
};
const conn = await SQLConnection.getConnection();
const pr = conn.getRepository(PhotoEntity);
await conn.getRepository(DirectoryEntity).save(p.directory);
await savePhoto(p);
await savePhoto(p2);
await savePhoto(p_faceLess);
await conn.getRepository(VideoEntity).save(v);*/
// await SQLConnection.close();
};
@ -151,53 +127,46 @@ describe('SearchManager', (sqlHelper: SQLTestHelper) => {
return a.text.localeCompare(b.text);
};
expect((await sm.autocomplete('tat'))).to.deep.equalInAnyOrder([new AutoCompleteItem('Tatooine', SearchQueryTypes.position)]);
expect((await sm.autocomplete('star'))).to.deep.equalInAnyOrder([new AutoCompleteItem('star wars', SearchQueryTypes.keyword),
expect((await sm.autocomplete('tat', SearchQueryTypes.any_text))).to.deep.equalInAnyOrder([
new AutoCompleteItem('Tatooine', SearchQueryTypes.position)]);
expect((await sm.autocomplete('star', SearchQueryTypes.any_text))).to.deep.equalInAnyOrder([
new AutoCompleteItem('star wars', SearchQueryTypes.keyword),
new AutoCompleteItem('death star', SearchQueryTypes.keyword)]);
expect((await sm.autocomplete('wars'))).to.deep.equalInAnyOrder([new AutoCompleteItem('star wars', SearchQueryTypes.keyword),
expect((await sm.autocomplete('wars', SearchQueryTypes.any_text))).to.deep.equalInAnyOrder([
new AutoCompleteItem('star wars', SearchQueryTypes.keyword),
new AutoCompleteItem('wars dir', SearchQueryTypes.directory)]);
expect((await sm.autocomplete('arch'))).eql([new AutoCompleteItem('Research City', SearchQueryTypes.position)]);
expect((await sm.autocomplete('arch', SearchQueryTypes.any_text))).eql([
new AutoCompleteItem('Research City', SearchQueryTypes.position)]);
Config.Client.Search.AutoComplete.maxItemsPerCategory = 99999;
expect((await sm.autocomplete('a')).sort(cmp)).eql([
new AutoCompleteItem('Boba Fett', SearchQueryTypes.keyword),
new AutoCompleteItem('Boba Fett', SearchQueryTypes.person),
expect((await sm.autocomplete('wa', SearchQueryTypes.any_text))).to.deep.equalInAnyOrder([
new AutoCompleteItem('star wars', SearchQueryTypes.keyword),
new AutoCompleteItem('Anakin', SearchQueryTypes.keyword),
new AutoCompleteItem('Anakin Skywalker', SearchQueryTypes.person),
new AutoCompleteItem('Luke Skywalker', SearchQueryTypes.person),
new AutoCompleteItem('Han Solo', SearchQueryTypes.person),
new AutoCompleteItem('death star', SearchQueryTypes.keyword),
new AutoCompleteItem('Padmé Amidala', SearchQueryTypes.person),
new AutoCompleteItem('Obivan Kenobi', SearchQueryTypes.person),
new AutoCompleteItem('Arvíztűrő Tükörfúrógép', SearchQueryTypes.person),
new AutoCompleteItem('Padmé Amidala', SearchQueryTypes.keyword),
new AutoCompleteItem('Natalie Portman', SearchQueryTypes.keyword),
new AutoCompleteItem('Han Solo\'s dice', SearchQueryTypes.caption),
new AutoCompleteItem('Kamino', SearchQueryTypes.position),
new AutoCompleteItem('Tatooine', SearchQueryTypes.position),
new AutoCompleteItem('wars dir', SearchQueryTypes.directory),
new AutoCompleteItem('Research City', SearchQueryTypes.position)].sort(cmp));
new AutoCompleteItem('wars dir', SearchQueryTypes.directory)]);
Config.Client.Search.AutoComplete.maxItemsPerCategory = 1;
expect((await sm.autocomplete('a')).sort(cmp)).eql([
new AutoCompleteItem('Anakin', SearchQueryTypes.keyword),
expect((await sm.autocomplete('a', SearchQueryTypes.any_text))).to.deep.equalInAnyOrder([
new AutoCompleteItem('Ajan Kloss', SearchQueryTypes.position),
new AutoCompleteItem('Amber stone', SearchQueryTypes.caption),
new AutoCompleteItem('star wars', SearchQueryTypes.keyword),
new AutoCompleteItem('death star', SearchQueryTypes.keyword),
new AutoCompleteItem('Anakin Skywalker', SearchQueryTypes.person),
new AutoCompleteItem('Han Solo\'s dice', SearchQueryTypes.caption),
new AutoCompleteItem('Kamino', SearchQueryTypes.position),
new AutoCompleteItem('Research City', SearchQueryTypes.position),
new AutoCompleteItem('wars dir', SearchQueryTypes.directory),
new AutoCompleteItem('Boba Fett', SearchQueryTypes.keyword)].sort(cmp));
new AutoCompleteItem('Castilon', SearchQueryTypes.position),
new AutoCompleteItem('Devaron', SearchQueryTypes.position),
new AutoCompleteItem('The Phantom Menace', SearchQueryTypes.directory)]);
Config.Client.Search.AutoComplete.maxItemsPerCategory = 5;
expect((await sm.autocomplete('sw')).sort(cmp)).to.deep.equalInAnyOrder([new AutoCompleteItem('sw1', SearchQueryTypes.file_name),
new AutoCompleteItem('sw2', SearchQueryTypes.file_name), new AutoCompleteItem(v.name, SearchQueryTypes.file_name)].sort(cmp));
expect((await sm.autocomplete('sw', SearchQueryTypes.any_text))).to.deep.equalInAnyOrder([
new AutoCompleteItem('sw1.jpg', SearchQueryTypes.file_name),
new AutoCompleteItem('sw2.jpg', SearchQueryTypes.file_name),
new AutoCompleteItem('sw3.jpg', SearchQueryTypes.file_name),
new AutoCompleteItem('sw4.jpg', SearchQueryTypes.file_name),
new AutoCompleteItem(v.name, SearchQueryTypes.file_name)]);
expect((await sm.autocomplete(v.name)).sort(cmp)).to.deep.equalInAnyOrder([new AutoCompleteItem(v.name, SearchQueryTypes.file_name)]);
expect((await sm.autocomplete(v.name, SearchQueryTypes.any_text))).to.deep.equalInAnyOrder(
[new AutoCompleteItem(v.name, SearchQueryTypes.file_name)]);
});
@ -896,7 +865,7 @@ describe('SearchManager', (sqlHelper: SQLTestHelper) => {
resultOverflow: false
}));
query = <RatingSearch>{min: 0, max: 5, type: SearchQueryTypes.rating};
query = <RatingSearch>{min: 0, max: 5, type: SearchQueryTypes.rating};
expect(Utils.clone(await sm.search(query)))
.to.deep.equalInAnyOrder(removeDir(<SearchResultDTO>{
searchQuery: query,
@ -1117,57 +1086,22 @@ describe('SearchManager', (sqlHelper: SQLTestHelper) => {
});
it('should instant search', async () => {
it('should get random photo', async () => {
const sm = new SearchManager();
expect(Utils.clone(await sm.instantSearch('sw'))).to.deep.equalInAnyOrder(Utils.clone({
searchText: 'sw',
directories: [],
media: [p, p2, v],
metaFile: [],
resultOverflow: false
}));
let query = <TextSearch>{
text: 'xyz',
type: SearchQueryTypes.keyword
};
expect(await sm.getRandomPhoto(query)).to.not.exist;
expect(Utils.clone(await sm.instantSearch('Tatooine'))).to.deep.equalInAnyOrder(Utils.clone({
searchText: 'Tatooine',
directories: [],
media: [p],
metaFile: [],
resultOverflow: false
}));
expect(Utils.clone(await sm.instantSearch('ortm'))).to.deep.equalInAnyOrder(Utils.clone({
searchText: 'ortm',
directories: [],
media: [p2, p_faceLess],
metaFile: [],
resultOverflow: false
}));
expect(Utils.clone(await sm.instantSearch('wa'))).to.deep.equalInAnyOrder(Utils.clone({
searchText: 'wa',
directories: [dir],
media: [p, p2, p_faceLess],
metaFile: [],
resultOverflow: false
}));
expect(Utils.clone(await sm.instantSearch('han'))).to.deep.equalInAnyOrder(Utils.clone({
searchText: 'han',
directories: [],
media: [p],
metaFile: [],
resultOverflow: false
}));
expect(Utils.clone(await sm.instantSearch('Boba'))).to.deep.equalInAnyOrder(Utils.clone({
searchText: 'Boba',
directories: [],
media: [p],
metaFile: [],
resultOverflow: false
}));
query = <TextSearch>{
text: 'wookiees',
matchType: TextSearchQueryTypes.exact_match,
type: SearchQueryTypes.keyword
};
expect(Utils.clone(await sm.getRandomPhoto(query))).to.deep.equalInAnyOrder(searchifyMedia(p_faceLess));
});
});