mirror of
https://github.com/fabioformosa/quartz-manager.git
synced 2025-12-30 22:23:15 +09:00
#56 added a new FE component to schedule a simple trigger
This commit is contained in:
@@ -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",
|
||||
|
||||
@@ -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: [
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
export * from './simple-trigger-config.component';
|
||||
export {SimpleTriggerCommand} from '../../model/simple-trigger.command';
|
||||
@@ -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>
|
||||
@@ -0,0 +1,3 @@
|
||||
.small{
|
||||
font-size: 0.8em;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
4
quartz-manager-frontend/src/app/model/jobKey.model.ts
Normal file
4
quartz-manager-frontend/src/app/model/jobKey.model.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export class JobKeyModel {
|
||||
name: string;
|
||||
group: string;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
export class SimpleTriggerCommand {
|
||||
startDate: Date;
|
||||
endDate: Date;
|
||||
repeatCount: number;
|
||||
repeatInterval: number;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
import {Moment} from 'moment/moment';
|
||||
|
||||
export class SimpleTriggerForm {
|
||||
startDate: Moment;
|
||||
endDate: Moment;
|
||||
repeatCount: number;
|
||||
repeatInterval: number;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
import {Trigger} from './trigger.model';
|
||||
|
||||
export class SimpleTrigger extends Trigger {
|
||||
repeatCount: number;
|
||||
repeatInterval: number;
|
||||
timesTriggered: number;
|
||||
}
|
||||
15
quartz-manager-frontend/src/app/model/trigger.model.ts
Normal file
15
quartz-manager-frontend/src/app/model/trigger.model.ts
Normal 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;
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user