1
0
mirror of https://github.com/bpatrik/pigallery2.git synced 2025-01-26 05:27:35 +02:00

improving metadata config

This commit is contained in:
Patrik J. Braun 2022-01-13 22:41:30 +01:00
parent 268754127d
commit f4f22118ab
13 changed files with 135 additions and 94 deletions

View File

@ -242,7 +242,11 @@ export class GalleryManager implements IGalleryManager, ISQLGalleryManager {
.leftJoinAndSelect('directory.directories', 'directories')
.leftJoinAndSelect('directory.media', 'media');
if (Config.Client.MetaFile.enabled === true) {
// TODO: do better filtering
// NOTE: it should not cause an issue as it also do not shave to the DB
if (Config.Client.MetaFile.gpx === true ||
Config.Client.MetaFile.pg2conf === true ||
Config.Client.MetaFile.markdown === true) {
query.leftJoinAndSelect('directory.metaFile', 'metaFile');
}

View File

@ -65,8 +65,7 @@ export class ConfigDiagnostics {
static async testMetaFileConfig(metaFileConfig: ClientMetaFileConfig, config: IPrivateConfig): Promise<void> {
// TODO: now we have metadata for pg2conf files too not only gpx that also runs without map
if (metaFileConfig.enabled === true &&
if (metaFileConfig.gpx === true &&
config.Client.Map.enabled === false) {
throw new Error('*.gpx meta files are not supported without MAP');
}
@ -275,9 +274,9 @@ export class ConfigDiagnostics {
await ConfigDiagnostics.testMetaFileConfig(Config.Client.MetaFile, Config);
} catch (ex) {
const err: Error = ex;
NotificationManager.warning('Meta file support error, switching off..', err.toString());
NotificationManager.warning('Meta file support error, switching off gpx..', err.toString());
Logger.warn(LOG_TAG, 'Meta file support error, switching off..', err.toString());
Config.Client.MetaFile.enabled = false;
Config.Client.MetaFile.gpx = false;
}
try {

View File

@ -174,10 +174,11 @@ export class DiskMangerWorker {
}
} else if (DiskMangerWorker.isMetaFile(fullFilePath)) {
if (Config.Client.MetaFile.enabled === false || settings.noMetaFile === true || settings.previewOnly === true) {
if (!DiskMangerWorker.isEnabledMetaFile(fullFilePath) ||
settings.noMetaFile === true ||
settings.previewOnly === true) {
continue;
}
directory.metaFile.push({
name: file,
directory: null,
@ -197,6 +198,22 @@ export class DiskMangerWorker {
return SupportedFormats.WithDots.MetaFiles.indexOf(extension) !== -1;
}
private static isEnabledMetaFile(fullPath: string): boolean {
const extension = path.extname(fullPath).toLowerCase();
switch (extension) {
case '.gpx':
return Config.Client.MetaFile.gpx;
case '.md':
return Config.Client.MetaFile.markdown;
case '.pg2conf':
return Config.Client.MetaFile.pg2conf;
}
return false;
}
}
export interface DirectoryScanSettings {

View File

@ -154,8 +154,12 @@ export class ClientMediaConfig {
@SubConfigClass()
export class ClientMetaFileConfig {
@ConfigProperty()
enabled: boolean = true;
@ConfigProperty({description: 'Reads *.gpx files and renders them on the map'})
gpx: boolean = true;
@ConfigProperty({description: 'Reads *.md files in a directory and shows the next to the map'})
markdown: boolean = true;
@ConfigProperty({description: 'Reads *.pg2conf files'})
pg2conf: boolean = true;
}
@SubConfigClass()

View File

@ -2,6 +2,7 @@ import {ClientConfig} from './ClientConfig';
import {WebConfigClass} from 'typeconfig/src/decorators/class/WebConfigClass';
import {WebConfigClassBuilder} from 'typeconfig/src/decorators/builders/WebConfigClassBuilder';
import {ConfigProperty} from 'typeconfig/src/decorators/property/ConfigPropoerty';
import {IWebConfigClass} from 'typeconfig/common';
/**
@ -20,7 +21,7 @@ declare namespace ServerInject {
export const ConfigInject: ClientClass;
}
export let Config = WebConfigClassBuilder.attachInterface(new ClientClass());
export let Config: IWebConfigClass & ClientClass = WebConfigClassBuilder.attachInterface(new ClientClass());
if (typeof ServerInject !== 'undefined' && typeof ServerInject.ConfigInject !== 'undefined') {

View File

@ -106,11 +106,12 @@ import {AlbumsService} from './ui/albums/albums.service';
import {GallerySearchQueryBuilderComponent} from './ui/gallery/search/query-builder/query-bulder.gallery.component';
import {SavedSearchPopupComponent} from './ui/albums/saved-search-popup/saved-search-popup.component';
import {AlbumsSettingsComponent} from './ui/settings/albums/albums.settings.component';
import { MarkdownModule } from 'ngx-markdown';
import {MarkdownModule} from 'ngx-markdown';
import {GalleryBlogComponent} from './ui/gallery/blog/blog.gallery.component';
import {MDFilesFilterPipe} from './pipes/MDFilesFilterPipe';
import {FileDTOToPathPipe} from './pipes/FileDTOToPathPipe';
import {BlogService} from './ui/gallery/blog/blog.service';
import {PhotoFilterPipe} from './pipes/PhotoFilterPipe';
@Injectable()
export class MyHammerConfig extends HammerGestureConfig {
@ -177,7 +178,7 @@ Marker.prototype.options.icon = iconDefault;
LoadingBarModule,
LeafletModule,
LeafletMarkerClusterModule,
MarkdownModule.forRoot({ loader: HttpClient }),
MarkdownModule.forRoot({loader: HttpClient}),
],
declarations: [AppComponent,
LoginComponent,
@ -250,7 +251,8 @@ Marker.prototype.options.icon = iconDefault;
GPXFilesFilterPipe,
MDFilesFilterPipe,
StringifySearchQuery,
FileDTOToPathPipe
FileDTOToPathPipe,
PhotoFilterPipe
],
providers: [
{provide: HTTP_INTERCEPTORS, useClass: CSRFInterceptor, multi: true},

View File

@ -1,10 +1,14 @@
import {Pipe, PipeTransform} from '@angular/core';
import {FileDTO} from '../../../common/entities/FileDTO';
import {Config} from '../../../common/config/public/Config';
@Pipe({name: 'gpxFiles'})
export class GPXFilesFilterPipe implements PipeTransform {
transform(metaFiles: FileDTO[]): FileDTO[] | null {
if (!Config.Client.MetaFile.gpx) {
return [];
}
if (!metaFiles) {
return null;
}

View File

@ -0,0 +1,14 @@
import {Pipe, PipeTransform} from '@angular/core';
import {MediaDTO, MediaDTOUtils} from '../../../common/entities/MediaDTO';
import {PhotoDTO} from '../../../common/entities/PhotoDTO';
@Pipe({name: 'photosOnly'})
export class PhotoFilterPipe implements PipeTransform {
transform(media: MediaDTO[]): PhotoDTO[] | null {
if (!media) {
return null;
}
return media.filter((m: MediaDTO): boolean => MediaDTOUtils.isPhoto(m)) as PhotoDTO[];
}
}

View File

@ -28,78 +28,52 @@
<div body class="container-fluid">
<ng-container *ngIf="galleryService.content.value.error">
<ng-container *ngIf="ContentWrapper.error">
<div class="alert alert-danger" role="alert">
{{galleryService.content.value.error}}
{{ContentWrapper.error}}
</div>
</ng-container>
<ng-container *ngIf="!galleryService.content.value.error">
<ng-container *ngIf="galleryService.content.value.directory">
<ng-container *ngIf="!ContentWrapper.error && (ContentWrapper.searchResult || ContentWrapper.directory)">
<!-- Show search result overflow -->
<div class="alert alert-info" role="alert"
*ngIf="ContentWrapper.searchResult && ContentWrapper.searchResult.resultOverflow == true" i18n>
Too many results to show. Refine your search.
</div>
<app-gallery-navbar [directory]="galleryService.content.value.directory"></app-gallery-navbar>
<app-gallery-directories class="directories" [directories]="directories"></app-gallery-directories>
<div class="blog-map-row">
<ng-container
*ngIf="galleryService.content.value.directory.metaFile && (galleryService.content.value.directory.metaFile | mdFiles).length>0">
<app-gallery-blog [collapsed]="!blogOpen"
[mdFiles]="galleryService.content.value.directory.metaFile | mdFiles"></app-gallery-blog>
<!-- Its safe to hand over both as only one should have a value (search result or dir listing)-->
<app-gallery-navbar [searchResult]="ContentWrapper.searchResult"
[directory]="ContentWrapper.directory"></app-gallery-navbar>
<button class="btn btn-blog-details" (click)="blogOpen=!blogOpen"><span
class="oi oi-chevron-{{blogOpen ? 'top' : 'bottom'}}"></span>
</button>
</ng-container>
<app-gallery-map *ngIf="isPhotoWithLocation && mapEnabled"
[photos]="galleryService.content.value.directory.media"
[gpxFiles]="galleryService.content.value.directory.metaFile | gpxFiles"></app-gallery-map>
</div>
<app-gallery-grid [media]="galleryService.content.value.directory.media"
[lightbox]="lightbox"></app-gallery-grid>
<app-gallery-directories class="directories" [directories]="directories"></app-gallery-directories>
<div class="blog-map-row">
<ng-container
*ngIf="config.Client.MetaFile.markdown && Content.metaFile && (Content.metaFile | mdFiles).length>0">
<app-gallery-blog [collapsed]="!blogOpen"
[mdFiles]="Content.metaFile | mdFiles"></app-gallery-blog>
</ng-container>
<!-- Search-->
<ng-container *ngIf="galleryService.content.value.searchResult">
<div class="alert alert-info" role="alert"
*ngIf="galleryService.content.value.searchResult.resultOverflow == true" i18n>
Too many results to show. Refine your search.
</div>
<app-gallery-navbar [searchResult]="galleryService.content.value.searchResult"></app-gallery-navbar>
<button class="btn btn-blog-details" (click)="blogOpen=!blogOpen"><span
class="oi oi-chevron-{{blogOpen ? 'top' : 'bottom'}}"></span>
</button>
</ng-container>
<app-gallery-map *ngIf="isPhotoWithLocation && mapEnabled"
[photos]="Content.media | photosOnly"
[gpxFiles]="Content.metaFile | gpxFiles"></app-gallery-map>
</div>
<app-gallery-grid [media]="Content.media"
[lightbox]="lightbox"></app-gallery-grid>
<app-gallery-directories class="directories" [directories]="directories"></app-gallery-directories>
<div class="blog-map-row">
<ng-container
*ngIf="galleryService.content.value.searchResult.metaFile && (galleryService.content.value.searchResult.metaFile | mdFiles).length>0">
<app-gallery-blog [collapsed]="!blogOpen"
[mdFiles]="galleryService.content.value.searchResult.metaFile | mdFiles"></app-gallery-blog>
<button class="btn btn-blog-details" (click)="blogOpen=!blogOpen"><span
class="oi oi-chevron-{{blogOpen ? 'top' : 'bottom'}}"></span>
</button>
</ng-container>
<app-gallery-map *ngIf="isPhotoWithLocation && mapEnabled"
[photos]="galleryService.content.value.searchResult.media"
[gpxFiles]="galleryService.content.value.searchResult.metaFile | gpxFiles"></app-gallery-map>
</div>
<app-gallery-grid [media]="galleryService.content.value.searchResult.media"
[lightbox]="lightbox"></app-gallery-grid>
</ng-container>
</ng-container>
</div>
<div body class="container"
style="width: 100%; padding:0"
*ngIf="(!galleryService.content.value.directory ||
galleryService.content.value.directory.isPartial == true)
&& !galleryService.content.value.searchResult
&& !galleryService.content.value.error">
*ngIf="(!ContentWrapper.directory ||
ContentWrapper.directory.isPartial == true)
&& !ContentWrapper.searchResult
&& !ContentWrapper.error">
<div class="spinner">
</div>

View File

@ -1,7 +1,7 @@
import {Component, OnDestroy, OnInit, ViewChild} from '@angular/core';
import {AuthenticationService} from '../../model/network/authentication.service';
import {ActivatedRoute, Params, Router} from '@angular/router';
import {GalleryService} from './gallery.service';
import {ContentWrapperWithError, GalleryService} from './gallery.service';
import {GalleryGridComponent} from './grid/grid.gallery.component';
import {Config} from '../../../../common/config/public/Config';
import {ParentDirectoryDTO, SubDirectoryDTO} from '../../../../common/entities/DirectoryDTO';
@ -32,6 +32,7 @@ export class GalleryComponent implements OnInit, OnDestroy {
public showRandomPhotoBuilder = false;
public blogOpen = false;
config = Config;
public directories: SubDirectoryDTO[] = [];
public isPhotoWithLocation = false;
public countDown: { day: number, hour: number, minute: number, second: number } = null;
@ -56,6 +57,15 @@ export class GalleryComponent implements OnInit, OnDestroy {
PageHelper.showScrollY();
}
get Content(): SearchResultDTO | ParentDirectoryDTO {
const cont = (this.ContentWrapper.searchResult || this.ContentWrapper.directory);
return cont ? cont : {} as any;
}
get ContentWrapper(): ContentWrapperWithError {
return this.galleryService.content.value;
}
updateTimer(t: number): void {
if (this.shareService.sharingSubject.value == null) {
return;

View File

@ -31,7 +31,7 @@ export class SettingsEntryComponent implements ControlValueAccessor, Validator,
@Input() options: { key: number | string, value: number | string }[];
@Input() simplifiedMode = false;
@Input() allowSpaces = false;
@Input() description: boolean;
@Input() description: string;
state: {
isEnumType: boolean,
isConfigType: boolean,

View File

@ -2,27 +2,31 @@
<div class="card mb-4">
<h5 class="card-header">
{{Name}}
<div class="switch-wrapper">
<bSwitch
class="switch"
name="enabled"
switch-on-color="success"
switch-inverse="true"
switch-off-text="Disabled"
switch-on-text="Enabled"
i18n-switch-off-text
i18n-switch-on-text
[switch-disabled]="inProgress"
switch-handle-width="100"
switch-label-width="20"
[(ngModel)]="states.enabled.value">
</bSwitch>
</div>
</h5>
<div class="card-body">
<div [hidden]="!error" class="alert alert-danger" role="alert"><strong>Error: </strong>{{error}}</div>
<ng-container i18n>Reads and show *.gpx files on the map and *.md files (blogs) in the gallery.</ng-container>&nbsp;
<app-settings-entry
name="*.gpx files"
description="Reads *.gpx files and renders them on the map."
i18n-description i18n-name
[ngModel]="states.gpx">
</app-settings-entry>
<app-settings-entry
name="Markdown files"
description="Reads *.md files in a directory and shows the next to the map."
i18n-description i18n-name
[ngModel]="states.markdown">
</app-settings-entry>
<app-settings-entry
name="*.pg2conf files"
description="Reads *.md files in a directory and shows the next to the map."
i18n-description i18n-name
[ngModel]="states.markdown">
</app-settings-entry>
<button class="btn btn-success float-right"

View File

@ -427,10 +427,14 @@ describe('IndexingManager', (sqlHelper: DBTestHelper) => {
const p2 = TestHelper.getRandomizedPhotoEntry(parent, 'Photo2');
const gpx = TestHelper.getRandomizedGPXEntry(parent, 'GPX1');
DirectoryDTOUtils.packDirectory(parent);
Config.Client.MetaFile.enabled = true;
Config.Client.MetaFile.gpx = true;
Config.Client.MetaFile.markdown = true;
Config.Client.MetaFile.pg2conf = true;
await im.saveToDB(Utils.clone(parent) as ParentDirectoryDTO);
Config.Client.MetaFile.enabled = false;
Config.Client.MetaFile.gpx = false;
Config.Client.MetaFile.markdown = false;
Config.Client.MetaFile.pg2conf = false;
const conn = await SQLConnection.getConnection();
const selected = await gm.selectParentDir(conn, parent.name, parent.path);
await gm.fillParentDir(conn, selected);
@ -481,7 +485,9 @@ describe('IndexingManager', (sqlHelper: DBTestHelper) => {
const conn = await SQLConnection.getConnection();
const gm = new GalleryManagerTest();
const im = new IndexingManagerTest();
Config.Client.MetaFile.enabled = true;
Config.Client.MetaFile.gpx = true;
Config.Client.MetaFile.markdown = true;
Config.Client.MetaFile.pg2conf = true;
const parent = TestHelper.getRandomizedDirectoryEntry();
const p1 = TestHelper.getRandomizedPhotoEntry(parent, 'Photo1');
const p2 = TestHelper.getRandomizedPhotoEntry(parent, 'Photo2');
@ -544,7 +550,9 @@ describe('IndexingManager', (sqlHelper: DBTestHelper) => {
const conn = await SQLConnection.getConnection();
const gm = new GalleryManagerTest();
const im = new IndexingManagerTest();
Config.Client.MetaFile.enabled = true;
Config.Client.MetaFile.gpx = true;
Config.Client.MetaFile.markdown = true;
Config.Client.MetaFile.pg2conf = true;
const parent = TestHelper.getRandomizedDirectoryEntry();
DirectoryDTOUtils.packDirectory(parent);
await im.saveToDB(Utils.clone(parent) as ParentDirectoryDTO);