Skip to content

Commit

Permalink
Reading saved searches from .saved_searches.pg2conf #45
Browse files Browse the repository at this point in the history
  • Loading branch information
bpatrik committed May 29, 2021
1 parent 77b2d7e commit a9e88f1
Show file tree
Hide file tree
Showing 21 changed files with 319 additions and 32 deletions.
9 changes: 8 additions & 1 deletion src/backend/model/database/interfaces/IAlbumManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,14 @@ export interface IAlbumManager {
/**
* Creates a saved search type of album
*/
addSavedSearch(name: string, searchQuery: SearchQueryDTO): Promise<void>;
addSavedSearch(name: string, searchQuery: SearchQueryDTO, lockedAlbum?: boolean): Promise<void>;


/**
* Creates a saved search type of album if the album is not yet exists
* lockAlbum: Album cannot be removed from the UI
*/
addIfNotExistSavedSearch(name: string, searchQuery: SearchQueryDTO, lockedAlbum?: boolean): Promise<void>;

/**
* Deletes an album
Expand Down
6 changes: 4 additions & 2 deletions src/backend/model/database/memory/AlbumManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ import {SearchQueryDTO} from '../../../../common/entities/SearchQueryDTO';
import {IAlbumManager} from '../interfaces/IAlbumManager';

export class AlbumManager implements IAlbumManager {

public async addSavedSearch(name: string, searchQuery: SearchQueryDTO): Promise<void> {
addIfNotExistSavedSearch(name: string, searchQuery: SearchQueryDTO, lockedAlbum?: boolean): Promise<void> {
throw new Error('not supported by memory DB');
}

public async addSavedSearch(name: string, searchQuery: SearchQueryDTO, lockedAlbum?: boolean): Promise<void> {
throw new Error('not supported by memory DB');
}

public async deleteAlbum(id: number): Promise<void> {
Expand Down
7 changes: 5 additions & 2 deletions src/backend/model/database/memory/GalleryManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ import {ProjectPath} from '../../../ProjectPath';
import {Config} from '../../../../common/config/private/Config';
import {DiskMangerWorker} from '../../threading/DiskMangerWorker';
import {ReIndexingSensitivity} from '../../../../common/config/private/PrivateConfig';
import {ServerPG2ConfMap} from '../../../../common/PG2ConfMap';

export class GalleryManager implements IGalleryManager {

public listDirectory(relativeDirectoryName: string, knownLastModified?: number, knownLastScanned?: number): Promise<DirectoryDTO> {
public async listDirectory(relativeDirectoryName: string, knownLastModified?: number, knownLastScanned?: number): Promise<DirectoryDTO> {
// If it seems that the content did not changed, do not work on it
if (knownLastModified && knownLastScanned) {
const stat = fs.statSync(path.join(ProjectPath.ImageFolder, relativeDirectoryName));
Expand All @@ -21,7 +22,9 @@ export class GalleryManager implements IGalleryManager {
return Promise.resolve(null);
}
}
return DiskManager.scanDirectory(relativeDirectoryName);
const dir = await DiskManager.scanDirectory(relativeDirectoryName);
dir.metaFile = dir.metaFile.filter(m => !ServerPG2ConfMap[m.name]);
return dir;
}

}
26 changes: 21 additions & 5 deletions src/backend/model/database/sql/AlbumManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import {ObjectManagers} from '../../ObjectManagers';
import {ISQLSearchManager} from './ISearchManager';
import {SearchQueryDTO} from '../../../../common/entities/SearchQueryDTO';
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');
Expand All @@ -17,15 +17,31 @@ export class AlbumManager implements IAlbumManager{
.getPreview((album as SavedSearchDTO).searchQuery);
}

public async addSavedSearch(name: string, searchQuery: SearchQueryDTO): Promise<void> {
public async addIfNotExistSavedSearch(name: string, searchQuery: SearchQueryDTO, lockedAlbum: boolean): Promise<void> {
const connection = await SQLConnection.getConnection();
await connection.getRepository(SavedSearchEntity).insert({name, searchQuery});
const album = await connection.getRepository(SavedSearchEntity)
.findOne({name, searchQuery});
if (album) {
return;
}
this.addSavedSearch(name, searchQuery, lockedAlbum);
}

public async addSavedSearch(name: string, searchQuery: SearchQueryDTO, lockedAlbum?: boolean): Promise<void> {
const connection = await SQLConnection.getConnection();
await connection.getRepository(SavedSearchEntity).insert({name, searchQuery, locked: lockedAlbum});
}

public async deleteAlbum(id: number): Promise<void> {
const connection = await SQLConnection.getConnection();
await connection.getRepository(AlbumBaseEntity).delete({id});

if (await connection.getRepository(AlbumBaseEntity)
.count({id, locked: false}) !== 1) {
throw new Error('Could not delete album, id:' + id);
}

await connection.getRepository(AlbumBaseEntity).delete({id, locked: false});

}

public async getAlbums(): Promise<AlbumBaseDTO[]> {
Expand Down
29 changes: 29 additions & 0 deletions src/backend/model/database/sql/IndexingManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ import {ObjectManagers} from '../../ObjectManagers';
import {IIndexingManager} from '../interfaces/IIndexingManager';
import {DiskMangerWorker} from '../../threading/DiskMangerWorker';
import {Logger} from '../../../Logger';
import {ServerPG2ConfMap, ServerSidePG2ConfAction} from '../../../../common/PG2ConfMap';
import {ProjectPath} from '../../../ProjectPath';
import * as path from 'path';
import * as fs from 'fs';
import {SearchQueryDTO} from '../../../../common/entities/SearchQueryDTO';

const LOG_TAG = '[IndexingManager]';

Expand All @@ -31,6 +36,21 @@ export class IndexingManager implements IIndexingManager {
return this.SavingReady !== null;
}

private static async processServerSidePG2Conf(files: FileDTO[]): Promise<void> {
for (const f of files) {
if (ServerPG2ConfMap[f.name] === ServerSidePG2ConfAction.SAVED_SEARCH) {
const fullMediaPath = path.join(ProjectPath.ImageFolder, f.directory.path, f.directory.name, f.name);

Logger.silly(LOG_TAG, 'Saving saved searches to DB from:', fullMediaPath);
const savedSearches: { name: string, searchQuery: SearchQueryDTO }[] =
JSON.parse(await fs.promises.readFile(fullMediaPath, 'utf8'));
for (const s of savedSearches) {
await ObjectManagers.getInstance().AlbumManager.addIfNotExistSavedSearch(s.name, s.searchQuery, true);
}
}
}
}

public indexDirectory(relativeDirectoryName: string): Promise<DirectoryDTO> {
return new Promise(async (resolve, reject): Promise<void> => {
try {
Expand All @@ -41,8 +61,17 @@ export class IndexingManager implements IIndexingManager {
scannedDirectory.preview.readyThumbnails = [];
}
scannedDirectory.media.forEach((p): any[] => p.readyThumbnails = []);

// filter server side pg2conf
const serverSideConfs = scannedDirectory.metaFile.filter(m => ServerPG2ConfMap[m.name]);
scannedDirectory.metaFile = scannedDirectory.metaFile.filter(m => !ServerPG2ConfMap[m.name]);

resolve(scannedDirectory);

// process server side pg2conf
await IndexingManager.processServerSidePG2Conf(serverSideConfs);

// save directory to DB
this.queueForSave(scannedDirectory).catch(console.error);

} catch (error) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ export class AlbumBaseEntity implements AlbumBaseDTO {
@Column(columnCharsetCS)
name: string;

/**
* Locked albums are not possible to remove
*/
@Column({default: false})
locked: boolean;

// not saving to database, it is only assigned when querying the DB
public preview: MediaEntity;

Expand Down
2 changes: 1 addition & 1 deletion src/common/DataStructureVersion.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export const DataStructureVersion = 22;
export const DataStructureVersion = 23;
15 changes: 15 additions & 0 deletions src/common/PG2ConfMap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,18 @@ export const PG2ConfMap = {
'.order_random.pg2conf': SortingMethods.random
}
};

