1
0
mirror of https://github.com/bpatrik/pigallery2.git synced 2025-02-11 13:53:28 +02:00

Implement MediaPickDTO to allow multiple search queries to send top pick mails. #683

This commit is contained in:
Patrik J. Braun 2023-08-04 00:17:54 +02:00
parent 3e6bb7bff7
commit 794039d824
9 changed files with 204 additions and 116 deletions

View File

@ -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: [{
type: SearchQueryTypes.date_pattern, searchQuery: {
daysLength: 7, type: SearchQueryTypes.date_pattern,
frequency: DatePatternFrequency.every_year daysLength: 7,
} as DatePatternSearch, frequency: DatePatternFrequency.every_year
}, { } as DatePatternSearch,
id: 'sortby', sortBy: [SortingMethods.descRating, SortingMethods.descPersonCount],
type: 'sort-array', pick: 5
name: backendTexts.sortBy.name, }] as MediaPickDTO[],
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,

View File

@ -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}

View File

@ -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({

View File

@ -0,0 +1,8 @@
import {SearchQueryDTO} from './SearchQueryDTO';
import {SortingMethods} from './SortingMethods';
export interface MediaPickDTO {
searchQuery: SearchQueryDTO;
sortBy: SortingMethods[];
pick: number;
}

View File

@ -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,

View File

@ -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

View File

@ -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:

View File

@ -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"
<div class="row col-12 mt-1 m-0 p-0"> [for]="configEntry.id+'_'+i" i18n>Search Query - {{(j + 1)}}</label>
<div class="col p-0"> <div class="col-md-10">
<select <div class="input-group">
[id]="configEntry.id+'_'+i+'_'+j" <app-gallery-search-field
[name]="configEntry.id+'_'+i+'_'+j" [(ngModel)]="mp.searchQuery"
(ngModelChange)="onChange($event)" [id]="'sq_'+configEntry.id+'_'+i+'_'+j"
class="form-select" [(ngModel)]="AsSortArray(schedule.config[configEntry.id])[j]"> [name]="'sq_'+configEntry.id+'_'+i+'_'+j"
<option *ngFor="let opt of SortingMethods" [ngValue]="opt.key">{{opt.value}} (change)="onChange($event)"
</option> placeholder="Search Query">
</select> </app-gallery-search-field>
</div>
<ng-container>
<div class="col-auto pe-0">
<button class="btn btn-secondary float-end"
[id]="'list_btn_'+configEntry.id+'_'+i+'_'+j"
[name]="'list_btn_'+configEntry.id+'_'+i+'_'+j"
(click)="removeSorting(schedule.config[configEntry.id],j)"><span
class="oi oi-trash"></span>
</button>
</div> </div>
</ng-container> <small class="form-text text-muted" i18n>
Search query to list photos and videos.
</small>
</div>
</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="col p-0">
<select
[id]="configEntry.id+'_'+i+'_'+j+'_'+k"
[name]="configEntry.id+'_'+i+'_'+j+'_'+k"
(ngModelChange)="onChange($event)"
class="form-select"
[(ngModel)]="mp.sortBy[k]">
<option *ngFor="let opt of SortingMethods" [ngValue]="opt.key">{{opt.value}}
</option>
</select>
</div>
<div class="col-auto pe-0">
<button class="btn btn-danger float-end"
[class.btn-secondary]="mp.sortBy.length < 2"
[class.btn-danger]="mp.sortBy.length >= 2"
[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>
</button>
</div>
</div>
</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> <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">

View File

@ -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',
@ -69,9 +71,9 @@ export class WorkflowComponent implements ControlValueAccessor, Validator, OnIni
error: string; error: string;
constructor( constructor(
public settingsService: SettingsService, public settingsService: SettingsService,
public jobsService: ScheduledJobsService, public jobsService: ScheduledJobsService,
public backendTextService: BackendtextService, public backendTextService: BackendtextService,
) { ) {
this.JobTriggerTypeMap = [ this.JobTriggerTypeMap = [
{key: JobTriggerType.after, value: $localize`after`}, {key: JobTriggerType.after, value: $localize`after`},
@ -113,27 +115,27 @@ export class WorkflowComponent implements ControlValueAccessor, Validator, OnIni
remove(schedule: JobScheduleDTO): void { remove(schedule: JobScheduleDTO): void {
this.schedules.splice( this.schedules.splice(
this.schedules.indexOf(schedule), this.schedules.indexOf(schedule),
1 1
); );
} }
jobTypeChanged(schedule: JobScheduleDTO): void { jobTypeChanged(schedule: JobScheduleDTO): void {
const job = this.jobsService.availableJobs.value.find( const job = this.jobsService.availableJobs.value.find(
(t) => t.Name === schedule.jobName (t) => t.Name === schedule.jobName
); );
schedule.config = schedule.config || {}; schedule.config = schedule.config || {};
if (job.ConfigTemplate) { if (job.ConfigTemplate) {
job.ConfigTemplate.forEach( job.ConfigTemplate.forEach(
(ct) => (schedule.config[ct.id] = ct.defaultValue) (ct) => (schedule.config[ct.id] = ct.defaultValue)
); );
} }
} }
jobTriggerTypeChanged( jobTriggerTypeChanged(
triggerType: JobTriggerType, triggerType: JobTriggerType,
schedule: JobScheduleDTO schedule: JobScheduleDTO
): void { ): void {
switch (triggerType) { switch (triggerType) {
case JobTriggerType.never: case JobTriggerType.never:
@ -163,7 +165,7 @@ export class WorkflowComponent implements ControlValueAccessor, Validator, OnIni
value = value.replace(new RegExp(',', 'g'), ';'); value = value.replace(new RegExp(',', 'g'), ';');
value = value.replace(new RegExp(' ', 'g'), ';'); value = value.replace(new RegExp(' ', 'g'), ';');
configElement[id] = value configElement[id] = value
.split(';').filter((i: string) => i != ''); .split(';').filter((i: string) => i != '');
} }
getArray(configElement: Record<string, number[]>, id: string): string { getArray(configElement: Record<string, number[]>, id: string): string {
@ -174,46 +176,46 @@ export class WorkflowComponent implements ControlValueAccessor, Validator, OnIni
value = value.replace(new RegExp(',', 'g'), ';'); value = value.replace(new RegExp(',', 'g'), ';');
value = value.replace(new RegExp(' ', 'g'), ';'); value = value.replace(new RegExp(' ', 'g'), ';');
configElement[id] = value configElement[id] = value
.split(';') .split(';')
.map((s: string) => parseInt(s, 10)) .map((s: string) => parseInt(s, 10))
.filter((i: number) => !isNaN(i) && i > 0); .filter((i: number) => !isNaN(i) && i > 0);
} }
public shouldIdent(curr: JobScheduleDTO, prev: JobScheduleDTO): boolean { public shouldIdent(curr: JobScheduleDTO, prev: JobScheduleDTO): boolean {
return ( return (
curr && curr &&
curr.trigger.type === JobTriggerType.after && curr.trigger.type === JobTriggerType.after &&
prev && prev &&
prev.name === curr.trigger.afterScheduleName prev.name === curr.trigger.afterScheduleName
); );
} }
public sortedSchedules(): JobScheduleDTO[] { public sortedSchedules(): JobScheduleDTO[] {
return (this.schedules || []) return (this.schedules || [])
.slice() .slice()
.sort((a: JobScheduleDTO, b: JobScheduleDTO) => { .sort((a: JobScheduleDTO, b: JobScheduleDTO) => {
return ( return (
this.getNextRunningDate(a, this.schedules) - this.getNextRunningDate(a, this.schedules) -
this.getNextRunningDate(b, this.schedules) this.getNextRunningDate(b, this.schedules)
); );
}); });
} }
prepareNewJob(): void { prepareNewJob(): void {
const jobName = this.jobsService.availableJobs.value[0].Name; const jobName = this.jobsService.availableJobs.value[0].Name;
this.newSchedule = new JobScheduleConfig('new job', this.newSchedule = new JobScheduleConfig('new job',
jobName, jobName,
new NeverJobTriggerConfig()); new NeverJobTriggerConfig());
// setup job specific config // setup job specific config
const job = this.jobsService.availableJobs.value.find( const job = this.jobsService.availableJobs.value.find(
(t) => t.Name === jobName (t) => t.Name === jobName
); );
this.newSchedule.config = this.newSchedule.config || {}; this.newSchedule.config = this.newSchedule.config || {};
if (job.ConfigTemplate) { if (job.ConfigTemplate) {
job.ConfigTemplate.forEach( job.ConfigTemplate.forEach(
(ct) => (this.newSchedule.config[ct.id] = ct.defaultValue) (ct) => (this.newSchedule.config[ct.id] = ct.defaultValue)
); );
} }
this.jobModalQL.first.show(); this.jobModalQL.first.show();
@ -223,12 +225,12 @@ export class WorkflowComponent implements ControlValueAccessor, Validator, OnIni
// make unique job name // make unique job name
const jobName = this.newSchedule.jobName; const jobName = this.newSchedule.jobName;
const count = this.schedules.filter( const count = this.schedules.filter(
(s: JobScheduleDTO) => s.jobName === jobName (s: JobScheduleDTO) => s.jobName === jobName
).length; ).length;
this.newSchedule.name = this.newSchedule.name =
count === 0 count === 0
? jobName ? jobName
: this.backendTextService.getJobName(jobName) + ' ' + (count + 1); : this.backendTextService.getJobName(jobName) + ' ' + (count + 1);
this.schedules.push(this.newSchedule); this.schedules.push(this.newSchedule);
this.jobModalQL.first.hide(); this.jobModalQL.first.hide();
@ -240,24 +242,24 @@ export class WorkflowComponent implements ControlValueAccessor, Validator, OnIni
} }
private getNextRunningDate( private getNextRunningDate(
sch: JobScheduleDTO, sch: JobScheduleDTO,
list: JobScheduleDTO[], list: JobScheduleDTO[],
depth = 0 depth = 0
): number { ): number {
if (depth > list.length) { if (depth > list.length) {
return 0; return 0;
} }
if (sch.trigger.type === JobTriggerType.never) { if (sch.trigger.type === JobTriggerType.never) {
return ( return (
list list
.map((s) => s.name) .map((s) => s.name)
.sort() .sort()
.indexOf(sch.name) * -1 .indexOf(sch.name) * -1
); );
} }
if (sch.trigger.type === JobTriggerType.after) { if (sch.trigger.type === JobTriggerType.after) {
const parent = list.find( const parent = list.find(
(s) => s.name === (sch.trigger as AfterJobTrigger).afterScheduleName (s) => s.name === (sch.trigger as AfterJobTrigger).afterScheduleName
); );
if (parent) { if (parent) {
return this.getNextRunningDate(parent, list, depth + 1) + 0.001; return this.getNextRunningDate(parent, list, depth + 1) + 0.001;
@ -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
});
}
} }