@firestitch/system 18.0.33 → 18.0.34
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/process/process.component.d.ts +5 -4
- package/app/modules/system/components/processes/processes.component.d.ts +4 -4
- package/app/modules/system/interfaces/process.d.ts +2 -0
- package/esm2022/app/modules/system/components/api-logs/api-logs.component.mjs +3 -3
- package/esm2022/app/modules/system/components/process/process.component.mjs +58 -37
- package/esm2022/app/modules/system/components/processes/processes.component.mjs +53 -47
- package/esm2022/app/modules/system/interfaces/process.mjs +1 -1
- package/fesm2022/firestitch-system.mjs +75 -48
- package/fesm2022/firestitch-system.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -255,7 +255,7 @@ class ApiLogsComponent {
|
|
|
255
255
|
};
|
|
256
256
|
}
|
|
257
257
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ApiLogsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
258
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.7", type: ApiLogsComponent, isStandalone: true, selector: "fs-system-api-logs", inputs: { loadApiLogs: "loadApiLogs" }, 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 href=\"javascript:;\" (click)=\"open(row)\">\n {{row.type || 'Unknown'}}\n @if (row.direction=='outgoing') {\n <mat-icon class=\"direction\">arrow_upward</mat-icon>\n }\n @if (row.direction=='incoming') {\n <mat-icon class=\"direction\">arrow_downward</mat-icon>\n }\n </a>\n </ng-template>\n </fs-list-column>\n <fs-list-column>\n <ng-template fs-list-header>Status</ng-template>\n <ng-template fs-list-cell let-row=\"row\">\n {{apiLogStates[row.state]}}\n @if (row.code) {\n <span class=\"code\" [ngClass]=\"{'success': row.code
|
|
258
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.7", type: ApiLogsComponent, isStandalone: true, selector: "fs-system-api-logs", inputs: { loadApiLogs: "loadApiLogs" }, 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 href=\"javascript:;\" (click)=\"open(row)\">\n {{row.type || 'Unknown'}}\n @if (row.direction=='outgoing') {\n <mat-icon class=\"direction\">arrow_upward</mat-icon>\n }\n @if (row.direction=='incoming') {\n <mat-icon class=\"direction\">arrow_downward</mat-icon>\n }\n </a>\n </ng-template>\n </fs-list-column>\n <fs-list-column>\n <ng-template fs-list-header>Status</ng-template>\n <ng-template fs-list-cell let-row=\"row\">\n {{apiLogStates[row.state]}}\n @if (row.code) {\n <span class=\"code\" [ngClass]=\"{'success': row.code >= 200 && row.code < 300,'error': row.code < 200 || row.code >= 300 }\">[{{row.code}}]</span>\n }\n </ng-template>\n </fs-list-column>\n <fs-list-column>\n <ng-template fs-list-header>Message</ng-template>\n <ng-template fs-list-cell let-row=\"row\">\n {{row.message}}\n </ng-template>\n </fs-list-column>\n <fs-list-column>\n <ng-template fs-list-header>Date</ng-template>\n <ng-template fs-list-cell let-row=\"row\">\n <fs-date-ago [date]=\"row.createDate\"></fs-date-ago>\n <div>@if (row.length) {\n <small>Duration: {{ row.length | fsDateDuration }}</small>\n }</div>\n </ng-template>\n </fs-list-column>\n</fs-list>\n", styles: [".code.success{color:green}.code.error{color:red}.direction{font-size:14px;height:14px;line-height:14px;width:14px}\n"], dependencies: [{ kind: "ngmodule", type: FsListModule }, { kind: "component", type: i1$1.FsListComponent, selector: "fs-list", inputs: ["config", "loaderLines"], outputs: ["filtersReady"] }, { kind: "directive", type: i1$1.FsListColumnDirective, selector: "fs-list-column", inputs: ["show", "title", "name", "customizable", "sortable", "sortableDefault", "sortableDirection", "direction", "align", "width", "class"] }, { kind: "directive", type: i1$1.FsListCellDirective, selector: "[fs-list-cell]", inputs: ["colspan", "align", "class"] }, { kind: "directive", type: i1$1.FsListHeaderDirective, selector: "[fs-list-header]", inputs: ["colspan", "align", "class"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: FsDateModule }, { kind: "pipe", type: i4.FsDateDurationPipe, name: "fsDateDuration" }, { kind: "component", type: i4.FsDateAgoComponent, selector: "fs-date-ago", inputs: ["date", "showTime", "format", "showTooltip", "tooltipDateFormat"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
259
259
|
}
|
|
260
260
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ApiLogsComponent, decorators: [{
|
|
261
261
|
type: Component,
|
|
@@ -264,7 +264,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImpor
|
|
|
264
264
|
MatIcon,
|
|
265
265
|
NgClass,
|
|
266
266
|
FsDateModule,
|
|
267
|
-
], 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 href=\"javascript:;\" (click)=\"open(row)\">\n {{row.type || 'Unknown'}}\n @if (row.direction=='outgoing') {\n <mat-icon class=\"direction\">arrow_upward</mat-icon>\n }\n @if (row.direction=='incoming') {\n <mat-icon class=\"direction\">arrow_downward</mat-icon>\n }\n </a>\n </ng-template>\n </fs-list-column>\n <fs-list-column>\n <ng-template fs-list-header>Status</ng-template>\n <ng-template fs-list-cell let-row=\"row\">\n {{apiLogStates[row.state]}}\n @if (row.code) {\n <span class=\"code\" [ngClass]=\"{'success': row.code
|
|
267
|
+
], 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 href=\"javascript:;\" (click)=\"open(row)\">\n {{row.type || 'Unknown'}}\n @if (row.direction=='outgoing') {\n <mat-icon class=\"direction\">arrow_upward</mat-icon>\n }\n @if (row.direction=='incoming') {\n <mat-icon class=\"direction\">arrow_downward</mat-icon>\n }\n </a>\n </ng-template>\n </fs-list-column>\n <fs-list-column>\n <ng-template fs-list-header>Status</ng-template>\n <ng-template fs-list-cell let-row=\"row\">\n {{apiLogStates[row.state]}}\n @if (row.code) {\n <span class=\"code\" [ngClass]=\"{'success': row.code >= 200 && row.code < 300,'error': row.code < 200 || row.code >= 300 }\">[{{row.code}}]</span>\n }\n </ng-template>\n </fs-list-column>\n <fs-list-column>\n <ng-template fs-list-header>Message</ng-template>\n <ng-template fs-list-cell let-row=\"row\">\n {{row.message}}\n </ng-template>\n </fs-list-column>\n <fs-list-column>\n <ng-template fs-list-header>Date</ng-template>\n <ng-template fs-list-cell let-row=\"row\">\n <fs-date-ago [date]=\"row.createDate\"></fs-date-ago>\n <div>@if (row.length) {\n <small>Duration: {{ row.length | fsDateDuration }}</small>\n }</div>\n </ng-template>\n </fs-list-column>\n</fs-list>\n", styles: [".code.success{color:green}.code.error{color:red}.direction{font-size:14px;height:14px;line-height:14px;width:14px}\n"] }]
|
|
268
268
|
}], propDecorators: { list: [{
|
|
269
269
|
type: ViewChild,
|
|
270
270
|
args: [FsListComponent, { static: true }]
|
|
@@ -1007,14 +1007,12 @@ class ProcessComponent {
|
|
|
1007
1007
|
_destroy$ = new Subject();
|
|
1008
1008
|
_processData = inject(ProcessData);
|
|
1009
1009
|
ngOnInit() {
|
|
1010
|
-
this.load$()
|
|
1011
|
-
.subscribe(() => {
|
|
1010
|
+
this.load$().subscribe(() => {
|
|
1012
1011
|
this.runningRefresh();
|
|
1013
1012
|
});
|
|
1014
1013
|
}
|
|
1015
1014
|
load$() {
|
|
1016
|
-
return this._processData.get(this.data.process.id)
|
|
1017
|
-
.pipe(tap((process) => {
|
|
1015
|
+
return this._processData.get(this.data.process.id).pipe(tap((process) => {
|
|
1018
1016
|
this.process = process;
|
|
1019
1017
|
this._cdRef.markForCheck();
|
|
1020
1018
|
}));
|
|
@@ -1025,21 +1023,22 @@ class ProcessComponent {
|
|
|
1025
1023
|
.subscribe();
|
|
1026
1024
|
}
|
|
1027
1025
|
kill() {
|
|
1028
|
-
this._prompt
|
|
1029
|
-
|
|
1030
|
-
|
|
1026
|
+
this._prompt
|
|
1027
|
+
.confirm({
|
|
1028
|
+
title: "Kill process",
|
|
1029
|
+
template: "Are you sure you would like to kill the process?",
|
|
1031
1030
|
})
|
|
1032
1031
|
.pipe(switchMap(() => this._processData.kill(this.data.process)), switchMap(() => this.load$()))
|
|
1033
1032
|
.subscribe(() => {
|
|
1034
|
-
this._message.success(
|
|
1033
|
+
this._message.success("Killed process");
|
|
1035
1034
|
});
|
|
1036
1035
|
}
|
|
1037
1036
|
run() {
|
|
1038
|
-
this._process
|
|
1039
|
-
.run(`Run ${this.process.name}`, this._api
|
|
1037
|
+
this._process.run(`Run ${this.process.name}`, this._api
|
|
1040
1038
|
.stream(RequestMethod.Post, `processes/${this.process.id}/run`)
|
|
1041
1039
|
.pipe(tap((event) => {
|
|
1042
|
-
if (event instanceof StreamEventData &&
|
|
1040
|
+
if (event instanceof StreamEventData &&
|
|
1041
|
+
event.type === StreamEventType.Sent) {
|
|
1043
1042
|
this.process.state = ProcessState.Running;
|
|
1044
1043
|
this._cdRef.markForCheck();
|
|
1045
1044
|
}
|
|
@@ -1048,20 +1047,42 @@ class ProcessComponent {
|
|
|
1048
1047
|
}), filter((data) => !!data)));
|
|
1049
1048
|
}
|
|
1050
1049
|
queue() {
|
|
1051
|
-
this._message.success(
|
|
1052
|
-
this._processData
|
|
1050
|
+
this._message.success("Running process");
|
|
1051
|
+
this._processData
|
|
1052
|
+
.queue(this.data.process)
|
|
1053
1053
|
.pipe(switchMap(() => this.load$()))
|
|
1054
1054
|
.subscribe();
|
|
1055
1055
|
}
|
|
1056
1056
|
download() {
|
|
1057
1057
|
this._processData.download(this.data.process);
|
|
1058
1058
|
}
|
|
1059
|
+
get formattedProcessData() {
|
|
1060
|
+
const d = this.process?.data;
|
|
1061
|
+
if (d === null || d === undefined) {
|
|
1062
|
+
return null;
|
|
1063
|
+
}
|
|
1064
|
+
let value = d;
|
|
1065
|
+
if (typeof d === "string") {
|
|
1066
|
+
try {
|
|
1067
|
+
value = JSON.parse(d);
|
|
1068
|
+
}
|
|
1069
|
+
catch {
|
|
1070
|
+
return d;
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1073
|
+
try {
|
|
1074
|
+
return JSON.stringify(value, null, 2);
|
|
1075
|
+
}
|
|
1076
|
+
catch {
|
|
1077
|
+
return String(value);
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
1059
1080
|
ngOnDestroy() {
|
|
1060
1081
|
this._destroy$.next(null);
|
|
1061
1082
|
this._destroy$.complete();
|
|
1062
1083
|
}
|
|
1063
1084
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ProcessComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1064
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.7", type: ProcessComponent, isStandalone: true, selector: "ng-component", ngImport: i0, template: "<fs-dialog *fsSkeleton=\"process\">\n <div mat-dialog-title>\n Process\n </div>\n <mat-dialog-content>\n <div class=\"column\">\n <div class=\"fs-row.gap-lg.wrap.align-start\">\n <fs-label-field>\n <fs-label>\n Name\n </fs-label>\n {{ process.prettyName }}\n </fs-label-field>\n <fs-label-field>\n <fs-label>\n Status\n </fs-label>\n <div\n
|
|
1085
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.7", type: ProcessComponent, isStandalone: true, selector: "ng-component", ngImport: i0, template: "<fs-dialog *fsSkeleton=\"process\">\n <div mat-dialog-title>\n Process\n </div>\n <mat-dialog-content>\n <div class=\"column\">\n <div class=\"fs-row.gap-lg.wrap.align-start\">\n <fs-label-field>\n <fs-label>\n Name\n </fs-label>\n {{ process.prettyName }}\n </fs-label-field>\n <fs-label-field>\n <fs-label>\n Class\n </fs-label>\n {{ process.class || 'None' }}\n </fs-label-field>\n <fs-label-field>\n <fs-label>\n Function\n </fs-label>\n {{ process['function'] || 'None' }}\n </fs-label-field>\n <fs-label-field>\n <fs-label>\n Status\n </fs-label>\n <div\n class=\"status\"\n [ngClass]=\"{ 'running': process.state === ProcessState.Running }\">\n {{ ProcessStates[process.state] }}\n @if (process.state === ProcessState.Running) {\n <mat-progress-spinner\n [diameter]=\"20\"\n [mode]=\"'indeterminate'\">\n </mat-progress-spinner>\n }\n </div>\n </fs-label-field>\n <fs-label-field>\n <fs-label>\n Notification Email\n </fs-label>\n @if (process.notify) {\n <a [href]=\"'mailto:' + process.notify\">\n {{ process.notify }}\n </a>\n } @else {\n None\n }\n </fs-label-field>\n <fs-label-field>\n <fs-label>\n Process ID\n </fs-label>\n {{ process.pid || 'None' }}\n @if (process.pid) {\n <div class=\"small\">\n {{ ProcessProcessStates[process.processState] || 'Unknown' }}\n </div>\n }\n </fs-label-field>\n @if (process.createDate) {\n <fs-label-field>\n <fs-label>\n Create Date\n </fs-label>\n {{ process.createDate | fsDateFormat: 'date-time' }}\n </fs-label-field>\n }\n @if (process.startDate) {\n <fs-label-field>\n <fs-label>\n Start Date\n </fs-label>\n {{ process.startDate | fsDateFormat: 'date-time' }}\n </fs-label-field>\n }\n @if (process.endDate) {\n <fs-label-field>\n <fs-label>\n Complete Date\n </fs-label>\n {{ process.endDate | fsDateFormat: 'date-time' }}\n </fs-label-field>\n }\n @if (process.duration) {\n <fs-label-field>\n <fs-label>\n Duration\n </fs-label>\n {{ process.duration | fsDateDuration: {hours: true, minutes: true, seconds: true} }}\n </fs-label-field>\n }\n </div>\n <fs-label-field>\n <fs-label>\n Data\n </fs-label>\n @if (formattedProcessData === null) {\n None\n } @else {\n <pre class=\"log json-block\">\n {{ formattedProcessData }}\n </pre>\n }\n </fs-label-field>\n @if (process.message) {\n <fs-label-field>\n <fs-label>\n Message\n </fs-label>\n {{ process.message }}\n </fs-label-field>\n }\n @if (process.log) {\n <fs-label-field>\n <fs-label>\n Log\n </fs-label>\n <div class=\"log\">\n {{ process.log }}\n </div>\n </fs-label-field>\n }\n </div>\n </mat-dialog-content>\n <mat-dialog-actions>\n <button\n mat-button\n [mat-dialog-close]=\"true\"\n color=\"primary\">\n Close\n </button>\n @if (process.state === ProcessState.Running) {\n <button\n mat-button\n (click)=\"kill()\">\n Kill\n </button>\n }\n @if (process.state !== ProcessState.Running) {\n <button\n mat-button\n (click)=\"run()\">\n Run\n </button>\n }\n @if (( process.state !== ProcessState.Running && process.state !== ProcessState.Queued )) {\n <button\n mat-button\n (click)=\"queue()\">\n Queue\n </button>\n }\n @if (process.filename) {\n <button\n mat-button\n (click)=\"download()\">\n Download\n </button>\n }\n </mat-dialog-actions>\n</fs-dialog>", styles: [".log{white-space:pre-line;font-family:monospace;font-size:95%;line-height:130%}.json-block{max-height:320px;margin:0;overflow:auto;white-space:pre-wrap;word-break:break-word}.status{display:flex}.status.running{margin-right:28px}.status.running mat-progress-spinner{position:absolute;right:0}\n"], dependencies: [{ kind: "ngmodule", type: FsSkeletonModule }, { kind: "directive", type: i1.FsSkeletonContentDirective, selector: "[fsSkeleton]", inputs: ["fsSkeleton", "fsSkeletonPattern"] }, { kind: "ngmodule", type: FsDialogModule }, { kind: "component", type: i2.FsDialogComponent, selector: "fs-dialog", inputs: ["mobileMode", "mobileButtonPlacement", "mobileWidth", "mode", "buttonLayout"] }, { kind: "directive", type: MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "ngmodule", type: FsLabelModule }, { kind: "component", type: i3.FsLabelComponent, selector: "fs-label" }, { kind: "component", type: i3.FsLabelFieldComponent, selector: "fs-label-field", inputs: ["appearance", "showOutline", "disabled", "focused", "hoverable", "padless"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "directive", type: MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "component", type: MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "directive", type: MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "ngmodule", type: FsDateModule }, { kind: "pipe", type: i4.FsDateDurationPipe, name: "fsDateDuration" }, { kind: "pipe", type: i4.FsDateFormatPipe, name: "fsDateFormat" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1065
1086
|
}
|
|
1066
1087
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ProcessComponent, decorators: [{
|
|
1067
1088
|
type: Component,
|
|
@@ -1078,7 +1099,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImpor
|
|
|
1078
1099
|
MatButton,
|
|
1079
1100
|
MatDialogClose,
|
|
1080
1101
|
FsDateModule,
|
|
1081
|
-
], template: "<fs-dialog *fsSkeleton=\"process\">\n <div mat-dialog-title>\n Process\n </div>\n <mat-dialog-content>\n <div class=\"column\">\n <div class=\"fs-row.gap-lg.wrap.align-start\">\n <fs-label-field>\n <fs-label>\n Name\n </fs-label>\n {{ process.prettyName }}\n </fs-label-field>\n <fs-label-field>\n <fs-label>\n Status\n </fs-label>\n <div\n
|
|
1102
|
+
], template: "<fs-dialog *fsSkeleton=\"process\">\n <div mat-dialog-title>\n Process\n </div>\n <mat-dialog-content>\n <div class=\"column\">\n <div class=\"fs-row.gap-lg.wrap.align-start\">\n <fs-label-field>\n <fs-label>\n Name\n </fs-label>\n {{ process.prettyName }}\n </fs-label-field>\n <fs-label-field>\n <fs-label>\n Class\n </fs-label>\n {{ process.class || 'None' }}\n </fs-label-field>\n <fs-label-field>\n <fs-label>\n Function\n </fs-label>\n {{ process['function'] || 'None' }}\n </fs-label-field>\n <fs-label-field>\n <fs-label>\n Status\n </fs-label>\n <div\n class=\"status\"\n [ngClass]=\"{ 'running': process.state === ProcessState.Running }\">\n {{ ProcessStates[process.state] }}\n @if (process.state === ProcessState.Running) {\n <mat-progress-spinner\n [diameter]=\"20\"\n [mode]=\"'indeterminate'\">\n </mat-progress-spinner>\n }\n </div>\n </fs-label-field>\n <fs-label-field>\n <fs-label>\n Notification Email\n </fs-label>\n @if (process.notify) {\n <a [href]=\"'mailto:' + process.notify\">\n {{ process.notify }}\n </a>\n } @else {\n None\n }\n </fs-label-field>\n <fs-label-field>\n <fs-label>\n Process ID\n </fs-label>\n {{ process.pid || 'None' }}\n @if (process.pid) {\n <div class=\"small\">\n {{ ProcessProcessStates[process.processState] || 'Unknown' }}\n </div>\n }\n </fs-label-field>\n @if (process.createDate) {\n <fs-label-field>\n <fs-label>\n Create Date\n </fs-label>\n {{ process.createDate | fsDateFormat: 'date-time' }}\n </fs-label-field>\n }\n @if (process.startDate) {\n <fs-label-field>\n <fs-label>\n Start Date\n </fs-label>\n {{ process.startDate | fsDateFormat: 'date-time' }}\n </fs-label-field>\n }\n @if (process.endDate) {\n <fs-label-field>\n <fs-label>\n Complete Date\n </fs-label>\n {{ process.endDate | fsDateFormat: 'date-time' }}\n </fs-label-field>\n }\n @if (process.duration) {\n <fs-label-field>\n <fs-label>\n Duration\n </fs-label>\n {{ process.duration | fsDateDuration: {hours: true, minutes: true, seconds: true} }}\n </fs-label-field>\n }\n </div>\n <fs-label-field>\n <fs-label>\n Data\n </fs-label>\n @if (formattedProcessData === null) {\n None\n } @else {\n <pre class=\"log json-block\">\n {{ formattedProcessData }}\n </pre>\n }\n </fs-label-field>\n @if (process.message) {\n <fs-label-field>\n <fs-label>\n Message\n </fs-label>\n {{ process.message }}\n </fs-label-field>\n }\n @if (process.log) {\n <fs-label-field>\n <fs-label>\n Log\n </fs-label>\n <div class=\"log\">\n {{ process.log }}\n </div>\n </fs-label-field>\n }\n </div>\n </mat-dialog-content>\n <mat-dialog-actions>\n <button\n mat-button\n [mat-dialog-close]=\"true\"\n color=\"primary\">\n Close\n </button>\n @if (process.state === ProcessState.Running) {\n <button\n mat-button\n (click)=\"kill()\">\n Kill\n </button>\n }\n @if (process.state !== ProcessState.Running) {\n <button\n mat-button\n (click)=\"run()\">\n Run\n </button>\n }\n @if (( process.state !== ProcessState.Running && process.state !== ProcessState.Queued )) {\n <button\n mat-button\n (click)=\"queue()\">\n Queue\n </button>\n }\n @if (process.filename) {\n <button\n mat-button\n (click)=\"download()\">\n Download\n </button>\n }\n </mat-dialog-actions>\n</fs-dialog>", styles: [".log{white-space:pre-line;font-family:monospace;font-size:95%;line-height:130%}.json-block{max-height:320px;margin:0;overflow:auto;white-space:pre-wrap;word-break:break-word}.status{display:flex}.status.running{margin-right:28px}.status.running mat-progress-spinner{position:absolute;right:0}\n"] }]
|
|
1082
1103
|
}] });
|
|
1083
1104
|
|
|
1084
1105
|
class ProcessesComponent {
|
|
@@ -1105,7 +1126,7 @@ class ProcessesComponent {
|
|
|
1105
1126
|
data: {
|
|
1106
1127
|
process,
|
|
1107
1128
|
},
|
|
1108
|
-
width:
|
|
1129
|
+
width: "85%",
|
|
1109
1130
|
})
|
|
1110
1131
|
.afterClosed()
|
|
1111
1132
|
.pipe(takeUntil(this._destroy$))
|
|
@@ -1125,36 +1146,34 @@ class ProcessesComponent {
|
|
|
1125
1146
|
actions: [],
|
|
1126
1147
|
rowActions: [
|
|
1127
1148
|
{
|
|
1128
|
-
label:
|
|
1149
|
+
label: "Queue",
|
|
1129
1150
|
show: (process) => {
|
|
1130
|
-
return process.state !== ProcessState.Running &&
|
|
1131
|
-
process.state !== ProcessState.Queued;
|
|
1151
|
+
return (process.state !== ProcessState.Running &&
|
|
1152
|
+
process.state !== ProcessState.Queued);
|
|
1132
1153
|
},
|
|
1133
1154
|
click: (data) => {
|
|
1134
|
-
this._processData.queue(data)
|
|
1135
|
-
.subscribe(() => {
|
|
1155
|
+
this._processData.queue(data).subscribe(() => {
|
|
1136
1156
|
this.reload();
|
|
1137
|
-
this._message.success(
|
|
1157
|
+
this._message.success("Queued process");
|
|
1138
1158
|
});
|
|
1139
1159
|
},
|
|
1140
1160
|
},
|
|
1141
1161
|
{
|
|
1142
|
-
label:
|
|
1162
|
+
label: "Run",
|
|
1143
1163
|
show: (data) => {
|
|
1144
1164
|
return data.state !== ProcessState.Running;
|
|
1145
1165
|
},
|
|
1146
1166
|
click: (process) => {
|
|
1147
|
-
this._process
|
|
1148
|
-
.run(`Run ${process.name}`, this._api
|
|
1167
|
+
this._process.run(`Run ${process.name}`, this._api
|
|
1149
1168
|
.stream(RequestMethod.Post, `processes/${process.id}/run`)
|
|
1150
1169
|
.pipe(tap((event) => {
|
|
1151
|
-
if (event instanceof StreamEventData &&
|
|
1170
|
+
if (event instanceof StreamEventData &&
|
|
1171
|
+
event.type === StreamEventType.Sent) {
|
|
1152
1172
|
process = {
|
|
1153
1173
|
...process,
|
|
1154
1174
|
state: ProcessState.Running,
|
|
1155
1175
|
};
|
|
1156
|
-
this.list
|
|
1157
|
-
.updateData(process, (row) => {
|
|
1176
|
+
this.list.updateData(process, (row) => {
|
|
1158
1177
|
return process.id === row.id;
|
|
1159
1178
|
});
|
|
1160
1179
|
}
|
|
@@ -1166,26 +1185,24 @@ class ProcessesComponent {
|
|
|
1166
1185
|
},
|
|
1167
1186
|
},
|
|
1168
1187
|
{
|
|
1169
|
-
label:
|
|
1188
|
+
label: "Kill",
|
|
1170
1189
|
show: (data) => {
|
|
1171
1190
|
return !!data.pid;
|
|
1172
1191
|
},
|
|
1173
1192
|
click: (data) => {
|
|
1174
|
-
this._message.info(
|
|
1175
|
-
this._processData.kill(data)
|
|
1176
|
-
.subscribe(() => {
|
|
1193
|
+
this._message.info("Killing process...");
|
|
1194
|
+
this._processData.kill(data).subscribe(() => {
|
|
1177
1195
|
this.reload();
|
|
1178
|
-
this._message.success(
|
|
1196
|
+
this._message.success("Killed process");
|
|
1179
1197
|
});
|
|
1180
1198
|
},
|
|
1181
1199
|
},
|
|
1182
1200
|
{
|
|
1183
|
-
label:
|
|
1201
|
+
label: "Delete",
|
|
1184
1202
|
click: (data) => {
|
|
1185
|
-
this._processData.delete(data)
|
|
1186
|
-
.subscribe(() => {
|
|
1203
|
+
this._processData.delete(data).subscribe(() => {
|
|
1187
1204
|
this.reload();
|
|
1188
|
-
this._message.success(
|
|
1205
|
+
this._message.success("Deleted process");
|
|
1189
1206
|
});
|
|
1190
1207
|
},
|
|
1191
1208
|
},
|
|
@@ -1193,19 +1210,28 @@ class ProcessesComponent {
|
|
|
1193
1210
|
filters: [
|
|
1194
1211
|
{
|
|
1195
1212
|
type: ItemType.Keyword,
|
|
1196
|
-
name:
|
|
1197
|
-
label:
|
|
1213
|
+
name: "keyword",
|
|
1214
|
+
label: "Search",
|
|
1198
1215
|
},
|
|
1199
1216
|
{
|
|
1200
1217
|
type: ItemType.Select,
|
|
1201
|
-
name:
|
|
1202
|
-
label:
|
|
1218
|
+
name: "state",
|
|
1219
|
+
label: "Status",
|
|
1203
1220
|
values: ProcessStates,
|
|
1204
1221
|
},
|
|
1222
|
+
{
|
|
1223
|
+
name: "createDate",
|
|
1224
|
+
type: ItemType.DateRange,
|
|
1225
|
+
label: ["From Date", "To Date"],
|
|
1226
|
+
},
|
|
1205
1227
|
],
|
|
1206
1228
|
fetch: (query) => {
|
|
1207
|
-
return this._processData
|
|
1208
|
-
.
|
|
1229
|
+
return this._processData
|
|
1230
|
+
.gets(query, { key: null })
|
|
1231
|
+
.pipe(map((response) => ({
|
|
1232
|
+
data: response.processes,
|
|
1233
|
+
paging: response.paging,
|
|
1234
|
+
})));
|
|
1209
1235
|
},
|
|
1210
1236
|
};
|
|
1211
1237
|
this.actions.forEach((action) => {
|
|
@@ -1218,8 +1244,9 @@ class ProcessesComponent {
|
|
|
1218
1244
|
action.click(data);
|
|
1219
1245
|
}
|
|
1220
1246
|
if (action.component) {
|
|
1221
|
-
this._dialog
|
|
1222
|
-
|
|
1247
|
+
this._dialog
|
|
1248
|
+
.open(action.component, {
|
|
1249
|
+
width: "800px",
|
|
1223
1250
|
})
|
|
1224
1251
|
.afterClosed()
|
|
1225
1252
|
.pipe(takeUntil(this._destroy$))
|
|
@@ -1236,7 +1263,7 @@ class ProcessesComponent {
|
|
|
1236
1263
|
}
|
|
1237
1264
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ProcessesComponent, decorators: [{
|
|
1238
1265
|
type: Component,
|
|
1239
|
-
args: [{ selector:
|
|
1266
|
+
args: [{ selector: "fs-system-processes", changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [FsListModule, FsDateModule], template: "<fs-list [config]=\"config\">\n <fs-list-column>\n <ng-template fs-list-header>\n Name\n </ng-template>\n <ng-template\n fs-list-cell\n let-row=\"row\">\n <a (click)=\"open(row)\">\n {{ row.name }}\n </a>\n </ng-template>\n </fs-list-column>\n <fs-list-column>\n <ng-template fs-list-header>\n Status\n </ng-template>\n <ng-template\n fs-list-cell\n let-row=\"row\">\n {{ ProcessStates[row.state] }}\n <small>\n @if (row.state===ProcessState.Running && row.percent) {\n <div>\n Complete: {{ row.percent }}%\n </div>\n }\n @if (row.state===ProcessState.Completed && row.filename) {\n <div>\n <a\n href=\"javascript:;\"\n (click)=\"download(row)\">\n {{ row.filename }}\n </a>\n </div>\n }\n @if (row.pid) {\n <div>\n PID: {{ row.pid }}\n </div>\n }\n @if (row.state===ProcessState.Running && row.notify) {\n <div>\n Notify: {{ row.notify }}\n </div>\n }\n </small>\n </ng-template>\n </fs-list-column>\n <fs-list-column>\n <ng-template fs-list-header>\n Duration\n </ng-template>\n <ng-template\n fs-list-cell\n let-row=\"row\">\n {{ row.duration | fsDateDuration: {hours: true, minutes: true, seconds: true} }}\n </ng-template>\n </fs-list-column>\n <fs-list-column>\n <ng-template fs-list-header>\n Message\n </ng-template>\n <ng-template\n fs-list-cell\n let-row=\"row\">\n {{ row.message }}\n </ng-template>\n </fs-list-column>\n <fs-list-column>\n <ng-template fs-list-header>\n Completed\n </ng-template>\n <ng-template\n fs-list-cell\n let-row=\"row\">\n <fs-date-ago [date]=\"row.endDate\"></fs-date-ago>\n </ng-template>\n </fs-list-column>\n</fs-list>" }]
|
|
1240
1267
|
}], propDecorators: { list: [{
|
|
1241
1268
|
type: ViewChild,
|
|
1242
1269
|
args: [FsListComponent]
|