/**
* These files are processed on the server side,
* do not get passed down to the client or saved to the DB
*/


export enum ServerSidePG2ConfAction {
SAVED_SEARCH = 1
}

export const ServerPG2ConfMap: { [key: string]: ServerSidePG2ConfAction } = {
'.saved_searches.pg2conf': ServerSidePG2ConfAction.SAVED_SEARCH
};

3 changes: 2 additions & 1 deletion src/common/SupportedFormats.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,14 @@ export const SupportedFormats = {
// These formats need to be transcoded (with the build-in ffmpeg support)
TranscodeNeed: {
// based on libvips, all supported formats for sharp: https://github.com/libvips/libvips
// all supported formats for gm: http://www.graphicsmagick.org/GraphicsMagick.html
Photos: [] as string[],
Videos: [
'avi', 'mkv', 'mov', 'wmv', 'flv', 'mts', 'm2ts', 'mpg', '3gp', 'm4v', 'mpeg', 'vob',
'divx', 'xvid', 'ts'
],
},
// --------------------------------------------
// Below this, it is autogenerated, DO NOT EDIT
WithDots: {
Photos: [] as string[],
Videos: [] as string[],
Expand Down
3 changes: 2 additions & 1 deletion src/common/entities/album/AlbumBaseDTO.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@ import {PreviewPhotoDTO} from '../PhotoDTO';
export interface AlbumBaseDTO {
id: number;
name: string;
preview: PreviewPhotoDTO;
preview?: PreviewPhotoDTO;
locked: boolean;
}
3 changes: 2 additions & 1 deletion src/common/entities/album/SavedSearchDTO.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import {SearchQueryDTO} from '../SearchQueryDTO';
export interface SavedSearchDTO extends AlbumBaseDTO {
id: number;
name: string;
preview: PreviewPhotoDTO;
preview?: PreviewPhotoDTO;
locked: boolean;

searchQuery: SearchQueryDTO;
}
3 changes: 2 additions & 1 deletion src/frontend/app/ui/albums/album/album.component.css
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
.delete {
.info-button{
margin: 2px;
cursor: default;
}


.delete {
cursor: pointer;
transition: all .05s ease-in-out;
Expand Down
12 changes: 8 additions & 4 deletions src/frontend/app/ui/albums/album/album.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,14 @@
<!--Info box -->
<div class="info">
{{album.name}}
<span *ngIf="CanUpdate"
(click)="deleteAlbum($event)"
class="delete oi oi-trash float-right"></span>

<span *ngIf="CanUpdate && !album.locked"
(click)="deleteAlbum($event)"
class="info-button delete oi oi-trash float-right"></span>

<span *ngIf="album.locked"
title="Album is locked, cannot be deleted from the webpage."
i18n-title
class="info-button oi oi-lock-locked float-right"></span>
</div>
</a>

1 change: 1 addition & 0 deletions src/frontend/app/ui/albums/albums.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
[size]="size"></app-album>

<div class="add-saved-search btn btn-secondary"
*ngIf="CanCreateAlbum"
[style.width.px]="size"
[style.height.px]="size"
(click)="openModal(modal)">
Expand Down
10 changes: 9 additions & 1 deletion src/frontend/app/ui/albums/albums.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import {AlbumsService} from './albums.service';
import {BsModalService} from 'ngx-bootstrap/modal';
import {BsModalRef} from 'ngx-bootstrap/modal/bs-modal-ref.service';
import {SearchQueryTypes, TextSearch} from '../../../../common/entities/SearchQueryDTO';
import {UserRoles} from '../../../../common/entities/UserDTO';
import {AuthenticationService} from '../../model/network/authentication.service';

@Component({
selector: 'app-albums',
Expand All @@ -19,7 +21,8 @@ export class AlbumsComponent implements OnInit {
private modalRef: BsModalRef;

constructor(public albumsService: AlbumsService,
private modalService: BsModalService) {
private modalService: BsModalService,
public authenticationService: AuthenticationService) {
this.albumsService.getAlbums().catch(console.error);
}

Expand All @@ -29,6 +32,11 @@ export class AlbumsComponent implements OnInit {
}


get CanCreateAlbum(): boolean {
return this.authenticationService.user.getValue().role >= UserRoles.Admin;
}


public async openModal(template: TemplateRef<any>): Promise<void> {
this.modalRef = this.modalService.show(template, {class: 'modal-lg'});
document.body.style.paddingRight = '0px';
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
app-album {
margin: 2px;
display: inline-block;
}

.no-item-msg {
height: 100vh;
text-align: center;
}

.no-face-msg h2 {
color: #6c757d;
}

.add-saved-search {
vertical-align: baseline;
position: absolute;
margin: 2px;
}

.add-saved-search .text {
position: relative;
top: calc(50% - 40px);
text-align: center;
}

.add-saved-search .text .oi {
font-size: 80px;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<app-frame>

<div body #container class="container-fluid">
<app-album *ngFor="let album of albumsService.albums | async"
[album]="album"
[size]="size"></app-album>

<div class="add-saved-search btn btn-secondary"
*ngIf="CanCreateAlbum"
[style.width.px]="size"
[style.height.px]="size"
(click)="openModal(modal)">
<div class="text">
<span class="oi oi-plus" aria-hidden="true"> </span><br/>
<span i18n>Add saved search</span>
</div>
</div>

<div class="d-flex no-item-msg"
*ngIf="(albumsService.albums | async) && (albumsService.albums | async).length == 0">
<div class="flex-fill">
<h2>:(
<ng-container i18n>No albums to show.</ng-container>
</h2>
</div>
</div>
</div>
</app-frame>


<ng-template #modal>
<!-- sharing Modal-->
<div class="modal-header">
<h5 class="modal-title" i18n>Add Saved Search</h5>
<button type="button" class="close" (click)="hideModal()" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<form #savedSearchPanelForm="ngForm" class="form-horizontal">
<div class="row">

</div>

<div class="form-group">
<label for="saveSearchName">Album name</label>
<input
id="saveSearchName"
name="saveSearchName"
placeholder="Search text"
class="form-control input-md"
[(ngModel)]="savedSearch.name"
type="text"/>
</div>
<div class="form-group">
<label for="album-search-query-builder">Search query</label>
<app-gallery-search-query-builder
id="album-search-query-builder"
name="album-search-query-builder"
[(ngModel)]="savedSearch.searchQuery">
</app-gallery-search-query-builder>
</div>


<div class="input-group-btn float-right row" style="display: block">

<button class="btn btn-primary" type="button"
[disabled]="savedSearch.searchQuery.text == ''"
(click)="saveSearch()">
<span class="oi oi-folder"></span> Save
</button>
</div>
</form>
</div>
</ng-template>
Loading

0 comments on commit a9e88f1

Please sign in to comment.