mirror of
https://github.com/xuthus83/pigallery2.git
synced 2025-01-14 14:43:17 +08:00
Adding count and precalculated preview to saved search #45
This commit is contained in:
parent
2e12af46d1
commit
597d179f7d
@ -23,4 +23,9 @@ export interface IAlbumManager {
|
|||||||
* Returns with all albums
|
* Returns with all albums
|
||||||
*/
|
*/
|
||||||
getAlbums(): Promise<AlbumBaseDTO[]>;
|
getAlbums(): Promise<AlbumBaseDTO[]>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates previews and album counts
|
||||||
|
*/
|
||||||
|
onGalleryIndexUpdate(): Promise<void>;
|
||||||
}
|
}
|
||||||
|
@ -9,14 +9,6 @@ import {SavedSearchEntity} from './enitites/album/SavedSearchEntity';
|
|||||||
import {IAlbumManager} from '../interfaces/IAlbumManager';
|
import {IAlbumManager} from '../interfaces/IAlbumManager';
|
||||||
|
|
||||||
export class AlbumManager implements IAlbumManager {
|
export class AlbumManager implements IAlbumManager {
|
||||||
private static async fillPreviewToAlbum(album: AlbumBaseDTO): Promise<void> {
|
|
||||||
if (!(album as SavedSearchDTO).searchQuery) {
|
|
||||||
throw new Error('no search query present');
|
|
||||||
}
|
|
||||||
album.preview = await (ObjectManagers.getInstance().SearchManager as ISQLSearchManager)
|
|
||||||
.getPreview((album as SavedSearchDTO).searchQuery);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async addIfNotExistSavedSearch(name: string, searchQuery: SearchQueryDTO, lockedAlbum: boolean): Promise<void> {
|
public async addIfNotExistSavedSearch(name: string, searchQuery: SearchQueryDTO, lockedAlbum: boolean): Promise<void> {
|
||||||
const connection = await SQLConnection.getConnection();
|
const connection = await SQLConnection.getConnection();
|
||||||
const album = await connection.getRepository(SavedSearchEntity)
|
const album = await connection.getRepository(SavedSearchEntity)
|
||||||
@ -24,12 +16,13 @@ export class AlbumManager implements IAlbumManager {
|
|||||||
if (album) {
|
if (album) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.addSavedSearch(name, searchQuery, lockedAlbum);
|
await this.addSavedSearch(name, searchQuery, lockedAlbum);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async addSavedSearch(name: string, searchQuery: SearchQueryDTO, lockedAlbum?: boolean): Promise<void> {
|
public async addSavedSearch(name: string, searchQuery: SearchQueryDTO, lockedAlbum?: boolean): Promise<void> {
|
||||||
const connection = await SQLConnection.getConnection();
|
const connection = await SQLConnection.getConnection();
|
||||||
await connection.getRepository(SavedSearchEntity).insert({name, searchQuery, locked: lockedAlbum});
|
const a = await connection.getRepository(SavedSearchEntity).save({name, searchQuery, locked: lockedAlbum});
|
||||||
|
await this.updateAlbum(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async deleteAlbum(id: number): Promise<void> {
|
public async deleteAlbum(id: number): Promise<void> {
|
||||||
@ -46,12 +39,36 @@ export class AlbumManager implements IAlbumManager {
|
|||||||
|
|
||||||
public async getAlbums(): Promise<AlbumBaseDTO[]> {
|
public async getAlbums(): Promise<AlbumBaseDTO[]> {
|
||||||
const connection = await SQLConnection.getConnection();
|
const connection = await SQLConnection.getConnection();
|
||||||
const albums = await connection.getRepository(AlbumBaseEntity).find();
|
return await connection.getRepository(AlbumBaseEntity).find({
|
||||||
|
relations: ['preview', 'preview.directory']
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public async onGalleryIndexUpdate(): Promise<void> {
|
||||||
|
await this.updateAlbums();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private async updateAlbums(): Promise<void> {
|
||||||
|
const albums = await this.getAlbums();
|
||||||
|
|
||||||
for (const a of albums) {
|
for (const a of albums) {
|
||||||
await AlbumManager.fillPreviewToAlbum(a);
|
await this.updateAlbum(a as SavedSearchEntity);
|
||||||
}
|
}
|
||||||
|
|
||||||
return albums;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async updateAlbum(album: SavedSearchEntity): Promise<void> {
|
||||||
|
const connection = await SQLConnection.getConnection();
|
||||||
|
const preview = await (ObjectManagers.getInstance().SearchManager as ISQLSearchManager)
|
||||||
|
.getPreview((album as SavedSearchDTO).searchQuery);
|
||||||
|
const count = await (ObjectManagers.getInstance().SearchManager as ISQLSearchManager)
|
||||||
|
.getCount((album as SavedSearchDTO).searchQuery);
|
||||||
|
await connection
|
||||||
|
.createQueryBuilder()
|
||||||
|
.update(AlbumBaseEntity)
|
||||||
|
.set({preview, count})
|
||||||
|
.where('id = :id', {id: album.id})
|
||||||
|
.execute();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -14,4 +14,5 @@ export interface ISQLSearchManager extends ISearchManager {
|
|||||||
|
|
||||||
// "Protected" functions. only called from other Managers, not from middlewares
|
// "Protected" functions. only called from other Managers, not from middlewares
|
||||||
getPreview(query: SearchQueryDTO): Promise<MediaDTO>;
|
getPreview(query: SearchQueryDTO): Promise<MediaDTO>;
|
||||||
|
getCount(query: SearchQueryDTO): Promise<number>;
|
||||||
}
|
}
|
||||||
|
@ -370,6 +370,7 @@ export class IndexingManager implements IIndexingManager {
|
|||||||
await this.saveMedia(connection, currentDirId, scannedDirectory.media);
|
await this.saveMedia(connection, currentDirId, scannedDirectory.media);
|
||||||
await this.saveMetaFiles(connection, currentDirId, scannedDirectory);
|
await this.saveMetaFiles(connection, currentDirId, scannedDirectory);
|
||||||
await ObjectManagers.getInstance().PersonManager.onGalleryIndexUpdate();
|
await ObjectManagers.getInstance().PersonManager.onGalleryIndexUpdate();
|
||||||
|
await ObjectManagers.getInstance().AlbumManager.onGalleryIndexUpdate();
|
||||||
await ObjectManagers.getInstance().VersionManager.updateDataVersion();
|
await ObjectManagers.getInstance().VersionManager.updateDataVersion();
|
||||||
await IndexingManager.processServerSidePG2Conf(serverSideConfigs);
|
await IndexingManager.processServerSidePG2Conf(serverSideConfigs);
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -237,6 +237,18 @@ export class SearchManager implements ISQLSearchManager {
|
|||||||
.getOne();
|
.getOne();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async getCount(queryIN: SearchQueryDTO): Promise<number> {
|
||||||
|
const query = await this.prepareQuery(queryIN);
|
||||||
|
const connection = await SQLConnection.getConnection();
|
||||||
|
|
||||||
|
return await connection
|
||||||
|
.getRepository(MediaEntity)
|
||||||
|
.createQueryBuilder('media')
|
||||||
|
.innerJoin('media.directory', 'directory')
|
||||||
|
.where(this.buildWhereQuery(query))
|
||||||
|
.getCount();
|
||||||
|
}
|
||||||
|
|
||||||
protected flattenSameOfQueries(query: SearchQueryDTO): SearchQueryDTO {
|
protected flattenSameOfQueries(query: SearchQueryDTO): SearchQueryDTO {
|
||||||
switch (query.type) {
|
switch (query.type) {
|
||||||
case SearchQueryTypes.AND:
|
case SearchQueryTypes.AND:
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import {Column, Entity, Index, PrimaryGeneratedColumn, TableInheritance} from 'typeorm';
|
import {Column, Entity, Index, ManyToOne, PrimaryGeneratedColumn, TableInheritance} from 'typeorm';
|
||||||
import {MediaEntity} from '../MediaEntity';
|
import {MediaEntity} from '../MediaEntity';
|
||||||
import {columnCharsetCS} from '../EntityUtils';
|
import {columnCharsetCS} from '../EntityUtils';
|
||||||
import {AlbumBaseDTO} from '../../../../../../common/entities/album/AlbumBaseDTO';
|
import {AlbumBaseDTO} from '../../../../../../common/entities/album/AlbumBaseDTO';
|
||||||
@ -21,7 +21,10 @@ export class AlbumBaseEntity implements AlbumBaseDTO {
|
|||||||
@Column({default: false})
|
@Column({default: false})
|
||||||
locked: boolean;
|
locked: boolean;
|
||||||
|
|
||||||
// not saving to database, it is only assigned when querying the DB
|
@Column('int', {unsigned: true, default: 0})
|
||||||
|
count: number;
|
||||||
|
|
||||||
|
@ManyToOne(type => MediaEntity, {onDelete: 'SET NULL', nullable: true})
|
||||||
public preview: MediaEntity;
|
public preview: MediaEntity;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/**
|
/**
|
||||||
* This version indicates that the SQL sql/entities/*Entity.ts files got changed and the db needs to be recreated
|
* This version indicates that the SQL sql/entities/*Entity.ts files got changed and the db needs to be recreated
|
||||||
*/
|
*/
|
||||||
export const DataStructureVersion = 24;
|
export const DataStructureVersion = 25;
|
||||||
|
@ -4,5 +4,6 @@ export interface AlbumBaseDTO {
|
|||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
preview?: PreviewPhotoDTO;
|
preview?: PreviewPhotoDTO;
|
||||||
|
count: number;
|
||||||
locked: boolean;
|
locked: boolean;
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ export interface SavedSearchDTO extends AlbumBaseDTO {
|
|||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
preview?: PreviewPhotoDTO;
|
preview?: PreviewPhotoDTO;
|
||||||
|
count: number;
|
||||||
locked: boolean;
|
locked: boolean;
|
||||||
|
|
||||||
searchQuery: SearchQueryDTO;
|
searchQuery: SearchQueryDTO;
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
<!--Info box -->
|
<!--Info box -->
|
||||||
<div class="info">
|
<div class="info">
|
||||||
{{album.name}}
|
{{album.name}} ({{album.count}})
|
||||||
<span *ngIf="CanUpdate && !album.locked"
|
<span *ngIf="CanUpdate && !album.locked"
|
||||||
(click)="deleteAlbum($event)"
|
(click)="deleteAlbum($event)"
|
||||||
class="info-button delete oi oi-trash float-right"></span>
|
class="info-button delete oi oi-trash float-right"></span>
|
||||||
|
@ -119,6 +119,7 @@ describe('AlbumManager', (sqlHelper: DBTestHelper) => {
|
|||||||
id: 1,
|
id: 1,
|
||||||
name: 'Test Album',
|
name: 'Test Album',
|
||||||
locked: false,
|
locked: false,
|
||||||
|
count: 0,
|
||||||
searchQuery: query
|
searchQuery: query
|
||||||
} as SavedSearchDTO]);
|
} as SavedSearchDTO]);
|
||||||
});
|
});
|
||||||
@ -138,12 +139,14 @@ describe('AlbumManager', (sqlHelper: DBTestHelper) => {
|
|||||||
id: 1,
|
id: 1,
|
||||||
name: 'Test Album',
|
name: 'Test Album',
|
||||||
locked: false,
|
locked: false,
|
||||||
|
count: 0,
|
||||||
searchQuery: query
|
searchQuery: query
|
||||||
} as SavedSearchDTO,
|
} as SavedSearchDTO,
|
||||||
{
|
{
|
||||||
id: 2,
|
id: 2,
|
||||||
name: 'Test Album2',
|
name: 'Test Album2',
|
||||||
locked: true,
|
locked: true,
|
||||||
|
count: 0,
|
||||||
searchQuery: query
|
searchQuery: query
|
||||||
} as SavedSearchDTO]);
|
} as SavedSearchDTO]);
|
||||||
|
|
||||||
@ -152,6 +155,7 @@ describe('AlbumManager', (sqlHelper: DBTestHelper) => {
|
|||||||
id: 2,
|
id: 2,
|
||||||
name: 'Test Album2',
|
name: 'Test Album2',
|
||||||
locked: true,
|
locked: true,
|
||||||
|
count: 0,
|
||||||
searchQuery: query
|
searchQuery: query
|
||||||
} as SavedSearchDTO]);
|
} as SavedSearchDTO]);
|
||||||
|
|
||||||
@ -165,6 +169,7 @@ describe('AlbumManager', (sqlHelper: DBTestHelper) => {
|
|||||||
id: 2,
|
id: 2,
|
||||||
name: 'Test Album2',
|
name: 'Test Album2',
|
||||||
locked: true,
|
locked: true,
|
||||||
|
count: 0,
|
||||||
searchQuery: query
|
searchQuery: query
|
||||||
} as SavedSearchDTO]);
|
} as SavedSearchDTO]);
|
||||||
});
|
});
|
||||||
@ -182,6 +187,7 @@ describe('AlbumManager', (sqlHelper: DBTestHelper) => {
|
|||||||
name: 'Test Album',
|
name: 'Test Album',
|
||||||
searchQuery: query,
|
searchQuery: query,
|
||||||
locked: false,
|
locked: false,
|
||||||
|
count: 1,
|
||||||
preview: toAlbumPreview(p)
|
preview: toAlbumPreview(p)
|
||||||
} as SavedSearchDTO]));
|
} as SavedSearchDTO]));
|
||||||
|
|
||||||
|
@ -14,11 +14,11 @@ import {ObjectManagers} from '../../../../../src/backend/model/ObjectManagers';
|
|||||||
import {DBTestHelper} from '../../../DBTestHelper';
|
import {DBTestHelper} from '../../../DBTestHelper';
|
||||||
import {DiskMangerWorker} from '../../../../../src/backend/model/threading/DiskMangerWorker';
|
import {DiskMangerWorker} from '../../../../../src/backend/model/threading/DiskMangerWorker';
|
||||||
import {ReIndexingSensitivity} from '../../../../../src/common/config/private/PrivateConfig';
|
import {ReIndexingSensitivity} from '../../../../../src/common/config/private/PrivateConfig';
|
||||||
import {AlbumManager} from '../../../../../src/backend/model/database/sql/AlbumManager';
|
|
||||||
import {SearchQueryTypes, TextSearch, TextSearchQueryMatchTypes} from '../../../../../src/common/entities/SearchQueryDTO';
|
import {SearchQueryTypes, TextSearch, TextSearchQueryMatchTypes} from '../../../../../src/common/entities/SearchQueryDTO';
|
||||||
import {ProjectPath} from '../../../../../src/backend/ProjectPath';
|
import {ProjectPath} from '../../../../../src/backend/ProjectPath';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import {DiskManager} from '../../../../../src/backend/model/DiskManger';
|
import {DiskManager} from '../../../../../src/backend/model/DiskManger';
|
||||||
|
import {AlbumManager} from '../../../../../src/backend/model/database/sql/AlbumManager';
|
||||||
|
|
||||||
const deepEqualInAnyOrder = require('deep-equal-in-any-order');
|
const deepEqualInAnyOrder = require('deep-equal-in-any-order');
|
||||||
const chai = require('chai');
|
const chai = require('chai');
|
||||||
@ -47,7 +47,7 @@ class IndexingManagerTest extends IndexingManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async saveToDB(scannedDirectory: DirectoryDTO): Promise<void> {
|
public async saveToDB(scannedDirectory: DirectoryDTO): Promise<void> {
|
||||||
return super.saveToDB(scannedDirectory);
|
return await super.saveToDB(scannedDirectory);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -591,16 +591,18 @@ describe('IndexingManager', (sqlHelper: DBTestHelper) => {
|
|||||||
const am = new AlbumManager();
|
const am = new AlbumManager();
|
||||||
|
|
||||||
const dir = await DiskManager.scanDirectory('/');
|
const dir = await DiskManager.scanDirectory('/');
|
||||||
|
|
||||||
await im.saveToDB(dir);
|
await im.saveToDB(dir);
|
||||||
|
|
||||||
const albums = await am.getAlbums();
|
const albums = await am.getAlbums();
|
||||||
// expect(albums[0].preview).to.be.an('object');
|
expect(albums[0].preview).to.be.an('object');
|
||||||
delete albums[0].preview;
|
delete albums[0].preview;
|
||||||
expect(albums).to.be.equalInAnyOrder([
|
expect(albums).to.be.equalInAnyOrder([
|
||||||
{
|
{
|
||||||
id: 1,
|
id: 1,
|
||||||
name: 'Alvin',
|
name: 'Alvin',
|
||||||
locked: true,
|
locked: true,
|
||||||
|
count: 1,
|
||||||
searchQuery: {
|
searchQuery: {
|
||||||
type: SearchQueryTypes.person,
|
type: SearchQueryTypes.person,
|
||||||
text: 'Alvin',
|
text: 'Alvin',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user