@firestitch/system 13.0.4 → 13.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/app/modules/system/components/cron-next-run/cron-next-run.component.d.ts +18 -0
- package/app/modules/system/components/cron-next-run/index.d.ts +1 -0
- package/app/modules/system/fs-system.module.d.ts +37 -36
- package/esm2020/app/modules/system/components/cron-next-run/cron-next-run.component.mjs +99 -0
- package/esm2020/app/modules/system/components/cron-next-run/index.mjs +2 -0
- package/esm2020/app/modules/system/components/crons/crons.component.mjs +5 -4
- package/esm2020/app/modules/system/fs-system.module.mjs +4 -1
- package/fesm2015/firestitch-system.mjs +99 -5
- package/fesm2015/firestitch-system.mjs.map +1 -1
- package/fesm2020/firestitch-system.mjs +99 -5
- package/fesm2020/firestitch-system.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -28,7 +28,7 @@ import { FsListComponent, FsListModule } from '@firestitch/list';
|
|
|
28
28
|
import * as i7 from '@firestitch/popover';
|
|
29
29
|
import { FsPopoverModule } from '@firestitch/popover';
|
|
30
30
|
import { ItemType } from '@firestitch/filter';
|
|
31
|
-
import { map, tap,
|
|
31
|
+
import { map, tap, takeUntil, switchMap } from 'rxjs/operators';
|
|
32
32
|
import * as i4$3 from '@angular/material/expansion';
|
|
33
33
|
import { MatExpansionModule } from '@angular/material/expansion';
|
|
34
34
|
import * as i7$1 from '@angular/material/form-field';
|
|
@@ -52,9 +52,9 @@ import * as i6 from '@firestitch/menu';
|
|
|
52
52
|
import { FsMenuModule } from '@firestitch/menu';
|
|
53
53
|
import * as i5 from '@firestitch/skeleton';
|
|
54
54
|
import { FsSkeletonModule } from '@firestitch/skeleton';
|
|
55
|
+
import { Subject, timer } from 'rxjs';
|
|
56
|
+
import { addMinutes, addHours, addDays, subSeconds, differenceInSeconds, getDaysInMonth, differenceInMinutes } from 'date-fns';
|
|
55
57
|
import { SelectionActionType } from '@firestitch/selection';
|
|
56
|
-
import { Subject } from 'rxjs';
|
|
57
|
-
import { differenceInSeconds, differenceInMinutes } from 'date-fns';
|
|
58
58
|
import * as i1$1 from '@firestitch/message';
|
|
59
59
|
import * as i3$3 from '@firestitch/prompt';
|
|
60
60
|
import * as i2$3 from '@firestitch/build';
|
|
@@ -580,6 +580,98 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImpor
|
|
|
580
580
|
}] }, { type: i1.MatDialog }, { type: i0.ChangeDetectorRef }];
|
|
581
581
|
} });
|
|
582
582
|
|
|
583
|
+
class CronNextRunComponent {
|
|
584
|
+
constructor(_cdRef) {
|
|
585
|
+
this._cdRef = _cdRef;
|
|
586
|
+
this._destroy$ = new Subject();
|
|
587
|
+
}
|
|
588
|
+
ngOnInit() {
|
|
589
|
+
this.update();
|
|
590
|
+
}
|
|
591
|
+
calculateDuration() {
|
|
592
|
+
const now = new Date();
|
|
593
|
+
const nextMinutes = this._getNextMinutes(now);
|
|
594
|
+
const nextHours = this._getNextHours(now);
|
|
595
|
+
const nextDays = this._getNextDays(now);
|
|
596
|
+
if (this.cron.cronSetting.minutes.length ||
|
|
597
|
+
this.cron.cronSetting.hours.length ||
|
|
598
|
+
this.cron.cronSetting.days.length) {
|
|
599
|
+
let next = new Date();
|
|
600
|
+
next = addMinutes(next, nextMinutes);
|
|
601
|
+
next = addHours(next, nextHours);
|
|
602
|
+
next = addDays(next, nextDays);
|
|
603
|
+
next = subSeconds(next, next.getSeconds());
|
|
604
|
+
this.duration = differenceInSeconds(next, now);
|
|
605
|
+
}
|
|
606
|
+
else {
|
|
607
|
+
this.duration = 60 - now.getSeconds();
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
update() {
|
|
611
|
+
this.calculateDuration();
|
|
612
|
+
timer(0, 1000)
|
|
613
|
+
.pipe(tap(() => {
|
|
614
|
+
this.duration -= 1;
|
|
615
|
+
if (this.duration % 60 === 0 || this.duration < (60 * 5)) {
|
|
616
|
+
this._cdRef.markForCheck();
|
|
617
|
+
}
|
|
618
|
+
if (this.duration <= 0) {
|
|
619
|
+
this.calculateDuration();
|
|
620
|
+
this._cdRef.markForCheck();
|
|
621
|
+
}
|
|
622
|
+
}), takeUntil(this._destroy$))
|
|
623
|
+
.subscribe();
|
|
624
|
+
}
|
|
625
|
+
ngOnDestroy() {
|
|
626
|
+
this._destroy$.next();
|
|
627
|
+
this._destroy$.complete();
|
|
628
|
+
}
|
|
629
|
+
_getNextMinutes(now) {
|
|
630
|
+
const minutes = this.cron.cronSetting.minutes;
|
|
631
|
+
if (minutes.length) {
|
|
632
|
+
for (let i = minutes.length - 1; i >= 0; i--) {
|
|
633
|
+
if (now.getUTCMinutes() >= minutes[i]) {
|
|
634
|
+
return (minutes[i + 1] ? minutes[i + 1] - now.getUTCMinutes() : (60 - now.getUTCMinutes() + minutes[i]));
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
return minutes[0] - now.getMinutes();
|
|
638
|
+
}
|
|
639
|
+
return 0;
|
|
640
|
+
}
|
|
641
|
+
_getNextHours(now) {
|
|
642
|
+
const hours = this.cron.cronSetting.hours;
|
|
643
|
+
if (hours.length) {
|
|
644
|
+
for (let i = hours.length - 1; i >= 0; i--) {
|
|
645
|
+
if (now.getUTCHours() >= hours[i]) {
|
|
646
|
+
return (hours[i + 1] ? hours[i + 1] - now.getUTCHours() : (24 - now.getUTCHours() + hours[i]));
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
return hours[0] - now.getUTCHours();
|
|
650
|
+
}
|
|
651
|
+
return 0;
|
|
652
|
+
}
|
|
653
|
+
_getNextDays(now) {
|
|
654
|
+
const days = this.cron.cronSetting.days;
|
|
655
|
+
if (days.length) {
|
|
656
|
+
for (let i = days.length - 1; i >= 0; i--) {
|
|
657
|
+
if (now.getDate() >= days[i]) {
|
|
658
|
+
return (days[i + 1] ? days[i + 1] : getDaysInMonth(now)) - now.getDate();
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
return days[0] - getDaysInMonth(now);
|
|
662
|
+
}
|
|
663
|
+
return 0;
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
CronNextRunComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: CronNextRunComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
667
|
+
CronNextRunComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: CronNextRunComponent, selector: "app-next-run", inputs: { cron: "cron" }, ngImport: i0, template: "<ng-container *ngIf=\"duration > 60; else seconds\">\n {{duration | fsDateDuration: { hours: true, seconds: true, minutes: true, days: true} }}\n</ng-container>\n\n<ng-template #seconds>\n {{duration}}s\n</ng-template>\n\n", styles: [""], directives: [{ type: i8.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], pipes: { "fsDateDuration": i4$2.FsDateDurationPipe }, changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
668
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: CronNextRunComponent, decorators: [{
|
|
669
|
+
type: Component,
|
|
670
|
+
args: [{ selector: 'app-next-run', changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-container *ngIf=\"duration > 60; else seconds\">\n {{duration | fsDateDuration: { hours: true, seconds: true, minutes: true, days: true} }}\n</ng-container>\n\n<ng-template #seconds>\n {{duration}}s\n</ng-template>\n\n", styles: [""] }]
|
|
671
|
+
}], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }]; }, propDecorators: { cron: [{
|
|
672
|
+
type: Input
|
|
673
|
+
}] } });
|
|
674
|
+
|
|
583
675
|
class CronsComponent {
|
|
584
676
|
constructor(_message, _dialog, _prompt) {
|
|
585
677
|
this._message = _message;
|
|
@@ -756,10 +848,10 @@ class CronsComponent {
|
|
|
756
848
|
}
|
|
757
849
|
}
|
|
758
850
|
CronsComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: CronsComponent, deps: [{ token: i1$1.FsMessage }, { token: i1.MatDialog }, { token: i3$3.FsPrompt }], target: i0.ɵɵFactoryTarget.Component });
|
|
759
|
-
CronsComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: CronsComponent, selector: "fs-system-crons", inputs: { enable: "enable", disable: "disable", kill: "kill", queue: "queue", run: "run", loadCrons: "loadCrons", loadCron: "loadCron", loadCronLogs: "loadCronLogs", bulk: "bulk" }, viewQueries: [{ propertyName: "list", first: true, predicate: FsListComponent, descendants: true, static: true }], ngImport: i0, template: "<fs-list [config]=\"config\">\n <fs-list-column>\n <ng-template fs-list-header>Name</ng-template>\n <ng-template fs-list-cell let-row=\"row\">\n <a (click)=\"open(row)\">{{row.name}}</a>\n <div *ngIf=\"row.cronSetting\">\n <small>{{row.cronSetting.summary}}</small>\n </div>\n </ng-template>\n </fs-list-column>\n <fs-list-column align=\"center\">\n <ng-template fs-list-header>Status</ng-template>\n <ng-template fs-list-cell let-row=\"row\">\n <ng-container *ngIf=\"row.host || row.processId; else status\">\n <fs-popover \n [maxWidth]=\"null\"\n [template]=\"statusPopover\" \n size=\"small\">\n <ng-container *ngTemplateOutlet=\"status\"></ng-container>\n </fs-popover>\n <ng-template #statusPopover>\n <div *ngIf=\"row.host\">Host: {{row.host}}</div>\n <div *ngIf=\"row.processId\">Process ID: {{row.processId}}</div>\n <div *ngIf=\"row.processState\">Process State: {{CronProcessStates[row.processState]}}</div>\n </ng-template>\n </ng-container>\n <ng-template #status>\n {{CronStates[row.state]}}\n </ng-template>\n <ng-container *ngIf=\"row.state === CronState.Running\">\n <div class=\"small\">\n Duration: {{ row.runningDuration | fsDateDuration: { hours: true, minutes: true, seconds: true } }}\n </div>\n </ng-container> \n </ng-template>\n </fs-list-column>\n <fs-list-column>\n <ng-template fs-list-header>Last Ran</ng-template>\n <ng-template fs-list-cell let-row=\"row\">\n <ng-container *ngIf=\"row.duration===null; else lastRan\">\n Never\n </ng-container>\n <ng-template #lastRan>\n <fs-date-ago [date]=\"row.createDate\"></fs-date-ago>\n <div class=\"small\" *ngIf=\"row.duration\">\n Duration: {{ row.duration | fsDateDuration: { hours: true, minutes: true, seconds: true } }}\n </div>\n </ng-template>\n </ng-template>\n </fs-list-column>\n</fs-list>\n", styles: [""], components: [{ type: i2$2.FsListComponent, selector: "fs-list", inputs: ["config", "loaderLines"], outputs: ["filtersReady"] }, { type: i7.FsPopoverComponent, selector: "fs-popover" }, { type: i4$2.FsDateAgoComponent, selector: "fs-date-ago", inputs: ["date", "showTime", "format", "showTooltip", "tooltipDateFormat"] }], directives: [{ type: i2$2.FsListColumnDirective, selector: "fs-list-column", inputs: ["show", "title", "name", "customize", "sortable", "sortableDefault", "direction", "align", "width", "class"] }, { type: i2$2.FsListHeaderDirective, selector: "[fs-list-header]", inputs: ["colspan", "align", "class"] }, { type: i2$2.FsListCellDirective, selector: "[fs-list-cell]", inputs: ["colspan", "align", "class"] }, { type: i8.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i8.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }], pipes: { "fsDateDuration": i4$2.FsDateDurationPipe } });
|
|
851
|
+
CronsComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: CronsComponent, selector: "fs-system-crons", inputs: { enable: "enable", disable: "disable", kill: "kill", queue: "queue", run: "run", loadCrons: "loadCrons", loadCron: "loadCron", loadCronLogs: "loadCronLogs", bulk: "bulk" }, viewQueries: [{ propertyName: "list", first: true, predicate: FsListComponent, descendants: true, static: true }], ngImport: i0, template: "<fs-list [config]=\"config\">\n <fs-list-column>\n <ng-template fs-list-header>Name</ng-template>\n <ng-template fs-list-cell let-row=\"row\">\n <a (click)=\"open(row)\">{{row.name}}</a>\n <div *ngIf=\"row.cronSetting\">\n <small>{{row.cronSetting.summary}}</small>\n </div>\n </ng-template>\n </fs-list-column>\n <fs-list-column align=\"center\">\n <ng-template fs-list-header>Status</ng-template>\n <ng-template fs-list-cell let-row=\"row\">\n <ng-container *ngIf=\"row.host || row.processId; else status\">\n <fs-popover \n [maxWidth]=\"null\"\n [template]=\"statusPopover\" \n size=\"small\">\n <ng-container *ngTemplateOutlet=\"status\"></ng-container>\n </fs-popover>\n <ng-template #statusPopover>\n <div *ngIf=\"row.host\">Host: {{row.host}}</div>\n <div *ngIf=\"row.processId\">Process ID: {{row.processId}}</div>\n <div *ngIf=\"row.processState\">Process State: {{CronProcessStates[row.processState]}}</div>\n </ng-template>\n </ng-container>\n <ng-template #status>\n {{CronStates[row.state]}}\n </ng-template>\n <ng-container *ngIf=\"row.state === CronState.Running\">\n <div class=\"small\">\n Duration: {{ row.runningDuration | fsDateDuration: { hours: true, minutes: true, seconds: true } }}\n </div>\n </ng-container> \n </ng-template>\n </fs-list-column>\n <fs-list-column>\n <ng-template fs-list-header>Last Ran</ng-template>\n <ng-template fs-list-cell let-row=\"row\">\n <ng-container *ngIf=\"row.duration===null; else lastRan\">\n Never\n </ng-container>\n <ng-template #lastRan>\n <fs-date-ago [date]=\"row.createDate\"></fs-date-ago>\n <div class=\"small\" *ngIf=\"row.duration\">\n Duration: {{ row.duration | fsDateDuration: { hours: true, minutes: true, seconds: true } }}\n </div>\n </ng-template>\n </ng-template>\n </fs-list-column>\n <fs-list-column>\n <ng-template fs-list-header>Next Run</ng-template>\n <ng-template fs-list-cell let-row=\"row\">\n <ng-container *ngIf=\"row.state !== CronState.Disabled\">\n <app-next-run [cron]=\"row\"></app-next-run>\n </ng-container>\n </ng-template>\n </fs-list-column>\n</fs-list>\n", styles: [""], components: [{ type: i2$2.FsListComponent, selector: "fs-list", inputs: ["config", "loaderLines"], outputs: ["filtersReady"] }, { type: i7.FsPopoverComponent, selector: "fs-popover" }, { type: i4$2.FsDateAgoComponent, selector: "fs-date-ago", inputs: ["date", "showTime", "format", "showTooltip", "tooltipDateFormat"] }, { type: CronNextRunComponent, selector: "app-next-run", inputs: ["cron"] }], directives: [{ type: i2$2.FsListColumnDirective, selector: "fs-list-column", inputs: ["show", "title", "name", "customize", "sortable", "sortableDefault", "direction", "align", "width", "class"] }, { type: i2$2.FsListHeaderDirective, selector: "[fs-list-header]", inputs: ["colspan", "align", "class"] }, { type: i2$2.FsListCellDirective, selector: "[fs-list-cell]", inputs: ["colspan", "align", "class"] }, { type: i8.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i8.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }], pipes: { "fsDateDuration": i4$2.FsDateDurationPipe } });
|
|
760
852
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: CronsComponent, decorators: [{
|
|
761
853
|
type: Component,
|
|
762
|
-
args: [{ selector: 'fs-system-crons', template: "<fs-list [config]=\"config\">\n <fs-list-column>\n <ng-template fs-list-header>Name</ng-template>\n <ng-template fs-list-cell let-row=\"row\">\n <a (click)=\"open(row)\">{{row.name}}</a>\n <div *ngIf=\"row.cronSetting\">\n <small>{{row.cronSetting.summary}}</small>\n </div>\n </ng-template>\n </fs-list-column>\n <fs-list-column align=\"center\">\n <ng-template fs-list-header>Status</ng-template>\n <ng-template fs-list-cell let-row=\"row\">\n <ng-container *ngIf=\"row.host || row.processId; else status\">\n <fs-popover \n [maxWidth]=\"null\"\n [template]=\"statusPopover\" \n size=\"small\">\n <ng-container *ngTemplateOutlet=\"status\"></ng-container>\n </fs-popover>\n <ng-template #statusPopover>\n <div *ngIf=\"row.host\">Host: {{row.host}}</div>\n <div *ngIf=\"row.processId\">Process ID: {{row.processId}}</div>\n <div *ngIf=\"row.processState\">Process State: {{CronProcessStates[row.processState]}}</div>\n </ng-template>\n </ng-container>\n <ng-template #status>\n {{CronStates[row.state]}}\n </ng-template>\n <ng-container *ngIf=\"row.state === CronState.Running\">\n <div class=\"small\">\n Duration: {{ row.runningDuration | fsDateDuration: { hours: true, minutes: true, seconds: true } }}\n </div>\n </ng-container> \n </ng-template>\n </fs-list-column>\n <fs-list-column>\n <ng-template fs-list-header>Last Ran</ng-template>\n <ng-template fs-list-cell let-row=\"row\">\n <ng-container *ngIf=\"row.duration===null; else lastRan\">\n Never\n </ng-container>\n <ng-template #lastRan>\n <fs-date-ago [date]=\"row.createDate\"></fs-date-ago>\n <div class=\"small\" *ngIf=\"row.duration\">\n Duration: {{ row.duration | fsDateDuration: { hours: true, minutes: true, seconds: true } }}\n </div>\n </ng-template>\n </ng-template>\n </fs-list-column>\n</fs-list>\n", styles: [""] }]
|
|
854
|
+
args: [{ selector: 'fs-system-crons', template: "<fs-list [config]=\"config\">\n <fs-list-column>\n <ng-template fs-list-header>Name</ng-template>\n <ng-template fs-list-cell let-row=\"row\">\n <a (click)=\"open(row)\">{{row.name}}</a>\n <div *ngIf=\"row.cronSetting\">\n <small>{{row.cronSetting.summary}}</small>\n </div>\n </ng-template>\n </fs-list-column>\n <fs-list-column align=\"center\">\n <ng-template fs-list-header>Status</ng-template>\n <ng-template fs-list-cell let-row=\"row\">\n <ng-container *ngIf=\"row.host || row.processId; else status\">\n <fs-popover \n [maxWidth]=\"null\"\n [template]=\"statusPopover\" \n size=\"small\">\n <ng-container *ngTemplateOutlet=\"status\"></ng-container>\n </fs-popover>\n <ng-template #statusPopover>\n <div *ngIf=\"row.host\">Host: {{row.host}}</div>\n <div *ngIf=\"row.processId\">Process ID: {{row.processId}}</div>\n <div *ngIf=\"row.processState\">Process State: {{CronProcessStates[row.processState]}}</div>\n </ng-template>\n </ng-container>\n <ng-template #status>\n {{CronStates[row.state]}}\n </ng-template>\n <ng-container *ngIf=\"row.state === CronState.Running\">\n <div class=\"small\">\n Duration: {{ row.runningDuration | fsDateDuration: { hours: true, minutes: true, seconds: true } }}\n </div>\n </ng-container> \n </ng-template>\n </fs-list-column>\n <fs-list-column>\n <ng-template fs-list-header>Last Ran</ng-template>\n <ng-template fs-list-cell let-row=\"row\">\n <ng-container *ngIf=\"row.duration===null; else lastRan\">\n Never\n </ng-container>\n <ng-template #lastRan>\n <fs-date-ago [date]=\"row.createDate\"></fs-date-ago>\n <div class=\"small\" *ngIf=\"row.duration\">\n Duration: {{ row.duration | fsDateDuration: { hours: true, minutes: true, seconds: true } }}\n </div>\n </ng-template>\n </ng-template>\n </fs-list-column>\n <fs-list-column>\n <ng-template fs-list-header>Next Run</ng-template>\n <ng-template fs-list-cell let-row=\"row\">\n <ng-container *ngIf=\"row.state !== CronState.Disabled\">\n <app-next-run [cron]=\"row\"></app-next-run>\n </ng-container>\n </ng-template>\n </fs-list-column>\n</fs-list>\n", styles: [""] }]
|
|
763
855
|
}], ctorParameters: function () { return [{ type: i1$1.FsMessage }, { type: i1.MatDialog }, { type: i3$3.FsPrompt }]; }, propDecorators: { list: [{
|
|
764
856
|
type: ViewChild,
|
|
765
857
|
args: [FsListComponent, { static: true }]
|
|
@@ -1336,6 +1428,7 @@ class FsSystemModule {
|
|
|
1336
1428
|
}
|
|
1337
1429
|
FsSystemModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: FsSystemModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
1338
1430
|
FsSystemModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: FsSystemModule, declarations: [DashboardComponent,
|
|
1431
|
+
CronNextRunComponent,
|
|
1339
1432
|
CronsComponent,
|
|
1340
1433
|
SettingsComponent,
|
|
1341
1434
|
KeyNameValuePipe,
|
|
@@ -1440,6 +1533,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImpor
|
|
|
1440
1533
|
],
|
|
1441
1534
|
declarations: [
|
|
1442
1535
|
DashboardComponent,
|
|
1536
|
+
CronNextRunComponent,
|
|
1443
1537
|
CronsComponent,
|
|
1444
1538
|
SettingsComponent,
|
|
1445
1539
|
KeyNameValuePipe,
|