@bitblit/ngx-acute-common 6.0.146-alpha → 6.0.147-alpha
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/package.json +7 -6
- package/src/acute-common-type-guards.ts +12 -0
- package/src/build/ngx-acute-common-info.ts +19 -0
- package/src/components/dialogs/alert/alert.component.ts +41 -0
- package/src/components/dynamic-404-helper/dynamic-404-helper.component.html +24 -0
- package/src/components/dynamic-404-helper/dynamic-404-helper.component.ts +47 -0
- package/src/components/log-display/log-display.component.html +27 -0
- package/src/components/log-display/log-display.component.ts +122 -0
- package/src/components/process-monitor-simple-display/process-monitor-simple-display.component.html +19 -0
- package/src/components/process-monitor-simple-display/process-monitor-simple-display.component.ts +41 -0
- package/src/components/process-monitor-simple-modal-display/process-monitor-simple-modal-display.component.html +21 -0
- package/src/components/process-monitor-simple-modal-display/process-monitor-simple-modal-display.component.ts +41 -0
- package/src/constants.ts +3 -0
- package/src/index.ts +41 -0
- package/src/model/google-analytics-config.ts +3 -0
- package/src/pipes/capitalize.pipe.ts +8 -0
- package/src/pipes/dollar-formatted.pipe.ts +10 -0
- package/src/pipes/duration-ms-formatted.pipe.ts +25 -0
- package/src/pipes/map-values.pipe.ts +19 -0
- package/src/pipes/number-with-commas.pipe.ts +8 -0
- package/src/pipes/order-by.pipe.ts +59 -0
- package/src/pipes/percent-formatted.pipe.ts +9 -0
- package/src/pipes/plural.pipe.ts +9 -0
- package/src/pipes/round.pipe.ts +8 -0
- package/src/pipes/time-ago-formatted.pipe.ts +10 -0
- package/src/pipes/timing.pipe.ts +18 -0
- package/src/services/css-theme.service.spec.ts +17 -0
- package/src/services/css-theme.service.ts +84 -0
- package/src/services/google-analytics.service.spec.ts +17 -0
- package/src/services/google-analytics.service.ts +65 -0
- package/src/services/graphql-query-execution-display-style.ts +5 -0
- package/src/services/graphql-query-execution-options.ts +10 -0
- package/src/services/graphql-query.service.spec.ts +17 -0
- package/src/services/graphql-query.service.ts +85 -0
- package/src/services/local-storage.service.spec.ts +17 -0
- package/src/services/local-storage.service.ts +114 -0
- package/src/services/process-monitor/monitored-processes.ts +5 -0
- package/src/services/process-monitor/process-holder.ts +10 -0
- package/src/services/process-monitor/process-monitor-display-mode.ts +6 -0
- package/src/services/process-monitor/process-monitor-service.ts +178 -0
- package/src/services/process-monitor/process-monitor-state.ts +7 -0
- package/src/services/window-ref.service.spec.ts +17 -0
- package/src/services/window-ref.service.ts +34 -0
package/package.json
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bitblit/ngx-acute-common",
|
|
3
|
-
"version": "6.0.
|
|
3
|
+
"version": "6.0.147-alpha",
|
|
4
4
|
"description": "Library for using angular",
|
|
5
5
|
"module": "lib/index.js",
|
|
6
6
|
"types": "lib/index.d.ts",
|
|
7
7
|
"files": [
|
|
8
|
+
"src/**",
|
|
8
9
|
"lib/**",
|
|
9
10
|
"bin/**"
|
|
10
11
|
],
|
|
@@ -48,8 +49,8 @@
|
|
|
48
49
|
"@angular/platform-browser": "20.3.9",
|
|
49
50
|
"@angular/platform-browser-dynamic": "20.3.9",
|
|
50
51
|
"@angular/router": "20.3.9",
|
|
51
|
-
"@bitblit/ratchet-common": "6.0.
|
|
52
|
-
"@bitblit/ratchet-graphql": "6.0.
|
|
52
|
+
"@bitblit/ratchet-common": "6.0.147-alpha",
|
|
53
|
+
"@bitblit/ratchet-graphql": "6.0.147-alpha",
|
|
53
54
|
"primeflex": "4.0.0",
|
|
54
55
|
"primeicons": "7.0.0",
|
|
55
56
|
"primeng": "20.3.0",
|
|
@@ -66,8 +67,8 @@
|
|
|
66
67
|
"@angular/platform-browser": "^20.3.9",
|
|
67
68
|
"@angular/platform-browser-dynamic": "^20.3.9",
|
|
68
69
|
"@angular/router": "^20.3.9",
|
|
69
|
-
"@bitblit/ratchet-common": "6.0.
|
|
70
|
-
"@bitblit/ratchet-graphql": "6.0.
|
|
70
|
+
"@bitblit/ratchet-common": "6.0.147-alpha",
|
|
71
|
+
"@bitblit/ratchet-graphql": "6.0.147-alpha",
|
|
71
72
|
"primeflex": "4.0.0",
|
|
72
73
|
"primeicons": "7.0.0",
|
|
73
74
|
"primeng": "20.3.0",
|
|
@@ -76,6 +77,6 @@
|
|
|
76
77
|
},
|
|
77
78
|
"devDependencies": {
|
|
78
79
|
"@angular/compiler-cli": "20.3.9",
|
|
79
|
-
"@bitblit/ratchet-node-only": "6.0.
|
|
80
|
+
"@bitblit/ratchet-node-only": "6.0.147-alpha"
|
|
80
81
|
}
|
|
81
82
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// Simple switch to see what kind of event I am looking at
|
|
2
|
+
|
|
3
|
+
import { ProcessMonitorState } from "./services/process-monitor/process-monitor-state";
|
|
4
|
+
|
|
5
|
+
export class AcuteCommonTypeGuards {
|
|
6
|
+
public static isProcessMonitorState(item: any): item is ProcessMonitorState {
|
|
7
|
+
return item && item.label && typeof item.label === 'string'
|
|
8
|
+
&& !item.detail || typeof item.detail === 'string'
|
|
9
|
+
&& !item.group || typeof item.group === 'string'
|
|
10
|
+
&& !item.percentComplete || typeof item.percentComplete === 'number';
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { BuildInformation } from '@bitblit/ratchet-common/build/build-information';
|
|
2
|
+
|
|
3
|
+
export class NgxAcuteCommonInfo {
|
|
4
|
+
// Empty constructor prevents instantiation
|
|
5
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
6
|
+
private constructor() {}
|
|
7
|
+
|
|
8
|
+
public static buildInformation(): BuildInformation {
|
|
9
|
+
const val: BuildInformation = {
|
|
10
|
+
version: 'LOCAL-SNAPSHOT',
|
|
11
|
+
hash: 'LOCAL-HASH',
|
|
12
|
+
branch: 'LOCAL-BRANCH',
|
|
13
|
+
tag: 'LOCAL-TAG',
|
|
14
|
+
timeBuiltISO: 'LOCAL-TIME-ISO',
|
|
15
|
+
notes: 'LOCAL-NOTES',
|
|
16
|
+
};
|
|
17
|
+
return val;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Component } from '@angular/core';
|
|
2
|
+
import { DialogService, DynamicDialogConfig, DynamicDialogRef } from 'primeng/dynamicdialog';
|
|
3
|
+
import { Logger } from '@bitblit/ratchet-common/logger/logger';
|
|
4
|
+
import { BehaviorSubject } from 'rxjs';
|
|
5
|
+
import { ButtonModule } from 'primeng/button';
|
|
6
|
+
import { AsyncPipe } from '@angular/common';
|
|
7
|
+
|
|
8
|
+
@Component({
|
|
9
|
+
selector: 'ngx-acute-common-alert',
|
|
10
|
+
template:
|
|
11
|
+
'<div style="display: flex; flex-direction:column; width: 33vw; max-height: 25vh; gap: 5px">' +
|
|
12
|
+
'<pre style="width: 30vw; max-height: 80%;white-space: pre-wrap">{{cfg.data.message | async}}</pre>' +
|
|
13
|
+
'<div style="display:flex; flex-direction: row; justify-content: flex-end">' +
|
|
14
|
+
'<p-button label="Ok" severity="primary" (click)="ref.close()" />' +
|
|
15
|
+
'</div></div>',
|
|
16
|
+
standalone: true,
|
|
17
|
+
imports: [ButtonModule, AsyncPipe],
|
|
18
|
+
})
|
|
19
|
+
export class AlertComponent {
|
|
20
|
+
constructor(
|
|
21
|
+
public cfg: DynamicDialogConfig,
|
|
22
|
+
protected ref: DynamicDialogRef,
|
|
23
|
+
) {
|
|
24
|
+
Logger.info('Creating AlertComponent with %j', this.cfg);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
public static showAlert(dialogSvc: DialogService, message: BehaviorSubject<string> | string, title: string = 'Alert'): DynamicDialogRef {
|
|
28
|
+
const dlg: DynamicDialogRef = dialogSvc.open(AlertComponent, {
|
|
29
|
+
//disableClose: true,
|
|
30
|
+
//autoFocus: true,
|
|
31
|
+
data: {
|
|
32
|
+
message: message instanceof BehaviorSubject ? message : new BehaviorSubject<string>(message),
|
|
33
|
+
},
|
|
34
|
+
header: title,
|
|
35
|
+
modal: true,
|
|
36
|
+
maximizable: false,
|
|
37
|
+
position: 'top',
|
|
38
|
+
});
|
|
39
|
+
return dlg;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<div class="container">
|
|
2
|
+
@if (redirectState !== 'REDIR') {
|
|
3
|
+
<div class="row">
|
|
4
|
+
<div class="col-sm-2">
|
|
5
|
+
<h3>Page Not Found</h3>
|
|
6
|
+
</div>
|
|
7
|
+
<div class="col-sm-10">
|
|
8
|
+
<h4>Oops!</h4>
|
|
9
|
+
<p>We can't find the page you are trying to reach - please <a routerLink="/secure/dashboard"> go back</a> and try again.</p>
|
|
10
|
+
</div>
|
|
11
|
+
</div>
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
@if (redirectState === 'REDIR') {
|
|
15
|
+
<div class="row">
|
|
16
|
+
<div class="col-sm-2">
|
|
17
|
+
<h3>Redirecting</h3>
|
|
18
|
+
</div>
|
|
19
|
+
<div class="col-sm-10">
|
|
20
|
+
<p>Sending you to the new version of that page...</p>
|
|
21
|
+
</div>
|
|
22
|
+
</div>
|
|
23
|
+
}
|
|
24
|
+
</div>
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { Component, OnInit } from '@angular/core';
|
|
2
|
+
import { Router, RouterModule } from '@angular/router';
|
|
3
|
+
import { Logger } from '@bitblit/ratchet-common/logger/logger';
|
|
4
|
+
import { FormsModule } from '@angular/forms';
|
|
5
|
+
import { CommonModule } from '@angular/common';
|
|
6
|
+
|
|
7
|
+
@Component({
|
|
8
|
+
selector: 'ngx-acute-common-dynamic-404-helper',
|
|
9
|
+
templateUrl: './dynamic-404-helper.component.html',
|
|
10
|
+
standalone: true,
|
|
11
|
+
imports: [RouterModule, FormsModule, CommonModule],
|
|
12
|
+
})
|
|
13
|
+
export class Dynamic404HelperComponent implements OnInit {
|
|
14
|
+
redirectState: string = null;
|
|
15
|
+
|
|
16
|
+
// These handle redirecting historical urls
|
|
17
|
+
historicalUrl: any = {
|
|
18
|
+
'/faq': '/help-faq-general',
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
constructor(public router: Router) {}
|
|
22
|
+
|
|
23
|
+
ngOnInit(): void {
|
|
24
|
+
// Check backward compatibility list
|
|
25
|
+
const oldTarget = location.pathname;
|
|
26
|
+
let currentTarget = oldTarget;
|
|
27
|
+
|
|
28
|
+
// First, strip any html extensions
|
|
29
|
+
if (currentTarget && currentTarget.toLowerCase().endsWith('.html')) {
|
|
30
|
+
currentTarget = oldTarget.substring(0, oldTarget.length - 5);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Next, check any mappings
|
|
34
|
+
if (currentTarget && this.historicalUrl[currentTarget]) {
|
|
35
|
+
currentTarget = this.historicalUrl[currentTarget];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Finally, if set, redirect
|
|
39
|
+
if (currentTarget != oldTarget) {
|
|
40
|
+
this.redirectState = 'REDIR';
|
|
41
|
+
Logger.warn('Redirecting ' + oldTarget + ' to ' + currentTarget);
|
|
42
|
+
window.location.pathname = currentTarget;
|
|
43
|
+
} else {
|
|
44
|
+
this.redirectState = 'NO';
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
<p-drawer
|
|
2
|
+
[(visible)]="visible"
|
|
3
|
+
header="Logs (Updated {{ formatTime(updatedEpoch) }}, Recording down to {{ levelLogged() }})"
|
|
4
|
+
position="full"
|
|
5
|
+
>
|
|
6
|
+
<div style="display: flex; flex-direction: row; justify-content: start; gap: 5vw">
|
|
7
|
+
<p-button (click)="refresh()" pTooltip="Refresh" icon="pi pi-refresh"></p-button>
|
|
8
|
+
<p-select-button [options]="levelFilterOptions" [(ngModel)]="levelFilterIdx" (onChange)="refresh()"></p-select-button>
|
|
9
|
+
</div>
|
|
10
|
+
<p-table [value]="snap | async">
|
|
11
|
+
<ng-template pTemplate="header">
|
|
12
|
+
<tr>
|
|
13
|
+
<th pSortableColumn="timestamp">Timestamp <p-sortIcon field="timestamp" /></th>
|
|
14
|
+
<th>Level</th>
|
|
15
|
+
<th>Message</th>
|
|
16
|
+
</tr>
|
|
17
|
+
</ng-template>
|
|
18
|
+
<ng-template pTemplate="body" let-element>
|
|
19
|
+
<tr>
|
|
20
|
+
<td>{{ formatTime(element.timestamp) }}</td>
|
|
21
|
+
<td>{{ element.lvl }}</td>
|
|
22
|
+
<td>{{ format(element) }}</td>
|
|
23
|
+
</tr>
|
|
24
|
+
</ng-template>
|
|
25
|
+
</p-table>
|
|
26
|
+
</p-drawer>
|
|
27
|
+
<p-button (click)="open()" [icon]="buttonIcon" [hidden]="!displayShowIcon" />
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { Component, HostListener, Input } from '@angular/core';
|
|
2
|
+
import { Router } from '@angular/router';
|
|
3
|
+
import { CardModule } from 'primeng/card';
|
|
4
|
+
import { ButtonModule } from 'primeng/button';
|
|
5
|
+
import { TooltipModule } from 'primeng/tooltip';
|
|
6
|
+
import { DividerModule } from 'primeng/divider';
|
|
7
|
+
import { InputTextModule } from 'primeng/inputtext';
|
|
8
|
+
import { Drawer } from 'primeng/drawer';
|
|
9
|
+
import { TableModule } from 'primeng/table';
|
|
10
|
+
import { BehaviorSubject } from 'rxjs';
|
|
11
|
+
import { AsyncPipe } from '@angular/common';
|
|
12
|
+
import { LogMessage } from '@bitblit/ratchet-common/logger/log-message';
|
|
13
|
+
import { Logger } from '@bitblit/ratchet-common/logger/logger';
|
|
14
|
+
import { DurationRatchet } from '@bitblit/ratchet-common/lang/duration-ratchet';
|
|
15
|
+
import { LoggerUtil } from '@bitblit/ratchet-common/logger/logger-util';
|
|
16
|
+
import { SelectButton } from 'primeng/selectbutton';
|
|
17
|
+
import { FormsModule } from '@angular/forms';
|
|
18
|
+
import { LoggerLevelName } from '@bitblit/ratchet-common/logger/logger-level-name';
|
|
19
|
+
|
|
20
|
+
@Component({
|
|
21
|
+
selector: 'ngx-acute-common-log-display',
|
|
22
|
+
templateUrl: './log-display.component.html',
|
|
23
|
+
styleUrls: [],
|
|
24
|
+
standalone: true,
|
|
25
|
+
imports: [
|
|
26
|
+
CardModule,
|
|
27
|
+
ButtonModule,
|
|
28
|
+
TooltipModule,
|
|
29
|
+
DividerModule,
|
|
30
|
+
InputTextModule,
|
|
31
|
+
Drawer,
|
|
32
|
+
TableModule,
|
|
33
|
+
AsyncPipe,
|
|
34
|
+
SelectButton,
|
|
35
|
+
FormsModule,
|
|
36
|
+
],
|
|
37
|
+
})
|
|
38
|
+
export class LogDisplayComponent {
|
|
39
|
+
@Input() public buttonIcon: string = 'pi pi-arrow-up';
|
|
40
|
+
@Input() public displayShowIcon: boolean = true;
|
|
41
|
+
@Input() public hotkeyEnabled: boolean = true;
|
|
42
|
+
public visible: boolean = false;
|
|
43
|
+
public snap: BehaviorSubject<LogMessage[]> = new BehaviorSubject<LogMessage[]>(this.fetchMessagesCopy());
|
|
44
|
+
public updatedEpoch: number;
|
|
45
|
+
|
|
46
|
+
public levelFilterIdx: number = LoggerUtil.loggerLevelIndex(LoggerLevelName.info);
|
|
47
|
+
public levelFilterOptions: any[];
|
|
48
|
+
|
|
49
|
+
constructor(public router: Router) {
|
|
50
|
+
const loggerLevel: number = LoggerUtil.loggerLevelIndex(Logger.getLevel());
|
|
51
|
+
this.levelFilterOptions = [];
|
|
52
|
+
for (let i = 0; i <= loggerLevel; i++) {
|
|
53
|
+
this.levelFilterOptions.push({ label: LoggerUtil.indexToLevel(i), value: i });
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
public filterLevelChange(delta: number): void {
|
|
58
|
+
const loggerLevel: number = LoggerUtil.loggerLevelIndex(Logger.getLevel());
|
|
59
|
+
const newLevelIdx: number = this.levelFilterIdx + delta;
|
|
60
|
+
if (newLevelIdx <= loggerLevel) {
|
|
61
|
+
if (LoggerUtil.indexToLevel(newLevelIdx)) {
|
|
62
|
+
this.levelFilterIdx = newLevelIdx;
|
|
63
|
+
this.refresh();
|
|
64
|
+
}
|
|
65
|
+
} else {
|
|
66
|
+
// Cant take it below what's being logged
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
public levelLoggedIdx(): number {
|
|
71
|
+
return LoggerUtil.loggerLevelIndex(Logger.getLevel());
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
public levelLogged(): LoggerLevelName {
|
|
75
|
+
return Logger.getLevel();
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
public levelFilter(): LoggerLevelName {
|
|
79
|
+
const rval: LoggerLevelName = LoggerUtil.indexToLevel(this.levelFilterIdx);
|
|
80
|
+
return rval;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
public fetchMessagesCopy(): LogMessage[] {
|
|
84
|
+
let rval: LogMessage[] = Object.assign([], Logger.getRingBuffer().getMessages().reverse());
|
|
85
|
+
rval = rval.filter((r) => {
|
|
86
|
+
return LoggerUtil.levelIsEnabled(r.lvl, this.levelFilter());
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
return rval;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
public refresh(): void {
|
|
93
|
+
this.snap.next(this.fetchMessagesCopy());
|
|
94
|
+
this.updatedEpoch = Date.now();
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
public formatTime(tm: number): string {
|
|
98
|
+
const rval: string = new Date(tm).toLocaleTimeString() + ' (' + DurationRatchet.thinFormatMsDuration(Date.now() - tm) + ' ago)';
|
|
99
|
+
return rval;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
public format(lm: LogMessage): string {
|
|
103
|
+
const rval: string = Logger.getLogger().formatMessage(lm);
|
|
104
|
+
return rval;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
public open(): void {
|
|
108
|
+
this.refresh();
|
|
109
|
+
this.visible = true;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
@HostListener('document:keypress', ['$event'])
|
|
113
|
+
systemKeypress(evt: KeyboardEvent) {
|
|
114
|
+
if (this.hotkeyEnabled && evt.code === 'KeyL' && evt.ctrlKey && evt.shiftKey) {
|
|
115
|
+
if (this.visible) {
|
|
116
|
+
this.visible = false;
|
|
117
|
+
} else {
|
|
118
|
+
this.open();
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
package/src/components/process-monitor-simple-display/process-monitor-simple-display.component.html
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
|
|
2
|
+
<p-dialog [header]="normalHeader" [closable]="false"
|
|
3
|
+
[modal]="false" [visible]="processMonitorService.hasStandardProcesses()()" position="bottom" [style]="{ width: '90rem' }">
|
|
4
|
+
|
|
5
|
+
@for(pm of processMonitorService.standardProcesses()().processes; track pm) {
|
|
6
|
+
<div style="display: flex; flex-direction: row; width: 100%">
|
|
7
|
+
<div style="display: flex; flex-direction: column; width: 50%; gap: 2px">
|
|
8
|
+
<div style="font-weight: bolder">{{pm.input().label}}</div>
|
|
9
|
+
<div style="font-style: italic; margin-left: 15px">{{pm.input().detail}}</div>
|
|
10
|
+
</div>
|
|
11
|
+
@if (pm.input().percentComplete) {
|
|
12
|
+
<div style="min-width: 50vw">
|
|
13
|
+
<p-progress-bar [value]="pm.input().percentComplete" />
|
|
14
|
+
</div>
|
|
15
|
+
}
|
|
16
|
+
</div>
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
</p-dialog>
|
package/src/components/process-monitor-simple-display/process-monitor-simple-display.component.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Component, Input } from "@angular/core";
|
|
2
|
+
import { FormsModule, ReactiveFormsModule } from "@angular/forms";
|
|
3
|
+
import { ContextMenuModule } from "primeng/contextmenu";
|
|
4
|
+
import { CardModule } from "primeng/card";
|
|
5
|
+
import { MultiSelectModule } from "primeng/multiselect";
|
|
6
|
+
import { TableModule } from "primeng/table";
|
|
7
|
+
import { PanelModule } from "primeng/panel";
|
|
8
|
+
import { InputGroupAddonModule } from "primeng/inputgroupaddon";
|
|
9
|
+
import { InputGroupModule } from "primeng/inputgroup";
|
|
10
|
+
import { ProgressBar } from "primeng/progressbar";
|
|
11
|
+
import { Dialog } from "primeng/dialog";
|
|
12
|
+
import { ProcessMonitorService } from "../../services/process-monitor/process-monitor-service";
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@Component({
|
|
16
|
+
selector: 'ngx-acute-common-process-monitor-simple-display',
|
|
17
|
+
templateUrl: './process-monitor-simple-display.component.html',
|
|
18
|
+
imports: [
|
|
19
|
+
CardModule,
|
|
20
|
+
MultiSelectModule,
|
|
21
|
+
ContextMenuModule,
|
|
22
|
+
TableModule,
|
|
23
|
+
ReactiveFormsModule,
|
|
24
|
+
PanelModule,
|
|
25
|
+
InputGroupAddonModule,
|
|
26
|
+
InputGroupModule,
|
|
27
|
+
FormsModule,
|
|
28
|
+
ProgressBar,
|
|
29
|
+
Dialog
|
|
30
|
+
],
|
|
31
|
+
standalone: true
|
|
32
|
+
})
|
|
33
|
+
export class ProcessMonitorSimpleDisplayComponent {
|
|
34
|
+
@Input() public normalHeader: string=null;
|
|
35
|
+
|
|
36
|
+
constructor(
|
|
37
|
+
public processMonitorService: ProcessMonitorService
|
|
38
|
+
) {
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
|
|
2
|
+
<p-dialog [header]="header" [modal]="true"
|
|
3
|
+
[closable]="false"
|
|
4
|
+
[visible]="processMonitorService.hasModalProcesses()()" position="center" [style]="{ width: '90rem' }">
|
|
5
|
+
@for(pm of processMonitorService.modalProcesses()().processes; track pm) {
|
|
6
|
+
<div style="display: flex; flex-direction: row; width: 100%">
|
|
7
|
+
|
|
8
|
+
<div style="display: flex; flex-direction: column; width: 50%; gap: 2px">
|
|
9
|
+
<div style="font-weight: bolder">{{pm.input().label}}</div>
|
|
10
|
+
@if (pm.input().detail) {
|
|
11
|
+
<div style="font-style: italic; margin-left: 15px">{{pm.input().detail}}</div>
|
|
12
|
+
}
|
|
13
|
+
</div>
|
|
14
|
+
@if(pm.input().percentComplete) {
|
|
15
|
+
<div style="min-width: 50vw">
|
|
16
|
+
<p-progress-bar [value]="pm.input().percentComplete" />
|
|
17
|
+
</div>
|
|
18
|
+
}
|
|
19
|
+
</div>
|
|
20
|
+
}
|
|
21
|
+
</p-dialog>
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Component, Input } from "@angular/core";
|
|
2
|
+
import { FormsModule, ReactiveFormsModule } from "@angular/forms";
|
|
3
|
+
import { ContextMenuModule } from "primeng/contextmenu";
|
|
4
|
+
import { CardModule } from "primeng/card";
|
|
5
|
+
import { MultiSelectModule } from "primeng/multiselect";
|
|
6
|
+
import { TableModule } from "primeng/table";
|
|
7
|
+
import { PanelModule } from "primeng/panel";
|
|
8
|
+
import { InputGroupAddonModule } from "primeng/inputgroupaddon";
|
|
9
|
+
import { InputGroupModule } from "primeng/inputgroup";
|
|
10
|
+
import { ProgressBar } from "primeng/progressbar";
|
|
11
|
+
import { Dialog } from "primeng/dialog";
|
|
12
|
+
import { ProcessMonitorService } from "../../services/process-monitor/process-monitor-service";
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@Component({
|
|
16
|
+
selector: 'ngx-acute-common-process-monitor-simple-modal-display',
|
|
17
|
+
templateUrl: './process-monitor-simple-modal-display.component.html',
|
|
18
|
+
imports: [
|
|
19
|
+
CardModule,
|
|
20
|
+
MultiSelectModule,
|
|
21
|
+
ContextMenuModule,
|
|
22
|
+
TableModule,
|
|
23
|
+
ReactiveFormsModule,
|
|
24
|
+
PanelModule,
|
|
25
|
+
InputGroupAddonModule,
|
|
26
|
+
InputGroupModule,
|
|
27
|
+
FormsModule,
|
|
28
|
+
ProgressBar,
|
|
29
|
+
Dialog
|
|
30
|
+
],
|
|
31
|
+
standalone: true
|
|
32
|
+
})
|
|
33
|
+
export class ProcessMonitorSimpleModalDisplayComponent {
|
|
34
|
+
@Input() public header: string=null;
|
|
35
|
+
|
|
36
|
+
constructor(
|
|
37
|
+
public processMonitorService: ProcessMonitorService
|
|
38
|
+
) {
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
}
|
package/src/constants.ts
ADDED
package/src/index.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export * from './constants';
|
|
2
|
+
|
|
3
|
+
export * from './build/ngx-acute-common-info';
|
|
4
|
+
|
|
5
|
+
export * from './components/log-display/log-display.component';
|
|
6
|
+
|
|
7
|
+
export * from './components/dialogs/alert/alert.component';
|
|
8
|
+
|
|
9
|
+
export * from './components/process-monitor-simple-modal-display/process-monitor-simple-modal-display.component';
|
|
10
|
+
export * from './components/process-monitor-simple-display/process-monitor-simple-display.component';
|
|
11
|
+
|
|
12
|
+
export * from './acute-common-type-guards';
|
|
13
|
+
|
|
14
|
+
export * from './model/google-analytics-config';
|
|
15
|
+
|
|
16
|
+
export * from './pipes/capitalize.pipe';
|
|
17
|
+
export * from './pipes/dollar-formatted.pipe';
|
|
18
|
+
export * from './pipes/map-values.pipe';
|
|
19
|
+
export * from './pipes/number-with-commas.pipe';
|
|
20
|
+
export * from './pipes/order-by.pipe';
|
|
21
|
+
export * from './pipes/percent-formatted.pipe';
|
|
22
|
+
export * from './pipes/plural.pipe';
|
|
23
|
+
export * from './pipes/round.pipe';
|
|
24
|
+
export * from './pipes/time-ago-formatted.pipe';
|
|
25
|
+
export * from './pipes/timing.pipe';
|
|
26
|
+
export * from './pipes/duration-ms-formatted.pipe';
|
|
27
|
+
|
|
28
|
+
export * from './services/google-analytics.service';
|
|
29
|
+
export * from './services/graphql-query.service';
|
|
30
|
+
export * from './services/graphql-query-execution-display-style';
|
|
31
|
+
export * from './services/graphql-query-execution-options';
|
|
32
|
+
export * from './services/local-storage.service';
|
|
33
|
+
export * from './services/css-theme.service';
|
|
34
|
+
export * from './services/window-ref.service';
|
|
35
|
+
|
|
36
|
+
export * from './services/process-monitor/monitored-processes';
|
|
37
|
+
export * from './services/process-monitor/process-holder';
|
|
38
|
+
export * from './services/process-monitor/process-monitor-display-mode';
|
|
39
|
+
export * from './services/process-monitor/process-monitor-service';
|
|
40
|
+
export * from './services/process-monitor/process-monitor-state';
|
|
41
|
+
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Pipe, PipeTransform } from '@angular/core';
|
|
2
|
+
|
|
3
|
+
@Pipe({ name: 'ngxAcuteCapitalize', standalone: true })
|
|
4
|
+
export class CapitalizePipe implements PipeTransform {
|
|
5
|
+
transform(input: string): string {
|
|
6
|
+
return input && input.length ? input.charAt(0).toUpperCase() + input.slice(1).toLowerCase() : input;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Pipe, PipeTransform } from '@angular/core';
|
|
2
|
+
import { CurrencyRatchet } from '@bitblit/ratchet-common/lang/currency-ratchet';
|
|
3
|
+
|
|
4
|
+
@Pipe({ name: 'ngxAcuteDollars', standalone: true })
|
|
5
|
+
export class DollarFormattedPipe implements PipeTransform {
|
|
6
|
+
transform(input: number): string {
|
|
7
|
+
const rval: string = input === null || input === undefined ? 'Null' : CurrencyRatchet.dollarFormat(input);
|
|
8
|
+
return rval;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Pipe, PipeTransform } from "@angular/core";
|
|
2
|
+
import { DurationRatchet } from "@bitblit/ratchet-common/lang/duration-ratchet";
|
|
3
|
+
import { StringRatchet } from "@bitblit/ratchet-common/lang/string-ratchet";
|
|
4
|
+
import { NumberRatchet } from "@bitblit/ratchet-common/lang/number-ratchet";
|
|
5
|
+
|
|
6
|
+
@Pipe({ name: "ngxDurationMsFormat", standalone: true })
|
|
7
|
+
export class DurationMsFormattedPipe implements PipeTransform {
|
|
8
|
+
transform(ms: number | string, style: string='standard', includeMS: boolean=false): string {
|
|
9
|
+
const toFormat: number = NumberRatchet.safeNumber(ms, 0);
|
|
10
|
+
let rval: string;
|
|
11
|
+
switch (StringRatchet.trimToEmpty(style)) {
|
|
12
|
+
case "thin":
|
|
13
|
+
rval = DurationRatchet.thinFormatMsDuration(toFormat, includeMS);
|
|
14
|
+
break;
|
|
15
|
+
case "colon":
|
|
16
|
+
rval = DurationRatchet.colonFormatMsDuration(toFormat, includeMS);
|
|
17
|
+
break;
|
|
18
|
+
default:
|
|
19
|
+
rval = DurationRatchet.formatMsDuration(toFormat, includeMS);
|
|
20
|
+
break;
|
|
21
|
+
}
|
|
22
|
+
return rval;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Pipe, PipeTransform } from '@angular/core';
|
|
2
|
+
import { Logger } from '@bitblit/ratchet-common/logger/logger';
|
|
3
|
+
|
|
4
|
+
@Pipe({ name: 'ngxAcuteMapValues', standalone: true })
|
|
5
|
+
export class MapValuesPipe implements PipeTransform {
|
|
6
|
+
transform(value: any, args?: any[]): any[] {
|
|
7
|
+
const returnArray = [];
|
|
8
|
+
|
|
9
|
+
for (const k of Object.keys(value)) {
|
|
10
|
+
returnArray.push({
|
|
11
|
+
key: k,
|
|
12
|
+
val: value[k],
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
Logger.info('Map values : %j : %j', returnArray, args);
|
|
17
|
+
return returnArray;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Pipe, PipeTransform } from '@angular/core';
|
|
2
|
+
|
|
3
|
+
@Pipe({ name: 'ngxAcuteNumberWithCommas', standalone: true })
|
|
4
|
+
export class NumberWithCommasPipe implements PipeTransform {
|
|
5
|
+
transform(input: number): string {
|
|
6
|
+
return new Intl.NumberFormat().format(input);
|
|
7
|
+
}
|
|
8
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { Pipe, PipeTransform } from '@angular/core';
|
|
2
|
+
|
|
3
|
+
@Pipe({ name: 'ngxAcuteOderBy', pure: false, standalone: true })
|
|
4
|
+
export class OrderByPipe implements PipeTransform {
|
|
5
|
+
static _orderByComparator(a: any, b: any): number {
|
|
6
|
+
if (isNaN(parseFloat(a)) || !isFinite(a) || isNaN(parseFloat(b)) || !isFinite(b)) {
|
|
7
|
+
//Isn't a number so lowercase the string to properly compare
|
|
8
|
+
if (String(a).toLowerCase() < String(b).toLowerCase()) return -1;
|
|
9
|
+
if (String(a).toLowerCase() > String(b).toLowerCase()) return 1;
|
|
10
|
+
} else {
|
|
11
|
+
//Parse strings as numbers to compare properly
|
|
12
|
+
if (parseFloat(a) < parseFloat(b)) return -1;
|
|
13
|
+
if (parseFloat(a) > parseFloat(b)) return 1;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return 0; //equal each other
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
transform(input: any, [config = '+']): any {
|
|
20
|
+
if (!Array.isArray(input)) return input;
|
|
21
|
+
|
|
22
|
+
if (!Array.isArray(config) || (Array.isArray(config) && config.length == 1)) {
|
|
23
|
+
const propertyToCheck: string = !Array.isArray(config) ? config : config[0];
|
|
24
|
+
const desc = propertyToCheck.substr(0, 1) == '-';
|
|
25
|
+
|
|
26
|
+
//Basic array
|
|
27
|
+
if (!propertyToCheck || propertyToCheck == '-' || propertyToCheck == '+') {
|
|
28
|
+
return !desc ? input.sort() : input.sort().reverse();
|
|
29
|
+
} else {
|
|
30
|
+
const property: string =
|
|
31
|
+
propertyToCheck.substr(0, 1) == '+' || propertyToCheck.substr(0, 1) == '-' ? propertyToCheck.substr(1) : propertyToCheck;
|
|
32
|
+
|
|
33
|
+
return input.sort(function (a: any, b: any) {
|
|
34
|
+
return !desc
|
|
35
|
+
? OrderByPipe._orderByComparator(a[property], b[property])
|
|
36
|
+
: -OrderByPipe._orderByComparator(a[property], b[property]);
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
} else {
|
|
40
|
+
//Loop over property of the array in order and sort
|
|
41
|
+
return input.sort(function (a: any, b: any) {
|
|
42
|
+
for (const cEntry of config) {
|
|
43
|
+
//for (let i: number = 0; i < config.length; i++) {
|
|
44
|
+
const desc = cEntry.substr(0, 1) == '-';
|
|
45
|
+
const property = cEntry.substr(0, 1) == '+' || cEntry.substr(0, 1) == '-' ? cEntry.substr(1) : cEntry;
|
|
46
|
+
|
|
47
|
+
const comparison = !desc
|
|
48
|
+
? OrderByPipe._orderByComparator(a[property], b[property])
|
|
49
|
+
: -OrderByPipe._orderByComparator(a[property], b[property]);
|
|
50
|
+
|
|
51
|
+
//Don't return 0 yet in case of needing to sort by next property
|
|
52
|
+
if (comparison != 0) return comparison;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return 0; //equal each other
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|