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-label>Email List</mat-label>
|
||||
<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>
|
||||
<input matInput placeholder="Search for existing intervals" [matAutocomplete]="auto" [(ngModel)]="settingFields.interval" name="intervalName">
|
||||
<mat-autocomplete #auto="matAutocomplete" (optionSelected)="intervalSelected($event)">
|
||||
<mat-option value="custom">Custom</mat-option>
|
||||
<mat-option value="daily">Daily</mat-option>
|
||||
<mat-option value="hourly">Hourly</mat-option>
|
||||
<mat-option value="weekly">Weekly</mat-option>
|
||||
<mat-option *ngFor="let option of intervalOptions" [value]="option"> {{ option.charAt(0).toUpperCase() + option.slice(1) }}</mat-option>
|
||||
</mat-autocomplete>
|
||||
</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-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>
|
||||
|
||||
<div class="w-100 create-step-button">
|
||||
<button type="submit" class="btn btn-dark-fill center" [disabled]="settingsForm.invalid">Save</button>
|
||||
</div>
|
||||
|
@ -27,4 +27,12 @@
|
||||
}
|
||||
::ng-deep .dark-theme .mat-mdc-option.mdc-list-item:hover {
|
||||
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']
|
||||
})
|
||||
export class PipelineSettingFormComponent implements OnDestroy {
|
||||
public readonly intervalsRoot = {label: 'My interval', value: null};
|
||||
@ViewChild('intervalInput') intervalInput: NgModel;
|
||||
@ViewChild('emailList') emailList: ElementRef;
|
||||
@ViewChild('expression') expression: NgModel;
|
||||
|
||||
@ -31,67 +29,50 @@ export class PipelineSettingFormComponent implements OnDestroy {
|
||||
interval: null,
|
||||
expression: ''
|
||||
};
|
||||
|
||||
intervalsOptions: { label: string; value: string }[];
|
||||
intervalsNames: string[];
|
||||
rootFiltered = false;
|
||||
isAutoCompleteOpen = false;
|
||||
loading = false;
|
||||
noMoreOptions = false;
|
||||
|
||||
|
||||
private subs = new Subscription();
|
||||
|
||||
constructor() {}
|
||||
|
||||
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 || '');
|
||||
}
|
||||
}));
|
||||
});
|
||||
}
|
||||
ngOnInit(): void {}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
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 {
|
||||
this.settingFields.interval = event.option.viewValue;
|
||||
}
|
||||
setIsAutoCompleteOpen(focus: boolean) {
|
||||
this.isAutoCompleteOpen = focus;
|
||||
const selectedInterval = event.option.value;
|
||||
this.settingFields.interval = selectedInterval;
|
||||
this.settingFields.expression = this.cronExpressions[selectedInterval];
|
||||
}
|
||||
|
||||
displayFn(interval: IOption | string) {
|
||||
return typeof interval === 'string' ? interval : interval?.label;
|
||||
checkCronExpression(): void {
|
||||
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() {
|
||||
this.intervalInput.control.setValue('');
|
||||
navigateToWebsite(): void {
|
||||
window.open('https://en.wikipedia.org/wiki/Cron', '_blank');
|
||||
}
|
||||
|
||||
send() {
|
||||
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 matDialogRef: MatDialogRef<PipelineSettingDialogComponent>,
|
||||
@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) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log("i am form", pipelineForm)
|
||||
const pipeline = this.convertFormToPipeline(pipelineForm);
|
||||
this.matDialogRef.close(pipeline);
|
||||
}
|
||||
|
@ -215,7 +215,7 @@ export class PipelinesEffects {
|
||||
catchError(err => {
|
||||
return [
|
||||
requestFailed(err),
|
||||
setServerError(err, null, 'failed to create a new pipeline step'),
|
||||
setServerError(err, null, 'failed to make changes in settings'),
|
||||
deactivateLoader(pipelineSettings.type),
|
||||
]
|
||||
})))
|
||||
|
Loading…
Reference in New Issue
Block a user