@firestitch/system 18.0.30 → 18.0.33
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/query-logs/components/explain/explain.component.d.ts +2 -2
- package/app/modules/query-logs/components/query-log/query-log.component.d.ts +2 -3
- package/app/modules/query-logs/components/query-logs/query-logs.component.d.ts +1 -3
- package/app/modules/system/components/api-log/api-log.component.d.ts +1 -3
- package/app/modules/system/components/api-logs/api-logs.component.d.ts +1 -3
- package/app/modules/system/components/cron/cron.component.d.ts +1 -1
- package/app/modules/system/components/cron-log/cron-log.component.d.ts +1 -2
- package/app/modules/system/components/cron-next-run/cron-next-run.component.d.ts +2 -3
- package/app/modules/system/components/crons/crons.component.d.ts +1 -1
- package/app/modules/system/components/dashboard/dashboard.component.d.ts +3 -5
- package/app/modules/system/components/info/info.component.d.ts +1 -1
- package/app/modules/system/components/process/process.component.d.ts +3 -12
- package/app/modules/system/components/processes/processes.component.d.ts +1 -6
- package/app/modules/system/components/server-logs/components/server-log/server-log.component.d.ts +0 -1
- package/app/modules/system/components/server-logs/server-logs.component.d.ts +1 -4
- package/app/modules/system/components/settings/settings.component.d.ts +2 -6
- package/app/modules/system/components/upgrade-logs/upgrade-logs.component.d.ts +1 -1
- package/app/modules/system/data/cron.data.d.ts +0 -2
- package/app/modules/system/data/process.data.d.ts +1 -2
- package/app/modules/system/fs-system.module.d.ts +40 -40
- package/app/modules/system/pipes/key-name-value.pipe.d.ts +1 -1
- package/esm2022/app/modules/query-logs/components/explain/explain.component.mjs +27 -18
- package/esm2022/app/modules/query-logs/components/index.mjs +1 -1
- package/esm2022/app/modules/query-logs/components/query-log/query-log.component.mjs +44 -25
- package/esm2022/app/modules/query-logs/components/query-logs/query-logs.component.mjs +19 -16
- package/esm2022/app/modules/system/components/api-log/api-log.component.mjs +20 -23
- package/esm2022/app/modules/system/components/api-log/index.mjs +1 -1
- package/esm2022/app/modules/system/components/api-logs/api-logs.component.mjs +18 -16
- package/esm2022/app/modules/system/components/api-logs/index.mjs +1 -1
- package/esm2022/app/modules/system/components/cron/cron.component.mjs +31 -13
- package/esm2022/app/modules/system/components/cron/index.mjs +1 -1
- package/esm2022/app/modules/system/components/cron-log/cron-log.component.mjs +30 -20
- package/esm2022/app/modules/system/components/cron-log/index.mjs +1 -1
- package/esm2022/app/modules/system/components/cron-logs/cron-logs.component.mjs +3 -3
- package/esm2022/app/modules/system/components/cron-next-run/cron-next-run.component.mjs +13 -16
- package/esm2022/app/modules/system/components/crons/crons.component.mjs +17 -10
- package/esm2022/app/modules/system/components/crons/index.mjs +1 -1
- package/esm2022/app/modules/system/components/dashboard/dashboard.component.mjs +30 -24
- package/esm2022/app/modules/system/components/dashboard/index.mjs +1 -1
- package/esm2022/app/modules/system/components/info/index.mjs +1 -1
- package/esm2022/app/modules/system/components/info/info.component.mjs +3 -3
- package/esm2022/app/modules/system/components/process/index.mjs +1 -1
- package/esm2022/app/modules/system/components/process/process.component.mjs +38 -36
- package/esm2022/app/modules/system/components/processes/index.mjs +1 -1
- package/esm2022/app/modules/system/components/processes/processes.component.mjs +13 -23
- package/esm2022/app/modules/system/components/server-logs/components/server-log/server-log.component.mjs +7 -13
- package/esm2022/app/modules/system/components/server-logs/index.mjs +1 -1
- package/esm2022/app/modules/system/components/server-logs/server-logs.component.mjs +17 -17
- package/esm2022/app/modules/system/components/settings/index.mjs +1 -1
- package/esm2022/app/modules/system/components/settings/settings.component.mjs +49 -33
- package/esm2022/app/modules/system/components/upgrade-logs/index.mjs +1 -1
- package/esm2022/app/modules/system/components/upgrade-logs/upgrade-logs.component.mjs +7 -6
- package/esm2022/app/modules/system/consts/api-log-states.const.mjs +1 -1
- package/esm2022/app/modules/system/consts/process-states.const.mjs +1 -1
- package/esm2022/app/modules/system/consts/setting-interface-types.const.mjs +1 -1
- package/esm2022/app/modules/system/data/cron.data.mjs +5 -9
- package/esm2022/app/modules/system/data/process.data.mjs +5 -9
- package/esm2022/app/modules/system/enums/api-log-state.enum.mjs +1 -1
- package/esm2022/app/modules/system/enums/index.mjs +1 -1
- package/esm2022/app/modules/system/enums/process-state.enum.mjs +1 -1
- package/esm2022/app/modules/system/enums/setting-interface-type.enum.mjs +1 -1
- package/esm2022/app/modules/system/fs-system.module.mjs +37 -26
- package/esm2022/app/modules/system/helpers/index-name-value.mjs +1 -1
- package/esm2022/app/modules/system/injectors/system-config.injector.mjs +1 -1
- package/esm2022/app/modules/system/interfaces/dashboard-action.mjs +1 -1
- package/esm2022/app/modules/system/interfaces/process-action.mjs +1 -1
- package/esm2022/app/modules/system/interfaces/system-config.mjs +1 -1
- package/esm2022/app/modules/system/pipes/key-name-value.pipe.mjs +3 -2
- package/esm2022/public_api.mjs +1 -2
- package/fesm2022/firestitch-system.mjs +416 -438
- package/fesm2022/firestitch-system.mjs.map +1 -1
- package/package.json +1 -1
- package/public_api.d.ts +0 -1
- package/app/modules/query-logs/query-logs.module.d.ts +0 -23
- package/esm2022/app/modules/query-logs/query-logs.module.mjs +0 -83
|
@@ -1,282 +1,62 @@
|
|
|
1
|
-
import * as i1$
|
|
2
|
-
import { CommonModule,
|
|
1
|
+
import * as i1$2 from '@angular/common';
|
|
2
|
+
import { JsonPipe, NgClass, NgStyle, CommonModule, NgTemplateOutlet } from '@angular/common';
|
|
3
3
|
import * as i0 from '@angular/core';
|
|
4
|
-
import { Component, ChangeDetectionStrategy,
|
|
5
|
-
import * as
|
|
4
|
+
import { inject, Component, ChangeDetectionStrategy, ViewChild, Input, Injectable, ChangeDetectorRef, EventEmitter, Output, Pipe, InjectionToken, NgModule } from '@angular/core';
|
|
5
|
+
import * as i1$3 from '@angular/forms';
|
|
6
6
|
import { FormsModule } from '@angular/forms';
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
import {
|
|
12
|
-
import
|
|
13
|
-
import {
|
|
14
|
-
import
|
|
15
|
-
import {
|
|
16
|
-
import
|
|
17
|
-
import {
|
|
18
|
-
import
|
|
19
|
-
import
|
|
20
|
-
import * as i8 from '@firestitch/dialog';
|
|
21
|
-
import { FsDialogModule } from '@firestitch/dialog';
|
|
22
|
-
import * as i3 from '@firestitch/form';
|
|
23
|
-
import { FsFormModule } from '@firestitch/form';
|
|
24
|
-
import * as i6$1 from '@firestitch/label';
|
|
25
|
-
import { FsLabelModule } from '@firestitch/label';
|
|
26
|
-
import * as i4$1 from '@firestitch/list';
|
|
27
|
-
import { FsListComponent, FsListModule, PaginationStrategy } from '@firestitch/list';
|
|
28
|
-
import * as i7 from '@firestitch/popover';
|
|
29
|
-
import { FsPopoverModule } from '@firestitch/popover';
|
|
30
|
-
import { ItemType } from '@firestitch/filter';
|
|
31
|
-
import { map, tap, takeUntil, switchMap, filter, take, finalize } from 'rxjs/operators';
|
|
32
|
-
import * as i7$1 from '@angular/material/expansion';
|
|
33
|
-
import { MatExpansionModule } from '@angular/material/expansion';
|
|
34
|
-
import * as i10$1 from '@angular/material/form-field';
|
|
35
|
-
import { MatFormFieldModule } from '@angular/material/form-field';
|
|
36
|
-
import * as i3$2 from '@angular/material/icon';
|
|
37
|
-
import { MatIconModule } from '@angular/material/icon';
|
|
38
|
-
import * as i11 from '@angular/material/input';
|
|
39
|
-
import { MatInputModule } from '@angular/material/input';
|
|
40
|
-
import * as i8$1 from '@angular/material/progress-spinner';
|
|
41
|
-
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
|
42
|
-
import * as i12 from '@angular/material/select';
|
|
43
|
-
import { MatSelectModule } from '@angular/material/select';
|
|
44
|
-
import * as i5 from '@angular/material/tooltip';
|
|
45
|
-
import { MatTooltipModule } from '@angular/material/tooltip';
|
|
46
|
-
import * as i5$1 from '@firestitch/badge';
|
|
7
|
+
import * as i3$2 from '@angular/material/button';
|
|
8
|
+
import { MatButton, MatButtonModule, MatIconButton } from '@angular/material/button';
|
|
9
|
+
import * as i2$2 from '@angular/material/dialog';
|
|
10
|
+
import { MatDialogRef, MAT_DIALOG_DATA, MatDialogTitle, MatDialogContent, MatDialogActions, MatDialogClose, MatDialog, MatDialogModule } from '@angular/material/dialog';
|
|
11
|
+
import { MatAccordion, MatExpansionPanel, MatExpansionPanelHeader, MatExpansionPanelTitle, MatExpansionModule } from '@angular/material/expansion';
|
|
12
|
+
import { MatFormField, MatLabel, MatHint, MatFormFieldModule } from '@angular/material/form-field';
|
|
13
|
+
import { MatIcon, MatIconModule } from '@angular/material/icon';
|
|
14
|
+
import { MatInput, MatInputModule } from '@angular/material/input';
|
|
15
|
+
import { MatProgressSpinner, MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
|
16
|
+
import { MatSelect, MatSelectModule } from '@angular/material/select';
|
|
17
|
+
import { MatTabGroup, MatTab, MatTabContent, MatTabsModule } from '@angular/material/tabs';
|
|
18
|
+
import { MatTooltip, MatTooltipModule } from '@angular/material/tooltip';
|
|
19
|
+
import * as i2$3 from '@firestitch/badge';
|
|
47
20
|
import { FsBadgeModule } from '@firestitch/badge';
|
|
48
|
-
import * as
|
|
21
|
+
import * as i3$3 from '@firestitch/colorpicker';
|
|
49
22
|
import { FsColorPickerModule } from '@firestitch/colorpicker';
|
|
50
|
-
import * as
|
|
23
|
+
import * as i4 from '@firestitch/date';
|
|
24
|
+
import { FsDateModule, parse } from '@firestitch/date';
|
|
25
|
+
import * as i2$4 from '@firestitch/datepicker';
|
|
51
26
|
import { FsDatePickerModule } from '@firestitch/datepicker';
|
|
52
|
-
import * as
|
|
27
|
+
import * as i2 from '@firestitch/dialog';
|
|
28
|
+
import { FsDialogModule } from '@firestitch/dialog';
|
|
29
|
+
import * as i4$1 from '@firestitch/file';
|
|
53
30
|
import { FsFileModule } from '@firestitch/file';
|
|
54
31
|
import { FsFileManagerModule } from '@firestitch/file-manager';
|
|
55
|
-
import * as
|
|
32
|
+
import * as i3 from '@firestitch/label';
|
|
33
|
+
import { FsLabelModule } from '@firestitch/label';
|
|
34
|
+
import * as i1$1 from '@firestitch/list';
|
|
35
|
+
import { PaginationStrategy, FsListComponent, FsListModule } from '@firestitch/list';
|
|
36
|
+
import * as i3$1 from '@firestitch/menu';
|
|
56
37
|
import { FsMenuModule } from '@firestitch/menu';
|
|
57
|
-
import * as
|
|
38
|
+
import * as i2$1 from '@firestitch/popover';
|
|
39
|
+
import { FsPopoverModule } from '@firestitch/popover';
|
|
40
|
+
import * as i1 from '@firestitch/skeleton';
|
|
58
41
|
import { FsSkeletonModule } from '@firestitch/skeleton';
|
|
59
|
-
import
|
|
42
|
+
import { CdkScrollable } from '@angular/cdk/scrolling';
|
|
43
|
+
import { ItemType } from '@firestitch/filter';
|
|
44
|
+
import { map, tap, takeUntil, switchMap, filter, take, finalize } from 'rxjs/operators';
|
|
60
45
|
import { FsApi, RequestMethod, StreamEventData, StreamEventType } from '@firestitch/api';
|
|
61
46
|
import { Subject, timer, Observable } from 'rxjs';
|
|
62
47
|
import { addMinutes, addHours, addDays, subSeconds, differenceInSeconds, getDaysInMonth, differenceInMinutes } from 'date-fns';
|
|
63
|
-
import * as i1$3 from '@firestitch/message';
|
|
64
48
|
import { FsMessage } from '@firestitch/message';
|
|
65
|
-
import * as i3$3 from '@firestitch/process';
|
|
66
49
|
import { FsProcess } from '@firestitch/process';
|
|
67
|
-
import * as i2$2 from '@firestitch/prompt';
|
|
68
50
|
import { FsPrompt } from '@firestitch/prompt';
|
|
69
51
|
import { SelectionActionType } from '@firestitch/selection';
|
|
70
|
-
import
|
|
71
|
-
import * as
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
this.explain = _data.explain;
|
|
79
|
-
}
|
|
80
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ExplainComponent, deps: [{ token: MAT_DIALOG_DATA }], target: i0.ɵɵFactoryTarget.Component });
|
|
81
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.7", type: ExplainComponent, selector: "ng-component", ngImport: i0, template: "<fs-dialog>\n <h1 mat-dialog-title>Explain</h1>\n <mat-dialog-content>\n <div class=\"explain-popover\">{{explain | json}}</div>\n </mat-dialog-content>\n <mat-dialog-actions>\n <button\n mat-button\n type=\"button\"\n color=\"primary\"\n [mat-dialog-close]=\"undefined\">\n Done\n </button>\n </mat-dialog-actions>\n</fs-dialog>\n", styles: [".explain-popover{white-space:pre}\n"], dependencies: [{ kind: "component", type: i6.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "directive", type: i1.MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "directive", type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "directive", type: i3.FsButtonDirective, selector: "[mat-raised-button]:not([fsFormButtonStandalone]),[mat-button]:not([fsFormButtonStandalone]),[mat-flat-button]:not([fsFormButtonStandalone]),[mat-stroked-button]:not([fsFormButtonStandalone])", inputs: ["name", "dirtySubmit", "form"] }, { kind: "component", type: i8.FsDialogComponent, selector: "fs-dialog", inputs: ["mobileMode", "mobileButtonPlacement", "mobileWidth", "mode", "buttonLayout"] }, { kind: "pipe", type: i1$1.JsonPipe, name: "json" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
82
|
-
}
|
|
83
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ExplainComponent, decorators: [{
|
|
84
|
-
type: Component,
|
|
85
|
-
args: [{ changeDetection: ChangeDetectionStrategy.OnPush, template: "<fs-dialog>\n <h1 mat-dialog-title>Explain</h1>\n <mat-dialog-content>\n <div class=\"explain-popover\">{{explain | json}}</div>\n </mat-dialog-content>\n <mat-dialog-actions>\n <button\n mat-button\n type=\"button\"\n color=\"primary\"\n [mat-dialog-close]=\"undefined\">\n Done\n </button>\n </mat-dialog-actions>\n</fs-dialog>\n", styles: [".explain-popover{white-space:pre}\n"] }]
|
|
86
|
-
}], ctorParameters: () => [{ type: undefined, decorators: [{
|
|
87
|
-
type: Inject,
|
|
88
|
-
args: [MAT_DIALOG_DATA]
|
|
89
|
-
}] }] });
|
|
90
|
-
|
|
91
|
-
class QueryLogComponent {
|
|
92
|
-
_data;
|
|
93
|
-
_dialog;
|
|
94
|
-
queryLog;
|
|
95
|
-
accessTypes = {
|
|
96
|
-
NULL: 'This access method means MySQL can resolve the query during the optimization phase and will not even access the table or index during the execution stage.',
|
|
97
|
-
system: 'The table is empty or has one row.',
|
|
98
|
-
const: 'The value of the column can be treated as a constant (there is one row matching the query). Note: Primary Key Lookup, Unique Index Lookup',
|
|
99
|
-
eq_ref: 'The index is clustered and is being used by the operation (either the index is a PRIMARY KEY or UNIQUE INDEX with all key columns defined as NOT NULL)',
|
|
100
|
-
ref: 'The indexed column was accessed using an equality operator Note: The ref_or_null access type is a variation on ref. It means MySQL must do a second lookup to find NULL entries after doing the initial lookup.',
|
|
101
|
-
fulltext: 'Operation (JOIN) is using the table’s fulltext index',
|
|
102
|
-
index: 'The entire index is scanned to find a match for the query. Note: The main advantage is that this avoids sorting. The biggest disadvantage is the cost of reading an entire table in index order. This usually means accessing the rows in random order, which is very expensive.',
|
|
103
|
-
index_merge: 'This join type indicates that the Index Merge optimization is used. In this case, the key column in the output row contains a list of indexes used. It indicates a query can make limited use of multiple indexes on a single table.',
|
|
104
|
-
range: 'This type replaces eq_ref for some IN subqueries of the following form: value IN (SELECT primary_key FROM single_table WHERE some_expr)',
|
|
105
|
-
unique_subquery: '',
|
|
106
|
-
ALL: 'MySQL scans the entire table to satisfy the query',
|
|
107
|
-
};
|
|
108
|
-
constructor(_data, _dialog) {
|
|
109
|
-
this._data = _data;
|
|
110
|
-
this._dialog = _dialog;
|
|
111
|
-
this.queryLog = _data.queryLog;
|
|
112
|
-
}
|
|
113
|
-
openExplain() {
|
|
114
|
-
this._dialog.open(ExplainComponent, {
|
|
115
|
-
data: { explain: this.explain },
|
|
116
|
-
});
|
|
117
|
-
}
|
|
118
|
-
get explain() {
|
|
119
|
-
return this.queryLog.explain;
|
|
120
|
-
}
|
|
121
|
-
get queryBlock() {
|
|
122
|
-
return this.explain?.queryBlock;
|
|
123
|
-
}
|
|
124
|
-
get orderingOperation() {
|
|
125
|
-
return this.queryBlock?.orderingOperation;
|
|
126
|
-
}
|
|
127
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: QueryLogComponent, deps: [{ token: MAT_DIALOG_DATA }, { token: i1.MatDialog }], target: i0.ɵɵFactoryTarget.Component });
|
|
128
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.7", type: QueryLogComponent, selector: "ng-component", ngImport: i0, template: "<fs-dialog>\n <h1 mat-dialog-title>Query Log</h1>\n <mat-dialog-content>\n <div class=\"fs-row.gap-lg.wrap.align-start\">\n <fs-label-field>\n <fs-label>Duration</fs-label>\n {{queryLog.duration}}\n </fs-label-field>\n\n <fs-label-field>\n <fs-label>Optimized</fs-label>\n {{queryLog.optimized ? 'Yes' : 'No'}}\n </fs-label-field>\n\n <fs-label-field>\n <fs-label>Query Cost</fs-label>\n {{queryLog.queryCost}}\n </fs-label-field>\n\n <fs-label-field>\n <fs-label>Raw Explain</fs-label>\n <a (click)=\"openExplain()\">View</a>\n </fs-label-field>\n\n <fs-label-field>\n <fs-label>URL</fs-label>\n {{queryLog.path | fsFormatTruncate: 50}}\n </fs-label-field>\n </div>\n\n <mat-tab-group>\n <mat-tab label=\"Query\">\n <fs-clipboard-button\n [content]=\"queryLog.prettyQuery\">\n </fs-clipboard-button>\n <div [innerHTML]=\"queryLog.prettyQuery\" class=\"query\"></div>\n </mat-tab>\n \n <mat-tab label=\"Explain\">\n <ng-container [ngTemplateOutlet]=\"nestedLoop\" [ngTemplateOutletContext]=\"{ queryBlock: queryBlock, selectId: queryBlock.selectId, costInfo: queryBlock.costInfo }\"></ng-container>\n </mat-tab>\n </mat-tab-group>\n\n </mat-dialog-content>\n <mat-dialog-actions>\n <button\n mat-button\n type=\"button\"\n color=\"primary\"\n [mat-dialog-close]=\"undefined\">\n Done\n </button>\n </mat-dialog-actions>\n</fs-dialog>\n\n<ng-template #nestedLoop let-queryBlock=\"queryBlock\" let-selectId=\"selectId\" let-costInfo=\"costInfo\">\n <ng-container *ngIf=\"selectId\">\n <h1>Select {{selectId}}</h1>\n </ng-container>\n \n <div class=\"fs-row.gap-lg.wrap.align-start\">\n <ng-container *ngIf=\"costInfo?.queryCost\">\n <fs-label-field>\n <fs-label>Query Cost</fs-label>\n {{costInfo.queryCost}}\n </fs-label-field>\n </ng-container>\n <ng-container *ngIf=\"queryBlock.orderingOperation\">\n <fs-label-field>\n <fs-label>Ordering Operation</fs-label>\n <ng-container [ngTemplateOutlet]=\"queryBlockCritical\" [ngTemplateOutletContext]=\"{ queryBlock: queryBlock.orderingOperation }\"></ng-container>\n </fs-label-field>\n </ng-container>\n\n <ng-container *ngIf=\"queryBlock.groupingOperation\">\n <fs-label-field>\n <fs-label>Grouping Operation</fs-label>\n <ng-container [ngTemplateOutlet]=\"queryBlockCritical\" [ngTemplateOutletContext]=\"{ queryBlock: queryBlock.groupingOperation }\"></ng-container>\n </fs-label-field>\n </ng-container>\n\n <ng-container *ngIf=\"queryBlock.duplicatesRemoval\">\n <fs-label-field>\n <fs-label>Duplicates Removal</fs-label>\n <ng-container [ngTemplateOutlet]=\"queryBlockCritical\" [ngTemplateOutletContext]=\"{ queryBlock: queryBlock.duplicatesRemoval }\"></ng-container>\n </fs-label-field>\n </ng-container>\n </div>\n\n <ng-container *ngIf=\"queryBlock.orderingOperation\">\n <ng-container [ngTemplateOutlet]=\"nestedLoop\" [ngTemplateOutletContext]=\"{ queryBlock: queryBlock.orderingOperation }\"></ng-container>\n </ng-container>\n\n <ng-container *ngIf=\"queryBlock.groupingOperation\">\n <ng-container [ngTemplateOutlet]=\"nestedLoop\" [ngTemplateOutletContext]=\"{ queryBlock: queryBlock.groupingOperation }\"></ng-container>\n </ng-container>\n\n <ng-container *ngIf=\"queryBlock.duplicatesRemoval\">\n <ng-container [ngTemplateOutlet]=\"nestedLoop\" [ngTemplateOutletContext]=\"{ queryBlock: queryBlock.duplicatesRemoval }\"></ng-container>\n </ng-container>\n\n <ng-container *ngIf=\"queryBlock.table\">\n <ng-container [ngTemplateOutlet]=\"nestedLoop\" [ngTemplateOutletContext]=\"{ queryBlock: { nestedLoop: [ queryBlock ]} }\"></ng-container>\n \n <ng-container *ngIf=\"queryBlock.table.attachedSubqueries\"> \n <fs-label>Attached Subqueries</fs-label>\n <ng-container *ngFor=\"let subquery of queryBlock.table.attachedSubqueries\">\n <ng-container [ngTemplateOutlet]=\"queryBlockCritical\" [ngTemplateOutletContext]=\"{ queryBlock: subquery.queryBlock }\"></ng-container> \n <ng-container [ngTemplateOutlet]=\"nestedLoop\" [ngTemplateOutletContext]=\"{ queryBlock: subquery.queryBlock, selectId: subquery.queryBlock.selectId, costInfo: subquery.queryBlock.costInfo }\"></ng-container>\n </ng-container>\n </ng-container> \n </ng-container>\n\n <ng-container *ngIf=\"queryBlock.nestedLoop\">\n <table class=\"fs-list-table style-line\">\n <thead>\n <tr>\n <th>Table</th>\n <th>Type</th>\n <th>Keys</th>\n <th>Ref</th>\n <th>Rows</th>\n <th>Filtered</th>\n <th>Extra</th>\n <th>Cost</th>\n </tr>\n </thead>\n <tbody>\n <ng-container *ngFor=\"let item of queryBlock.nestedLoop; let index = index\">\n <tr>\n <td>\n {{item.table.tableName}}\n </td>\n <td>\n <fs-popover [template]=\"accessTypePopover\" [data]=\"item.table.accessType\">\n <span class=\"access-type\" [ngClass]=\"item.table.accessType\">{{item.table.accessType}}</span>\n </fs-popover> \n </td>\n <td>\n <fs-popover \n [template]=\"keysPopover\"\n [maxWidth]=\"null\"\n [data]=\"{ possibleKeys: item.table.possibleKeys, key: item.table.key }\">\n {{item.table.key}}\n </fs-popover>\n </td>\n <td>\n <div class=\"fs-delimit\">\n <ng-container *ngFor=\"let ref of item.table.ref\">\n <span>{{ref}}</span>\n </ng-container>\n </div>\n </td>\n <td>\n {{item.table.rowsExaminedPerScan}}\n </td>\n <td>\n {{item.table.filtered}}\n </td>\n <td>\n <div class=\"fs-delimit\">\n <ng-container *ngIf=\"item.table.indexCondition\">\n <span>\n <fs-popover \n [template]=\"usingIndexCondition\" \n [maxWidth]=\"null\"\n [data]=\"item.table.indexCondition\">\n Using Index Condition\n </fs-popover>\n </span>\n </ng-container>\n <ng-container *ngIf=\"item.table.attachedCondition\">\n <span>\n <fs-popover \n [template]=\"usingWhere\" \n [maxWidth]=\"null\"\n [data]=\"item.table.attachedCondition\">\n Using Where\n </fs-popover>\n </span>\n </ng-container>\n <ng-container *ngIf=\"item.usingIndex\">\n <span>Using Index</span>\n </ng-container> \n <ng-container *ngIf=\"item.usingFilesort\">\n <span class=\"critical\">Using File Sort</span>\n </ng-container>\n \n <ng-container *ngIf=\"item.usingTemporaryTable\">\n <span class=\"critical\">Temporary Table</span>\n </ng-container>\n </div>\n </td>\n <td> \n <fs-popover [template]=\"tableCostPopover\" [data]=\"item.table?.costInfo\">\n {{item.table?.costInfo.prefixCost}}\n </fs-popover>\n <ng-template #tableCostPopover let-data=\"data\">\n <div>Eval Cost: {{data.evalCost}}</div>\n <div>Read Cost: {{data.readCost}}</div>\n <div>Prefix Cost: {{data.prefixCost}}</div>\n <div>Data Read Per Join: {{data.dataReadPerJoin}}</div>\n </ng-template>\n </td>\n </tr>\n </ng-container>\n </tbody>\n </table>\n <br>\n </ng-container> \n \n <ng-container *ngIf=\"queryBlock.selectListSubqueries\">\n <br>\n <fs-label>Select List Subqueries</fs-label>\n <ng-container *ngFor=\"let subquery of queryBlock.selectListSubqueries\">\n <ng-container [ngTemplateOutlet]=\"queryBlockCritical\" [ngTemplateOutletContext]=\"{ queryBlock: subquery.queryBlock }\"></ng-container> \n <ng-container [ngTemplateOutlet]=\"nestedLoop\" [ngTemplateOutletContext]=\"{ queryBlock: subquery.queryBlock, selectId: subquery.queryBlock.selectId, costInfo: subquery.queryBlock.costInfo }\"></ng-container>\n </ng-container>\n </ng-container>\n<!-- \n <ng-container *ngIf=\"queryBlock.queryBlockattachedSubqueries\">\n <br>\n <fs-label>Attached Subqueries</fs-label>\n <ng-container *ngFor=\"let subquery of queryBlock.attachedSubqueries\">\n <ng-container [ngTemplateOutlet]=\"queryBlockCritical\" [ngTemplateOutletContext]=\"{ queryBlock: subquery.queryBlock }\"></ng-container>\n <ng-container [ngTemplateOutlet]=\"nestedLoop\" [ngTemplateOutletContext]=\"{ queryBlock: subquery.queryBlock }\"></ng-container>\n </ng-container>\n </ng-container> -->\n</ng-template>\n\n<ng-template #keysPopover let-data=\"data\">\n <div class=\"fs-delimit\">\n <ng-container *ngFor=\"let possibleKey of data.possibleKeys\">\n <span [ngClass]=\"{ 'query-log-used-key': possibleKey === data.key }\">{{possibleKey}}</span>\n </ng-container>\n </div>\n</ng-template>\n\n<ng-template #usingWhere let-data=\"data\">\n {{data}}\n</ng-template>\n\n<ng-template #usingIndexCondition let-data=\"data\">\n {{data}}\n</ng-template>\n\n<ng-template #accessTypePopover let-data=\"data\">\n {{accessTypes[data]}}\n</ng-template>\n\n\n<ng-template #queryBlockCritical let-queryBlock=\"queryBlock\">\n <div class=\"fs-delimit\">\n <ng-container *ngIf=\"queryBlock.usingFilesort\">\n <span class=\"critical\">Using File Sort</span>\n </ng-container>\n \n <ng-container *ngIf=\"queryBlock.usingTemporaryTable\">\n <span class=\"critical\">Temporary Table</span>\n </ng-container>\n </div>\n</ng-template>", styles: ["::ng-deep .query-log-used-key{font-weight:700}::ng-deep .explain-popover{white-space:pre}.critical{color:red}fs-clipboard-button{float:right}.query{white-space:break-spaces}.access-type{color:green}.access-type.fulltext,.access-type.index,.access-type.range{color:orange}.access-type.ALL{color:red}\n"], dependencies: [{ kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i4.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass"], exportAs: ["matTab"] }, { kind: "component", type: i4.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "component", type: i6.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "directive", type: i1.MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "directive", type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "directive", type: i3.FsButtonDirective, selector: "[mat-raised-button]:not([fsFormButtonStandalone]),[mat-button]:not([fsFormButtonStandalone]),[mat-flat-button]:not([fsFormButtonStandalone]),[mat-stroked-button]:not([fsFormButtonStandalone])", inputs: ["name", "dirtySubmit", "form"] }, { kind: "component", type: i6$1.FsLabelComponent, selector: "fs-label" }, { kind: "component", type: i6$1.FsLabelFieldComponent, selector: "fs-label-field", inputs: ["appearance", "showOutline", "disabled", "focused", "hoverable", "padless"] }, { kind: "component", type: i7.FsPopoverComponent, selector: "fs-popover" }, { kind: "component", type: i8.FsDialogComponent, selector: "fs-dialog", inputs: ["mobileMode", "mobileButtonPlacement", "mobileWidth", "mode", "buttonLayout"] }, { kind: "component", type: i2.FsClipboardButtonComponent, selector: "fs-clipboard-button", inputs: ["content", "tooltip"] }, { kind: "pipe", type: i10.FsFormatTruncatePipe, name: "fsFormatTruncate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
129
|
-
}
|
|
130
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: QueryLogComponent, decorators: [{
|
|
131
|
-
type: Component,
|
|
132
|
-
args: [{ changeDetection: ChangeDetectionStrategy.OnPush, template: "<fs-dialog>\n <h1 mat-dialog-title>Query Log</h1>\n <mat-dialog-content>\n <div class=\"fs-row.gap-lg.wrap.align-start\">\n <fs-label-field>\n <fs-label>Duration</fs-label>\n {{queryLog.duration}}\n </fs-label-field>\n\n <fs-label-field>\n <fs-label>Optimized</fs-label>\n {{queryLog.optimized ? 'Yes' : 'No'}}\n </fs-label-field>\n\n <fs-label-field>\n <fs-label>Query Cost</fs-label>\n {{queryLog.queryCost}}\n </fs-label-field>\n\n <fs-label-field>\n <fs-label>Raw Explain</fs-label>\n <a (click)=\"openExplain()\">View</a>\n </fs-label-field>\n\n <fs-label-field>\n <fs-label>URL</fs-label>\n {{queryLog.path | fsFormatTruncate: 50}}\n </fs-label-field>\n </div>\n\n <mat-tab-group>\n <mat-tab label=\"Query\">\n <fs-clipboard-button\n [content]=\"queryLog.prettyQuery\">\n </fs-clipboard-button>\n <div [innerHTML]=\"queryLog.prettyQuery\" class=\"query\"></div>\n </mat-tab>\n \n <mat-tab label=\"Explain\">\n <ng-container [ngTemplateOutlet]=\"nestedLoop\" [ngTemplateOutletContext]=\"{ queryBlock: queryBlock, selectId: queryBlock.selectId, costInfo: queryBlock.costInfo }\"></ng-container>\n </mat-tab>\n </mat-tab-group>\n\n </mat-dialog-content>\n <mat-dialog-actions>\n <button\n mat-button\n type=\"button\"\n color=\"primary\"\n [mat-dialog-close]=\"undefined\">\n Done\n </button>\n </mat-dialog-actions>\n</fs-dialog>\n\n<ng-template #nestedLoop let-queryBlock=\"queryBlock\" let-selectId=\"selectId\" let-costInfo=\"costInfo\">\n <ng-container *ngIf=\"selectId\">\n <h1>Select {{selectId}}</h1>\n </ng-container>\n \n <div class=\"fs-row.gap-lg.wrap.align-start\">\n <ng-container *ngIf=\"costInfo?.queryCost\">\n <fs-label-field>\n <fs-label>Query Cost</fs-label>\n {{costInfo.queryCost}}\n </fs-label-field>\n </ng-container>\n <ng-container *ngIf=\"queryBlock.orderingOperation\">\n <fs-label-field>\n <fs-label>Ordering Operation</fs-label>\n <ng-container [ngTemplateOutlet]=\"queryBlockCritical\" [ngTemplateOutletContext]=\"{ queryBlock: queryBlock.orderingOperation }\"></ng-container>\n </fs-label-field>\n </ng-container>\n\n <ng-container *ngIf=\"queryBlock.groupingOperation\">\n <fs-label-field>\n <fs-label>Grouping Operation</fs-label>\n <ng-container [ngTemplateOutlet]=\"queryBlockCritical\" [ngTemplateOutletContext]=\"{ queryBlock: queryBlock.groupingOperation }\"></ng-container>\n </fs-label-field>\n </ng-container>\n\n <ng-container *ngIf=\"queryBlock.duplicatesRemoval\">\n <fs-label-field>\n <fs-label>Duplicates Removal</fs-label>\n <ng-container [ngTemplateOutlet]=\"queryBlockCritical\" [ngTemplateOutletContext]=\"{ queryBlock: queryBlock.duplicatesRemoval }\"></ng-container>\n </fs-label-field>\n </ng-container>\n </div>\n\n <ng-container *ngIf=\"queryBlock.orderingOperation\">\n <ng-container [ngTemplateOutlet]=\"nestedLoop\" [ngTemplateOutletContext]=\"{ queryBlock: queryBlock.orderingOperation }\"></ng-container>\n </ng-container>\n\n <ng-container *ngIf=\"queryBlock.groupingOperation\">\n <ng-container [ngTemplateOutlet]=\"nestedLoop\" [ngTemplateOutletContext]=\"{ queryBlock: queryBlock.groupingOperation }\"></ng-container>\n </ng-container>\n\n <ng-container *ngIf=\"queryBlock.duplicatesRemoval\">\n <ng-container [ngTemplateOutlet]=\"nestedLoop\" [ngTemplateOutletContext]=\"{ queryBlock: queryBlock.duplicatesRemoval }\"></ng-container>\n </ng-container>\n\n <ng-container *ngIf=\"queryBlock.table\">\n <ng-container [ngTemplateOutlet]=\"nestedLoop\" [ngTemplateOutletContext]=\"{ queryBlock: { nestedLoop: [ queryBlock ]} }\"></ng-container>\n \n <ng-container *ngIf=\"queryBlock.table.attachedSubqueries\"> \n <fs-label>Attached Subqueries</fs-label>\n <ng-container *ngFor=\"let subquery of queryBlock.table.attachedSubqueries\">\n <ng-container [ngTemplateOutlet]=\"queryBlockCritical\" [ngTemplateOutletContext]=\"{ queryBlock: subquery.queryBlock }\"></ng-container> \n <ng-container [ngTemplateOutlet]=\"nestedLoop\" [ngTemplateOutletContext]=\"{ queryBlock: subquery.queryBlock, selectId: subquery.queryBlock.selectId, costInfo: subquery.queryBlock.costInfo }\"></ng-container>\n </ng-container>\n </ng-container> \n </ng-container>\n\n <ng-container *ngIf=\"queryBlock.nestedLoop\">\n <table class=\"fs-list-table style-line\">\n <thead>\n <tr>\n <th>Table</th>\n <th>Type</th>\n <th>Keys</th>\n <th>Ref</th>\n <th>Rows</th>\n <th>Filtered</th>\n <th>Extra</th>\n <th>Cost</th>\n </tr>\n </thead>\n <tbody>\n <ng-container *ngFor=\"let item of queryBlock.nestedLoop; let index = index\">\n <tr>\n <td>\n {{item.table.tableName}}\n </td>\n <td>\n <fs-popover [template]=\"accessTypePopover\" [data]=\"item.table.accessType\">\n <span class=\"access-type\" [ngClass]=\"item.table.accessType\">{{item.table.accessType}}</span>\n </fs-popover> \n </td>\n <td>\n <fs-popover \n [template]=\"keysPopover\"\n [maxWidth]=\"null\"\n [data]=\"{ possibleKeys: item.table.possibleKeys, key: item.table.key }\">\n {{item.table.key}}\n </fs-popover>\n </td>\n <td>\n <div class=\"fs-delimit\">\n <ng-container *ngFor=\"let ref of item.table.ref\">\n <span>{{ref}}</span>\n </ng-container>\n </div>\n </td>\n <td>\n {{item.table.rowsExaminedPerScan}}\n </td>\n <td>\n {{item.table.filtered}}\n </td>\n <td>\n <div class=\"fs-delimit\">\n <ng-container *ngIf=\"item.table.indexCondition\">\n <span>\n <fs-popover \n [template]=\"usingIndexCondition\" \n [maxWidth]=\"null\"\n [data]=\"item.table.indexCondition\">\n Using Index Condition\n </fs-popover>\n </span>\n </ng-container>\n <ng-container *ngIf=\"item.table.attachedCondition\">\n <span>\n <fs-popover \n [template]=\"usingWhere\" \n [maxWidth]=\"null\"\n [data]=\"item.table.attachedCondition\">\n Using Where\n </fs-popover>\n </span>\n </ng-container>\n <ng-container *ngIf=\"item.usingIndex\">\n <span>Using Index</span>\n </ng-container> \n <ng-container *ngIf=\"item.usingFilesort\">\n <span class=\"critical\">Using File Sort</span>\n </ng-container>\n \n <ng-container *ngIf=\"item.usingTemporaryTable\">\n <span class=\"critical\">Temporary Table</span>\n </ng-container>\n </div>\n </td>\n <td> \n <fs-popover [template]=\"tableCostPopover\" [data]=\"item.table?.costInfo\">\n {{item.table?.costInfo.prefixCost}}\n </fs-popover>\n <ng-template #tableCostPopover let-data=\"data\">\n <div>Eval Cost: {{data.evalCost}}</div>\n <div>Read Cost: {{data.readCost}}</div>\n <div>Prefix Cost: {{data.prefixCost}}</div>\n <div>Data Read Per Join: {{data.dataReadPerJoin}}</div>\n </ng-template>\n </td>\n </tr>\n </ng-container>\n </tbody>\n </table>\n <br>\n </ng-container> \n \n <ng-container *ngIf=\"queryBlock.selectListSubqueries\">\n <br>\n <fs-label>Select List Subqueries</fs-label>\n <ng-container *ngFor=\"let subquery of queryBlock.selectListSubqueries\">\n <ng-container [ngTemplateOutlet]=\"queryBlockCritical\" [ngTemplateOutletContext]=\"{ queryBlock: subquery.queryBlock }\"></ng-container> \n <ng-container [ngTemplateOutlet]=\"nestedLoop\" [ngTemplateOutletContext]=\"{ queryBlock: subquery.queryBlock, selectId: subquery.queryBlock.selectId, costInfo: subquery.queryBlock.costInfo }\"></ng-container>\n </ng-container>\n </ng-container>\n<!-- \n <ng-container *ngIf=\"queryBlock.queryBlockattachedSubqueries\">\n <br>\n <fs-label>Attached Subqueries</fs-label>\n <ng-container *ngFor=\"let subquery of queryBlock.attachedSubqueries\">\n <ng-container [ngTemplateOutlet]=\"queryBlockCritical\" [ngTemplateOutletContext]=\"{ queryBlock: subquery.queryBlock }\"></ng-container>\n <ng-container [ngTemplateOutlet]=\"nestedLoop\" [ngTemplateOutletContext]=\"{ queryBlock: subquery.queryBlock }\"></ng-container>\n </ng-container>\n </ng-container> -->\n</ng-template>\n\n<ng-template #keysPopover let-data=\"data\">\n <div class=\"fs-delimit\">\n <ng-container *ngFor=\"let possibleKey of data.possibleKeys\">\n <span [ngClass]=\"{ 'query-log-used-key': possibleKey === data.key }\">{{possibleKey}}</span>\n </ng-container>\n </div>\n</ng-template>\n\n<ng-template #usingWhere let-data=\"data\">\n {{data}}\n</ng-template>\n\n<ng-template #usingIndexCondition let-data=\"data\">\n {{data}}\n</ng-template>\n\n<ng-template #accessTypePopover let-data=\"data\">\n {{accessTypes[data]}}\n</ng-template>\n\n\n<ng-template #queryBlockCritical let-queryBlock=\"queryBlock\">\n <div class=\"fs-delimit\">\n <ng-container *ngIf=\"queryBlock.usingFilesort\">\n <span class=\"critical\">Using File Sort</span>\n </ng-container>\n \n <ng-container *ngIf=\"queryBlock.usingTemporaryTable\">\n <span class=\"critical\">Temporary Table</span>\n </ng-container>\n </div>\n</ng-template>", styles: ["::ng-deep .query-log-used-key{font-weight:700}::ng-deep .explain-popover{white-space:pre}.critical{color:red}fs-clipboard-button{float:right}.query{white-space:break-spaces}.access-type{color:green}.access-type.fulltext,.access-type.index,.access-type.range{color:orange}.access-type.ALL{color:red}\n"] }]
|
|
133
|
-
}], ctorParameters: () => [{ type: undefined, decorators: [{
|
|
134
|
-
type: Inject,
|
|
135
|
-
args: [MAT_DIALOG_DATA]
|
|
136
|
-
}] }, { type: i1.MatDialog }] });
|
|
137
|
-
|
|
138
|
-
class QueryLogsComponent {
|
|
139
|
-
_dialog;
|
|
140
|
-
list;
|
|
141
|
-
loadQueryLogs;
|
|
142
|
-
purgeQueryLogs;
|
|
143
|
-
listConfig;
|
|
144
|
-
constructor(_dialog) {
|
|
145
|
-
this._dialog = _dialog;
|
|
146
|
-
}
|
|
147
|
-
openQueryLog(queryLog) {
|
|
148
|
-
this._dialog.open(QueryLogComponent, {
|
|
149
|
-
data: { queryLog },
|
|
150
|
-
width: '100%',
|
|
151
|
-
});
|
|
152
|
-
}
|
|
153
|
-
ngOnInit() {
|
|
154
|
-
this.listConfig = {
|
|
155
|
-
filters: [
|
|
156
|
-
{
|
|
157
|
-
name: 'keyword',
|
|
158
|
-
type: ItemType.Keyword,
|
|
159
|
-
label: 'Search',
|
|
160
|
-
},
|
|
161
|
-
{
|
|
162
|
-
name: 'optimized',
|
|
163
|
-
type: ItemType.Select,
|
|
164
|
-
label: 'Optimization',
|
|
165
|
-
values: [
|
|
166
|
-
{ name: 'Any', value: undefined },
|
|
167
|
-
{ name: 'Yes', value: 'true' },
|
|
168
|
-
{ name: 'No', value: 'false' },
|
|
169
|
-
],
|
|
170
|
-
},
|
|
171
|
-
{
|
|
172
|
-
name: 'createDate',
|
|
173
|
-
type: ItemType.DateTimeRange,
|
|
174
|
-
label: ['From Date', 'To Date'],
|
|
175
|
-
},
|
|
176
|
-
{
|
|
177
|
-
name: 'duration',
|
|
178
|
-
type: ItemType.Range,
|
|
179
|
-
label: ['Min Duration', 'Max Duration'],
|
|
180
|
-
},
|
|
181
|
-
],
|
|
182
|
-
actions: [
|
|
183
|
-
{
|
|
184
|
-
label: 'Purge',
|
|
185
|
-
primary: false,
|
|
186
|
-
click: () => {
|
|
187
|
-
this.purgeQueryLogs()
|
|
188
|
-
.subscribe(() => {
|
|
189
|
-
this.list.reload();
|
|
190
|
-
});
|
|
191
|
-
},
|
|
192
|
-
},
|
|
193
|
-
],
|
|
194
|
-
fetch: (query) => {
|
|
195
|
-
return this.loadQueryLogs(query)
|
|
196
|
-
.pipe(map((response) => ({ data: response.data, paging: response.paging })));
|
|
197
|
-
},
|
|
198
|
-
};
|
|
199
|
-
}
|
|
200
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: QueryLogsComponent, deps: [{ token: i1.MatDialog }], target: i0.ɵɵFactoryTarget.Component });
|
|
201
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.7", type: QueryLogsComponent, selector: "fs-system-query-logs", inputs: { loadQueryLogs: "loadQueryLogs", purgeQueryLogs: "purgeQueryLogs" }, viewQueries: [{ propertyName: "list", first: true, predicate: FsListComponent, descendants: true }], ngImport: i0, template: "<fs-list [config]=\"listConfig\">\n <fs-list-column title=\"Optimized\" name=\"optimized\" [sortable]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n <span [ngClass]=\"{ optimized: row.optimized, 'not-optimized': !row.optimized }\">\n {{row.optimized ? 'Yes' : 'No'}}\n </span>\n </ng-template>\n </fs-list-column>\n <fs-list-column title=\"Duration\" name=\"duration\" [sortable]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n {{row.duration}}\n </ng-template>\n </fs-list-column>\n <fs-list-column title=\"Cost\" name=\"query_cost\" [sortable]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n {{row.queryCost}}\n </ng-template>\n </fs-list-column>\n <fs-list-column title=\"Query\">\n <ng-template fs-list-cell let-row=\"row\">\n <a (click)=\"openQueryLog(row)\">{{ row.query | fsFormatTruncate: 500 }}</a>\n </ng-template>\n </fs-list-column>\n <fs-list-column title=\"Created\" name=\"query_log_id\" [sortable]=\"true\" [direction]=\"'desc'\" [sortableDefault]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n <fs-date-ago [date]=\"row.createDate\"></fs-date-ago>\n </ng-template>\n </fs-list-column>\n</fs-list>", styles: [":host ::ng-deep .optimized{color:green}:host ::ng-deep .not-optimized{color:red}\n"], dependencies: [{ kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: i3$1.FsDateAgoComponent, selector: "fs-date-ago", inputs: ["date", "showTime", "format", "showTooltip", "tooltipDateFormat"] }, { kind: "component", type: i4$1.FsListComponent, selector: "fs-list", inputs: ["config", "loaderLines"], outputs: ["filtersReady"] }, { kind: "directive", type: i4$1.FsListColumnDirective, selector: "fs-list-column", inputs: ["show", "title", "name", "customizable", "sortable", "sortableDefault", "sortableDirection", "direction", "align", "width", "class"] }, { kind: "directive", type: i4$1.FsListCellDirective, selector: "[fs-list-cell]", inputs: ["colspan", "align", "class"] }, { kind: "pipe", type: i10.FsFormatTruncatePipe, name: "fsFormatTruncate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
202
|
-
}
|
|
203
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: QueryLogsComponent, decorators: [{
|
|
204
|
-
type: Component,
|
|
205
|
-
args: [{ selector: 'fs-system-query-logs', changeDetection: ChangeDetectionStrategy.OnPush, template: "<fs-list [config]=\"listConfig\">\n <fs-list-column title=\"Optimized\" name=\"optimized\" [sortable]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n <span [ngClass]=\"{ optimized: row.optimized, 'not-optimized': !row.optimized }\">\n {{row.optimized ? 'Yes' : 'No'}}\n </span>\n </ng-template>\n </fs-list-column>\n <fs-list-column title=\"Duration\" name=\"duration\" [sortable]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n {{row.duration}}\n </ng-template>\n </fs-list-column>\n <fs-list-column title=\"Cost\" name=\"query_cost\" [sortable]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n {{row.queryCost}}\n </ng-template>\n </fs-list-column>\n <fs-list-column title=\"Query\">\n <ng-template fs-list-cell let-row=\"row\">\n <a (click)=\"openQueryLog(row)\">{{ row.query | fsFormatTruncate: 500 }}</a>\n </ng-template>\n </fs-list-column>\n <fs-list-column title=\"Created\" name=\"query_log_id\" [sortable]=\"true\" [direction]=\"'desc'\" [sortableDefault]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n <fs-date-ago [date]=\"row.createDate\"></fs-date-ago>\n </ng-template>\n </fs-list-column>\n</fs-list>", styles: [":host ::ng-deep .optimized{color:green}:host ::ng-deep .not-optimized{color:red}\n"] }]
|
|
206
|
-
}], ctorParameters: () => [{ type: i1.MatDialog }], propDecorators: { list: [{
|
|
207
|
-
type: ViewChild,
|
|
208
|
-
args: [FsListComponent]
|
|
209
|
-
}], loadQueryLogs: [{
|
|
210
|
-
type: Input
|
|
211
|
-
}], purgeQueryLogs: [{
|
|
212
|
-
type: Input
|
|
213
|
-
}] } });
|
|
214
|
-
|
|
215
|
-
class FsSystemQueryLogsModule {
|
|
216
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: FsSystemQueryLogsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
217
|
-
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.7", ngImport: i0, type: FsSystemQueryLogsModule, declarations: [QueryLogsComponent,
|
|
218
|
-
QueryLogComponent,
|
|
219
|
-
ExplainComponent], imports: [CommonModule,
|
|
220
|
-
RouterModule,
|
|
221
|
-
CommonModule,
|
|
222
|
-
FormsModule,
|
|
223
|
-
MatTabsModule,
|
|
224
|
-
MatButtonModule,
|
|
225
|
-
MatDialogModule,
|
|
226
|
-
FsFormModule,
|
|
227
|
-
FsLabelModule,
|
|
228
|
-
FsPopoverModule,
|
|
229
|
-
FsCommonModule,
|
|
230
|
-
FsDateModule,
|
|
231
|
-
FsDialogModule,
|
|
232
|
-
FsListModule,
|
|
233
|
-
FsClipboardModule], exports: [QueryLogsComponent] });
|
|
234
|
-
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: FsSystemQueryLogsModule, imports: [CommonModule,
|
|
235
|
-
RouterModule,
|
|
236
|
-
CommonModule,
|
|
237
|
-
FormsModule,
|
|
238
|
-
MatTabsModule,
|
|
239
|
-
MatButtonModule,
|
|
240
|
-
MatDialogModule,
|
|
241
|
-
FsFormModule,
|
|
242
|
-
FsLabelModule,
|
|
243
|
-
FsPopoverModule,
|
|
244
|
-
FsCommonModule,
|
|
245
|
-
FsDateModule,
|
|
246
|
-
FsDialogModule,
|
|
247
|
-
FsListModule,
|
|
248
|
-
FsClipboardModule] });
|
|
249
|
-
}
|
|
250
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: FsSystemQueryLogsModule, decorators: [{
|
|
251
|
-
type: NgModule,
|
|
252
|
-
args: [{
|
|
253
|
-
imports: [
|
|
254
|
-
CommonModule,
|
|
255
|
-
RouterModule,
|
|
256
|
-
CommonModule,
|
|
257
|
-
FormsModule,
|
|
258
|
-
MatTabsModule,
|
|
259
|
-
MatButtonModule,
|
|
260
|
-
MatDialogModule,
|
|
261
|
-
FsFormModule,
|
|
262
|
-
FsLabelModule,
|
|
263
|
-
FsPopoverModule,
|
|
264
|
-
FsCommonModule,
|
|
265
|
-
FsDateModule,
|
|
266
|
-
FsDialogModule,
|
|
267
|
-
FsListModule,
|
|
268
|
-
FsClipboardModule,
|
|
269
|
-
],
|
|
270
|
-
declarations: [
|
|
271
|
-
QueryLogsComponent,
|
|
272
|
-
QueryLogComponent,
|
|
273
|
-
ExplainComponent,
|
|
274
|
-
],
|
|
275
|
-
exports: [
|
|
276
|
-
QueryLogsComponent,
|
|
277
|
-
],
|
|
278
|
-
}]
|
|
279
|
-
}] });
|
|
52
|
+
import { FsBuildService } from '@firestitch/build';
|
|
53
|
+
import * as i6 from '@firestitch/common';
|
|
54
|
+
import { index, FsCommonModule } from '@firestitch/common';
|
|
55
|
+
import * as i3$4 from '@firestitch/clipboard';
|
|
56
|
+
import { FsClipboard, FsClipboardModule } from '@firestitch/clipboard';
|
|
57
|
+
import { MatOption } from '@angular/material/core';
|
|
58
|
+
import * as i2$5 from '@firestitch/form';
|
|
59
|
+
import { FsFormModule } from '@firestitch/form';
|
|
280
60
|
|
|
281
61
|
var CronState;
|
|
282
62
|
(function (CronState) {
|
|
@@ -411,40 +191,30 @@ function indexNameValue(arry) {
|
|
|
411
191
|
}
|
|
412
192
|
|
|
413
193
|
class ApiLogComponent {
|
|
414
|
-
_dialogRef;
|
|
415
|
-
data;
|
|
194
|
+
_dialogRef = inject(MatDialogRef);
|
|
195
|
+
data = inject(MAT_DIALOG_DATA);
|
|
416
196
|
apiLog;
|
|
417
197
|
apiLogStates;
|
|
418
|
-
constructor(_dialogRef, data) {
|
|
419
|
-
this._dialogRef = _dialogRef;
|
|
420
|
-
this.data = data;
|
|
421
|
-
}
|
|
422
198
|
ngOnInit() {
|
|
423
199
|
this.apiLogStates = indexNameValue(ApiLogStates);
|
|
424
200
|
if (this.data.apiLog) {
|
|
425
201
|
this.apiLog = this.data.apiLog;
|
|
426
202
|
}
|
|
427
203
|
}
|
|
428
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ApiLogComponent, deps: [
|
|
429
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "
|
|
204
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ApiLogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
205
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.7", type: ApiLogComponent, isStandalone: true, selector: "ng-component", ngImport: i0, template: "<fs-dialog *fsSkeleton=\"apiLog\">\n\n <div mat-dialog-title>API Log</div>\n\n <mat-dialog-content>\n <div class=\"fs-row.gap-lg.wrap.align-start\">\n <fs-label-field>\n <fs-label>\n Type\n </fs-label>\n {{apiLog.type}}\n </fs-label-field>\n\n <fs-label-field>\n <fs-label>\n Status\n </fs-label>\n {{apiLogStates[apiLog.state]}}\n </fs-label-field>\n\n @if (apiLog.code) {\n <fs-label-field>\n <fs-label>\n Code\n </fs-label>\n {{apiLog.code}}\n </fs-label-field>\n }\n\n <fs-label-field>\n <fs-label>\n Date\n </fs-label>\n {{apiLog.createDate|fsDateFormat: 'full-date-time'}}\n </fs-label-field>\n\n @if (apiLog.direction) {\n <fs-label-field>\n <fs-label>\n Direction\n </fs-label>\n {{apiLog.direction}}\n </fs-label-field>\n }\n\n @if (apiLog.length) {\n <fs-label-field>\n <fs-label>\n Duration\n </fs-label>\n {{ apiLog.length | fsDateDuration }}\n </fs-label-field>\n }\n\n @if (apiLog.method) {\n @if (apiLog.method) {\n <fs-label-field>\n <fs-label>\n Method\n </fs-label>\n {{apiLog.method}}\n </fs-label-field>\n }\n }\n\n @if (apiLog.url) {\n <fs-label-field>\n <fs-label>\n URL\n </fs-label>\n {{apiLog.url}}\n </fs-label-field>\n }\n </div>\n\n @if (apiLog.message) {\n <fs-label-field>\n <fs-label>\n Message\n </fs-label>\n {{apiLog.message}}\n </fs-label-field>\n }\n\n <div>\n @if (apiLog.request) {\n <fs-label-field>\n <fs-label>\n Request\n </fs-label>\n <pre>{{apiLog.request|json}}</pre>\n </fs-label-field>\n }\n\n @if (apiLog.response) {\n <fs-label-field>\n <fs-label>\n Response\n </fs-label>\n <pre>{{apiLog.response|json}}</pre>\n </fs-label-field>\n }\n\n @if (apiLog.headers) {\n <fs-label-field>\n <fs-label>\n Headers\n </fs-label>\n <pre>{{apiLog.headers|json}}</pre>\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 Done\n </button>\n </mat-dialog-actions>\n</fs-dialog>\n", styles: [""], 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: 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: "pipe", type: JsonPipe, name: "json" }, { kind: "ngmodule", type: FsDateModule }, { kind: "pipe", type: i4.FsDateDurationPipe, name: "fsDateDuration" }, { kind: "pipe", type: i4.FsDateFormatPipe, name: "fsDateFormat" }] });
|
|
430
206
|
}
|
|
431
207
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ApiLogComponent, decorators: [{
|
|
432
208
|
type: Component,
|
|
433
|
-
args: [{ template: "<fs-dialog *fsSkeleton=\"apiLog\">\n\n <div mat-dialog-title>API Log</div>\n\n <mat-dialog-content>\n <div class=\"fs-row.gap-lg.wrap.align-start\">\n <fs-label-field>\n <fs-label>\n Type\n </fs-label>\n {{apiLog.type}}\n </fs-label-field>\n\n <fs-label-field>\n <fs-label>\n Status\n </fs-label>\n {{apiLogStates[apiLog.state]}}\n </fs-label-field>\n\n <fs-label-field
|
|
434
|
-
}]
|
|
435
|
-
type: Inject,
|
|
436
|
-
args: [MAT_DIALOG_DATA]
|
|
437
|
-
}] }] });
|
|
209
|
+
args: [{ standalone: true, imports: [FsSkeletonModule, FsDialogModule, MatDialogTitle, CdkScrollable, MatDialogContent, FsLabelModule, MatDialogActions, MatButton, MatDialogClose, JsonPipe, FsDateModule], template: "<fs-dialog *fsSkeleton=\"apiLog\">\n\n <div mat-dialog-title>API Log</div>\n\n <mat-dialog-content>\n <div class=\"fs-row.gap-lg.wrap.align-start\">\n <fs-label-field>\n <fs-label>\n Type\n </fs-label>\n {{apiLog.type}}\n </fs-label-field>\n\n <fs-label-field>\n <fs-label>\n Status\n </fs-label>\n {{apiLogStates[apiLog.state]}}\n </fs-label-field>\n\n @if (apiLog.code) {\n <fs-label-field>\n <fs-label>\n Code\n </fs-label>\n {{apiLog.code}}\n </fs-label-field>\n }\n\n <fs-label-field>\n <fs-label>\n Date\n </fs-label>\n {{apiLog.createDate|fsDateFormat: 'full-date-time'}}\n </fs-label-field>\n\n @if (apiLog.direction) {\n <fs-label-field>\n <fs-label>\n Direction\n </fs-label>\n {{apiLog.direction}}\n </fs-label-field>\n }\n\n @if (apiLog.length) {\n <fs-label-field>\n <fs-label>\n Duration\n </fs-label>\n {{ apiLog.length | fsDateDuration }}\n </fs-label-field>\n }\n\n @if (apiLog.method) {\n @if (apiLog.method) {\n <fs-label-field>\n <fs-label>\n Method\n </fs-label>\n {{apiLog.method}}\n </fs-label-field>\n }\n }\n\n @if (apiLog.url) {\n <fs-label-field>\n <fs-label>\n URL\n </fs-label>\n {{apiLog.url}}\n </fs-label-field>\n }\n </div>\n\n @if (apiLog.message) {\n <fs-label-field>\n <fs-label>\n Message\n </fs-label>\n {{apiLog.message}}\n </fs-label-field>\n }\n\n <div>\n @if (apiLog.request) {\n <fs-label-field>\n <fs-label>\n Request\n </fs-label>\n <pre>{{apiLog.request|json}}</pre>\n </fs-label-field>\n }\n\n @if (apiLog.response) {\n <fs-label-field>\n <fs-label>\n Response\n </fs-label>\n <pre>{{apiLog.response|json}}</pre>\n </fs-label-field>\n }\n\n @if (apiLog.headers) {\n <fs-label-field>\n <fs-label>\n Headers\n </fs-label>\n <pre>{{apiLog.headers|json}}</pre>\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 Done\n </button>\n </mat-dialog-actions>\n</fs-dialog>\n" }]
|
|
210
|
+
}] });
|
|
438
211
|
|
|
439
212
|
class ApiLogsComponent {
|
|
440
|
-
_dialog;
|
|
213
|
+
_dialog = inject(MatDialog);
|
|
441
214
|
list;
|
|
442
215
|
loadApiLogs;
|
|
443
216
|
config = null;
|
|
444
217
|
apiLogStates = indexNameValue(ApiLogStates);
|
|
445
|
-
constructor(_dialog) {
|
|
446
|
-
this._dialog = _dialog;
|
|
447
|
-
}
|
|
448
218
|
ngOnInit() {
|
|
449
219
|
this._configList();
|
|
450
220
|
}
|
|
@@ -484,13 +254,18 @@ class ApiLogsComponent {
|
|
|
484
254
|
},
|
|
485
255
|
};
|
|
486
256
|
}
|
|
487
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ApiLogsComponent, deps: [
|
|
488
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "
|
|
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==200,'error': row.code!=200 }\">[{{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 });
|
|
489
259
|
}
|
|
490
260
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ApiLogsComponent, decorators: [{
|
|
491
261
|
type: Component,
|
|
492
|
-
args: [{ selector: 'fs-system-api-logs', changeDetection: ChangeDetectionStrategy.OnPush,
|
|
493
|
-
|
|
262
|
+
args: [{ selector: 'fs-system-api-logs', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [
|
|
263
|
+
FsListModule,
|
|
264
|
+
MatIcon,
|
|
265
|
+
NgClass,
|
|
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==200,'error': row.code!=200 }\">[{{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
|
+
}], propDecorators: { list: [{
|
|
494
269
|
type: ViewChild,
|
|
495
270
|
args: [FsListComponent, { static: true }]
|
|
496
271
|
}], loadApiLogs: [{
|
|
@@ -498,10 +273,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImpor
|
|
|
498
273
|
}] } });
|
|
499
274
|
|
|
500
275
|
class CronData {
|
|
501
|
-
_fsApi;
|
|
502
|
-
constructor(_fsApi) {
|
|
503
|
-
this._fsApi = _fsApi;
|
|
504
|
-
}
|
|
276
|
+
_fsApi = inject(FsApi);
|
|
505
277
|
create(data = { id: null }) {
|
|
506
278
|
return data;
|
|
507
279
|
}
|
|
@@ -535,7 +307,7 @@ class CronData {
|
|
|
535
307
|
processes,
|
|
536
308
|
}, { key: 'cron', ...config });
|
|
537
309
|
}
|
|
538
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: CronData, deps: [
|
|
310
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: CronData, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
539
311
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: CronData, providedIn: 'root' });
|
|
540
312
|
}
|
|
541
313
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: CronData, decorators: [{
|
|
@@ -543,16 +315,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImpor
|
|
|
543
315
|
args: [{
|
|
544
316
|
providedIn: 'root',
|
|
545
317
|
}]
|
|
546
|
-
}]
|
|
318
|
+
}] });
|
|
547
319
|
|
|
548
320
|
class CronLogComponent {
|
|
549
|
-
_data;
|
|
321
|
+
_data = inject(MAT_DIALOG_DATA);
|
|
550
322
|
cronLog;
|
|
551
323
|
CronLogStates = indexNameValue(CronLogStates);
|
|
552
324
|
CronLogStateColors = {};
|
|
553
|
-
constructor(_data) {
|
|
554
|
-
this._data = _data;
|
|
555
|
-
}
|
|
556
325
|
ngOnInit() {
|
|
557
326
|
this.cronLog = this._data.cronLog;
|
|
558
327
|
this.CronLogStateColors = CronLogStates
|
|
@@ -561,16 +330,25 @@ class CronLogComponent {
|
|
|
561
330
|
return accum;
|
|
562
331
|
}, {});
|
|
563
332
|
}
|
|
564
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: CronLogComponent, deps: [
|
|
565
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "
|
|
333
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: CronLogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
334
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.7", type: CronLogComponent, isStandalone: true, selector: "ng-component", ngImport: i0, template: "<fs-dialog *fsSkeleton=\"cronLog\">\n <div mat-dialog-title>\n Cron Log\n </div>\n <mat-dialog-content>\n <div class=\"row\">\n <fs-label-field>\n <fs-label>\n Status\n </fs-label>\n <div [ngStyle]=\"{ color: CronLogStateColors[cronLog.state]}\">\n {{ CronLogStates[cronLog.state] || cronLog.state }}\n </div>\n </fs-label-field>\n <fs-label-field>\n <fs-label>\n Date\n </fs-label>\n <fs-date-ago [date]=\"cronLog.createDate\"></fs-date-ago>\n </fs-label-field>\n </div>\n @if (cronLog.message) {\n <fs-label-field>\n <fs-label>\n Message\n </fs-label>\n <div class=\"message\">\n {{ cronLog.message }}\n </div>\n </fs-label-field>\n }\n </mat-dialog-content>\n <mat-dialog-actions>\n <button\n mat-button\n [mat-dialog-close]=\"true\"\n color=\"primary\">\n Done\n </button>\n </mat-dialog-actions>\n</fs-dialog>", styles: [".message{white-space:pre-line}.row{display:flex;flex-wrap:wrap}.row fs-label-field:not(:last-child){margin-right:40px}\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: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: FsDateModule }, { kind: "component", type: i4.FsDateAgoComponent, selector: "fs-date-ago", inputs: ["date", "showTime", "format", "showTooltip", "tooltipDateFormat"] }, { 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"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
566
335
|
}
|
|
567
336
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: CronLogComponent, decorators: [{
|
|
568
337
|
type: Component,
|
|
569
|
-
args: [{ changeDetection: ChangeDetectionStrategy.OnPush,
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
338
|
+
args: [{ changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [
|
|
339
|
+
FsSkeletonModule,
|
|
340
|
+
FsDialogModule,
|
|
341
|
+
MatDialogTitle,
|
|
342
|
+
CdkScrollable,
|
|
343
|
+
MatDialogContent,
|
|
344
|
+
FsLabelModule,
|
|
345
|
+
NgStyle,
|
|
346
|
+
FsDateModule,
|
|
347
|
+
MatDialogActions,
|
|
348
|
+
MatButton,
|
|
349
|
+
MatDialogClose,
|
|
350
|
+
], template: "<fs-dialog *fsSkeleton=\"cronLog\">\n <div mat-dialog-title>\n Cron Log\n </div>\n <mat-dialog-content>\n <div class=\"row\">\n <fs-label-field>\n <fs-label>\n Status\n </fs-label>\n <div [ngStyle]=\"{ color: CronLogStateColors[cronLog.state]}\">\n {{ CronLogStates[cronLog.state] || cronLog.state }}\n </div>\n </fs-label-field>\n <fs-label-field>\n <fs-label>\n Date\n </fs-label>\n <fs-date-ago [date]=\"cronLog.createDate\"></fs-date-ago>\n </fs-label-field>\n </div>\n @if (cronLog.message) {\n <fs-label-field>\n <fs-label>\n Message\n </fs-label>\n <div class=\"message\">\n {{ cronLog.message }}\n </div>\n </fs-label-field>\n }\n </mat-dialog-content>\n <mat-dialog-actions>\n <button\n mat-button\n [mat-dialog-close]=\"true\"\n color=\"primary\">\n Done\n </button>\n </mat-dialog-actions>\n</fs-dialog>", styles: [".message{white-space:pre-line}.row{display:flex;flex-wrap:wrap}.row fs-label-field:not(:last-child){margin-right:40px}\n"] }]
|
|
351
|
+
}] });
|
|
574
352
|
|
|
575
353
|
class CronLogsComponent {
|
|
576
354
|
cron;
|
|
@@ -634,7 +412,7 @@ class CronLogsComponent {
|
|
|
634
412
|
};
|
|
635
413
|
}
|
|
636
414
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: CronLogsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
637
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "
|
|
415
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.7", type: CronLogsComponent, isStandalone: true, selector: "app-cron-logs", inputs: { cron: "cron" }, ngImport: i0, template: "<fs-list [config]=\"config\">\n <fs-list-column\n name=\"state\"\n title=\"Status\">\n <ng-template\n fs-list-cell\n let-row=\"row\">\n <a\n (click)=\"cronLogOpen(row)\"\n [ngStyle]=\"{ color: CronLogStateColors[row.state] }\">\n {{ CronLogStates[row.state] || row.state }}\n </a>\n </ng-template>\n </fs-list-column>\n <fs-list-column\n title=\"Message\"\n class=\"col-message\">\n <ng-template\n fs-list-cell\n let-row=\"row\">\n <div class=\"message\">\n {{ row.message }}\n </div>\n </ng-template>\n </fs-list-column>\n <fs-list-column\n title=\"Duration\"\n class=\"col-message\">\n <ng-template\n fs-list-cell\n let-row=\"row\">\n @if (row.duration) {\n {{ row.duration | fsDateDuration: 'hour-minute-second' }}\n }\n </ng-template>\n </fs-list-column>\n <fs-list-column\n name=\"create_date\"\n title=\"Date\"\n class=\"col-date\">\n <ng-template\n fs-list-cell\n let-row=\"row\">\n <fs-date-ago [date]=\"row.createDate\"></fs-date-ago>\n </ng-template>\n </fs-list-column>\n</fs-list>", styles: [":host ::ng-deep .col-message .message{white-space:break-spaces;display:-webkit-box;-webkit-line-clamp:1;-webkit-box-orient:vertical;overflow:hidden}:host ::ng-deep .col-date{white-space:nowrap}h1 .small{line-height:normal}.row{display:flex;flex-wrap:wrap}.row fs-label-field:not(:last-child){margin-right:40px}.message{white-space:pre-line}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { 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: "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 });
|
|
638
416
|
}
|
|
639
417
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: CronLogsComponent, decorators: [{
|
|
640
418
|
type: Component,
|
|
@@ -642,7 +420,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImpor
|
|
|
642
420
|
CommonModule,
|
|
643
421
|
FsListModule,
|
|
644
422
|
FsDateModule,
|
|
645
|
-
], template: "<fs-list [config]=\"config\">\n <fs-list-column\n
|
|
423
|
+
], template: "<fs-list [config]=\"config\">\n <fs-list-column\n name=\"state\"\n title=\"Status\">\n <ng-template\n fs-list-cell\n let-row=\"row\">\n <a\n (click)=\"cronLogOpen(row)\"\n [ngStyle]=\"{ color: CronLogStateColors[row.state] }\">\n {{ CronLogStates[row.state] || row.state }}\n </a>\n </ng-template>\n </fs-list-column>\n <fs-list-column\n title=\"Message\"\n class=\"col-message\">\n <ng-template\n fs-list-cell\n let-row=\"row\">\n <div class=\"message\">\n {{ row.message }}\n </div>\n </ng-template>\n </fs-list-column>\n <fs-list-column\n title=\"Duration\"\n class=\"col-message\">\n <ng-template\n fs-list-cell\n let-row=\"row\">\n @if (row.duration) {\n {{ row.duration | fsDateDuration: 'hour-minute-second' }}\n }\n </ng-template>\n </fs-list-column>\n <fs-list-column\n name=\"create_date\"\n title=\"Date\"\n class=\"col-date\">\n <ng-template\n fs-list-cell\n let-row=\"row\">\n <fs-date-ago [date]=\"row.createDate\"></fs-date-ago>\n </ng-template>\n </fs-list-column>\n</fs-list>", styles: [":host ::ng-deep .col-message .message{white-space:break-spaces;display:-webkit-box;-webkit-line-clamp:1;-webkit-box-orient:vertical;overflow:hidden}:host ::ng-deep .col-date{white-space:nowrap}h1 .small{line-height:normal}.row{display:flex;flex-wrap:wrap}.row fs-label-field:not(:last-child){margin-right:40px}.message{white-space:pre-line}\n"] }]
|
|
646
424
|
}], propDecorators: { cron: [{
|
|
647
425
|
type: Input
|
|
648
426
|
}] } });
|
|
@@ -687,21 +465,33 @@ class CronComponent {
|
|
|
687
465
|
});
|
|
688
466
|
}
|
|
689
467
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: CronComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
690
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "
|
|
468
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.7", type: CronComponent, isStandalone: true, selector: "ng-component", ngImport: i0, template: "<fs-dialog *fsSkeleton=\"cron\">\n <h1 mat-dialog-title>\n Cron\n <div class=\"small\">\n {{ cron.name }}\n </div>\n </h1>\n <mat-dialog-content>\n <mat-tab-group (selectedIndexChange)=\"selectedIndexChange($event)\">\n <mat-tab label=\"Overview\">\n <div class=\"fs-row.gap-lg.wrap.align-start\">\n <fs-label-field>\n <fs-label>\n Status\n </fs-label>\n {{ CronStates[cron.state] }}\n </fs-label-field>\n @if (cron.cronSetting) {\n <fs-label-field>\n <fs-label>\n Run Frequency\n </fs-label>\n {{ cron.cronSetting.summary }}\n </fs-label-field>\n }\n <fs-label-field>\n <fs-label>\n Process ID\n </fs-label>\n {{ cron.processId || 'None' }}\n @if (cron.processId) {\n <div class=\"small\">\n {{ CronProcessStates[cron.processState] || 'Unknown' }}\n </div>\n }\n </fs-label-field>\n <fs-label-field>\n <fs-label>\n Last Ran\n </fs-label>\n @if (cron.duration===null) {\n Never\n } @else {\n <fs-date-ago [date]=\"cron.createDate\"></fs-date-ago>\n <div>\n @if (cron.duration) {\n <small>\n Duration: {{ cron.duration | fsDateDuration }}\n </small>\n }\n </div>\n }\n </fs-label-field>\n <fs-label-field>\n <fs-label>\n Timeout hours\n </fs-label>\n {{ cron.cronSetting?.timeout || 'N/A' }}\n </fs-label-field>\n </div>\n @if (cron.message) {\n <fs-label-field>\n <fs-label>\n Last Message\n </fs-label>\n <div class=\"message\">\n {{ cron.message }}\n </div>\n </fs-label-field>\n }\n </mat-tab>\n <mat-tab label=\"Logs\">\n <ng-template matTabContent>\n <app-cron-logs [cron]=\"cron\"></app-cron-logs>\n </ng-template>\n </mat-tab>\n </mat-tab-group>\n </mat-dialog-content>\n <mat-dialog-actions>\n <button\n mat-button\n [mat-dialog-close]=\"true\"\n color=\"primary\">\n Done\n </button>\n @if (tabIndex === 0) {\n @for (cronAction of cronActions; track cronAction) {\n <button\n mat-button\n (click)=\"cronActionClick(cronAction)\">\n {{ cronAction.label }}\n </button>\n }\n }\n </mat-dialog-actions>\n</fs-dialog>", styles: [":host ::ng-deep .col-message .message{white-space:break-spaces;display:-webkit-box;-webkit-line-clamp:1;-webkit-box-orient:vertical;overflow:hidden}:host ::ng-deep .col-date{white-space:nowrap}h1 .small{line-height:normal}.row{display:flex;flex-wrap:wrap}.row fs-label-field:not(:last-child){margin-right:40px}.message{white-space:pre-line}\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: "component", type: MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "component", type: MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass"], exportAs: ["matTab"] }, { 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: "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"] }, { kind: "directive", type: MatTabContent, selector: "[matTabContent]" }, { kind: "component", type: CronLogsComponent, selector: "app-cron-logs", inputs: ["cron"] }, { 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"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
691
469
|
}
|
|
692
470
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: CronComponent, decorators: [{
|
|
693
471
|
type: Component,
|
|
694
|
-
args: [{ changeDetection: ChangeDetectionStrategy.OnPush,
|
|
472
|
+
args: [{ changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [
|
|
473
|
+
FsSkeletonModule,
|
|
474
|
+
FsDialogModule,
|
|
475
|
+
MatDialogTitle,
|
|
476
|
+
CdkScrollable,
|
|
477
|
+
MatDialogContent,
|
|
478
|
+
MatTabGroup,
|
|
479
|
+
MatTab,
|
|
480
|
+
FsLabelModule,
|
|
481
|
+
FsDateModule,
|
|
482
|
+
MatTabContent,
|
|
483
|
+
CronLogsComponent,
|
|
484
|
+
MatDialogActions,
|
|
485
|
+
MatButton,
|
|
486
|
+
MatDialogClose,
|
|
487
|
+
], template: "<fs-dialog *fsSkeleton=\"cron\">\n <h1 mat-dialog-title>\n Cron\n <div class=\"small\">\n {{ cron.name }}\n </div>\n </h1>\n <mat-dialog-content>\n <mat-tab-group (selectedIndexChange)=\"selectedIndexChange($event)\">\n <mat-tab label=\"Overview\">\n <div class=\"fs-row.gap-lg.wrap.align-start\">\n <fs-label-field>\n <fs-label>\n Status\n </fs-label>\n {{ CronStates[cron.state] }}\n </fs-label-field>\n @if (cron.cronSetting) {\n <fs-label-field>\n <fs-label>\n Run Frequency\n </fs-label>\n {{ cron.cronSetting.summary }}\n </fs-label-field>\n }\n <fs-label-field>\n <fs-label>\n Process ID\n </fs-label>\n {{ cron.processId || 'None' }}\n @if (cron.processId) {\n <div class=\"small\">\n {{ CronProcessStates[cron.processState] || 'Unknown' }}\n </div>\n }\n </fs-label-field>\n <fs-label-field>\n <fs-label>\n Last Ran\n </fs-label>\n @if (cron.duration===null) {\n Never\n } @else {\n <fs-date-ago [date]=\"cron.createDate\"></fs-date-ago>\n <div>\n @if (cron.duration) {\n <small>\n Duration: {{ cron.duration | fsDateDuration }}\n </small>\n }\n </div>\n }\n </fs-label-field>\n <fs-label-field>\n <fs-label>\n Timeout hours\n </fs-label>\n {{ cron.cronSetting?.timeout || 'N/A' }}\n </fs-label-field>\n </div>\n @if (cron.message) {\n <fs-label-field>\n <fs-label>\n Last Message\n </fs-label>\n <div class=\"message\">\n {{ cron.message }}\n </div>\n </fs-label-field>\n }\n </mat-tab>\n <mat-tab label=\"Logs\">\n <ng-template matTabContent>\n <app-cron-logs [cron]=\"cron\"></app-cron-logs>\n </ng-template>\n </mat-tab>\n </mat-tab-group>\n </mat-dialog-content>\n <mat-dialog-actions>\n <button\n mat-button\n [mat-dialog-close]=\"true\"\n color=\"primary\">\n Done\n </button>\n @if (tabIndex === 0) {\n @for (cronAction of cronActions; track cronAction) {\n <button\n mat-button\n (click)=\"cronActionClick(cronAction)\">\n {{ cronAction.label }}\n </button>\n }\n }\n </mat-dialog-actions>\n</fs-dialog>", styles: [":host ::ng-deep .col-message .message{white-space:break-spaces;display:-webkit-box;-webkit-line-clamp:1;-webkit-box-orient:vertical;overflow:hidden}:host ::ng-deep .col-date{white-space:nowrap}h1 .small{line-height:normal}.row{display:flex;flex-wrap:wrap}.row fs-label-field:not(:last-child){margin-right:40px}.message{white-space:pre-line}\n"] }]
|
|
695
488
|
}] });
|
|
696
489
|
|
|
697
490
|
class CronNextRunComponent {
|
|
698
|
-
_cdRef;
|
|
491
|
+
_cdRef = inject(ChangeDetectorRef);
|
|
699
492
|
cron;
|
|
700
493
|
duration;
|
|
701
494
|
_destroy$ = new Subject();
|
|
702
|
-
constructor(_cdRef) {
|
|
703
|
-
this._cdRef = _cdRef;
|
|
704
|
-
}
|
|
705
495
|
ngOnInit() {
|
|
706
496
|
this.update();
|
|
707
497
|
}
|
|
@@ -718,10 +508,10 @@ class CronNextRunComponent {
|
|
|
718
508
|
next = addHours(next, nextHours);
|
|
719
509
|
next = addDays(next, nextDays);
|
|
720
510
|
next = subSeconds(next, next.getSeconds());
|
|
721
|
-
this.duration = differenceInSeconds(next, now);
|
|
511
|
+
this.duration = Math.max(0, differenceInSeconds(next, now));
|
|
722
512
|
}
|
|
723
513
|
else {
|
|
724
|
-
this.duration = 60 - now.getSeconds();
|
|
514
|
+
this.duration = Math.max(0, 60 - now.getSeconds());
|
|
725
515
|
}
|
|
726
516
|
}
|
|
727
517
|
update() {
|
|
@@ -751,7 +541,7 @@ class CronNextRunComponent {
|
|
|
751
541
|
return (minutes[i + 1] ? minutes[i + 1] - now.getUTCMinutes() : (60 - now.getUTCMinutes() + minutes[i]));
|
|
752
542
|
}
|
|
753
543
|
}
|
|
754
|
-
return minutes[0] - now.
|
|
544
|
+
return minutes[0] - now.getUTCMinutes();
|
|
755
545
|
}
|
|
756
546
|
return 0;
|
|
757
547
|
}
|
|
@@ -775,17 +565,17 @@ class CronNextRunComponent {
|
|
|
775
565
|
return (days[i + 1] ? days[i + 1] : getDaysInMonth(now)) - now.getDate();
|
|
776
566
|
}
|
|
777
567
|
}
|
|
778
|
-
return days[0] -
|
|
568
|
+
return days[0] - now.getDate();
|
|
779
569
|
}
|
|
780
570
|
return 0;
|
|
781
571
|
}
|
|
782
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: CronNextRunComponent, deps: [
|
|
783
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "
|
|
572
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: CronNextRunComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
573
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.7", type: CronNextRunComponent, isStandalone: true, selector: "app-next-run", inputs: { cron: "cron" }, ngImport: i0, template: "@if (duration > 60) {\n {{ duration | fsDateDuration: { hours: true, seconds: true, minutes: true, days: true, maxOutputs: 2 } }}\n} @else {\n {{ duration }}s\n}\n<ng-template #seconds>\n {{ duration }}s\n</ng-template>", styles: [""], dependencies: [{ kind: "ngmodule", type: FsDateModule }, { kind: "pipe", type: i4.FsDateDurationPipe, name: "fsDateDuration" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
784
574
|
}
|
|
785
575
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: CronNextRunComponent, decorators: [{
|
|
786
576
|
type: Component,
|
|
787
|
-
args: [{ selector: 'app-next-run', changeDetection: ChangeDetectionStrategy.OnPush, template: "
|
|
788
|
-
}],
|
|
577
|
+
args: [{ selector: 'app-next-run', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [FsDateModule], template: "@if (duration > 60) {\n {{ duration | fsDateDuration: { hours: true, seconds: true, minutes: true, days: true, maxOutputs: 2 } }}\n} @else {\n {{ duration }}s\n}\n<ng-template #seconds>\n {{ duration }}s\n</ng-template>" }]
|
|
578
|
+
}], propDecorators: { cron: [{
|
|
789
579
|
type: Input
|
|
790
580
|
}] } });
|
|
791
581
|
|
|
@@ -1035,20 +825,26 @@ class CronsComponent {
|
|
|
1035
825
|
}
|
|
1036
826
|
}
|
|
1037
827
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: CronsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1038
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "
|
|
828
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.7", type: CronsComponent, isStandalone: true, selector: "fs-system-crons", 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>\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 <small>\n {{ row.cronSetting?.description }}\n </small>\n </ng-template>\n </fs-list-column>\n <fs-list-column align=\"center\">\n <ng-template fs-list-header>\n Status\n </ng-template>\n <ng-template\n fs-list-cell\n let-row=\"row\">\n @if (row.host || row.processId) {\n <fs-popover\n [maxWidth]=\"null\"\n [template]=\"statusPopover\"\n [indication]=\"true\"\n size=\"small\">\n <ng-container *ngTemplateOutlet=\"status\"></ng-container>\n </fs-popover>\n <ng-template #statusPopover>\n @if (row.host) {\n <div>\n Host: {{ row.host }}\n </div>\n }\n @if (row.processId) {\n <div>\n Process ID: {{ row.processId }}\n </div>\n }\n @if (row.processState) {\n <div>\n Process State: {{ CronProcessStates[row.processState] }}\n </div>\n }\n </ng-template>\n } @else {\n {{ CronStates[row.state] }}\n }\n <ng-template #status>\n {{ CronStates[row.state] }}\n </ng-template>\n @if (row.state === CronState.Running) {\n <div class=\"small\">\n Duration: {{ row.runningDuration | fsDateDuration: { hours: true, minutes: true, seconds: true } }}\n </div>\n }\n </ng-template>\n </fs-list-column>\n <fs-list-column>\n <ng-template fs-list-header>\n Frequency\n </ng-template>\n <ng-template\n fs-list-cell\n let-row=\"row\">\n {{ row.cronSetting?.summary }}\n </ng-template>\n </fs-list-column>\n <fs-list-column>\n <ng-template fs-list-header>\n Last Ran\n </ng-template>\n <ng-template\n fs-list-cell\n let-row=\"row\">\n @if (row.duration===null) {\n Never\n } @else {\n <fs-date-ago [date]=\"row.createDate\"></fs-date-ago>\n @if (row.duration) {\n <div\n class=\"small\"\n >\n Duration: {{ row.duration | fsDateDuration: { hours: true, minutes: true, seconds: true } }}\n </div>\n }\n }\n </ng-template>\n </fs-list-column>\n <fs-list-column>\n <ng-template fs-list-header>\n Next Run\n </ng-template>\n <ng-template\n fs-list-cell\n let-row=\"row\">\n @if (row.state !== CronState.Disabled) {\n <app-next-run [cron]=\"row\"></app-next-run>\n }\n </ng-template>\n </fs-list-column>\n <fs-list-column>\n <ng-template fs-list-header>\n Timeout\n </ng-template>\n <ng-template\n fs-list-cell\n let-row=\"row\">\n {{ row.cronSetting.timeout }}h\n </ng-template>\n </fs-list-column>\n</fs-list>", styles: [""], 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: "ngmodule", type: FsPopoverModule }, { kind: "component", type: i2$1.FsPopoverComponent, selector: "fs-popover" }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { 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"] }, { kind: "component", type: CronNextRunComponent, selector: "app-next-run", inputs: ["cron"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1039
829
|
}
|
|
1040
830
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: CronsComponent, decorators: [{
|
|
1041
831
|
type: Component,
|
|
1042
|
-
args: [{ selector: 'fs-system-crons', changeDetection: ChangeDetectionStrategy.OnPush,
|
|
832
|
+
args: [{ selector: 'fs-system-crons', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [
|
|
833
|
+
FsListModule,
|
|
834
|
+
FsPopoverModule,
|
|
835
|
+
NgTemplateOutlet,
|
|
836
|
+
FsDateModule,
|
|
837
|
+
CronNextRunComponent,
|
|
838
|
+
], 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 <small>\n {{ row.cronSetting?.description }}\n </small>\n </ng-template>\n </fs-list-column>\n <fs-list-column align=\"center\">\n <ng-template fs-list-header>\n Status\n </ng-template>\n <ng-template\n fs-list-cell\n let-row=\"row\">\n @if (row.host || row.processId) {\n <fs-popover\n [maxWidth]=\"null\"\n [template]=\"statusPopover\"\n [indication]=\"true\"\n size=\"small\">\n <ng-container *ngTemplateOutlet=\"status\"></ng-container>\n </fs-popover>\n <ng-template #statusPopover>\n @if (row.host) {\n <div>\n Host: {{ row.host }}\n </div>\n }\n @if (row.processId) {\n <div>\n Process ID: {{ row.processId }}\n </div>\n }\n @if (row.processState) {\n <div>\n Process State: {{ CronProcessStates[row.processState] }}\n </div>\n }\n </ng-template>\n } @else {\n {{ CronStates[row.state] }}\n }\n <ng-template #status>\n {{ CronStates[row.state] }}\n </ng-template>\n @if (row.state === CronState.Running) {\n <div class=\"small\">\n Duration: {{ row.runningDuration | fsDateDuration: { hours: true, minutes: true, seconds: true } }}\n </div>\n }\n </ng-template>\n </fs-list-column>\n <fs-list-column>\n <ng-template fs-list-header>\n Frequency\n </ng-template>\n <ng-template\n fs-list-cell\n let-row=\"row\">\n {{ row.cronSetting?.summary }}\n </ng-template>\n </fs-list-column>\n <fs-list-column>\n <ng-template fs-list-header>\n Last Ran\n </ng-template>\n <ng-template\n fs-list-cell\n let-row=\"row\">\n @if (row.duration===null) {\n Never\n } @else {\n <fs-date-ago [date]=\"row.createDate\"></fs-date-ago>\n @if (row.duration) {\n <div\n class=\"small\"\n >\n Duration: {{ row.duration | fsDateDuration: { hours: true, minutes: true, seconds: true } }}\n </div>\n }\n }\n </ng-template>\n </fs-list-column>\n <fs-list-column>\n <ng-template fs-list-header>\n Next Run\n </ng-template>\n <ng-template\n fs-list-cell\n let-row=\"row\">\n @if (row.state !== CronState.Disabled) {\n <app-next-run [cron]=\"row\"></app-next-run>\n }\n </ng-template>\n </fs-list-column>\n <fs-list-column>\n <ng-template fs-list-header>\n Timeout\n </ng-template>\n <ng-template\n fs-list-cell\n let-row=\"row\">\n {{ row.cronSetting.timeout }}h\n </ng-template>\n </fs-list-column>\n</fs-list>" }]
|
|
1043
839
|
}], propDecorators: { list: [{
|
|
1044
840
|
type: ViewChild,
|
|
1045
841
|
args: [FsListComponent, { static: true }]
|
|
1046
842
|
}] } });
|
|
1047
843
|
|
|
1048
844
|
class DashboardComponent {
|
|
1049
|
-
_message;
|
|
1050
|
-
_cdRef;
|
|
1051
|
-
_buildService;
|
|
845
|
+
_message = inject(FsMessage);
|
|
846
|
+
_cdRef = inject(ChangeDetectorRef);
|
|
847
|
+
_buildService = inject(FsBuildService);
|
|
1052
848
|
init;
|
|
1053
849
|
upgrade;
|
|
1054
850
|
load;
|
|
@@ -1058,11 +854,6 @@ class DashboardComponent {
|
|
|
1058
854
|
build;
|
|
1059
855
|
menuActions = [];
|
|
1060
856
|
_destroy$ = new Subject();
|
|
1061
|
-
constructor(_message, _cdRef, _buildService) {
|
|
1062
|
-
this._message = _message;
|
|
1063
|
-
this._cdRef = _cdRef;
|
|
1064
|
-
this._buildService = _buildService;
|
|
1065
|
-
}
|
|
1066
857
|
ngOnInit() {
|
|
1067
858
|
this._load();
|
|
1068
859
|
this.buttonActions = this.actions.filter((item) => {
|
|
@@ -1108,13 +899,22 @@ class DashboardComponent {
|
|
|
1108
899
|
this._cdRef.markForCheck();
|
|
1109
900
|
});
|
|
1110
901
|
}
|
|
1111
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: DashboardComponent, deps: [
|
|
1112
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "
|
|
902
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: DashboardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
903
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.7", type: DashboardComponent, isStandalone: true, selector: "fs-system-dashboard", inputs: { init: "init", upgrade: "upgrade", load: "load", actions: "actions" }, ngImport: i0, template: "<div *fsSkeleton=\"dashboard\">\n <div class=\"fs-row.gap-lg.wrap.align-start\">\n <div>\n <h2>\n Server\n </h2>\n <fs-label-field>\n <fs-label>\n Date/Time\n </fs-label>\n {{ dashboard.serverTime | fsDateFormat: 'date-time' }}\n </fs-label-field>\n <fs-label-field>\n <fs-label>\n Timezone\n </fs-label>\n {{ dashboard.serverTimezone }}\n </fs-label-field>\n <fs-label-field>\n <fs-label>\n Hostname\n </fs-label>\n {{ dashboard.serverHostname }}\n </fs-label-field>\n <fs-label-field>\n <fs-label>\n Directory\n </fs-label>\n {{ dashboard.appDirectory }}\n </fs-label-field>\n </div>\n <div>\n <h2>\n System\n </h2>\n <fs-label-field>\n <fs-label>\n Mode\n </fs-label>\n {{ dashboard.appMode }}\n </fs-label-field>\n <fs-label-field>\n <fs-label>\n Notification Recipients\n </fs-label>\n {{ dashboard.notifyRecipients.join(', ') }}\n </fs-label-field>\n </div>\n <div>\n <h2>\n Database\n </h2>\n <fs-label-field>\n <fs-label>\n Name\n </fs-label>\n {{ dashboard.databaseName }}\n </fs-label-field>\n <fs-label-field>\n <fs-label>\n Date/Time\n </fs-label>\n {{ dashboard.databaseTime | fsDateFormat: 'date-time' }}\n </fs-label-field>\n <fs-label-field>\n <fs-label>\n Timezone\n </fs-label>\n {{ dashboard.databaseTimezone }}\n </fs-label-field>\n </div>\n @if (build || dashboard.upgrades.length) {\n <div>\n @if (build) {\n <h2>\n Build\n </h2>\n <fs-label-field>\n <fs-label>\n Version\n </fs-label>\n {{ build.version || 'Unknown' }}\n </fs-label-field>\n <fs-label-field>\n <fs-label>\n Date\n </fs-label>\n {{ (build.date | fsDateFormat: 'date-time') || 'Unknown' }}\n </fs-label-field>\n }\n @if (dashboard.upgrades.length) {\n <fs-label-field>\n <fs-label>\n Pending Upgrades\n </fs-label>\n <span\n class=\"attention\"\n [ngClass]=\"{ 'needs-attention': !!dashboard.upgrades.length }\">\n {{ dashboard.upgrades.length }}\n <mat-icon\n [matTooltip]=\"dashboard.upgrades.join('\\n')\"\n matTooltipClass=\"tooltip-pending-upgrades\">\n warning\n </mat-icon>\n </span>\n </fs-label-field>\n }\n </div>\n }\n <div>\n <h2>\n Cron\n </h2>\n <fs-label-field>\n <fs-label>\n Last Ran\n </fs-label>\n <span\n class=\"attention\"\n [ngClass]=\"{ 'needs-attention': dashboard.cronRanAttention }\">\n @if (!dashboard.cronRan) {\n <span>\n Never\n </span>\n }\n @if (dashboard.cronRan) {\n <span>\n {{ dashboard.cronRan | fsDateFormat: 'date-time' }}\n </span>\n }\n <mat-icon>\n warning\n </mat-icon>\n </span>\n </fs-label-field>\n </div>\n </div>\n <div>\n <div class=\"actions\">\n <button\n mat-stroked-button\n (click)=\"upgradeClick()\">\n Run Upgrades\n </button>\n <button\n mat-stroked-button\n (click)=\"initClick()\">\n Init System\n </button>\n @for (action of buttonActions; track action) {\n <button\n mat-stroked-button\n (click)=\"actionClick(action)\">\n {{ action.label }}\n </button>\n }\n @if (menuActions.length) {\n <fs-menu buttonClass=\"mat-stroked-button menu-button\">\n @for (action of menuActions; track action) {\n <ng-template\n fs-menu-item\n (click)=\"actionClick(action)\">\n {{ action.label }}\n </ng-template>\n }\n </fs-menu>\n }\n </div>\n </div>\n</div>", styles: [":host ::ng-deep .menu-button{box-shadow:none}h2{margin-top:0}.actions{display:flex;align-items:center;flex-wrap:wrap}.actions button,.actions fs-menu{margin-bottom:10px;margin-right:5px}table td{padding:3px}.attention{display:flex;align-items:center}.attention mat-icon{display:none;margin-left:2px}.attention.needs-attention{color:#c00}.attention.needs-attention mat-icon{display:inline}::ng-deep .tooltip-pending-upgrades{white-space:pre-line}@media (max-width: 1000px){:host ::ng-deep .menu-button{width:100%;border-radius:4px}}\n"], dependencies: [{ kind: "ngmodule", type: FsSkeletonModule }, { kind: "directive", type: i1.FsSkeletonContentDirective, selector: "[fsSkeleton]", inputs: ["fsSkeleton", "fsSkeletonPattern"] }, { 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: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "ngmodule", type: FsMenuModule }, { kind: "component", type: i3$1.FsMenuComponent, selector: "fs-menu", inputs: ["class", "buttonClass", "buttonType", "buttonColor"], outputs: ["opened", "closed"] }, { kind: "directive", type: i3$1.FsMenuItemDirective, selector: "fs-menu-group,[fs-menu-item]" }, { kind: "ngmodule", type: FsDateModule }, { kind: "pipe", type: i4.FsDateFormatPipe, name: "fsDateFormat" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1113
904
|
}
|
|
1114
905
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: DashboardComponent, decorators: [{
|
|
1115
906
|
type: Component,
|
|
1116
|
-
args: [{ selector: 'fs-system-dashboard', changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1117
|
-
|
|
907
|
+
args: [{ selector: 'fs-system-dashboard', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [
|
|
908
|
+
FsSkeletonModule,
|
|
909
|
+
FsLabelModule,
|
|
910
|
+
NgClass,
|
|
911
|
+
MatIcon,
|
|
912
|
+
MatTooltip,
|
|
913
|
+
MatButton,
|
|
914
|
+
FsMenuModule,
|
|
915
|
+
FsDateModule,
|
|
916
|
+
], template: "<div *fsSkeleton=\"dashboard\">\n <div class=\"fs-row.gap-lg.wrap.align-start\">\n <div>\n <h2>\n Server\n </h2>\n <fs-label-field>\n <fs-label>\n Date/Time\n </fs-label>\n {{ dashboard.serverTime | fsDateFormat: 'date-time' }}\n </fs-label-field>\n <fs-label-field>\n <fs-label>\n Timezone\n </fs-label>\n {{ dashboard.serverTimezone }}\n </fs-label-field>\n <fs-label-field>\n <fs-label>\n Hostname\n </fs-label>\n {{ dashboard.serverHostname }}\n </fs-label-field>\n <fs-label-field>\n <fs-label>\n Directory\n </fs-label>\n {{ dashboard.appDirectory }}\n </fs-label-field>\n </div>\n <div>\n <h2>\n System\n </h2>\n <fs-label-field>\n <fs-label>\n Mode\n </fs-label>\n {{ dashboard.appMode }}\n </fs-label-field>\n <fs-label-field>\n <fs-label>\n Notification Recipients\n </fs-label>\n {{ dashboard.notifyRecipients.join(', ') }}\n </fs-label-field>\n </div>\n <div>\n <h2>\n Database\n </h2>\n <fs-label-field>\n <fs-label>\n Name\n </fs-label>\n {{ dashboard.databaseName }}\n </fs-label-field>\n <fs-label-field>\n <fs-label>\n Date/Time\n </fs-label>\n {{ dashboard.databaseTime | fsDateFormat: 'date-time' }}\n </fs-label-field>\n <fs-label-field>\n <fs-label>\n Timezone\n </fs-label>\n {{ dashboard.databaseTimezone }}\n </fs-label-field>\n </div>\n @if (build || dashboard.upgrades.length) {\n <div>\n @if (build) {\n <h2>\n Build\n </h2>\n <fs-label-field>\n <fs-label>\n Version\n </fs-label>\n {{ build.version || 'Unknown' }}\n </fs-label-field>\n <fs-label-field>\n <fs-label>\n Date\n </fs-label>\n {{ (build.date | fsDateFormat: 'date-time') || 'Unknown' }}\n </fs-label-field>\n }\n @if (dashboard.upgrades.length) {\n <fs-label-field>\n <fs-label>\n Pending Upgrades\n </fs-label>\n <span\n class=\"attention\"\n [ngClass]=\"{ 'needs-attention': !!dashboard.upgrades.length }\">\n {{ dashboard.upgrades.length }}\n <mat-icon\n [matTooltip]=\"dashboard.upgrades.join('\\n')\"\n matTooltipClass=\"tooltip-pending-upgrades\">\n warning\n </mat-icon>\n </span>\n </fs-label-field>\n }\n </div>\n }\n <div>\n <h2>\n Cron\n </h2>\n <fs-label-field>\n <fs-label>\n Last Ran\n </fs-label>\n <span\n class=\"attention\"\n [ngClass]=\"{ 'needs-attention': dashboard.cronRanAttention }\">\n @if (!dashboard.cronRan) {\n <span>\n Never\n </span>\n }\n @if (dashboard.cronRan) {\n <span>\n {{ dashboard.cronRan | fsDateFormat: 'date-time' }}\n </span>\n }\n <mat-icon>\n warning\n </mat-icon>\n </span>\n </fs-label-field>\n </div>\n </div>\n <div>\n <div class=\"actions\">\n <button\n mat-stroked-button\n (click)=\"upgradeClick()\">\n Run Upgrades\n </button>\n <button\n mat-stroked-button\n (click)=\"initClick()\">\n Init System\n </button>\n @for (action of buttonActions; track action) {\n <button\n mat-stroked-button\n (click)=\"actionClick(action)\">\n {{ action.label }}\n </button>\n }\n @if (menuActions.length) {\n <fs-menu buttonClass=\"mat-stroked-button menu-button\">\n @for (action of menuActions; track action) {\n <ng-template\n fs-menu-item\n (click)=\"actionClick(action)\">\n {{ action.label }}\n </ng-template>\n }\n </fs-menu>\n }\n </div>\n </div>\n</div>", styles: [":host ::ng-deep .menu-button{box-shadow:none}h2{margin-top:0}.actions{display:flex;align-items:center;flex-wrap:wrap}.actions button,.actions fs-menu{margin-bottom:10px;margin-right:5px}table td{padding:3px}.attention{display:flex;align-items:center}.attention mat-icon{display:none;margin-left:2px}.attention.needs-attention{color:#c00}.attention.needs-attention mat-icon{display:inline}::ng-deep .tooltip-pending-upgrades{white-space:pre-line}@media (max-width: 1000px){:host ::ng-deep .menu-button{width:100%;border-radius:4px}}\n"] }]
|
|
917
|
+
}], propDecorators: { init: [{
|
|
1118
918
|
type: Input
|
|
1119
919
|
}], upgrade: [{
|
|
1120
920
|
type: Input
|
|
@@ -1143,11 +943,11 @@ class InfoComponent {
|
|
|
1143
943
|
});
|
|
1144
944
|
}
|
|
1145
945
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: InfoComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1146
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.7", type: InfoComponent, selector: "fs-system-info", inputs: { load: "load" }, viewQueries: [{ propertyName: "iframe", first: true, predicate: ["iframe"], descendants: true }], ngImport: i0, template: "<iframe #iframe></iframe>\
|
|
946
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.7", type: InfoComponent, isStandalone: true, selector: "fs-system-info", inputs: { load: "load" }, viewQueries: [{ propertyName: "iframe", first: true, predicate: ["iframe"], descendants: true }], ngImport: i0, template: "<iframe #iframe></iframe>\n", styles: ["iframe{width:100%;border:0}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1147
947
|
}
|
|
1148
948
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: InfoComponent, decorators: [{
|
|
1149
949
|
type: Component,
|
|
1150
|
-
args: [{ selector: 'fs-system-info', changeDetection: ChangeDetectionStrategy.OnPush, template: "<iframe #iframe></iframe>\
|
|
950
|
+
args: [{ selector: 'fs-system-info', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, template: "<iframe #iframe></iframe>\n", styles: ["iframe{width:100%;border:0}\n"] }]
|
|
1151
951
|
}], propDecorators: { iframe: [{
|
|
1152
952
|
type: ViewChild,
|
|
1153
953
|
args: ['iframe']
|
|
@@ -1156,10 +956,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImpor
|
|
|
1156
956
|
}] } });
|
|
1157
957
|
|
|
1158
958
|
class ProcessData {
|
|
1159
|
-
_api;
|
|
1160
|
-
constructor(_api) {
|
|
1161
|
-
this._api = _api;
|
|
1162
|
-
}
|
|
959
|
+
_api = inject(FsApi);
|
|
1163
960
|
gets(data = {}, config = {}) {
|
|
1164
961
|
return this._api.get('processes', data, { key: 'processes', ...config });
|
|
1165
962
|
}
|
|
@@ -1186,7 +983,7 @@ class ProcessData {
|
|
|
1186
983
|
.createApiFile(`processes/${data.id}/download`)
|
|
1187
984
|
.download();
|
|
1188
985
|
}
|
|
1189
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ProcessData, deps: [
|
|
986
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ProcessData, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1190
987
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ProcessData, providedIn: 'root' });
|
|
1191
988
|
}
|
|
1192
989
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ProcessData, decorators: [{
|
|
@@ -1194,29 +991,21 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImpor
|
|
|
1194
991
|
args: [{
|
|
1195
992
|
providedIn: 'root',
|
|
1196
993
|
}]
|
|
1197
|
-
}]
|
|
994
|
+
}] });
|
|
1198
995
|
|
|
1199
996
|
class ProcessComponent {
|
|
1200
|
-
data;
|
|
1201
|
-
_message;
|
|
1202
|
-
_cdRef;
|
|
1203
|
-
_prompt;
|
|
1204
|
-
_process;
|
|
1205
|
-
_api;
|
|
997
|
+
data = inject(MAT_DIALOG_DATA);
|
|
998
|
+
_message = inject(FsMessage);
|
|
999
|
+
_cdRef = inject(ChangeDetectorRef);
|
|
1000
|
+
_prompt = inject(FsPrompt);
|
|
1001
|
+
_process = inject(FsProcess);
|
|
1002
|
+
_api = inject(FsApi);
|
|
1206
1003
|
process;
|
|
1207
1004
|
ProcessStates = indexNameValue(ProcessStates);
|
|
1208
1005
|
ProcessProcessStates = indexNameValue(ProcessProcessStates);
|
|
1209
1006
|
ProcessState = ProcessState;
|
|
1210
1007
|
_destroy$ = new Subject();
|
|
1211
1008
|
_processData = inject(ProcessData);
|
|
1212
|
-
constructor(data, _message, _cdRef, _prompt, _process, _api) {
|
|
1213
|
-
this.data = data;
|
|
1214
|
-
this._message = _message;
|
|
1215
|
-
this._cdRef = _cdRef;
|
|
1216
|
-
this._prompt = _prompt;
|
|
1217
|
-
this._process = _process;
|
|
1218
|
-
this._api = _api;
|
|
1219
|
-
}
|
|
1220
1009
|
ngOnInit() {
|
|
1221
1010
|
this.load$()
|
|
1222
1011
|
.subscribe(() => {
|
|
@@ -1271,22 +1060,32 @@ class ProcessComponent {
|
|
|
1271
1060
|
this._destroy$.next(null);
|
|
1272
1061
|
this._destroy$.complete();
|
|
1273
1062
|
}
|
|
1274
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ProcessComponent, deps: [
|
|
1275
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "
|
|
1063
|
+
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 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 @if (process.notify) {\n <fs-label-field>\n <fs-label>\n Notification Email\n </fs-label>\n {{ process.notify }}\n </fs-label-field>\n }\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 @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 ((\n process.state !== ProcessState.Running &&\n process.state !== ProcessState.Queued\n )) {\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%}.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 });
|
|
1276
1065
|
}
|
|
1277
1066
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ProcessComponent, decorators: [{
|
|
1278
1067
|
type: Component,
|
|
1279
|
-
args: [{ changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1068
|
+
args: [{ changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [
|
|
1069
|
+
FsSkeletonModule,
|
|
1070
|
+
FsDialogModule,
|
|
1071
|
+
MatDialogTitle,
|
|
1072
|
+
CdkScrollable,
|
|
1073
|
+
MatDialogContent,
|
|
1074
|
+
FsLabelModule,
|
|
1075
|
+
NgClass,
|
|
1076
|
+
MatProgressSpinner,
|
|
1077
|
+
MatDialogActions,
|
|
1078
|
+
MatButton,
|
|
1079
|
+
MatDialogClose,
|
|
1080
|
+
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 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 @if (process.notify) {\n <fs-label-field>\n <fs-label>\n Notification Email\n </fs-label>\n {{ process.notify }}\n </fs-label-field>\n }\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 @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 ((\n process.state !== ProcessState.Running &&\n process.state !== ProcessState.Queued\n )) {\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%}.status{display:flex}.status.running{margin-right:28px}.status.running mat-progress-spinner{position:absolute;right:0}\n"] }]
|
|
1082
|
+
}] });
|
|
1284
1083
|
|
|
1285
1084
|
class ProcessesComponent {
|
|
1286
|
-
_dialog;
|
|
1287
|
-
_message;
|
|
1288
|
-
_process;
|
|
1289
|
-
_api;
|
|
1085
|
+
_dialog = inject(MatDialog);
|
|
1086
|
+
_message = inject(FsMessage);
|
|
1087
|
+
_process = inject(FsProcess);
|
|
1088
|
+
_api = inject(FsApi);
|
|
1290
1089
|
list;
|
|
1291
1090
|
actions = [];
|
|
1292
1091
|
config = null;
|
|
@@ -1294,12 +1093,6 @@ class ProcessesComponent {
|
|
|
1294
1093
|
ProcessState = ProcessState;
|
|
1295
1094
|
_destroy$ = new Subject();
|
|
1296
1095
|
_processData = inject(ProcessData);
|
|
1297
|
-
constructor(_dialog, _message, _process, _api) {
|
|
1298
|
-
this._dialog = _dialog;
|
|
1299
|
-
this._message = _message;
|
|
1300
|
-
this._process = _process;
|
|
1301
|
-
this._api = _api;
|
|
1302
|
-
}
|
|
1303
1096
|
ngOnInit() {
|
|
1304
1097
|
this._configList();
|
|
1305
1098
|
}
|
|
@@ -1438,13 +1231,13 @@ class ProcessesComponent {
|
|
|
1438
1231
|
});
|
|
1439
1232
|
});
|
|
1440
1233
|
}
|
|
1441
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ProcessesComponent, deps: [
|
|
1442
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "
|
|
1234
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ProcessesComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1235
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.7", type: ProcessesComponent, isStandalone: true, selector: "fs-system-processes", inputs: { actions: "actions" }, viewQueries: [{ propertyName: "list", first: true, predicate: FsListComponent, descendants: true }], ngImport: i0, 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>", styles: [""], 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: "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 });
|
|
1443
1236
|
}
|
|
1444
1237
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ProcessesComponent, decorators: [{
|
|
1445
1238
|
type: Component,
|
|
1446
|
-
args: [{ selector: 'fs-system-processes', changeDetection: ChangeDetectionStrategy.OnPush, template: "<fs-list [config]=\"config\">\n <fs-list-column>\n <ng-template fs-list-header>\n Name\n </ng-template>\n <ng-template\n
|
|
1447
|
-
}],
|
|
1239
|
+
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
|
+
}], propDecorators: { list: [{
|
|
1448
1241
|
type: ViewChild,
|
|
1449
1242
|
args: [FsListComponent]
|
|
1450
1243
|
}], actions: [{
|
|
@@ -1471,11 +1264,8 @@ const LogTypes = [
|
|
|
1471
1264
|
];
|
|
1472
1265
|
|
|
1473
1266
|
class ServerLogComponent {
|
|
1474
|
-
data;
|
|
1267
|
+
data = inject(MAT_DIALOG_DATA);
|
|
1475
1268
|
log;
|
|
1476
|
-
constructor(data) {
|
|
1477
|
-
this.data = data;
|
|
1478
|
-
}
|
|
1479
1269
|
ngOnInit() {
|
|
1480
1270
|
if (this.data.log) {
|
|
1481
1271
|
this.log = this.data.log;
|
|
@@ -1493,8 +1283,8 @@ class ServerLogComponent {
|
|
|
1493
1283
|
}
|
|
1494
1284
|
}
|
|
1495
1285
|
}
|
|
1496
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ServerLogComponent, deps: [
|
|
1497
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "
|
|
1286
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ServerLogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1287
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.7", type: ServerLogComponent, isStandalone: true, selector: "ng-component", ngImport: i0, template: "<fs-dialog *fsSkeleton=\"log\">\n <div mat-dialog-title>\n Log\n </div>\n <mat-dialog-content>\n <div class=\"fs-row.gap-lg.wrap.align-start\">\n <fs-label-field>\n <fs-label>\n Error Type\n </fs-label>\n {{ log.type }}\n </fs-label-field>\n <fs-label-field>\n <fs-label>\n Message\n </fs-label>\n {{ log.message }}\n </fs-label-field>\n @if (log.url) {\n <fs-label-field>\n <fs-label>\n URL\n </fs-label>\n {{ log.url }}\n </fs-label-field>\n }\n <fs-label-field>\n <fs-label>\n Date\n </fs-label>\n {{ log.createDate|fsDateFormat: 'full-date-time' }}\n </fs-label-field>\n <fs-label-field>\n <fs-label>\n File\n </fs-label>\n {{ log.file }} @ {{ log.line }}\n </fs-label-field>\n </div>\n <fs-label-field>\n <fs-label>\n $_SERVER\n </fs-label>\n <pre>\n {{ log.server|json }}\n </pre>\n </fs-label-field>\n <fs-label-field>\n <fs-label>\n Backtrace\n </fs-label>\n <pre>\n {{ log.backtrace|json }}\n </pre>\n </fs-label-field>\n </mat-dialog-content>\n <mat-dialog-actions>\n <button\n mat-button\n [mat-dialog-close]=\"true\"\n color=\"primary\">\n Done\n </button>\n </mat-dialog-actions>\n</fs-dialog>", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: i1$2.JsonPipe, name: "json" }, { kind: "ngmodule", type: MatDialogModule }, { kind: "directive", type: i2$2.MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "directive", type: i2$2.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i2$2.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i2$2.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3$2.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "ngmodule", type: MatTooltipModule }, { 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: "ngmodule", type: FsBadgeModule }, { kind: "ngmodule", type: FsDateModule }, { kind: "pipe", type: i4.FsDateFormatPipe, name: "fsDateFormat" }, { 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"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1498
1288
|
}
|
|
1499
1289
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ServerLogComponent, decorators: [{
|
|
1500
1290
|
type: Component,
|
|
@@ -1511,25 +1301,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImpor
|
|
|
1511
1301
|
FsDateModule,
|
|
1512
1302
|
FsSkeletonModule,
|
|
1513
1303
|
FsDialogModule,
|
|
1514
|
-
], template: "<fs-dialog *fsSkeleton=\"log\">\n <div mat-dialog-title>\n Log\n </div>\n <mat-dialog-content>\n <div class=\"fs-row.gap-lg.wrap.align-start\">\n <fs-label-field>\n <fs-label>\n Error Type\n </fs-label>\n {{ log.type }}\n </fs-label-field>\n <fs-label-field>\n <fs-label>\n Message\n </fs-label>\n {{ log.message }}\n </fs-label-field>\n <fs-label-field
|
|
1515
|
-
}]
|
|
1516
|
-
type: Inject,
|
|
1517
|
-
args: [MAT_DIALOG_DATA]
|
|
1518
|
-
}] }] });
|
|
1304
|
+
], template: "<fs-dialog *fsSkeleton=\"log\">\n <div mat-dialog-title>\n Log\n </div>\n <mat-dialog-content>\n <div class=\"fs-row.gap-lg.wrap.align-start\">\n <fs-label-field>\n <fs-label>\n Error Type\n </fs-label>\n {{ log.type }}\n </fs-label-field>\n <fs-label-field>\n <fs-label>\n Message\n </fs-label>\n {{ log.message }}\n </fs-label-field>\n @if (log.url) {\n <fs-label-field>\n <fs-label>\n URL\n </fs-label>\n {{ log.url }}\n </fs-label-field>\n }\n <fs-label-field>\n <fs-label>\n Date\n </fs-label>\n {{ log.createDate|fsDateFormat: 'full-date-time' }}\n </fs-label-field>\n <fs-label-field>\n <fs-label>\n File\n </fs-label>\n {{ log.file }} @ {{ log.line }}\n </fs-label-field>\n </div>\n <fs-label-field>\n <fs-label>\n $_SERVER\n </fs-label>\n <pre>\n {{ log.server|json }}\n </pre>\n </fs-label-field>\n <fs-label-field>\n <fs-label>\n Backtrace\n </fs-label>\n <pre>\n {{ log.backtrace|json }}\n </pre>\n </fs-label-field>\n </mat-dialog-content>\n <mat-dialog-actions>\n <button\n mat-button\n [mat-dialog-close]=\"true\"\n color=\"primary\">\n Done\n </button>\n </mat-dialog-actions>\n</fs-dialog>" }]
|
|
1305
|
+
}] });
|
|
1519
1306
|
|
|
1520
1307
|
class ServerLogsComponent {
|
|
1521
|
-
_dialog;
|
|
1522
|
-
_api;
|
|
1308
|
+
_dialog = inject(MatDialog);
|
|
1309
|
+
_api = inject(FsApi);
|
|
1523
1310
|
list;
|
|
1524
1311
|
loadLogs;
|
|
1525
1312
|
acknowledgedAll = new EventEmitter();
|
|
1526
1313
|
config = null;
|
|
1527
1314
|
actions = [];
|
|
1528
1315
|
LogTypes = index(LogTypes, 'value', 'name');
|
|
1529
|
-
constructor(_dialog, _api) {
|
|
1530
|
-
this._dialog = _dialog;
|
|
1531
|
-
this._api = _api;
|
|
1532
|
-
}
|
|
1533
1316
|
ngOnInit() {
|
|
1534
1317
|
this._configList();
|
|
1535
1318
|
}
|
|
@@ -1585,13 +1368,17 @@ class ServerLogsComponent {
|
|
|
1585
1368
|
},
|
|
1586
1369
|
};
|
|
1587
1370
|
}
|
|
1588
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ServerLogsComponent, deps: [
|
|
1589
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.7", type: ServerLogsComponent, selector: "fs-system-server-logs", inputs: { loadLogs: "loadLogs" }, outputs: { acknowledgedAll: "acknowledgedAll" }, viewQueries: [{ propertyName: "list", first: true, predicate: FsListComponent, descendants: true }], ngImport: i0, template: "<fs-list [config]=\"config\">\n <fs-list-column width=\"1%\">\n <ng-template\n fs-list-cell\n let-row=\"row\">\n <a (click)=\"toggleAcknowledged(row)\">\n <fs-badge\n [size]=\"10\"\n [tooltip]=\"row.acknowledged ? 'Acknowledged' : 'Unacknowledged'\"\n [color]=\"row.acknowledged ? '#E3E3E3' : '#F30000'\">\n </fs-badge>\n </a>\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 <a\n href=\"javascript:;\"\n (click)=\"open(row)\">\n {{ row.message }}\n </a>\n </ng-template>\n </fs-list-column>\n <fs-list-column class=\"col-date\">\n <ng-template fs-list-header>\n Type\n </ng-template>\n <ng-template\n fs-list-cell\n let-row=\"row\">\n {{ LogTypes[row.type] }}\n </ng-template>\n </fs-list-column>\n <fs-list-column class=\"col-date\">\n <ng-template fs-list-header>\n Date\n </ng-template>\n <ng-template\n fs-list-cell\n let-row=\"row\">\n <fs-date-ago [date]=\"row.createDate\"></fs-date-ago>\n </ng-template>\n </fs-list-column>\n</fs-list>", styles: ["fs-list ::ng-deep .col-date,fs-list ::ng-deep .col-type{white-space:nowrap}\n"], dependencies: [{ kind: "
|
|
1371
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ServerLogsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1372
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.7", type: ServerLogsComponent, isStandalone: true, selector: "fs-system-server-logs", inputs: { loadLogs: "loadLogs" }, outputs: { acknowledgedAll: "acknowledgedAll" }, viewQueries: [{ propertyName: "list", first: true, predicate: FsListComponent, descendants: true }], ngImport: i0, template: "<fs-list [config]=\"config\">\n <fs-list-column width=\"1%\">\n <ng-template\n fs-list-cell\n let-row=\"row\">\n <a (click)=\"toggleAcknowledged(row)\">\n <fs-badge\n [size]=\"10\"\n [tooltip]=\"row.acknowledged ? 'Acknowledged' : 'Unacknowledged'\"\n [color]=\"row.acknowledged ? '#E3E3E3' : '#F30000'\">\n </fs-badge>\n </a>\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 <a\n href=\"javascript:;\"\n (click)=\"open(row)\">\n {{ row.message }}\n </a>\n </ng-template>\n </fs-list-column>\n <fs-list-column class=\"col-date\">\n <ng-template fs-list-header>\n Type\n </ng-template>\n <ng-template\n fs-list-cell\n let-row=\"row\">\n {{ LogTypes[row.type] }}\n </ng-template>\n </fs-list-column>\n <fs-list-column class=\"col-date\">\n <ng-template fs-list-header>\n Date\n </ng-template>\n <ng-template\n fs-list-cell\n let-row=\"row\">\n <fs-date-ago [date]=\"row.createDate\"></fs-date-ago>\n </ng-template>\n </fs-list-column>\n</fs-list>", styles: ["fs-list ::ng-deep .col-date,fs-list ::ng-deep .col-type{white-space:nowrap}\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: "ngmodule", type: FsBadgeModule }, { kind: "component", type: i2$3.FsBadgeComponent, selector: "fs-badge", inputs: ["color", "text", "tooltip", "size", "shape", "image", "icon", "iconSize", "iconSizePercent", "iconColor", "backgroundSize"] }, { kind: "ngmodule", type: FsDateModule }, { kind: "component", type: i4.FsDateAgoComponent, selector: "fs-date-ago", inputs: ["date", "showTime", "format", "showTooltip", "tooltipDateFormat"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1590
1373
|
}
|
|
1591
1374
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ServerLogsComponent, decorators: [{
|
|
1592
1375
|
type: Component,
|
|
1593
|
-
args: [{ selector: 'fs-system-server-logs', changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1594
|
-
|
|
1376
|
+
args: [{ selector: 'fs-system-server-logs', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [
|
|
1377
|
+
FsListModule,
|
|
1378
|
+
FsBadgeModule,
|
|
1379
|
+
FsDateModule,
|
|
1380
|
+
], template: "<fs-list [config]=\"config\">\n <fs-list-column width=\"1%\">\n <ng-template\n fs-list-cell\n let-row=\"row\">\n <a (click)=\"toggleAcknowledged(row)\">\n <fs-badge\n [size]=\"10\"\n [tooltip]=\"row.acknowledged ? 'Acknowledged' : 'Unacknowledged'\"\n [color]=\"row.acknowledged ? '#E3E3E3' : '#F30000'\">\n </fs-badge>\n </a>\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 <a\n href=\"javascript:;\"\n (click)=\"open(row)\">\n {{ row.message }}\n </a>\n </ng-template>\n </fs-list-column>\n <fs-list-column class=\"col-date\">\n <ng-template fs-list-header>\n Type\n </ng-template>\n <ng-template\n fs-list-cell\n let-row=\"row\">\n {{ LogTypes[row.type] }}\n </ng-template>\n </fs-list-column>\n <fs-list-column class=\"col-date\">\n <ng-template fs-list-header>\n Date\n </ng-template>\n <ng-template\n fs-list-cell\n let-row=\"row\">\n <fs-date-ago [date]=\"row.createDate\"></fs-date-ago>\n </ng-template>\n </fs-list-column>\n</fs-list>", styles: ["fs-list ::ng-deep .col-date,fs-list ::ng-deep .col-type{white-space:nowrap}\n"] }]
|
|
1381
|
+
}], propDecorators: { list: [{
|
|
1595
1382
|
type: ViewChild,
|
|
1596
1383
|
args: [FsListComponent]
|
|
1597
1384
|
}], loadLogs: [{
|
|
@@ -1607,23 +1394,24 @@ class KeyNameValuePipe {
|
|
|
1607
1394
|
});
|
|
1608
1395
|
}
|
|
1609
1396
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: KeyNameValuePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
1610
|
-
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "18.2.7", ngImport: i0, type: KeyNameValuePipe, name: "keyNameValue" });
|
|
1397
|
+
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "18.2.7", ngImport: i0, type: KeyNameValuePipe, isStandalone: true, name: "keyNameValue" });
|
|
1611
1398
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: KeyNameValuePipe });
|
|
1612
1399
|
}
|
|
1613
1400
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: KeyNameValuePipe, decorators: [{
|
|
1614
1401
|
type: Pipe,
|
|
1615
1402
|
args: [{
|
|
1616
1403
|
name: 'keyNameValue',
|
|
1404
|
+
standalone: true,
|
|
1617
1405
|
}]
|
|
1618
1406
|
}, {
|
|
1619
1407
|
type: Injectable
|
|
1620
1408
|
}] });
|
|
1621
1409
|
|
|
1622
1410
|
class SettingsComponent {
|
|
1623
|
-
_message;
|
|
1624
|
-
_clipboard;
|
|
1625
|
-
_prompt;
|
|
1626
|
-
_cdRef;
|
|
1411
|
+
_message = inject(FsMessage);
|
|
1412
|
+
_clipboard = inject(FsClipboard);
|
|
1413
|
+
_prompt = inject(FsPrompt);
|
|
1414
|
+
_cdRef = inject(ChangeDetectorRef);
|
|
1627
1415
|
loadSettings;
|
|
1628
1416
|
save;
|
|
1629
1417
|
fileRemove = new EventEmitter();
|
|
@@ -1631,12 +1419,6 @@ class SettingsComponent {
|
|
|
1631
1419
|
groupedSettings = [];
|
|
1632
1420
|
groups = [];
|
|
1633
1421
|
SettingInterfaceType = SettingInterfaceType;
|
|
1634
|
-
constructor(_message, _clipboard, _prompt, _cdRef) {
|
|
1635
|
-
this._message = _message;
|
|
1636
|
-
this._clipboard = _clipboard;
|
|
1637
|
-
this._prompt = _prompt;
|
|
1638
|
-
this._cdRef = _cdRef;
|
|
1639
|
-
}
|
|
1640
1422
|
ngOnInit() {
|
|
1641
1423
|
this.loadSettings({
|
|
1642
1424
|
visible: true,
|
|
@@ -1723,13 +1505,34 @@ class SettingsComponent {
|
|
|
1723
1505
|
this._message.success('Changes Saved');
|
|
1724
1506
|
});
|
|
1725
1507
|
}
|
|
1726
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: SettingsComponent, deps: [
|
|
1727
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.7", type: SettingsComponent, selector: "fs-system-settings", inputs: { loadSettings: "loadSettings", save: "save" }, outputs: { fileRemove: "fileRemove", fileSelect: "fileSelect" }, ngImport: i0, template: "<mat-accordion>\r\n <mat-expansion-panel\r\n hideToggle\r\n *ngFor=\"let group of groups\">\r\n <mat-expansion-panel-header>\r\n <mat-panel-title>\r\n <div class=\"title-row\">\r\n <div class=\"title\">\r\n {{ group || 'General' }}\r\n </div>\r\n <div class=\"actions\">\r\n <button\r\n type=\"button\"\r\n [matTooltip]=\"'Export ' + (group || 'General') + ' Settings'\"\r\n mat-icon-button\r\n (click)=\"export($event, groupedSettings[group])\">\r\n <mat-icon>\r\n cloud_download\r\n </mat-icon>\r\n </button>\r\n <button\r\n type=\"button\"\r\n [matTooltip]=\"'Import ' + (group || 'General') + ' Settings'\"\r\n mat-icon-button\r\n (click)=\"import($event, group)\">\r\n <mat-icon>\r\n cloud_upload\r\n </mat-icon>\r\n </button>\r\n </div>\r\n </div>\r\n </mat-panel-title>\r\n </mat-expansion-panel-header>\r\n <div\r\n hideToggle\r\n *ngFor=\"let setting of groupedSettings[group]\"\r\n class=\"setting\"\r\n [ngClass]=\"{ 'has-instruction': !! setting.instruction }\">\r\n <mat-form-field\r\n class=\"full-width form-field-multiline-subscript\"\r\n *ngIf=\"setting.interfaceType===SettingInterfaceType.InputBox\">\r\n <mat-label>\r\n {{ setting.label }}\r\n </mat-label>\r\n <input\r\n matInput\r\n [(ngModel)]=\"setting.value\"\r\n [name]=\"'setting' + setting.id\">\r\n <mat-hint>\r\n {{ setting.instruction }}\r\n </mat-hint>\r\n </mat-form-field>\r\n <mat-form-field\r\n class=\"full-width form-field-multiline-subscript\"\r\n *ngIf=\"setting.interfaceType===SettingInterfaceType.Textarea\">\r\n <mat-label>\r\n {{ setting.label }}\r\n </mat-label>\r\n <textarea\r\n matInput\r\n [(ngModel)]=\"setting.value\"\r\n [name]=\"'setting' + setting.id\">\r\n </textarea>\r\n <mat-hint>\r\n {{ setting.instruction }}\r\n </mat-hint>\r\n </mat-form-field>\r\n <mat-form-field\r\n class=\"full-width form-field-multiline-subscript\"\r\n *ngIf=\"setting.interfaceType===SettingInterfaceType.Select || setting.interfaceType===SettingInterfaceType.SelectMultiple\">\r\n <mat-label>\r\n {{ setting.label }}\r\n </mat-label>\r\n <mat-select\r\n [(ngModel)]=\"setting.value\"\r\n [multiple]=\"setting.interfaceType===SettingInterfaceType.SelectMultiple\"\r\n [name]=\"'setting' + setting.id\">\r\n <mat-option\r\n *ngFor=\"let item of setting.values | keyNameValue\"\r\n [value]=\"item.value\">\r\n {{ item.name }}\r\n </mat-option>\r\n </mat-select>\r\n <mat-hint>\r\n {{ setting.instruction }}\r\n </mat-hint>\r\n </mat-form-field>\r\n <mat-form-field\r\n class=\"full-width form-field-multiline-subscript\"\r\n *ngIf=\"setting.interfaceType===SettingInterfaceType.Date\">\r\n <mat-label>\r\n {{ setting.label }}\r\n </mat-label>\r\n <input\r\n matInput\r\n fsDatePicker\r\n [(ngModel)]=\"setting.value\"\r\n [name]=\"'setting' + setting.id\">\r\n <mat-hint>\r\n {{ setting.instruction }}\r\n </mat-hint>\r\n </mat-form-field>\r\n <mat-form-field\r\n class=\"full-width form-field-multiline-subscript\"\r\n *ngIf=\"setting.interfaceType===SettingInterfaceType.Color\">\r\n <mat-label>\r\n {{ setting.label }}\r\n </mat-label>\r\n <input\r\n matInput\r\n fsColorPicker\r\n [(ngModel)]=\"setting.value\"\r\n [name]=\"'setting' + setting.id\">\r\n <mat-hint>\r\n {{ setting.instruction }}\r\n </mat-hint>\r\n </mat-form-field>\r\n <mat-form-field\r\n class=\"full-width form-field-multiline-subscript\"\r\n *ngIf=\"setting.interfaceType===SettingInterfaceType.Time\">\r\n <mat-label>\r\n {{ setting.label }}\r\n </mat-label>\r\n <input\r\n matInput\r\n fsTimePicker\r\n [(ngModel)]=\"setting.value\"\r\n [name]=\"'setting' + setting.id\">\r\n <mat-hint>\r\n {{ setting.instruction }}\r\n </mat-hint>\r\n </mat-form-field>\r\n <fs-file-picker\r\n *ngIf=\"setting.interfaceType===SettingInterfaceType.File\"\r\n [allowRemove]=\"true\"\r\n [allowDownload]=\"true\"\r\n (select)=\"fileSelect.emit({ setting: setting, file: $event.file })\"\r\n (remove)=\"fileRemove.emit(setting)\"\r\n [url]=\"setting.value\">\r\n <div fsFileLabel>\r\n {{ setting.label }}\r\n </div>\r\n <div fsFileHint>\r\n {{ setting.instruction }}\r\n </div>\r\n </fs-file-picker>\r\n </div>\r\n <button\r\n mat-stroked-button\r\n color=\"primary\"\r\n type=\"button\"\r\n (click)=\"saveGroup(group)\">\r\n Save\r\n </button>\r\n </mat-expansion-panel>\r\n</mat-accordion>", styles: [".mat-expansion-panel-header{font-size:19px}.full-width{width:100%}.title-row{flex-direction:row;box-sizing:border-box;display:flex;place-content:center flex-start;align-items:center;width:100%}.title-row .title{display:flex;flex:1}:host ::ng-deep .mat-expansion-panel-header-title{margin:0}:host ::ng-deep .mat-expansion-panel .actions{display:none}:host ::ng-deep .mat-expansion-panel.mat-expanded .actions{display:block}:host ::ng-deep .setting.has-instruction fs-file-picker fs-label-message{display:block;padding-bottom:1em}\n"], dependencies: [{ kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i5$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i5$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i6.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i6.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "directive", type: i7$1.MatAccordion, selector: "mat-accordion", inputs: ["hideToggle", "displayMode", "togglePosition"], exportAs: ["matAccordion"] }, { kind: "component", type: i7$1.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i7$1.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i7$1.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "directive", type: i5.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: i3$2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i10$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i10$1.MatLabel, selector: "mat-label" }, { kind: "directive", type: i10$1.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i11.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: i12.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i13.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: i14.FsFilePickerComponent, selector: "fs-file-picker", inputs: ["minWidth", "minHeight", "imageWidth", "imageHeight", "imageQuality", "label", "showFilename", "allowDownload", "allowReupload", "multiple", "allowRemove", "url", "file", "accept", "disabled", "previewWidth", "previewHeight"], outputs: ["select", "remove", "download"] }, { kind: "directive", type: i14.FsFileLabelDirective, selector: "[fsFileLabel]" }, { kind: "component", type: i15.FsDatePickerComponent, selector: "[fsDatePicker]", inputs: ["minYear", "maxYear", "minDate", "maxDate", "startOfDay", "view", "format", "minutes"], outputs: ["change"] }, { kind: "component", type: i15.FsTimePickerComponent, selector: "[fsTimePicker]", inputs: ["view"] }, { kind: "component", type: i16.FsColorPickerComponent, selector: "[fsColorPicker]", inputs: ["showClear"] }, { kind: "pipe", type: KeyNameValuePipe, name: "keyNameValue" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1508
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: SettingsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1509
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.7", type: SettingsComponent, isStandalone: true, selector: "fs-system-settings", inputs: { loadSettings: "loadSettings", save: "save" }, outputs: { fileRemove: "fileRemove", fileSelect: "fileSelect" }, ngImport: i0, template: "<mat-accordion>\n @for (group of groups; track group) {\n <mat-expansion-panel\n hideToggle\n >\n <mat-expansion-panel-header>\n <mat-panel-title>\n <div class=\"title-row\">\n <div class=\"title\">\n {{ group || 'General' }}\n </div>\n <div class=\"actions\">\n <button\n type=\"button\"\n [matTooltip]=\"'Export ' + (group || 'General') + ' Settings'\"\n mat-icon-button\n (click)=\"export($event, groupedSettings[group])\">\n <mat-icon>\n cloud_download\n </mat-icon>\n </button>\n <button\n type=\"button\"\n [matTooltip]=\"'Import ' + (group || 'General') + ' Settings'\"\n mat-icon-button\n (click)=\"import($event, group)\">\n <mat-icon>\n cloud_upload\n </mat-icon>\n </button>\n </div>\n </div>\n </mat-panel-title>\n </mat-expansion-panel-header>\n @for (setting of groupedSettings[group]; track setting) {\n <div\n hideToggle\n class=\"setting\"\n [ngClass]=\"{ 'has-instruction': !! setting.instruction }\">\n @if (setting.interfaceType===SettingInterfaceType.InputBox) {\n <mat-form-field\n class=\"full-width form-field-multiline-subscript\"\n >\n <mat-label>\n {{ setting.label }}\n </mat-label>\n <input\n matInput\n [(ngModel)]=\"setting.value\"\n [name]=\"'setting' + setting.id\">\n <mat-hint>\n {{ setting.instruction }}\n </mat-hint>\n </mat-form-field>\n }\n @if (setting.interfaceType===SettingInterfaceType.Textarea) {\n <mat-form-field\n class=\"full-width form-field-multiline-subscript\"\n >\n <mat-label>\n {{ setting.label }}\n </mat-label>\n <textarea\n matInput\n [(ngModel)]=\"setting.value\"\n [name]=\"'setting' + setting.id\">\n </textarea>\n <mat-hint>\n {{ setting.instruction }}\n </mat-hint>\n </mat-form-field>\n }\n @if (setting.interfaceType===SettingInterfaceType.Select || setting.interfaceType===SettingInterfaceType.SelectMultiple) {\n <mat-form-field\n class=\"full-width form-field-multiline-subscript\"\n >\n <mat-label>\n {{ setting.label }}\n </mat-label>\n <mat-select\n [(ngModel)]=\"setting.value\"\n [multiple]=\"setting.interfaceType===SettingInterfaceType.SelectMultiple\"\n [name]=\"'setting' + setting.id\">\n @for (item of setting.values | keyNameValue; track item) {\n <mat-option\n [value]=\"item.value\">\n {{ item.name }}\n </mat-option>\n }\n </mat-select>\n <mat-hint>\n {{ setting.instruction }}\n </mat-hint>\n </mat-form-field>\n }\n @if (setting.interfaceType===SettingInterfaceType.Date) {\n <mat-form-field\n class=\"full-width form-field-multiline-subscript\"\n >\n <mat-label>\n {{ setting.label }}\n </mat-label>\n <input\n matInput\n fsDatePicker\n [(ngModel)]=\"setting.value\"\n [name]=\"'setting' + setting.id\">\n <mat-hint>\n {{ setting.instruction }}\n </mat-hint>\n </mat-form-field>\n }\n @if (setting.interfaceType===SettingInterfaceType.Color) {\n <mat-form-field\n class=\"full-width form-field-multiline-subscript\"\n >\n <mat-label>\n {{ setting.label }}\n </mat-label>\n <input\n matInput\n fsColorPicker\n [(ngModel)]=\"setting.value\"\n [name]=\"'setting' + setting.id\">\n <mat-hint>\n {{ setting.instruction }}\n </mat-hint>\n </mat-form-field>\n }\n @if (setting.interfaceType===SettingInterfaceType.Time) {\n <mat-form-field\n class=\"full-width form-field-multiline-subscript\"\n >\n <mat-label>\n {{ setting.label }}\n </mat-label>\n <input\n matInput\n fsTimePicker\n [(ngModel)]=\"setting.value\"\n [name]=\"'setting' + setting.id\">\n <mat-hint>\n {{ setting.instruction }}\n </mat-hint>\n </mat-form-field>\n }\n @if (setting.interfaceType===SettingInterfaceType.File) {\n <fs-file-picker\n [allowRemove]=\"true\"\n [allowDownload]=\"true\"\n (select)=\"fileSelect.emit({ setting: setting, file: $event.file })\"\n (remove)=\"fileRemove.emit(setting)\"\n [url]=\"setting.value\">\n <div fsFileLabel>\n {{ setting.label }}\n </div>\n <div fsFileHint>\n {{ setting.instruction }}\n </div>\n </fs-file-picker>\n }\n </div>\n }\n <button\n mat-stroked-button\n color=\"primary\"\n type=\"button\"\n (click)=\"saveGroup(group)\">\n Save\n </button>\n </mat-expansion-panel>\n }\n</mat-accordion>", styles: [".mat-expansion-panel-header{font-size:19px}.full-width{width:100%}.title-row{flex-direction:row;box-sizing:border-box;display:flex;place-content:center flex-start;align-items:center;width:100%}.title-row .title{display:flex;flex:1}:host ::ng-deep .mat-expansion-panel-header-title{margin:0}:host ::ng-deep .mat-expansion-panel .actions{display:none}:host ::ng-deep .mat-expansion-panel.mat-expanded .actions{display:block}:host ::ng-deep .setting.has-instruction fs-file-picker fs-label-message{display:block;padding-bottom:1em}\n"], dependencies: [{ kind: "directive", type: MatAccordion, selector: "mat-accordion", inputs: ["hideToggle", "displayMode", "togglePosition"], exportAs: ["matAccordion"] }, { kind: "component", type: MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { 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: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatLabel, selector: "mat-label" }, { kind: "directive", type: MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "component", type: MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: FsDatePickerModule }, { kind: "component", type: i2$4.FsDatePickerComponent, selector: "[fsDatePicker]", inputs: ["minYear", "maxYear", "minDate", "maxDate", "startOfDay", "view", "format", "minutes"], outputs: ["change"] }, { kind: "component", type: i2$4.FsTimePickerComponent, selector: "[fsTimePicker]", inputs: ["view"] }, { kind: "ngmodule", type: FsColorPickerModule }, { kind: "component", type: i3$3.FsColorPickerComponent, selector: "[fsColorPicker]", inputs: ["showClear"] }, { kind: "ngmodule", type: FsFileModule }, { kind: "component", type: i4$1.FsFilePickerComponent, selector: "fs-file-picker", inputs: ["minWidth", "minHeight", "imageWidth", "imageHeight", "imageQuality", "label", "showFilename", "allowDownload", "allowReupload", "multiple", "allowRemove", "url", "file", "accept", "disabled", "previewWidth", "previewHeight"], outputs: ["select", "remove", "download"] }, { kind: "directive", type: i4$1.FsFileLabelDirective, selector: "[fsFileLabel]" }, { kind: "component", type: MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "pipe", type: KeyNameValuePipe, name: "keyNameValue" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1728
1510
|
}
|
|
1729
1511
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: SettingsComponent, decorators: [{
|
|
1730
1512
|
type: Component,
|
|
1731
|
-
args: [{ selector: 'fs-system-settings', changeDetection: ChangeDetectionStrategy.OnPush,
|
|
1732
|
-
|
|
1513
|
+
args: [{ selector: 'fs-system-settings', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [
|
|
1514
|
+
MatAccordion,
|
|
1515
|
+
MatExpansionPanel,
|
|
1516
|
+
MatExpansionPanelHeader,
|
|
1517
|
+
MatExpansionPanelTitle,
|
|
1518
|
+
MatIconButton,
|
|
1519
|
+
MatTooltip,
|
|
1520
|
+
MatIcon,
|
|
1521
|
+
NgClass,
|
|
1522
|
+
MatFormField,
|
|
1523
|
+
MatLabel,
|
|
1524
|
+
MatInput,
|
|
1525
|
+
FormsModule,
|
|
1526
|
+
MatHint,
|
|
1527
|
+
MatSelect,
|
|
1528
|
+
MatOption,
|
|
1529
|
+
FsDatePickerModule,
|
|
1530
|
+
FsColorPickerModule,
|
|
1531
|
+
FsFileModule,
|
|
1532
|
+
MatButton,
|
|
1533
|
+
KeyNameValuePipe,
|
|
1534
|
+
], template: "<mat-accordion>\n @for (group of groups; track group) {\n <mat-expansion-panel\n hideToggle\n >\n <mat-expansion-panel-header>\n <mat-panel-title>\n <div class=\"title-row\">\n <div class=\"title\">\n {{ group || 'General' }}\n </div>\n <div class=\"actions\">\n <button\n type=\"button\"\n [matTooltip]=\"'Export ' + (group || 'General') + ' Settings'\"\n mat-icon-button\n (click)=\"export($event, groupedSettings[group])\">\n <mat-icon>\n cloud_download\n </mat-icon>\n </button>\n <button\n type=\"button\"\n [matTooltip]=\"'Import ' + (group || 'General') + ' Settings'\"\n mat-icon-button\n (click)=\"import($event, group)\">\n <mat-icon>\n cloud_upload\n </mat-icon>\n </button>\n </div>\n </div>\n </mat-panel-title>\n </mat-expansion-panel-header>\n @for (setting of groupedSettings[group]; track setting) {\n <div\n hideToggle\n class=\"setting\"\n [ngClass]=\"{ 'has-instruction': !! setting.instruction }\">\n @if (setting.interfaceType===SettingInterfaceType.InputBox) {\n <mat-form-field\n class=\"full-width form-field-multiline-subscript\"\n >\n <mat-label>\n {{ setting.label }}\n </mat-label>\n <input\n matInput\n [(ngModel)]=\"setting.value\"\n [name]=\"'setting' + setting.id\">\n <mat-hint>\n {{ setting.instruction }}\n </mat-hint>\n </mat-form-field>\n }\n @if (setting.interfaceType===SettingInterfaceType.Textarea) {\n <mat-form-field\n class=\"full-width form-field-multiline-subscript\"\n >\n <mat-label>\n {{ setting.label }}\n </mat-label>\n <textarea\n matInput\n [(ngModel)]=\"setting.value\"\n [name]=\"'setting' + setting.id\">\n </textarea>\n <mat-hint>\n {{ setting.instruction }}\n </mat-hint>\n </mat-form-field>\n }\n @if (setting.interfaceType===SettingInterfaceType.Select || setting.interfaceType===SettingInterfaceType.SelectMultiple) {\n <mat-form-field\n class=\"full-width form-field-multiline-subscript\"\n >\n <mat-label>\n {{ setting.label }}\n </mat-label>\n <mat-select\n [(ngModel)]=\"setting.value\"\n [multiple]=\"setting.interfaceType===SettingInterfaceType.SelectMultiple\"\n [name]=\"'setting' + setting.id\">\n @for (item of setting.values | keyNameValue; track item) {\n <mat-option\n [value]=\"item.value\">\n {{ item.name }}\n </mat-option>\n }\n </mat-select>\n <mat-hint>\n {{ setting.instruction }}\n </mat-hint>\n </mat-form-field>\n }\n @if (setting.interfaceType===SettingInterfaceType.Date) {\n <mat-form-field\n class=\"full-width form-field-multiline-subscript\"\n >\n <mat-label>\n {{ setting.label }}\n </mat-label>\n <input\n matInput\n fsDatePicker\n [(ngModel)]=\"setting.value\"\n [name]=\"'setting' + setting.id\">\n <mat-hint>\n {{ setting.instruction }}\n </mat-hint>\n </mat-form-field>\n }\n @if (setting.interfaceType===SettingInterfaceType.Color) {\n <mat-form-field\n class=\"full-width form-field-multiline-subscript\"\n >\n <mat-label>\n {{ setting.label }}\n </mat-label>\n <input\n matInput\n fsColorPicker\n [(ngModel)]=\"setting.value\"\n [name]=\"'setting' + setting.id\">\n <mat-hint>\n {{ setting.instruction }}\n </mat-hint>\n </mat-form-field>\n }\n @if (setting.interfaceType===SettingInterfaceType.Time) {\n <mat-form-field\n class=\"full-width form-field-multiline-subscript\"\n >\n <mat-label>\n {{ setting.label }}\n </mat-label>\n <input\n matInput\n fsTimePicker\n [(ngModel)]=\"setting.value\"\n [name]=\"'setting' + setting.id\">\n <mat-hint>\n {{ setting.instruction }}\n </mat-hint>\n </mat-form-field>\n }\n @if (setting.interfaceType===SettingInterfaceType.File) {\n <fs-file-picker\n [allowRemove]=\"true\"\n [allowDownload]=\"true\"\n (select)=\"fileSelect.emit({ setting: setting, file: $event.file })\"\n (remove)=\"fileRemove.emit(setting)\"\n [url]=\"setting.value\">\n <div fsFileLabel>\n {{ setting.label }}\n </div>\n <div fsFileHint>\n {{ setting.instruction }}\n </div>\n </fs-file-picker>\n }\n </div>\n }\n <button\n mat-stroked-button\n color=\"primary\"\n type=\"button\"\n (click)=\"saveGroup(group)\">\n Save\n </button>\n </mat-expansion-panel>\n }\n</mat-accordion>", styles: [".mat-expansion-panel-header{font-size:19px}.full-width{width:100%}.title-row{flex-direction:row;box-sizing:border-box;display:flex;place-content:center flex-start;align-items:center;width:100%}.title-row .title{display:flex;flex:1}:host ::ng-deep .mat-expansion-panel-header-title{margin:0}:host ::ng-deep .mat-expansion-panel .actions{display:none}:host ::ng-deep .mat-expansion-panel.mat-expanded .actions{display:block}:host ::ng-deep .setting.has-instruction fs-file-picker fs-label-message{display:block;padding-bottom:1em}\n"] }]
|
|
1535
|
+
}], propDecorators: { loadSettings: [{
|
|
1733
1536
|
type: Input
|
|
1734
1537
|
}], save: [{
|
|
1735
1538
|
type: Input
|
|
@@ -1764,11 +1567,11 @@ class UpgradeLogsComponent {
|
|
|
1764
1567
|
};
|
|
1765
1568
|
}
|
|
1766
1569
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: UpgradeLogsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1767
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.7", type: UpgradeLogsComponent, selector: "fs-system-upgrade-logs", inputs: { loadUpgradeLogs: "loadUpgradeLogs" }, viewQueries: [{ propertyName: "list", first: true, predicate: FsListComponent, descendants: true, static: true }], ngImport: i0, template: "<fs-list [config]=\"config\">\
|
|
1570
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.7", type: UpgradeLogsComponent, isStandalone: true, selector: "fs-system-upgrade-logs", inputs: { loadUpgradeLogs: "loadUpgradeLogs" }, 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 {{row.name}}\n </ng-template>\n </fs-list-column>\n\n <fs-list-column>\n <ng-template fs-list-header>Function</ng-template>\n <ng-template fs-list-cell let-row=\"row\">\n {{row.function}}()\n </ng-template>\n </fs-list-column>\n\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 </ng-template>\n </fs-list-column>\n</fs-list>\n", styles: [""], 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: "ngmodule", type: FsDateModule }, { kind: "component", type: i4.FsDateAgoComponent, selector: "fs-date-ago", inputs: ["date", "showTime", "format", "showTooltip", "tooltipDateFormat"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1768
1571
|
}
|
|
1769
1572
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: UpgradeLogsComponent, decorators: [{
|
|
1770
1573
|
type: Component,
|
|
1771
|
-
args: [{ selector: 'fs-system-upgrade-logs', changeDetection: ChangeDetectionStrategy.OnPush, template: "<fs-list [config]=\"config\">\
|
|
1574
|
+
args: [{ selector: 'fs-system-upgrade-logs', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [FsListModule, FsDateModule], 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 {{row.name}}\n </ng-template>\n </fs-list-column>\n\n <fs-list-column>\n <ng-template fs-list-header>Function</ng-template>\n <ng-template fs-list-cell let-row=\"row\">\n {{row.function}}()\n </ng-template>\n </fs-list-column>\n\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 </ng-template>\n </fs-list-column>\n</fs-list>\n" }]
|
|
1772
1575
|
}], propDecorators: { list: [{
|
|
1773
1576
|
type: ViewChild,
|
|
1774
1577
|
args: [FsListComponent, { static: true }]
|
|
@@ -1788,20 +1591,7 @@ class FsSystemModule {
|
|
|
1788
1591
|
};
|
|
1789
1592
|
}
|
|
1790
1593
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: FsSystemModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
1791
|
-
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.7", ngImport: i0, type: FsSystemModule,
|
|
1792
|
-
CronNextRunComponent,
|
|
1793
|
-
CronsComponent,
|
|
1794
|
-
SettingsComponent,
|
|
1795
|
-
KeyNameValuePipe,
|
|
1796
|
-
ProcessesComponent,
|
|
1797
|
-
ServerLogsComponent,
|
|
1798
|
-
UpgradeLogsComponent,
|
|
1799
|
-
ApiLogsComponent,
|
|
1800
|
-
ApiLogComponent,
|
|
1801
|
-
InfoComponent,
|
|
1802
|
-
ProcessComponent,
|
|
1803
|
-
CronComponent,
|
|
1804
|
-
CronLogComponent], imports: [CommonModule,
|
|
1594
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.7", ngImport: i0, type: FsSystemModule, imports: [CommonModule,
|
|
1805
1595
|
FormsModule,
|
|
1806
1596
|
MatButtonModule,
|
|
1807
1597
|
MatExpansionModule,
|
|
@@ -1825,7 +1615,21 @@ class FsSystemModule {
|
|
|
1825
1615
|
FsBadgeModule,
|
|
1826
1616
|
FsPopoverModule,
|
|
1827
1617
|
FsColorPickerModule,
|
|
1828
|
-
CronLogsComponent
|
|
1618
|
+
CronLogsComponent,
|
|
1619
|
+
DashboardComponent,
|
|
1620
|
+
CronNextRunComponent,
|
|
1621
|
+
CronsComponent,
|
|
1622
|
+
SettingsComponent,
|
|
1623
|
+
KeyNameValuePipe,
|
|
1624
|
+
ProcessesComponent,
|
|
1625
|
+
ServerLogsComponent,
|
|
1626
|
+
UpgradeLogsComponent,
|
|
1627
|
+
ApiLogsComponent,
|
|
1628
|
+
ApiLogComponent,
|
|
1629
|
+
InfoComponent,
|
|
1630
|
+
ProcessComponent,
|
|
1631
|
+
CronComponent,
|
|
1632
|
+
CronLogComponent], exports: [DashboardComponent,
|
|
1829
1633
|
CronsComponent,
|
|
1830
1634
|
SettingsComponent,
|
|
1831
1635
|
ProcessesComponent,
|
|
@@ -1857,7 +1661,19 @@ class FsSystemModule {
|
|
|
1857
1661
|
FsBadgeModule,
|
|
1858
1662
|
FsPopoverModule,
|
|
1859
1663
|
FsColorPickerModule,
|
|
1860
|
-
CronLogsComponent
|
|
1664
|
+
CronLogsComponent,
|
|
1665
|
+
DashboardComponent,
|
|
1666
|
+
CronNextRunComponent,
|
|
1667
|
+
CronsComponent,
|
|
1668
|
+
SettingsComponent,
|
|
1669
|
+
ProcessesComponent,
|
|
1670
|
+
ServerLogsComponent,
|
|
1671
|
+
UpgradeLogsComponent,
|
|
1672
|
+
ApiLogsComponent,
|
|
1673
|
+
ApiLogComponent,
|
|
1674
|
+
ProcessComponent,
|
|
1675
|
+
CronComponent,
|
|
1676
|
+
CronLogComponent] });
|
|
1861
1677
|
}
|
|
1862
1678
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: FsSystemModule, decorators: [{
|
|
1863
1679
|
type: NgModule,
|
|
@@ -1888,39 +1704,201 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImpor
|
|
|
1888
1704
|
FsPopoverModule,
|
|
1889
1705
|
FsColorPickerModule,
|
|
1890
1706
|
CronLogsComponent,
|
|
1891
|
-
],
|
|
1892
|
-
exports: [
|
|
1893
1707
|
DashboardComponent,
|
|
1708
|
+
CronNextRunComponent,
|
|
1894
1709
|
CronsComponent,
|
|
1895
1710
|
SettingsComponent,
|
|
1711
|
+
KeyNameValuePipe,
|
|
1896
1712
|
ProcessesComponent,
|
|
1897
1713
|
ServerLogsComponent,
|
|
1898
1714
|
UpgradeLogsComponent,
|
|
1899
1715
|
ApiLogsComponent,
|
|
1716
|
+
ApiLogComponent,
|
|
1900
1717
|
InfoComponent,
|
|
1718
|
+
ProcessComponent,
|
|
1719
|
+
CronComponent,
|
|
1720
|
+
CronLogComponent,
|
|
1901
1721
|
],
|
|
1902
|
-
|
|
1722
|
+
exports: [
|
|
1903
1723
|
DashboardComponent,
|
|
1904
|
-
CronNextRunComponent,
|
|
1905
1724
|
CronsComponent,
|
|
1906
1725
|
SettingsComponent,
|
|
1907
|
-
KeyNameValuePipe,
|
|
1908
1726
|
ProcessesComponent,
|
|
1909
1727
|
ServerLogsComponent,
|
|
1910
1728
|
UpgradeLogsComponent,
|
|
1911
1729
|
ApiLogsComponent,
|
|
1912
|
-
ApiLogComponent,
|
|
1913
1730
|
InfoComponent,
|
|
1914
|
-
ProcessComponent,
|
|
1915
|
-
CronComponent,
|
|
1916
|
-
CronLogComponent,
|
|
1917
1731
|
],
|
|
1918
1732
|
}]
|
|
1919
1733
|
}] });
|
|
1920
1734
|
|
|
1735
|
+
class ExplainComponent {
|
|
1736
|
+
_data = inject(MAT_DIALOG_DATA);
|
|
1737
|
+
explain;
|
|
1738
|
+
constructor() {
|
|
1739
|
+
const _data = this._data;
|
|
1740
|
+
this.explain = _data.explain;
|
|
1741
|
+
}
|
|
1742
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ExplainComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1743
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.7", type: ExplainComponent, isStandalone: true, selector: "ng-component", ngImport: i0, template: "<fs-dialog>\n <h1 mat-dialog-title>Explain</h1>\n <mat-dialog-content>\n <div class=\"explain-popover\">{{explain | json}}</div>\n </mat-dialog-content>\n <mat-dialog-actions>\n <button\n mat-button\n type=\"button\"\n color=\"primary\"\n [mat-dialog-close]=\"undefined\">\n Done\n </button>\n </mat-dialog-actions>\n</fs-dialog>\n", styles: [".explain-popover{white-space:pre}\n"], dependencies: [{ 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: "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: "ngmodule", type: FsFormModule }, { kind: "directive", type: i2$5.FsButtonDirective, selector: "[mat-raised-button]:not([fsFormButtonStandalone]),[mat-button]:not([fsFormButtonStandalone]),[mat-flat-button]:not([fsFormButtonStandalone]),[mat-stroked-button]:not([fsFormButtonStandalone])", inputs: ["name", "dirtySubmit", "form"] }, { kind: "directive", type: MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "pipe", type: JsonPipe, name: "json" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1744
|
+
}
|
|
1745
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: ExplainComponent, decorators: [{
|
|
1746
|
+
type: Component,
|
|
1747
|
+
args: [{ changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [
|
|
1748
|
+
FsDialogModule,
|
|
1749
|
+
MatDialogTitle,
|
|
1750
|
+
CdkScrollable,
|
|
1751
|
+
MatDialogContent,
|
|
1752
|
+
MatDialogActions,
|
|
1753
|
+
MatButton,
|
|
1754
|
+
FsFormModule,
|
|
1755
|
+
MatDialogClose,
|
|
1756
|
+
JsonPipe,
|
|
1757
|
+
], template: "<fs-dialog>\n <h1 mat-dialog-title>Explain</h1>\n <mat-dialog-content>\n <div class=\"explain-popover\">{{explain | json}}</div>\n </mat-dialog-content>\n <mat-dialog-actions>\n <button\n mat-button\n type=\"button\"\n color=\"primary\"\n [mat-dialog-close]=\"undefined\">\n Done\n </button>\n </mat-dialog-actions>\n</fs-dialog>\n", styles: [".explain-popover{white-space:pre}\n"] }]
|
|
1758
|
+
}], ctorParameters: () => [] });
|
|
1759
|
+
|
|
1760
|
+
class QueryLogComponent {
|
|
1761
|
+
_data = inject(MAT_DIALOG_DATA);
|
|
1762
|
+
_dialog = inject(MatDialog);
|
|
1763
|
+
queryLog;
|
|
1764
|
+
accessTypes = {
|
|
1765
|
+
NULL: 'This access method means MySQL can resolve the query during the optimization phase and will not even access the table or index during the execution stage.',
|
|
1766
|
+
system: 'The table is empty or has one row.',
|
|
1767
|
+
const: 'The value of the column can be treated as a constant (there is one row matching the query). Note: Primary Key Lookup, Unique Index Lookup',
|
|
1768
|
+
eq_ref: 'The index is clustered and is being used by the operation (either the index is a PRIMARY KEY or UNIQUE INDEX with all key columns defined as NOT NULL)',
|
|
1769
|
+
ref: 'The indexed column was accessed using an equality operator Note: The ref_or_null access type is a variation on ref. It means MySQL must do a second lookup to find NULL entries after doing the initial lookup.',
|
|
1770
|
+
fulltext: 'Operation (JOIN) is using the table’s fulltext index',
|
|
1771
|
+
index: 'The entire index is scanned to find a match for the query. Note: The main advantage is that this avoids sorting. The biggest disadvantage is the cost of reading an entire table in index order. This usually means accessing the rows in random order, which is very expensive.',
|
|
1772
|
+
index_merge: 'This join type indicates that the Index Merge optimization is used. In this case, the key column in the output row contains a list of indexes used. It indicates a query can make limited use of multiple indexes on a single table.',
|
|
1773
|
+
range: 'This type replaces eq_ref for some IN subqueries of the following form: value IN (SELECT primary_key FROM single_table WHERE some_expr)',
|
|
1774
|
+
unique_subquery: '',
|
|
1775
|
+
ALL: 'MySQL scans the entire table to satisfy the query',
|
|
1776
|
+
};
|
|
1777
|
+
constructor() {
|
|
1778
|
+
const _data = this._data;
|
|
1779
|
+
this.queryLog = _data.queryLog;
|
|
1780
|
+
}
|
|
1781
|
+
openExplain() {
|
|
1782
|
+
this._dialog.open(ExplainComponent, {
|
|
1783
|
+
data: { explain: this.explain },
|
|
1784
|
+
});
|
|
1785
|
+
}
|
|
1786
|
+
get explain() {
|
|
1787
|
+
return this.queryLog.explain;
|
|
1788
|
+
}
|
|
1789
|
+
get queryBlock() {
|
|
1790
|
+
return this.explain?.queryBlock;
|
|
1791
|
+
}
|
|
1792
|
+
get orderingOperation() {
|
|
1793
|
+
return this.queryBlock?.orderingOperation;
|
|
1794
|
+
}
|
|
1795
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: QueryLogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1796
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.7", type: QueryLogComponent, isStandalone: true, selector: "ng-component", ngImport: i0, template: "<fs-dialog>\n <h1 mat-dialog-title>Query Log</h1>\n <mat-dialog-content>\n <div class=\"fs-row.gap-lg.wrap.align-start\">\n <fs-label-field>\n <fs-label>Duration</fs-label>\n {{queryLog.duration}}\n </fs-label-field>\n\n <fs-label-field>\n <fs-label>Optimized</fs-label>\n {{queryLog.optimized ? 'Yes' : 'No'}}\n </fs-label-field>\n\n <fs-label-field>\n <fs-label>Query Cost</fs-label>\n {{queryLog.queryCost}}\n </fs-label-field>\n\n <fs-label-field>\n <fs-label>Raw Explain</fs-label>\n <a (click)=\"openExplain()\">View</a>\n </fs-label-field>\n\n <fs-label-field>\n <fs-label>URL</fs-label>\n {{queryLog.path | fsFormatTruncate: 50}}\n </fs-label-field>\n </div>\n\n <mat-tab-group>\n <mat-tab label=\"Query\">\n <fs-clipboard-button\n [content]=\"queryLog.prettyQuery\">\n </fs-clipboard-button>\n <div [innerHTML]=\"queryLog.prettyQuery\" class=\"query\"></div>\n </mat-tab>\n\n <mat-tab label=\"Explain\">\n <ng-container [ngTemplateOutlet]=\"nestedLoop\" [ngTemplateOutletContext]=\"{ queryBlock: queryBlock, selectId: queryBlock.selectId, costInfo: queryBlock.costInfo }\"></ng-container>\n </mat-tab>\n </mat-tab-group>\n\n </mat-dialog-content>\n <mat-dialog-actions>\n <button\n mat-button\n type=\"button\"\n color=\"primary\"\n [mat-dialog-close]=\"undefined\">\n Done\n </button>\n </mat-dialog-actions>\n</fs-dialog>\n\n<ng-template #nestedLoop let-queryBlock=\"queryBlock\" let-selectId=\"selectId\" let-costInfo=\"costInfo\">\n @if (selectId) {\n <h1>Select {{selectId}}</h1>\n }\n\n <div class=\"fs-row.gap-lg.wrap.align-start\">\n @if (costInfo?.queryCost) {\n <fs-label-field>\n <fs-label>Query Cost</fs-label>\n {{costInfo.queryCost}}\n </fs-label-field>\n }\n @if (queryBlock.orderingOperation) {\n <fs-label-field>\n <fs-label>Ordering Operation</fs-label>\n <ng-container [ngTemplateOutlet]=\"queryBlockCritical\" [ngTemplateOutletContext]=\"{ queryBlock: queryBlock.orderingOperation }\"></ng-container>\n </fs-label-field>\n }\n\n @if (queryBlock.groupingOperation) {\n <fs-label-field>\n <fs-label>Grouping Operation</fs-label>\n <ng-container [ngTemplateOutlet]=\"queryBlockCritical\" [ngTemplateOutletContext]=\"{ queryBlock: queryBlock.groupingOperation }\"></ng-container>\n </fs-label-field>\n }\n\n @if (queryBlock.duplicatesRemoval) {\n <fs-label-field>\n <fs-label>Duplicates Removal</fs-label>\n <ng-container [ngTemplateOutlet]=\"queryBlockCritical\" [ngTemplateOutletContext]=\"{ queryBlock: queryBlock.duplicatesRemoval }\"></ng-container>\n </fs-label-field>\n }\n </div>\n\n @if (queryBlock.orderingOperation) {\n <ng-container [ngTemplateOutlet]=\"nestedLoop\" [ngTemplateOutletContext]=\"{ queryBlock: queryBlock.orderingOperation }\"></ng-container>\n }\n\n @if (queryBlock.groupingOperation) {\n <ng-container [ngTemplateOutlet]=\"nestedLoop\" [ngTemplateOutletContext]=\"{ queryBlock: queryBlock.groupingOperation }\"></ng-container>\n }\n\n @if (queryBlock.duplicatesRemoval) {\n <ng-container [ngTemplateOutlet]=\"nestedLoop\" [ngTemplateOutletContext]=\"{ queryBlock: queryBlock.duplicatesRemoval }\"></ng-container>\n }\n\n @if (queryBlock.table) {\n <ng-container [ngTemplateOutlet]=\"nestedLoop\" [ngTemplateOutletContext]=\"{ queryBlock: { nestedLoop: [ queryBlock ]} }\"></ng-container>\n @if (queryBlock.table.attachedSubqueries) {\n <fs-label>Attached Subqueries</fs-label>\n @for (subquery of queryBlock.table.attachedSubqueries; track subquery) {\n <ng-container [ngTemplateOutlet]=\"queryBlockCritical\" [ngTemplateOutletContext]=\"{ queryBlock: subquery.queryBlock }\"></ng-container>\n <ng-container [ngTemplateOutlet]=\"nestedLoop\" [ngTemplateOutletContext]=\"{ queryBlock: subquery.queryBlock, selectId: subquery.queryBlock.selectId, costInfo: subquery.queryBlock.costInfo }\"></ng-container>\n }\n }\n }\n\n @if (queryBlock.nestedLoop) {\n <table class=\"fs-list-table style-line\">\n <thead>\n <tr>\n <th>Table</th>\n <th>Type</th>\n <th>Keys</th>\n <th>Ref</th>\n <th>Rows</th>\n <th>Filtered</th>\n <th>Extra</th>\n <th>Cost</th>\n </tr>\n </thead>\n <tbody>\n @for (item of queryBlock.nestedLoop; track item; let index = $index) {\n <tr>\n <td>\n {{item.table.tableName}}\n </td>\n <td>\n <fs-popover [template]=\"accessTypePopover\" [data]=\"item.table.accessType\">\n <span class=\"access-type\" [ngClass]=\"item.table.accessType\">{{item.table.accessType}}</span>\n </fs-popover>\n </td>\n <td>\n <fs-popover\n [template]=\"keysPopover\"\n [maxWidth]=\"null\"\n [data]=\"{ possibleKeys: item.table.possibleKeys, key: item.table.key }\">\n {{item.table.key}}\n </fs-popover>\n </td>\n <td>\n <div class=\"fs-delimit\">\n @for (ref of item.table.ref; track ref) {\n <span>{{ref}}</span>\n }\n </div>\n </td>\n <td>\n {{item.table.rowsExaminedPerScan}}\n </td>\n <td>\n {{item.table.filtered}}\n </td>\n <td>\n <div class=\"fs-delimit\">\n @if (item.table.indexCondition) {\n <span>\n <fs-popover\n [template]=\"usingIndexCondition\"\n [maxWidth]=\"null\"\n [data]=\"item.table.indexCondition\">\n Using Index Condition\n </fs-popover>\n </span>\n }\n @if (item.table.attachedCondition) {\n <span>\n <fs-popover\n [template]=\"usingWhere\"\n [maxWidth]=\"null\"\n [data]=\"item.table.attachedCondition\">\n Using Where\n </fs-popover>\n </span>\n }\n @if (item.usingIndex) {\n <span>Using Index</span>\n }\n @if (item.usingFilesort) {\n <span class=\"critical\">Using File Sort</span>\n }\n @if (item.usingTemporaryTable) {\n <span class=\"critical\">Temporary Table</span>\n }\n </div>\n </td>\n <td>\n <fs-popover [template]=\"tableCostPopover\" [data]=\"item.table?.costInfo\">\n {{item.table?.costInfo.prefixCost}}\n </fs-popover>\n <ng-template #tableCostPopover let-data=\"data\">\n <div>Eval Cost: {{data.evalCost}}</div>\n <div>Read Cost: {{data.readCost}}</div>\n <div>Prefix Cost: {{data.prefixCost}}</div>\n <div>Data Read Per Join: {{data.dataReadPerJoin}}</div>\n </ng-template>\n </td>\n </tr>\n }\n </tbody>\n </table>\n <br>\n }\n\n @if (queryBlock.selectListSubqueries) {\n <br>\n <fs-label>Select List Subqueries</fs-label>\n @for (subquery of queryBlock.selectListSubqueries; track subquery) {\n <ng-container [ngTemplateOutlet]=\"queryBlockCritical\" [ngTemplateOutletContext]=\"{ queryBlock: subquery.queryBlock }\"></ng-container>\n <ng-container [ngTemplateOutlet]=\"nestedLoop\" [ngTemplateOutletContext]=\"{ queryBlock: subquery.queryBlock, selectId: subquery.queryBlock.selectId, costInfo: subquery.queryBlock.costInfo }\"></ng-container>\n }\n }\n <!--\n <ng-container *ngIf=\"queryBlock.queryBlockattachedSubqueries\">\n <br>\n <fs-label>Attached Subqueries</fs-label>\n <ng-container *ngFor=\"let subquery of queryBlock.attachedSubqueries\">\n <ng-container [ngTemplateOutlet]=\"queryBlockCritical\" [ngTemplateOutletContext]=\"{ queryBlock: subquery.queryBlock }\"></ng-container>\n <ng-container [ngTemplateOutlet]=\"nestedLoop\" [ngTemplateOutletContext]=\"{ queryBlock: subquery.queryBlock }\"></ng-container>\n </ng-container>\n </ng-container> -->\n </ng-template>\n\n <ng-template #keysPopover let-data=\"data\">\n <div class=\"fs-delimit\">\n @for (possibleKey of data.possibleKeys; track possibleKey) {\n <span [ngClass]=\"{ 'query-log-used-key': possibleKey === data.key }\">{{possibleKey}}</span>\n }\n </div>\n </ng-template>\n\n <ng-template #usingWhere let-data=\"data\">\n {{data}}\n </ng-template>\n\n <ng-template #usingIndexCondition let-data=\"data\">\n {{data}}\n </ng-template>\n\n <ng-template #accessTypePopover let-data=\"data\">\n {{accessTypes[data]}}\n </ng-template>\n\n\n <ng-template #queryBlockCritical let-queryBlock=\"queryBlock\">\n <div class=\"fs-delimit\">\n @if (queryBlock.usingFilesort) {\n <span class=\"critical\">Using File Sort</span>\n }\n\n @if (queryBlock.usingTemporaryTable) {\n <span class=\"critical\">Temporary Table</span>\n }\n </div>\n </ng-template>", styles: ["::ng-deep .query-log-used-key{font-weight:700}::ng-deep .explain-popover{white-space:pre}.critical{color:red}fs-clipboard-button{float:right}.query{white-space:break-spaces}.access-type{color:green}.access-type.fulltext,.access-type.index,.access-type.range{color:orange}.access-type.ALL{color:red}\n"], dependencies: [{ 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: "component", type: MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "component", type: MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass"], exportAs: ["matTab"] }, { kind: "ngmodule", type: FsClipboardModule }, { kind: "component", type: i3$4.FsClipboardButtonComponent, selector: "fs-clipboard-button", inputs: ["content", "tooltip"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { 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: "ngmodule", type: FsFormModule }, { kind: "directive", type: i2$5.FsButtonDirective, selector: "[mat-raised-button]:not([fsFormButtonStandalone]),[mat-button]:not([fsFormButtonStandalone]),[mat-flat-button]:not([fsFormButtonStandalone]),[mat-stroked-button]:not([fsFormButtonStandalone])", inputs: ["name", "dirtySubmit", "form"] }, { kind: "directive", type: MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "ngmodule", type: FsPopoverModule }, { kind: "component", type: i2$1.FsPopoverComponent, selector: "fs-popover" }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: FsCommonModule }, { kind: "pipe", type: i6.FsFormatTruncatePipe, name: "fsFormatTruncate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1797
|
+
}
|
|
1798
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: QueryLogComponent, decorators: [{
|
|
1799
|
+
type: Component,
|
|
1800
|
+
args: [{ changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [
|
|
1801
|
+
FsDialogModule,
|
|
1802
|
+
MatDialogTitle,
|
|
1803
|
+
CdkScrollable,
|
|
1804
|
+
MatDialogContent,
|
|
1805
|
+
FsLabelModule,
|
|
1806
|
+
MatTabGroup,
|
|
1807
|
+
MatTab,
|
|
1808
|
+
FsClipboardModule,
|
|
1809
|
+
NgTemplateOutlet,
|
|
1810
|
+
MatDialogActions,
|
|
1811
|
+
MatButton,
|
|
1812
|
+
FsFormModule,
|
|
1813
|
+
MatDialogClose,
|
|
1814
|
+
FsPopoverModule,
|
|
1815
|
+
NgClass,
|
|
1816
|
+
FsCommonModule,
|
|
1817
|
+
], template: "<fs-dialog>\n <h1 mat-dialog-title>Query Log</h1>\n <mat-dialog-content>\n <div class=\"fs-row.gap-lg.wrap.align-start\">\n <fs-label-field>\n <fs-label>Duration</fs-label>\n {{queryLog.duration}}\n </fs-label-field>\n\n <fs-label-field>\n <fs-label>Optimized</fs-label>\n {{queryLog.optimized ? 'Yes' : 'No'}}\n </fs-label-field>\n\n <fs-label-field>\n <fs-label>Query Cost</fs-label>\n {{queryLog.queryCost}}\n </fs-label-field>\n\n <fs-label-field>\n <fs-label>Raw Explain</fs-label>\n <a (click)=\"openExplain()\">View</a>\n </fs-label-field>\n\n <fs-label-field>\n <fs-label>URL</fs-label>\n {{queryLog.path | fsFormatTruncate: 50}}\n </fs-label-field>\n </div>\n\n <mat-tab-group>\n <mat-tab label=\"Query\">\n <fs-clipboard-button\n [content]=\"queryLog.prettyQuery\">\n </fs-clipboard-button>\n <div [innerHTML]=\"queryLog.prettyQuery\" class=\"query\"></div>\n </mat-tab>\n\n <mat-tab label=\"Explain\">\n <ng-container [ngTemplateOutlet]=\"nestedLoop\" [ngTemplateOutletContext]=\"{ queryBlock: queryBlock, selectId: queryBlock.selectId, costInfo: queryBlock.costInfo }\"></ng-container>\n </mat-tab>\n </mat-tab-group>\n\n </mat-dialog-content>\n <mat-dialog-actions>\n <button\n mat-button\n type=\"button\"\n color=\"primary\"\n [mat-dialog-close]=\"undefined\">\n Done\n </button>\n </mat-dialog-actions>\n</fs-dialog>\n\n<ng-template #nestedLoop let-queryBlock=\"queryBlock\" let-selectId=\"selectId\" let-costInfo=\"costInfo\">\n @if (selectId) {\n <h1>Select {{selectId}}</h1>\n }\n\n <div class=\"fs-row.gap-lg.wrap.align-start\">\n @if (costInfo?.queryCost) {\n <fs-label-field>\n <fs-label>Query Cost</fs-label>\n {{costInfo.queryCost}}\n </fs-label-field>\n }\n @if (queryBlock.orderingOperation) {\n <fs-label-field>\n <fs-label>Ordering Operation</fs-label>\n <ng-container [ngTemplateOutlet]=\"queryBlockCritical\" [ngTemplateOutletContext]=\"{ queryBlock: queryBlock.orderingOperation }\"></ng-container>\n </fs-label-field>\n }\n\n @if (queryBlock.groupingOperation) {\n <fs-label-field>\n <fs-label>Grouping Operation</fs-label>\n <ng-container [ngTemplateOutlet]=\"queryBlockCritical\" [ngTemplateOutletContext]=\"{ queryBlock: queryBlock.groupingOperation }\"></ng-container>\n </fs-label-field>\n }\n\n @if (queryBlock.duplicatesRemoval) {\n <fs-label-field>\n <fs-label>Duplicates Removal</fs-label>\n <ng-container [ngTemplateOutlet]=\"queryBlockCritical\" [ngTemplateOutletContext]=\"{ queryBlock: queryBlock.duplicatesRemoval }\"></ng-container>\n </fs-label-field>\n }\n </div>\n\n @if (queryBlock.orderingOperation) {\n <ng-container [ngTemplateOutlet]=\"nestedLoop\" [ngTemplateOutletContext]=\"{ queryBlock: queryBlock.orderingOperation }\"></ng-container>\n }\n\n @if (queryBlock.groupingOperation) {\n <ng-container [ngTemplateOutlet]=\"nestedLoop\" [ngTemplateOutletContext]=\"{ queryBlock: queryBlock.groupingOperation }\"></ng-container>\n }\n\n @if (queryBlock.duplicatesRemoval) {\n <ng-container [ngTemplateOutlet]=\"nestedLoop\" [ngTemplateOutletContext]=\"{ queryBlock: queryBlock.duplicatesRemoval }\"></ng-container>\n }\n\n @if (queryBlock.table) {\n <ng-container [ngTemplateOutlet]=\"nestedLoop\" [ngTemplateOutletContext]=\"{ queryBlock: { nestedLoop: [ queryBlock ]} }\"></ng-container>\n @if (queryBlock.table.attachedSubqueries) {\n <fs-label>Attached Subqueries</fs-label>\n @for (subquery of queryBlock.table.attachedSubqueries; track subquery) {\n <ng-container [ngTemplateOutlet]=\"queryBlockCritical\" [ngTemplateOutletContext]=\"{ queryBlock: subquery.queryBlock }\"></ng-container>\n <ng-container [ngTemplateOutlet]=\"nestedLoop\" [ngTemplateOutletContext]=\"{ queryBlock: subquery.queryBlock, selectId: subquery.queryBlock.selectId, costInfo: subquery.queryBlock.costInfo }\"></ng-container>\n }\n }\n }\n\n @if (queryBlock.nestedLoop) {\n <table class=\"fs-list-table style-line\">\n <thead>\n <tr>\n <th>Table</th>\n <th>Type</th>\n <th>Keys</th>\n <th>Ref</th>\n <th>Rows</th>\n <th>Filtered</th>\n <th>Extra</th>\n <th>Cost</th>\n </tr>\n </thead>\n <tbody>\n @for (item of queryBlock.nestedLoop; track item; let index = $index) {\n <tr>\n <td>\n {{item.table.tableName}}\n </td>\n <td>\n <fs-popover [template]=\"accessTypePopover\" [data]=\"item.table.accessType\">\n <span class=\"access-type\" [ngClass]=\"item.table.accessType\">{{item.table.accessType}}</span>\n </fs-popover>\n </td>\n <td>\n <fs-popover\n [template]=\"keysPopover\"\n [maxWidth]=\"null\"\n [data]=\"{ possibleKeys: item.table.possibleKeys, key: item.table.key }\">\n {{item.table.key}}\n </fs-popover>\n </td>\n <td>\n <div class=\"fs-delimit\">\n @for (ref of item.table.ref; track ref) {\n <span>{{ref}}</span>\n }\n </div>\n </td>\n <td>\n {{item.table.rowsExaminedPerScan}}\n </td>\n <td>\n {{item.table.filtered}}\n </td>\n <td>\n <div class=\"fs-delimit\">\n @if (item.table.indexCondition) {\n <span>\n <fs-popover\n [template]=\"usingIndexCondition\"\n [maxWidth]=\"null\"\n [data]=\"item.table.indexCondition\">\n Using Index Condition\n </fs-popover>\n </span>\n }\n @if (item.table.attachedCondition) {\n <span>\n <fs-popover\n [template]=\"usingWhere\"\n [maxWidth]=\"null\"\n [data]=\"item.table.attachedCondition\">\n Using Where\n </fs-popover>\n </span>\n }\n @if (item.usingIndex) {\n <span>Using Index</span>\n }\n @if (item.usingFilesort) {\n <span class=\"critical\">Using File Sort</span>\n }\n @if (item.usingTemporaryTable) {\n <span class=\"critical\">Temporary Table</span>\n }\n </div>\n </td>\n <td>\n <fs-popover [template]=\"tableCostPopover\" [data]=\"item.table?.costInfo\">\n {{item.table?.costInfo.prefixCost}}\n </fs-popover>\n <ng-template #tableCostPopover let-data=\"data\">\n <div>Eval Cost: {{data.evalCost}}</div>\n <div>Read Cost: {{data.readCost}}</div>\n <div>Prefix Cost: {{data.prefixCost}}</div>\n <div>Data Read Per Join: {{data.dataReadPerJoin}}</div>\n </ng-template>\n </td>\n </tr>\n }\n </tbody>\n </table>\n <br>\n }\n\n @if (queryBlock.selectListSubqueries) {\n <br>\n <fs-label>Select List Subqueries</fs-label>\n @for (subquery of queryBlock.selectListSubqueries; track subquery) {\n <ng-container [ngTemplateOutlet]=\"queryBlockCritical\" [ngTemplateOutletContext]=\"{ queryBlock: subquery.queryBlock }\"></ng-container>\n <ng-container [ngTemplateOutlet]=\"nestedLoop\" [ngTemplateOutletContext]=\"{ queryBlock: subquery.queryBlock, selectId: subquery.queryBlock.selectId, costInfo: subquery.queryBlock.costInfo }\"></ng-container>\n }\n }\n <!--\n <ng-container *ngIf=\"queryBlock.queryBlockattachedSubqueries\">\n <br>\n <fs-label>Attached Subqueries</fs-label>\n <ng-container *ngFor=\"let subquery of queryBlock.attachedSubqueries\">\n <ng-container [ngTemplateOutlet]=\"queryBlockCritical\" [ngTemplateOutletContext]=\"{ queryBlock: subquery.queryBlock }\"></ng-container>\n <ng-container [ngTemplateOutlet]=\"nestedLoop\" [ngTemplateOutletContext]=\"{ queryBlock: subquery.queryBlock }\"></ng-container>\n </ng-container>\n </ng-container> -->\n </ng-template>\n\n <ng-template #keysPopover let-data=\"data\">\n <div class=\"fs-delimit\">\n @for (possibleKey of data.possibleKeys; track possibleKey) {\n <span [ngClass]=\"{ 'query-log-used-key': possibleKey === data.key }\">{{possibleKey}}</span>\n }\n </div>\n </ng-template>\n\n <ng-template #usingWhere let-data=\"data\">\n {{data}}\n </ng-template>\n\n <ng-template #usingIndexCondition let-data=\"data\">\n {{data}}\n </ng-template>\n\n <ng-template #accessTypePopover let-data=\"data\">\n {{accessTypes[data]}}\n </ng-template>\n\n\n <ng-template #queryBlockCritical let-queryBlock=\"queryBlock\">\n <div class=\"fs-delimit\">\n @if (queryBlock.usingFilesort) {\n <span class=\"critical\">Using File Sort</span>\n }\n\n @if (queryBlock.usingTemporaryTable) {\n <span class=\"critical\">Temporary Table</span>\n }\n </div>\n </ng-template>", styles: ["::ng-deep .query-log-used-key{font-weight:700}::ng-deep .explain-popover{white-space:pre}.critical{color:red}fs-clipboard-button{float:right}.query{white-space:break-spaces}.access-type{color:green}.access-type.fulltext,.access-type.index,.access-type.range{color:orange}.access-type.ALL{color:red}\n"] }]
|
|
1818
|
+
}], ctorParameters: () => [] });
|
|
1819
|
+
|
|
1820
|
+
class QueryLogsComponent {
|
|
1821
|
+
_dialog = inject(MatDialog);
|
|
1822
|
+
list;
|
|
1823
|
+
loadQueryLogs;
|
|
1824
|
+
purgeQueryLogs;
|
|
1825
|
+
listConfig;
|
|
1826
|
+
openQueryLog(queryLog) {
|
|
1827
|
+
this._dialog.open(QueryLogComponent, {
|
|
1828
|
+
data: { queryLog },
|
|
1829
|
+
width: '100%',
|
|
1830
|
+
});
|
|
1831
|
+
}
|
|
1832
|
+
ngOnInit() {
|
|
1833
|
+
this.listConfig = {
|
|
1834
|
+
filters: [
|
|
1835
|
+
{
|
|
1836
|
+
name: 'keyword',
|
|
1837
|
+
type: ItemType.Keyword,
|
|
1838
|
+
label: 'Search',
|
|
1839
|
+
},
|
|
1840
|
+
{
|
|
1841
|
+
name: 'optimized',
|
|
1842
|
+
type: ItemType.Select,
|
|
1843
|
+
label: 'Optimization',
|
|
1844
|
+
values: [
|
|
1845
|
+
{ name: 'Any', value: undefined },
|
|
1846
|
+
{ name: 'Yes', value: 'true' },
|
|
1847
|
+
{ name: 'No', value: 'false' },
|
|
1848
|
+
],
|
|
1849
|
+
},
|
|
1850
|
+
{
|
|
1851
|
+
name: 'createDate',
|
|
1852
|
+
type: ItemType.DateTimeRange,
|
|
1853
|
+
label: ['From Date', 'To Date'],
|
|
1854
|
+
},
|
|
1855
|
+
{
|
|
1856
|
+
name: 'duration',
|
|
1857
|
+
type: ItemType.Range,
|
|
1858
|
+
label: ['Min Duration', 'Max Duration'],
|
|
1859
|
+
},
|
|
1860
|
+
],
|
|
1861
|
+
actions: [
|
|
1862
|
+
{
|
|
1863
|
+
label: 'Purge',
|
|
1864
|
+
primary: false,
|
|
1865
|
+
click: () => {
|
|
1866
|
+
this.purgeQueryLogs()
|
|
1867
|
+
.subscribe(() => {
|
|
1868
|
+
this.list.reload();
|
|
1869
|
+
});
|
|
1870
|
+
},
|
|
1871
|
+
},
|
|
1872
|
+
],
|
|
1873
|
+
fetch: (query) => {
|
|
1874
|
+
return this.loadQueryLogs(query)
|
|
1875
|
+
.pipe(map((response) => ({ data: response.data, paging: response.paging })));
|
|
1876
|
+
},
|
|
1877
|
+
};
|
|
1878
|
+
}
|
|
1879
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: QueryLogsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1880
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.7", type: QueryLogsComponent, isStandalone: true, selector: "fs-system-query-logs", inputs: { loadQueryLogs: "loadQueryLogs", purgeQueryLogs: "purgeQueryLogs" }, viewQueries: [{ propertyName: "list", first: true, predicate: FsListComponent, descendants: true }], ngImport: i0, template: "<fs-list [config]=\"listConfig\">\n <fs-list-column title=\"Optimized\" name=\"optimized\" [sortable]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n <span [ngClass]=\"{ optimized: row.optimized, 'not-optimized': !row.optimized }\">\n {{row.optimized ? 'Yes' : 'No'}}\n </span>\n </ng-template>\n </fs-list-column>\n <fs-list-column title=\"Duration\" name=\"duration\" [sortable]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n {{row.duration}}\n </ng-template>\n </fs-list-column>\n <fs-list-column title=\"Cost\" name=\"query_cost\" [sortable]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n {{row.queryCost}}\n </ng-template>\n </fs-list-column>\n <fs-list-column title=\"Query\">\n <ng-template fs-list-cell let-row=\"row\">\n <a (click)=\"openQueryLog(row)\">{{ row.query | fsFormatTruncate: 500 }}</a>\n </ng-template>\n </fs-list-column>\n <fs-list-column title=\"Created\" name=\"query_log_id\" [sortable]=\"true\" [direction]=\"'desc'\" [sortableDefault]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n <fs-date-ago [date]=\"row.createDate\"></fs-date-ago>\n </ng-template>\n </fs-list-column>\n</fs-list>", styles: [":host ::ng-deep .optimized{color:green}:host ::ng-deep .not-optimized{color:red}\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: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: FsDateModule }, { kind: "component", type: i4.FsDateAgoComponent, selector: "fs-date-ago", inputs: ["date", "showTime", "format", "showTooltip", "tooltipDateFormat"] }, { kind: "ngmodule", type: FsCommonModule }, { kind: "pipe", type: i6.FsFormatTruncatePipe, name: "fsFormatTruncate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1881
|
+
}
|
|
1882
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: QueryLogsComponent, decorators: [{
|
|
1883
|
+
type: Component,
|
|
1884
|
+
args: [{ selector: 'fs-system-query-logs', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [
|
|
1885
|
+
FsListModule,
|
|
1886
|
+
NgClass,
|
|
1887
|
+
FsDateModule,
|
|
1888
|
+
FsCommonModule,
|
|
1889
|
+
], template: "<fs-list [config]=\"listConfig\">\n <fs-list-column title=\"Optimized\" name=\"optimized\" [sortable]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n <span [ngClass]=\"{ optimized: row.optimized, 'not-optimized': !row.optimized }\">\n {{row.optimized ? 'Yes' : 'No'}}\n </span>\n </ng-template>\n </fs-list-column>\n <fs-list-column title=\"Duration\" name=\"duration\" [sortable]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n {{row.duration}}\n </ng-template>\n </fs-list-column>\n <fs-list-column title=\"Cost\" name=\"query_cost\" [sortable]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n {{row.queryCost}}\n </ng-template>\n </fs-list-column>\n <fs-list-column title=\"Query\">\n <ng-template fs-list-cell let-row=\"row\">\n <a (click)=\"openQueryLog(row)\">{{ row.query | fsFormatTruncate: 500 }}</a>\n </ng-template>\n </fs-list-column>\n <fs-list-column title=\"Created\" name=\"query_log_id\" [sortable]=\"true\" [direction]=\"'desc'\" [sortableDefault]=\"true\">\n <ng-template fs-list-cell let-row=\"row\">\n <fs-date-ago [date]=\"row.createDate\"></fs-date-ago>\n </ng-template>\n </fs-list-column>\n</fs-list>", styles: [":host ::ng-deep .optimized{color:green}:host ::ng-deep .not-optimized{color:red}\n"] }]
|
|
1890
|
+
}], propDecorators: { list: [{
|
|
1891
|
+
type: ViewChild,
|
|
1892
|
+
args: [FsListComponent]
|
|
1893
|
+
}], loadQueryLogs: [{
|
|
1894
|
+
type: Input
|
|
1895
|
+
}], purgeQueryLogs: [{
|
|
1896
|
+
type: Input
|
|
1897
|
+
}] } });
|
|
1898
|
+
|
|
1921
1899
|
/**
|
|
1922
1900
|
* Generated bundle index. Do not edit.
|
|
1923
1901
|
*/
|
|
1924
1902
|
|
|
1925
|
-
export { ApiLogComponent, ApiLogState, ApiLogStates, ApiLogsComponent, CronComponent, CronLogComponent, CronState, CronStates, CronsComponent, DashboardComponent, FS_SYSTEM_CONFIG, FsSystemModule,
|
|
1903
|
+
export { ApiLogComponent, ApiLogState, ApiLogStates, ApiLogsComponent, CronComponent, CronLogComponent, CronState, CronStates, CronsComponent, DashboardComponent, FS_SYSTEM_CONFIG, FsSystemModule, InfoComponent, KeyNameValuePipe, ProcessComponent, ProcessState, ProcessStates, ProcessesComponent, QueryLogsComponent, ServerLogsComponent, SettingsComponent, UpgradeLogsComponent };
|
|
1926
1904
|
//# sourceMappingURL=firestitch-system.mjs.map
|