mirror of
https://github.com/clearml/clearml-web
synced 2025-03-13 07:08:17 +00:00
Cron expressions added
This commit is contained in:
parent
4a4cb27e16
commit
ff273177a4
@ -1,4 +1,4 @@
|
|||||||
<form (ngSubmit)="send()" #settingsForm='ngForm' class="d-flex flex-column">
|
<form (ngSubmit)="send()" #settingsForm='ngForm' class="d-flex flex-column" (click)="$event.stopPropagation()">
|
||||||
<mat-form-field appearance="outline" hideRequiredMarker class="mat-light">
|
<mat-form-field appearance="outline" hideRequiredMarker class="mat-light">
|
||||||
<mat-label>Email List</mat-label>
|
<mat-label>Email List</mat-label>
|
||||||
<mat-error *ngIf="settingsForm.controls.emailList?.touched && settingsForm.controls.emailList.errors?.required">*Please add an email.</mat-error>
|
<mat-error *ngIf="settingsForm.controls.emailList?.touched && settingsForm.controls.emailList.errors?.required">*Please add an email.</mat-error>
|
||||||
@ -12,19 +12,20 @@
|
|||||||
<mat-label>Schedule Interval</mat-label>
|
<mat-label>Schedule Interval</mat-label>
|
||||||
<input matInput placeholder="Search for existing intervals" [matAutocomplete]="auto" [(ngModel)]="settingFields.interval" name="intervalName">
|
<input matInput placeholder="Search for existing intervals" [matAutocomplete]="auto" [(ngModel)]="settingFields.interval" name="intervalName">
|
||||||
<mat-autocomplete #auto="matAutocomplete" (optionSelected)="intervalSelected($event)">
|
<mat-autocomplete #auto="matAutocomplete" (optionSelected)="intervalSelected($event)">
|
||||||
<mat-option value="custom">Custom</mat-option>
|
<mat-option *ngFor="let option of intervalOptions" [value]="option"> {{ option.charAt(0).toUpperCase() + option.slice(1) }}</mat-option>
|
||||||
<mat-option value="daily">Daily</mat-option>
|
|
||||||
<mat-option value="hourly">Hourly</mat-option>
|
|
||||||
<mat-option value="weekly">Weekly</mat-option>
|
|
||||||
</mat-autocomplete>
|
</mat-autocomplete>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
<mat-form-field appearance="outline" hideRequiredMarker>
|
<mat-form-field appearance="outline" hideRequiredMarker class="cron-expression-field">
|
||||||
<mat-error *ngIf="expression?.touched && expression?.invalid">*Please add Cron Expression.</mat-error>
|
<mat-error *ngIf="expression?.touched && expression?.invalid">*Please add Cron Expression.</mat-error>
|
||||||
<mat-label>Cron Expression</mat-label>
|
<mat-label>Cron Expression</mat-label>
|
||||||
<input class="step-expression" name="cronExpression" matInput [(ngModel)]="settingFields.expression" #expression="ngModel" required>
|
<div class="input-container">
|
||||||
|
<input class="step-expression" name="cronExpression" matInput [(ngModel)]="settingFields.expression" #expression="ngModel" (input)="checkCronExpression()">
|
||||||
|
<button type="button" class="btn btn-icon g-btn" (click)="navigateToWebsite()">
|
||||||
|
<i class="icon i-alert-purple"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
<div class="w-100 create-step-button">
|
<div class="w-100 create-step-button">
|
||||||
<button type="submit" class="btn btn-dark-fill center" [disabled]="settingsForm.invalid">Save</button>
|
<button type="submit" class="btn btn-dark-fill center" [disabled]="settingsForm.invalid">Save</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -27,4 +27,12 @@
|
|||||||
}
|
}
|
||||||
::ng-deep .dark-theme .mat-mdc-option.mdc-list-item:hover {
|
::ng-deep .dark-theme .mat-mdc-option.mdc-list-item:hover {
|
||||||
background-color: #dce0ee;
|
background-color: #dce0ee;
|
||||||
|
}
|
||||||
|
.cron-expression-field .mat-form-field-flex {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cron-expression-field .input-container {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
@ -13,8 +13,6 @@ import {
|
|||||||
styleUrls: ['./pipeline-setting-form.component.scss']
|
styleUrls: ['./pipeline-setting-form.component.scss']
|
||||||
})
|
})
|
||||||
export class PipelineSettingFormComponent implements OnDestroy {
|
export class PipelineSettingFormComponent implements OnDestroy {
|
||||||
public readonly intervalsRoot = {label: 'My interval', value: null};
|
|
||||||
@ViewChild('intervalInput') intervalInput: NgModel;
|
|
||||||
@ViewChild('emailList') emailList: ElementRef;
|
@ViewChild('emailList') emailList: ElementRef;
|
||||||
@ViewChild('expression') expression: NgModel;
|
@ViewChild('expression') expression: NgModel;
|
||||||
|
|
||||||
@ -31,67 +29,50 @@ export class PipelineSettingFormComponent implements OnDestroy {
|
|||||||
interval: null,
|
interval: null,
|
||||||
expression: ''
|
expression: ''
|
||||||
};
|
};
|
||||||
|
|
||||||
intervalsOptions: { label: string; value: string }[];
|
intervalsOptions: { label: string; value: string }[];
|
||||||
intervalsNames: string[];
|
intervalsNames: string[];
|
||||||
rootFiltered = false;
|
|
||||||
isAutoCompleteOpen = false;
|
|
||||||
loading = false;
|
|
||||||
noMoreOptions = false;
|
|
||||||
|
|
||||||
private subs = new Subscription();
|
private subs = new Subscription();
|
||||||
|
|
||||||
constructor() {}
|
constructor() {}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {}
|
||||||
this.searchChanged(['*', null].includes(this.defaultintervalId) ? '' : this.defaultintervalId);
|
|
||||||
setTimeout(() => {
|
|
||||||
this.subs.add(this.intervalInput.valueChanges.subscribe(searchString => {
|
|
||||||
if (searchString !== this.settingFields.interval) {
|
|
||||||
this.searchChanged(searchString?.label || searchString || '');
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
this.subs.unsubscribe();
|
this.subs.unsubscribe();
|
||||||
}
|
}
|
||||||
|
intervalOptions: string[] = ['custom', 'daily', 'hourly', 'weekly', 'monthly', 'yearly'];
|
||||||
|
cronExpressions: { [key: string]: string } = {
|
||||||
|
'custom': '',
|
||||||
|
'daily': '0 0 * * *',
|
||||||
|
'hourly': '0 * * * *',
|
||||||
|
'weekly': '0 0 * * 0',
|
||||||
|
'monthly': '0 0 1 * *',
|
||||||
|
'yearly': '0 0 1 1 *'
|
||||||
|
};
|
||||||
|
|
||||||
intervalSelected(event: MatAutocompleteSelectedEvent): void {
|
intervalSelected(event: MatAutocompleteSelectedEvent): void {
|
||||||
this.settingFields.interval = event.option.viewValue;
|
const selectedInterval = event.option.value;
|
||||||
}
|
this.settingFields.interval = selectedInterval;
|
||||||
setIsAutoCompleteOpen(focus: boolean) {
|
this.settingFields.expression = this.cronExpressions[selectedInterval];
|
||||||
this.isAutoCompleteOpen = focus;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
displayFn(interval: IOption | string) {
|
checkCronExpression(): void {
|
||||||
return typeof interval === 'string' ? interval : interval?.label;
|
const enteredExpression = this.settingFields.expression.trim();
|
||||||
|
const matchingInterval = Object.entries(this.cronExpressions).find(([interval, expression]) => expression === enteredExpression);
|
||||||
|
if (matchingInterval) {
|
||||||
|
this.settingFields.interval = matchingInterval[0];
|
||||||
|
} else {
|
||||||
|
this.settingFields.interval = 'custom';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
clear() {
|
navigateToWebsite(): void {
|
||||||
this.intervalInput.control.setValue('');
|
window.open('https://en.wikipedia.org/wiki/Cron', '_blank');
|
||||||
}
|
}
|
||||||
|
|
||||||
send() {
|
send() {
|
||||||
this.stepCreated.emit(this.settingFields);
|
this.stepCreated.emit(this.settingFields);
|
||||||
}
|
}
|
||||||
|
|
||||||
searchChanged(searchString: string) {
|
|
||||||
this.intervalsOptions = null;
|
|
||||||
this.intervalsNames = null;
|
|
||||||
this.rootFiltered = searchString && !this.intervalsRoot.label.toLowerCase().includes(searchString.toLowerCase());
|
|
||||||
searchString !== null && this.filterSearchChanged.emit({ value: searchString, loadMore: false });
|
|
||||||
}
|
|
||||||
|
|
||||||
loadMore(searchString) {
|
|
||||||
this.loading = true;
|
|
||||||
this.filterSearchChanged.emit({ value: searchString || '', loadMore: true });
|
|
||||||
}
|
|
||||||
|
|
||||||
isFocused(locationRef: HTMLInputElement) {
|
|
||||||
return document.activeElement === locationRef;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,16 +26,9 @@ export class PipelineSettingDialogComponent {
|
|||||||
private store: Store,
|
private store: Store,
|
||||||
private matDialogRef: MatDialogRef<PipelineSettingDialogComponent>,
|
private matDialogRef: MatDialogRef<PipelineSettingDialogComponent>,
|
||||||
@Inject(MAT_DIALOG_DATA) public data: { defaultExperimentId: string}
|
@Inject(MAT_DIALOG_DATA) public data: { defaultExperimentId: string}
|
||||||
) {
|
) {}
|
||||||
// this.experiments$ = this.store.select(selectExperiments);
|
|
||||||
// this.readOnlyIntervalNames$ = this.store.select(selectExperiments)
|
|
||||||
// .pipe(map(experiments => experiments?.filter(experiment => isReadOnly(experiment)).map(experiment=> experiment.name)));
|
|
||||||
// this.store.dispatch(resetTablesFilterProjectsOptions());
|
|
||||||
}
|
|
||||||
|
|
||||||
public settingsForm(pipelineForm) {
|
public settingsForm(pipelineForm) {
|
||||||
// eslint-disable-next-line no-console
|
|
||||||
console.log("i am form", pipelineForm)
|
|
||||||
const pipeline = this.convertFormToPipeline(pipelineForm);
|
const pipeline = this.convertFormToPipeline(pipelineForm);
|
||||||
this.matDialogRef.close(pipeline);
|
this.matDialogRef.close(pipeline);
|
||||||
}
|
}
|
||||||
|
@ -215,7 +215,7 @@ export class PipelinesEffects {
|
|||||||
catchError(err => {
|
catchError(err => {
|
||||||
return [
|
return [
|
||||||
requestFailed(err),
|
requestFailed(err),
|
||||||
setServerError(err, null, 'failed to create a new pipeline step'),
|
setServerError(err, null, 'failed to make changes in settings'),
|
||||||
deactivateLoader(pipelineSettings.type),
|
deactivateLoader(pipelineSettings.type),
|
||||||
]
|
]
|
||||||
})))
|
})))
|
||||||
|
Loading…
Reference in New Issue
Block a user