mirror of
https://github.com/bpatrik/pigallery2.git
synced 2025-02-07 13:41:44 +02:00
Implement MediaPickDTO to allow multiple search queries to send top pick mails. #683
This commit is contained in:
parent
3e6bb7bff7
commit
794039d824
@ -2,16 +2,15 @@ import {ConfigTemplateEntry, DefaultsJobs,} from '../../../../common/entities/jo
|
|||||||
import {Job} from './Job';
|
import {Job} from './Job';
|
||||||
import {backendTexts} from '../../../../common/BackendTexts';
|
import {backendTexts} from '../../../../common/BackendTexts';
|
||||||
import {SortingMethods} from '../../../../common/entities/SortingMethods';
|
import {SortingMethods} from '../../../../common/entities/SortingMethods';
|
||||||
import {DatePatternFrequency, DatePatternSearch, SearchQueryDTO, SearchQueryTypes} from '../../../../common/entities/SearchQueryDTO';
|
import {DatePatternFrequency, DatePatternSearch, SearchQueryTypes} from '../../../../common/entities/SearchQueryDTO';
|
||||||
import {ObjectManagers} from '../../ObjectManagers';
|
import {ObjectManagers} from '../../ObjectManagers';
|
||||||
import {PhotoEntity} from '../../database/enitites/PhotoEntity';
|
import {PhotoEntity} from '../../database/enitites/PhotoEntity';
|
||||||
import {EmailMediaMessenger} from '../../mediamessengers/EmailMediaMessenger';
|
import {EmailMediaMessenger} from '../../mediamessengers/EmailMediaMessenger';
|
||||||
|
import {MediaPickDTO} from '../../../../common/entities/MediaPickDTO';
|
||||||
|
|
||||||
|
|
||||||
export class TopPickSendJob extends Job<{
|
export class TopPickSendJob extends Job<{
|
||||||
searchQuery: SearchQueryDTO,
|
mediaPick: MediaPickDTO[],
|
||||||
sortBy: SortingMethods[],
|
|
||||||
pickAmount: number,
|
|
||||||
emailTo: string,
|
emailTo: string,
|
||||||
emailFrom: string,
|
emailFrom: string,
|
||||||
emailSubject: string,
|
emailSubject: string,
|
||||||
@ -21,27 +20,19 @@ export class TopPickSendJob extends Job<{
|
|||||||
public readonly Supported: boolean = true;
|
public readonly Supported: boolean = true;
|
||||||
public readonly ConfigTemplate: ConfigTemplateEntry[] = [
|
public readonly ConfigTemplate: ConfigTemplateEntry[] = [
|
||||||
{
|
{
|
||||||
id: 'searchQuery',
|
id: 'mediaPick',
|
||||||
type: 'SearchQuery',
|
type: 'MediaPickDTO-array',
|
||||||
name: backendTexts.searchQuery.name,
|
name: backendTexts.mediaPick.name,
|
||||||
description: backendTexts.searchQuery.description,
|
description: backendTexts.mediaPick.description,
|
||||||
defaultValue: {
|
defaultValue: [{
|
||||||
|
searchQuery: {
|
||||||
type: SearchQueryTypes.date_pattern,
|
type: SearchQueryTypes.date_pattern,
|
||||||
daysLength: 7,
|
daysLength: 7,
|
||||||
frequency: DatePatternFrequency.every_year
|
frequency: DatePatternFrequency.every_year
|
||||||
} as DatePatternSearch,
|
} as DatePatternSearch,
|
||||||
}, {
|
sortBy: [SortingMethods.descRating, SortingMethods.descPersonCount],
|
||||||
id: 'sortby',
|
pick: 5
|
||||||
type: 'sort-array',
|
}] as MediaPickDTO[],
|
||||||
name: backendTexts.sortBy.name,
|
|
||||||
description: backendTexts.sortBy.description,
|
|
||||||
defaultValue: [SortingMethods.descRating, SortingMethods.descPersonCount],
|
|
||||||
}, {
|
|
||||||
id: 'pickAmount',
|
|
||||||
type: 'number',
|
|
||||||
name: backendTexts.pickAmount.name,
|
|
||||||
description: backendTexts.pickAmount.description,
|
|
||||||
defaultValue: 5,
|
|
||||||
}, {
|
}, {
|
||||||
id: 'emailTo',
|
id: 'emailTo',
|
||||||
type: 'string-array',
|
type: 'string-array',
|
||||||
@ -88,15 +79,26 @@ export class TopPickSendJob extends Job<{
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async stepListing(): Promise<boolean> {
|
private async stepListing(): Promise<boolean> {
|
||||||
this.Progress.log('Collecting Photos and videos to Send');
|
this.Progress.log('Collecting Photos and videos to Send.');
|
||||||
|
this.mediaList = [];
|
||||||
|
for (let i = 0; i < this.config.mediaPick.length; ++i) {
|
||||||
|
const media = await ObjectManagers.getInstance().SearchManager.getNMedia(this.config.mediaPick[i].searchQuery, this.config.mediaPick[i].sortBy, this.config.mediaPick[i].pick);
|
||||||
|
this.Progress.log('Find ' + media.length + ' photos and videos from ' + (i + 1) + '. load');
|
||||||
|
this.mediaList = this.mediaList.concat(media);
|
||||||
|
}
|
||||||
|
|
||||||
this.Progress.Processed++;
|
this.Progress.Processed++;
|
||||||
this.mediaList = await ObjectManagers.getInstance().SearchManager.getNMedia(this.config.searchQuery, this.config.sortBy, this.config.pickAmount);
|
|
||||||
// console.log(this.mediaList);
|
// console.log(this.mediaList);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async stepSending(): Promise<boolean> {
|
private async stepSending(): Promise<boolean> {
|
||||||
this.Progress.log('Sending emails');
|
if (this.mediaList.length <= 0) {
|
||||||
|
this.Progress.log('No photos found skipping e-mail sending.');
|
||||||
|
this.Progress.Skipped++;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
this.Progress.log('Sending emails of ' + this.mediaList.length + ' photos.');
|
||||||
const messenger = new EmailMediaMessenger();
|
const messenger = new EmailMediaMessenger();
|
||||||
await messenger.sendMedia({
|
await messenger.sendMedia({
|
||||||
to: this.config.emailTo,
|
to: this.config.emailTo,
|
||||||
|
@ -3,9 +3,7 @@ export const backendTexts = {
|
|||||||
indexedFilesOnly: {name: 10, description: 12},
|
indexedFilesOnly: {name: 10, description: 12},
|
||||||
sizeToGenerate: {name: 20, description: 22},
|
sizeToGenerate: {name: 20, description: 22},
|
||||||
indexChangesOnly: {name: 30, description: 32},
|
indexChangesOnly: {name: 30, description: 32},
|
||||||
searchQuery: {name: 40, description: 42},
|
mediaPick: {name: 40, description: 42},
|
||||||
sortBy: {name: 50, description: 52},
|
|
||||||
pickAmount: {name: 60, description: 62},
|
|
||||||
emailTo: {name: 70, description: 72},
|
emailTo: {name: 70, description: 72},
|
||||||
emailSubject: {name: 90, description: 92},
|
emailSubject: {name: 90, description: 92},
|
||||||
emailText: {name: 100, description: 102}
|
emailText: {name: 100, description: 102}
|
||||||
|
@ -31,6 +31,7 @@ import {SearchQueryDTO, SearchQueryTypes, TextSearch,} from '../../entities/Sear
|
|||||||
import {SortingMethods} from '../../entities/SortingMethods';
|
import {SortingMethods} from '../../entities/SortingMethods';
|
||||||
import {UserRoles} from '../../entities/UserDTO';
|
import {UserRoles} from '../../entities/UserDTO';
|
||||||
import {EmailMessagingType, MessagingConfig} from './MessagingConfig';
|
import {EmailMessagingType, MessagingConfig} from './MessagingConfig';
|
||||||
|
import {MediaPickDTO} from '../../entities/MediaPickDTO';
|
||||||
|
|
||||||
declare let $localize: (s: TemplateStringsArray) => string;
|
declare let $localize: (s: TemplateStringsArray) => string;
|
||||||
|
|
||||||
@ -584,7 +585,7 @@ export class JobScheduleConfig implements JobScheduleDTO {
|
|||||||
@ConfigProperty()
|
@ConfigProperty()
|
||||||
jobName: string;
|
jobName: string;
|
||||||
@ConfigProperty()
|
@ConfigProperty()
|
||||||
config: Record<string, string | number | string[] | number[]> = {};
|
config: Record<string, string | number | string[] | number[] | MediaPickDTO[]> = {};
|
||||||
@ConfigProperty()
|
@ConfigProperty()
|
||||||
allowParallelRun: boolean = false;
|
allowParallelRun: boolean = false;
|
||||||
@ConfigProperty({
|
@ConfigProperty({
|
||||||
|
8
src/common/entities/MediaPickDTO.ts
Normal file
8
src/common/entities/MediaPickDTO.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import {SearchQueryDTO} from './SearchQueryDTO';
|
||||||
|
import {SortingMethods} from './SortingMethods';
|
||||||
|
|
||||||
|
export interface MediaPickDTO {
|
||||||
|
searchQuery: SearchQueryDTO;
|
||||||
|
sortBy: SortingMethods[];
|
||||||
|
pick: number;
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
import {backendText} from '../../BackendTexts';
|
import {backendText} from '../../BackendTexts';
|
||||||
|
|
||||||
export type fieldType = 'string' | 'string-array' | 'number' | 'boolean' | 'number-array' | 'SearchQuery' | 'sort-array';
|
export type fieldType = 'string' | 'string-array' | 'number' | 'boolean' | 'number-array' | 'MediaPickDTO-array';
|
||||||
|
|
||||||
export enum DefaultsJobs {
|
export enum DefaultsJobs {
|
||||||
Indexing = 1,
|
Indexing = 1,
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
/* eslint-disable no-case-declarations */
|
/* eslint-disable no-case-declarations */
|
||||||
|
import {MediaPickDTO} from '../MediaPickDTO';
|
||||||
|
|
||||||
export enum JobTriggerType {
|
export enum JobTriggerType {
|
||||||
never = 1,
|
never = 1,
|
||||||
scheduled = 2,
|
scheduled = 2,
|
||||||
@ -33,7 +35,7 @@ export interface AfterJobTrigger extends JobTrigger {
|
|||||||
export interface JobScheduleDTO {
|
export interface JobScheduleDTO {
|
||||||
name: string;
|
name: string;
|
||||||
jobName: string;
|
jobName: string;
|
||||||
config: Record<string, string | number | string[] | number[]>;
|
config: Record<string, string | number | string[] | number[] | MediaPickDTO[]>;
|
||||||
allowParallelRun: boolean;
|
allowParallelRun: boolean;
|
||||||
trigger:
|
trigger:
|
||||||
| NeverJobTrigger
|
| NeverJobTrigger
|
||||||
|
@ -19,18 +19,10 @@ export class BackendtextService {
|
|||||||
return $localize`Index changes only`;
|
return $localize`Index changes only`;
|
||||||
case backendTexts.indexChangesOnly.description:
|
case backendTexts.indexChangesOnly.description:
|
||||||
return $localize`Only indexes a folder if it got changed.`;
|
return $localize`Only indexes a folder if it got changed.`;
|
||||||
case backendTexts.searchQuery.name:
|
case backendTexts.mediaPick.name:
|
||||||
return $localize`Search query`;
|
return $localize`Media selectors`;
|
||||||
case backendTexts.searchQuery.description:
|
case backendTexts.mediaPick.description:
|
||||||
return $localize`Search query to list photos and videos.`;
|
return $localize`Set these search queries to find photos and videos to email.`;
|
||||||
case backendTexts.sortBy.name:
|
|
||||||
return $localize`Sorting`;
|
|
||||||
case backendTexts.sortBy.description:
|
|
||||||
return $localize`Sorts the photos and videos by this.`;
|
|
||||||
case backendTexts.pickAmount.name:
|
|
||||||
return $localize`Pick`;
|
|
||||||
case backendTexts.pickAmount.description:
|
|
||||||
return $localize`Number of photos and videos to pick.`;
|
|
||||||
case backendTexts.emailTo.name:
|
case backendTexts.emailTo.name:
|
||||||
return $localize`E-mail to`;
|
return $localize`E-mail to`;
|
||||||
case backendTexts.emailTo.description:
|
case backendTexts.emailTo.description:
|
||||||
|
@ -155,7 +155,7 @@
|
|||||||
<label class="col-md-2 control-label"
|
<label class="col-md-2 control-label"
|
||||||
[for]="configEntry.id+'_'+i">{{backendTextService.get(configEntry.name)}}</label>
|
[for]="configEntry.id+'_'+i">{{backendTextService.get(configEntry.name)}}</label>
|
||||||
<div class="col-md-10">
|
<div class="col-md-10">
|
||||||
<div class="input-group">
|
<div [class.input-group]="'MediaPickDTO-array'!=configEntry.type">
|
||||||
<ng-container [ngSwitch]="configEntry.type">
|
<ng-container [ngSwitch]="configEntry.type">
|
||||||
<div
|
<div
|
||||||
*ngSwitchCase="'boolean'"
|
*ngSwitchCase="'boolean'"
|
||||||
@ -208,44 +208,115 @@
|
|||||||
placeholder="Search Query">
|
placeholder="Search Query">
|
||||||
</app-gallery-search-field>
|
</app-gallery-search-field>
|
||||||
|
|
||||||
|
<ng-container *ngSwitchCase="'MediaPickDTO-array'">
|
||||||
|
<ng-container *ngFor="let mp of AsMediaPickDTOArray(schedule.config[configEntry.id]); let j=index">
|
||||||
|
|
||||||
<ng-container *ngSwitchCase="'sort-array'">
|
<div class="mb-3 row">
|
||||||
<ng-container *ngFor="let _ of AsSortArray(schedule.config[configEntry.id]); let j=index">
|
<label class="col-md-2 control-label"
|
||||||
|
[for]="configEntry.id+'_'+i" i18n>Search Query - {{(j + 1)}}</label>
|
||||||
|
<div class="col-md-10">
|
||||||
|
<div class="input-group">
|
||||||
|
<app-gallery-search-field
|
||||||
|
[(ngModel)]="mp.searchQuery"
|
||||||
|
[id]="'sq_'+configEntry.id+'_'+i+'_'+j"
|
||||||
|
[name]="'sq_'+configEntry.id+'_'+i+'_'+j"
|
||||||
|
(change)="onChange($event)"
|
||||||
|
placeholder="Search Query">
|
||||||
|
</app-gallery-search-field>
|
||||||
|
</div>
|
||||||
|
<small class="form-text text-muted" i18n>
|
||||||
|
Search query to list photos and videos.
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3 row">
|
||||||
|
<label class="col-md-2 control-label"
|
||||||
|
[for]="configEntry.id+'_'+i" i18n>Sort by</label>
|
||||||
|
<div class="col-md-10">
|
||||||
|
<div class="input-group">
|
||||||
|
<ng-container *ngFor="let _ of mp.sortBy; let k=index">
|
||||||
<div class="row col-12 mt-1 m-0 p-0">
|
<div class="row col-12 mt-1 m-0 p-0">
|
||||||
<div class="col p-0">
|
<div class="col p-0">
|
||||||
<select
|
<select
|
||||||
[id]="configEntry.id+'_'+i+'_'+j"
|
[id]="configEntry.id+'_'+i+'_'+j+'_'+k"
|
||||||
[name]="configEntry.id+'_'+i+'_'+j"
|
[name]="configEntry.id+'_'+i+'_'+j+'_'+k"
|
||||||
(ngModelChange)="onChange($event)"
|
(ngModelChange)="onChange($event)"
|
||||||
class="form-select" [(ngModel)]="AsSortArray(schedule.config[configEntry.id])[j]">
|
class="form-select"
|
||||||
|
[(ngModel)]="mp.sortBy[k]">
|
||||||
<option *ngFor="let opt of SortingMethods" [ngValue]="opt.key">{{opt.value}}
|
<option *ngFor="let opt of SortingMethods" [ngValue]="opt.key">{{opt.value}}
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<ng-container>
|
|
||||||
<div class="col-auto pe-0">
|
<div class="col-auto pe-0">
|
||||||
<button class="btn btn-secondary float-end"
|
<button class="btn btn-danger float-end"
|
||||||
[id]="'list_btn_'+configEntry.id+'_'+i+'_'+j"
|
[class.btn-secondary]="mp.sortBy.length < 2"
|
||||||
[name]="'list_btn_'+configEntry.id+'_'+i+'_'+j"
|
[class.btn-danger]="mp.sortBy.length >= 2"
|
||||||
(click)="removeSorting(schedule.config[configEntry.id],j)"><span
|
[disabled]="mp.sortBy.length < 2"
|
||||||
|
[id]="'list_btn_'+configEntry.id+'_'+i+'_'+j+'_'+k"
|
||||||
|
[name]="'list_btn_'+configEntry.id+'_'+i+'_'+j+'_'+k"
|
||||||
|
(click)="removeFromArray(mp.sortBy,k)"><span
|
||||||
class="oi oi-trash"></span>
|
class="oi oi-trash"></span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</ng-container>
|
|
||||||
</div>
|
</div>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
<div class="col-12 p-0">
|
||||||
|
<button class="btn btn-primary mt-1 float-end"
|
||||||
|
[id]="'btn_add_'+configEntry.id+'_'+i+'_'+j"
|
||||||
|
[name]="'btn_add_'+configEntry.id+'_'+i+'_'+j"
|
||||||
|
(click)="AddNewSorting(mp.sortBy)" i18n>+ Add
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<small class="form-text text-muted" i18n>
|
||||||
|
Sorts the photos and videos by this.
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3 row">
|
||||||
|
<label class="col-md-2 control-label"
|
||||||
|
[for]="configEntry.id+'_'+i" i18n>Pick</label>
|
||||||
|
<div class="col-md-10">
|
||||||
|
<div class="input-group">
|
||||||
|
<input type="number" class="form-control" [name]="configEntry.id+'_'+i+'_'+j"
|
||||||
|
[id]="configEntry.id+'_'+i+'_'+j"
|
||||||
|
(ngModelChange)="onChange($event)"
|
||||||
|
[(ngModel)]="mp.pick" required>
|
||||||
|
</div>
|
||||||
|
<small class="form-text text-muted" i18n>
|
||||||
|
Number of photos and videos to pick.
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<button class="btn float-end"
|
||||||
|
[class.btn-secondary]="AsMediaPickDTOArray(schedule.config[configEntry.id]).length < 2"
|
||||||
|
[class.btn-danger]="AsMediaPickDTOArray(schedule.config[configEntry.id]).length >= 2"
|
||||||
|
[disabled]="AsMediaPickDTOArray(schedule.config[configEntry.id]).length < 2"
|
||||||
|
[id]="'list_btn_'+configEntry.id+'_'+i+'_'+j"
|
||||||
|
[name]="'list_btn_'+configEntry.id+'_'+i+'_'+j"
|
||||||
|
(click)="removeFromArray(AsMediaPickDTOArray(schedule.config[configEntry.id]),j)"><span
|
||||||
|
class="oi oi-trash"></span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<hr/>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
<ng-container>
|
<ng-container>
|
||||||
<div class="col-12 p-0">
|
<div class="col-12 p-0">
|
||||||
<button class="btn btn-primary mt-1 float-end"
|
<button class="btn btn-primary mt-1 float-end"
|
||||||
[id]="'btn_add_'+configEntry.id+'_'+i"
|
[id]="'btn_add_'+configEntry.id+'_'+i"
|
||||||
[name]="'btn_add_'+configEntry.id+'_'+i"
|
[name]="'btn_add_'+configEntry.id+'_'+i"
|
||||||
(click)="AddNewSorting(schedule.config[configEntry.id])" i18n>+ Add
|
(click)="AddNewMediaPickDTO(schedule.config[configEntry.id])" i18n>+ Add
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
|
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</div>
|
</div>
|
||||||
<small class="form-text text-muted">
|
<small class="form-text text-muted">
|
||||||
|
@ -21,6 +21,8 @@ import {
|
|||||||
import {ControlValueAccessor, NG_VALIDATORS, NG_VALUE_ACCESSOR, ValidationErrors, Validator} from '@angular/forms';
|
import {ControlValueAccessor, NG_VALIDATORS, NG_VALUE_ACCESSOR, ValidationErrors, Validator} from '@angular/forms';
|
||||||
import {enumToTranslatedArray} from '../../EnumTranslations';
|
import {enumToTranslatedArray} from '../../EnumTranslations';
|
||||||
import {SortingMethods} from '../../../../../common/entities/SortingMethods';
|
import {SortingMethods} from '../../../../../common/entities/SortingMethods';
|
||||||
|
import {MediaPickDTO} from '../../../../../common/entities/MediaPickDTO';
|
||||||
|
import {SearchQueryTypes, TextSearch} from '../../../../../common/entities/SearchQueryDTO';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-settings-workflow',
|
selector: 'app-settings-workflow',
|
||||||
@ -292,15 +294,27 @@ export class WorkflowComponent implements ControlValueAccessor, Validator, OnIni
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
AsSortArray(configElement: string | number | string[] | number[]): SortingMethods[] {
|
AsSortArray(configElement: string | number | string[] | number[] | MediaPickDTO[]): SortingMethods[] {
|
||||||
return configElement as SortingMethods[];
|
return configElement as SortingMethods[];
|
||||||
}
|
}
|
||||||
|
|
||||||
removeSorting(configElement: string | number | string[] | number[], j: number): void {
|
AsMediaPickDTOArray(configElement: string | number | string[] | number[] | MediaPickDTO[]): MediaPickDTO[] {
|
||||||
(configElement as SortingMethods[]).splice(j);
|
return configElement as MediaPickDTO[];
|
||||||
}
|
}
|
||||||
|
|
||||||
AddNewSorting(configElement: string | number | string[] | number[]): void {
|
removeFromArray(configElement: any[], i: number): void {
|
||||||
|
configElement.splice(i, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
AddNewSorting(configElement: string | number | string[] | number[] | MediaPickDTO[]): void {
|
||||||
(configElement as SortingMethods[]).push(SortingMethods.ascDate);
|
(configElement as SortingMethods[]).push(SortingMethods.ascDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AddNewMediaPickDTO(configElement: string | number | string[] | number[] | MediaPickDTO[]): void {
|
||||||
|
(configElement as MediaPickDTO[]).push({
|
||||||
|
searchQuery: {type: SearchQueryTypes.any_text, text: ''} as TextSearch,
|
||||||
|
sortBy: [SortingMethods.descRating],
|
||||||
|
pick: 5
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user