#56 added a new FE component to schedule a simple trigger

This commit is contained in:
Fabio Formosa
2022-03-05 20:50:23 +01:00
parent 86badb8f41
commit 6bb768de59
14 changed files with 296 additions and 18 deletions

View File

@@ -12,6 +12,7 @@
},
"private": true,
"dependencies": {
"@angular-material-components/datetime-picker": "2.0.4",
"@angular/animations": "9.1.4",
"@angular/cdk": "9.2.1",
"@angular/common": "9.1.4",
@@ -32,6 +33,7 @@
"@types/jest": "^27.0.2",
"core-js": "2.5.1",
"hammerjs": "2.0.8",
"moment": "^2.29.1",
"net": "^1.0.2",
"rxjs": "6.5.5",
"stompjs": "^2.3.3",

View File

@@ -17,6 +17,11 @@ import {MatToolbarModule} from '@angular/material/toolbar';
import {MatIconModule} from '@angular/material/icon';
import {MatButtonModule} from '@angular/material/button';
import {MatCardModule} from '@angular/material/card';
import {MatDatepickerModule} from '@angular/material/datepicker';
import {MatNativeDateModule} from '@angular/material/core';
import { NgxMatTimepickerModule, NgxMatDatetimePickerModule} from '@angular-material-components/datetime-picker';
import { NgxMatMomentModule } from '@angular-material-components/moment-adapter';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { FlexLayoutModule } from '@angular/flex-layout';
@@ -52,6 +57,7 @@ import { ChangePasswordComponent } from './views/change-password/change-password
import { ForbiddenComponent } from './views/forbidden/forbidden.component';
import { APP_BASE_HREF } from '@angular/common';
import { environment } from '../environments/environment';
import {SimpleTriggerConfigComponent} from './components/simple-trigger-config';
export function initUserFactory(userService: UserService) {
return () => userService.jsessionInitUser();
@@ -102,6 +108,7 @@ export function jwtOptionsFactory(apiService: ApiService) {
NotFoundComponent,
AccountMenuComponent,
SchedulerConfigComponent,
SimpleTriggerConfigComponent,
SchedulerControlComponent,
LogsPanelComponent,
ProgressPanelComponent,
@@ -132,6 +139,9 @@ export function jwtOptionsFactory(apiService: ApiService) {
MatCardModule,
MatProgressSpinnerModule,
MatProgressBarModule,
MatDatepickerModule, MatNativeDateModule,
NgxMatMomentModule,
NgxMatDatetimePickerModule,
FlexLayoutModule
],
providers: [

View File

@@ -14,23 +14,25 @@
<mat-card-content *ngIf="existsATriggerInProgress() || enabledTriggerForm">
<div fxLayout="column">
<form name="configForm" fxFlex="1 1 100%" #configForm="ngForm">
<mat-form-field [appearance]="enabledTriggerForm ? 'fill': 'none'">
<mat-label>Freq [Num per day]</mat-label>
<input [readonly]="!enabledTriggerForm"
matInput placeholder="Freq [Num per day]" name="triggerPerDay" type="number"
[(ngModel)]="config.triggerPerDay"
>
</mat-form-field>
<mat-form-field [appearance]="enabledTriggerForm ? 'fill': 'none'">
<mat-label>Max Occurrences</mat-label>
<input [readonly]="!enabledTriggerForm"
matInput placeholder="Max Occurrences" name="maxCount" type="number"
[(ngModel)]="config.maxCount"
>
</mat-form-field>
<div>
<mat-form-field [appearance]="enabledTriggerForm ? 'standard': 'none'">
<mat-label>Freq [Num per day]</mat-label>
<input [readonly]="!enabledTriggerForm"
matInput placeholder="Freq [Num per day]" name="triggerPerDay" type="number"
[(ngModel)]="config.triggerPerDay"
>
</mat-form-field>
</div>
<div>
<mat-form-field [appearance]="enabledTriggerForm ? 'standard': 'none'">
<mat-label>Max Occurrences</mat-label>
<input [readonly]="!enabledTriggerForm"
matInput placeholder="Max Occurrences" name="maxCount" type="number"
[(ngModel)]="config.maxCount"
>
</mat-form-field>
</div>
<br>
<div>
<h5>Misfire Policy</h5>
<div>RESCHEDULE NEXT WITH REMAINING COUNT</div>

View File

@@ -0,0 +1,2 @@
export * from './simple-trigger-config.component';
export {SimpleTriggerCommand} from '../../model/simple-trigger.command';

View File

@@ -0,0 +1,103 @@
<mat-card>
<mat-card-header>
<mat-card-title><b>SCHEDULER CONFIG</b></mat-card-title>
</mat-card-header>
<!-- ADD BUTTON -->
<mat-card-content *ngIf="!existsATriggerInProgress() && !enabledTriggerForm">
<button mat-fab color="primary">
<mat-icon (click)="enableTriggerForm()">add</mat-icon>
</button>
</mat-card-content>
<!-- TRIGGER DETAILS -->
<mat-card-content *ngIf="existsATriggerInProgress() || enabledTriggerForm">
<div fxLayout="column">
<form name="configForm" fxFlex="1 1 100%" #configForm="ngForm">
<div>
<mat-form-field [appearance]="enabledTriggerForm ? 'standard': 'none'">
<mat-label>Start Date (optional)</mat-label>
<input [readonly]="!enabledTriggerForm"
matInput name="startDate"
[ngxMatDatetimePicker]="startDatePicker" placeholder="Choose a start date"
[(ngModel)]="simpleTriggerForm.startDate">
<mat-datepicker-toggle matSuffix [for]="startDatePicker"></mat-datepicker-toggle>
<ngx-mat-datetime-picker #startDatePicker showSpinners="true" showSeconds="true">
<!-- [stepHour]="stepHour"-->
<!-- [stepMinute]="stepMinute" [stepSecond]="stepSecond" [touchUi]="touchUi" [color]="color"-->
<!-- [enableMeridian]="enableMeridian" [disableMinute]="disableMinute" [hideTime]="hideTime">-->
</ngx-mat-datetime-picker>
</mat-form-field>
</div>
<div>
<mat-form-field [appearance]="enabledTriggerForm ? 'standard': 'none'">
<mat-label>End Date (optional)</mat-label>
<input [readonly]="!enabledTriggerForm"
matInput name="endDate"
[ngxMatDatetimePicker]="endDatePicker" placeholder="Choose a end date"
[(ngModel)]="simpleTriggerForm.endDate"
>
<mat-datepicker-toggle matSuffix [for]="endDatePicker"></mat-datepicker-toggle>
<ngx-mat-datetime-picker #endDatePicker showSpinners="true" showSeconds="true">
<!-- [stepHour]="stepHour"-->
<!-- [stepMinute]="stepMinute" [stepSecond]="stepSecond" [touchUi]="touchUi" [color]="color"-->
<!-- [enableMeridian]="enableMeridian" [disableMinute]="disableMinute" [hideTime]="hideTime">-->
</ngx-mat-datetime-picker>
</mat-form-field>
</div>
<div>
<mat-form-field [appearance]="enabledTriggerForm ? 'standard': 'none'">
<mat-label>Repeat Interval [in mills]</mat-label>
<input [readonly]="!enabledTriggerForm"
matInput placeholder="Repeat Interval [in mills]" name="repeatInterval" type="number"
[(ngModel)]="simpleTriggerForm.repeatInterval"
>
</mat-form-field>
</div>
<div>
<mat-form-field [appearance]="enabledTriggerForm ? 'standard': 'none'">
<mat-label>Repeat Count</mat-label>
<input [readonly]="!enabledTriggerForm"
matInput placeholder="Repeat Count (-1 REPEAT INDEFINITELY)" name="repeatCount" type="number"
[(ngModel)]="simpleTriggerForm.repeatCount"
>
</mat-form-field>
</div>
<br>
<div>
<h5>Misfire Policy</h5>
<div>RESCHEDULE NEXT WITH REMAINING COUNT</div>
<div class="small">
In case of misfire event, the trigger is re-scheduled to the next scheduled time after 'now' with the repeat count set to what it would be, if it had not missed any firings.
<br/>
<strong>Warning:</strong> This policy could cause the Trigger to go directly to the 'COMPLETE' state if all fire-times where missed.
</div>
</div>
<br>
<button mat-raised-button
type="button"
*ngIf="enabledTriggerForm"
(click)="cancelConfigForm()">
Cancel
</button>
<button mat-raised-button
type="button" color="primary"
*ngIf="enabledTriggerForm"
(click)="submitConfig()">
Submit
</button>
<button mat-raised-button type="button"
*ngIf="!enabledTriggerForm"
(click)="enabledTriggerForm = true">
Reschedule
</button>
</form>
</div>
</mat-card-content>
</mat-card>

View File

@@ -0,0 +1,3 @@
.small{
font-size: 0.8em;
}

View File

@@ -0,0 +1,99 @@
import {Component, OnInit} from '@angular/core';
import {SchedulerService} from '../../services';
import {Scheduler} from '../../model/scheduler.model';
import {SimpleTriggerCommand} from '../../model/simple-trigger.command';
import {SimpleTrigger} from '../../model/simple-trigger.model';
import {SimpleTriggerForm} from '../../model/simple-trigger.form';
import * as moment from 'moment';
@Component({
selector: 'qrzmng-simple-trigger-config',
templateUrl: './simple-trigger-config.component.html',
styleUrls: ['./simple-trigger-config.component.scss']
})
export class SimpleTriggerConfigComponent implements OnInit {
simpleTriggerForm: SimpleTriggerForm = new SimpleTriggerForm();
formBackup: SimpleTriggerForm = new SimpleTriggerForm();
trigger: SimpleTrigger;
scheduler: Scheduler;
triggerLoading = true;
enabledTriggerForm = false;
private fetchedTriggers = false;
private triggerInProgress = false;
constructor(
private schedulerService: SchedulerService
) { }
ngOnInit() {
this.triggerLoading = true;
this.retrieveConfiguredTriggerIfExists();
}
retrieveConfiguredTriggerIfExists = () => {
this.schedulerService.getSimpleTriggerConfig()
.subscribe((retTrigger: SimpleTrigger) => {
this.trigger = retTrigger;
this.formBackup = this.simpleTriggerForm;
this.simpleTriggerForm = this._fromTriggerToForm(retTrigger);
this.triggerLoading = false;
this.triggerInProgress = this.trigger.mayFireAgain;
})
}
existsATriggerInProgress = (): boolean => this.trigger && this.triggerInProgress;
cancelConfigForm = () => this.enabledTriggerForm = false;
submitConfig = () => {
const schedulerServiceCall = this.existsATriggerInProgress() ?
this.schedulerService.updateSimpleTriggerConfig : this.schedulerService.saveSimpleTriggerConfig;
const simpleTriggerCommand = this._fromFormToCommand(this.simpleTriggerForm);
schedulerServiceCall(simpleTriggerCommand)
.subscribe((retTrigger: SimpleTrigger) => {
this.trigger = retTrigger;
this.formBackup = this.simpleTriggerForm;
this.simpleTriggerForm = this._fromTriggerToForm(retTrigger);
this.enabledTriggerForm = false;
this.fetchedTriggers = true;
this.triggerInProgress = this.trigger.mayFireAgain;
}, error => {
this.simpleTriggerForm = this.formBackup;
});
};
enableTriggerForm = () => this.enabledTriggerForm = true;
private _fromTriggerToCommand = (simpleTrigger: SimpleTrigger) => {
const command = new SimpleTriggerCommand();
command.repeatCount = simpleTrigger.repeatCount;
command.repeatInterval = simpleTrigger.repeatInterval;
command.startDate = simpleTrigger.startTime;
command.endDate = simpleTrigger.endTime;
return command;
}
private _fromTriggerToForm = (simpleTrigger: SimpleTrigger): SimpleTriggerForm => {
const command = new SimpleTriggerForm();
command.repeatCount = simpleTrigger.repeatCount;
command.repeatInterval = simpleTrigger.repeatInterval;
command.startDate = moment(simpleTrigger.startTime);
command.endDate = moment(simpleTrigger.endTime);
return command;
}
private _fromFormToCommand = (simpleTriggerForm: SimpleTriggerForm): SimpleTriggerCommand => {
const simpleTriggerCommand = new SimpleTriggerCommand();
simpleTriggerCommand.repeatCount = simpleTriggerForm.repeatCount;
simpleTriggerCommand.repeatInterval = simpleTriggerForm.repeatInterval;
simpleTriggerCommand.startDate = simpleTriggerForm.startDate.toDate();
simpleTriggerCommand.endDate = simpleTriggerForm.endDate.toDate();
return simpleTriggerCommand;
}
}

View File

@@ -0,0 +1,4 @@
export class JobKeyModel {
name: string;
group: string;
}

View File

@@ -0,0 +1,6 @@
export class SimpleTriggerCommand {
startDate: Date;
endDate: Date;
repeatCount: number;
repeatInterval: number;
}

View File

@@ -0,0 +1,8 @@
import {Moment} from 'moment/moment';
export class SimpleTriggerForm {
startDate: Moment;
endDate: Moment;
repeatCount: number;
repeatInterval: number;
}

View File

@@ -0,0 +1,7 @@
import {Trigger} from './trigger.model';
export class SimpleTrigger extends Trigger {
repeatCount: number;
repeatInterval: number;
timesTriggered: number;
}

View File

@@ -0,0 +1,15 @@
import {TriggerKey} from './triggerKey.model';
import {JobKeyModel} from './jobKey.model';
export class Trigger {
triggerKeyDTO: TriggerKey;
priority: number;
startTime: Date;
description: string;
endTime: Date;
finalFireTime: Date;
misfireInstruction: number;
nextFireTime: Date;
jobKeyDTO: JobKeyModel;
mayFireAgain: boolean;
}

View File

@@ -1,6 +1,10 @@
import { Injectable } from '@angular/core';
import { getBaseUrl } from '.';
import { ApiService } from './api.service';
import {Trigger} from '../model/trigger.model';
import {Observable} from 'rxjs';
import {SimpleTriggerCommand} from '../model/simple-trigger.command';
import {SchedulerConfig} from '../model/schedulerConfig.model';
@Injectable()
export class SchedulerService {
@@ -33,17 +37,30 @@ export class SchedulerService {
return this.apiService.get(getBaseUrl() + '/quartz-manager/scheduler')
}
// deprecated
getConfig = () => {
return this.apiService.get(getBaseUrl() + '/quartz-manager/scheduler/config')
}
getSimpleTriggerConfig = (): Observable<Trigger> => {
return this.apiService.get(getBaseUrl() + '/quartz-manager/simple-triggers/my-simple-trigger');
}
saveConfig = (config: Object) => {
return this.apiService.post(getBaseUrl() + '/quartz-manager/triggers/mytrigger', config)
}
updateConfig = (config: Object) => {
saveSimpleTriggerConfig = (config: SimpleTriggerCommand) => {
return this.apiService.post(getBaseUrl() + '/quartz-manager/simple-triggers/mytrigger', config)
}
updateConfig = (config: SchedulerConfig) => {
return this.apiService.put(getBaseUrl() + '/quartz-manager/triggers/mytrigger', config)
}
updateSimpleTriggerConfig = (config: SimpleTriggerCommand) => {
return this.apiService.put(getBaseUrl() + '/quartz-manager/simple-triggers/mytrigger', config)
}
}

View File

@@ -4,7 +4,7 @@
<div fxLayout="column">
<scheduler-control></scheduler-control>
<br/>
<qrzmng-scheduler-config></qrzmng-scheduler-config>
<qrzmng-simple-trigger-config></qrzmng-simple-trigger-config>
</div>
</div>