@mosa-ng/material 17.0.0
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/.eslintrc.json +31 -0
- package/README.md +24 -0
- package/ng-package.json +10 -0
- package/package.json +12 -0
- package/src/lib/components/alert-widget/alert-widget.module.ts +17 -0
- package/src/lib/components/alert-widget/alert.widget.html +7 -0
- package/src/lib/components/alert-widget/alert.widget.scss +50 -0
- package/src/lib/components/alert-widget/alert.widget.ts +61 -0
- package/src/lib/components/base/base.module.ts +14 -0
- package/src/lib/components/base/cell-editor.base.component.ts +79 -0
- package/src/lib/components/cell-editor/cell-editor.component.html +6 -0
- package/src/lib/components/cell-editor/cell-editor.component.scss +53 -0
- package/src/lib/components/cell-editor/cell-editor.component.ts +115 -0
- package/src/lib/components/cell-editor/cell-editor.module.ts +15 -0
- package/src/lib/components/confirm-dialog/confirm-dialog.module.ts +19 -0
- package/src/lib/components/confirm-dialog/confirm.dialog.html +15 -0
- package/src/lib/components/confirm-dialog/confirm.dialog.scss +3 -0
- package/src/lib/components/confirm-dialog/confirm.dialog.ts +60 -0
- package/src/lib/components/loading-button/loading-button.component.html +42 -0
- package/src/lib/components/loading-button/loading-button.component.scss +40 -0
- package/src/lib/components/loading-button/loading-button.component.ts +42 -0
- package/src/lib/components/loading-button/loading-button.module.ts +21 -0
- package/src/lib/components/logger/README.md +83 -0
- package/src/lib/components/logger/logger.component.html +32 -0
- package/src/lib/components/logger/logger.component.scss +120 -0
- package/src/lib/components/logger/logger.component.ts +116 -0
- package/src/lib/components/logger/logger.module.ts +23 -0
- package/src/lib/components/skeleton-loader/base.skeleton-loader.ts +14 -0
- package/src/lib/components/skeleton-loader/list-skeleton-loader/list-skeleton-loader.module.ts +17 -0
- package/src/lib/components/skeleton-loader/list-skeleton-loader/list.skeleton-loader.html +5 -0
- package/src/lib/components/skeleton-loader/list-skeleton-loader/list.skeleton-loader.scss +0 -0
- package/src/lib/components/skeleton-loader/list-skeleton-loader/list.skeleton-loader.ts +26 -0
- package/src/lib/components/skeleton-loader/skeleton/skeleton.component.html +0 -0
- package/src/lib/components/skeleton-loader/skeleton/skeleton.component.scss +15 -0
- package/src/lib/components/skeleton-loader/skeleton/skeleton.component.ts +64 -0
- package/src/lib/components/skeleton-loader/skeleton-loader.module.ts +17 -0
- package/src/lib/components/skeleton-loader/table-skeleton-loader/table-skeleton-loader.module.ts +19 -0
- package/src/lib/components/skeleton-loader/table-skeleton-loader/table.skeleton-loader.html +12 -0
- package/src/lib/components/skeleton-loader/table-skeleton-loader/table.skeleton-loader.scss +3 -0
- package/src/lib/components/skeleton-loader/table-skeleton-loader/table.skeleton-loader.ts +44 -0
- package/src/lib/components/update-dialog/mat-update-dialog/mat-update.dialog.html +17 -0
- package/src/lib/components/update-dialog/mat-update-dialog/mat-update.dialog.scss +3 -0
- package/src/lib/components/update-dialog/mat-update-dialog/mat-update.dialog.ts +28 -0
- package/src/lib/components/update-dialog/update-dialog.module.ts +22 -0
- package/src/lib/components/update-dialog/update.dialog.ts +124 -0
- package/src/lib/directives/cell-editor/cell-editor.directive.module.ts +15 -0
- package/src/lib/directives/cell-editor/cell-editor.directive.ts +163 -0
- package/src/lib/directives/click-outside/click-outside.directive.module.ts +15 -0
- package/src/lib/directives/click-outside/click-outside.directive.ts +48 -0
- package/src/lib/models/confirm-dialog.model.ts +33 -0
- package/src/lib/models/skeleton.model.ts +19 -0
- package/src/lib/models/states/cell-editor-base-state.model.ts +3 -0
- package/src/lib/models/states/logger-state.model.ts +5 -0
- package/src/lib/models/table-item.model.ts +6 -0
- package/src/lib/models/update-config.model.ts +20 -0
- package/src/lib/mosa-material.module.ts +26 -0
- package/src/lib/services/cell-editor.service.ts +46 -0
- package/src/lib/services/facades/logger.facade.ts +37 -0
- package/src/lib/services/logger.service.ts +49 -0
- package/src/lib/styles/_vars.scss +71 -0
- package/src/public-api.ts +1 -0
- package/tsconfig.lib.json +14 -0
- package/tsconfig.lib.prod.json +10 -0
- package/tsconfig.spec.json +14 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
:host {
|
|
2
|
+
pointer-events: none;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
button:not(:disabled) {
|
|
6
|
+
pointer-events: all;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.icon-spinner {
|
|
10
|
+
position: absolute;
|
|
11
|
+
top: 0;
|
|
12
|
+
left: 0;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.spinner {
|
|
16
|
+
.spinner-inner {
|
|
17
|
+
display: flex;
|
|
18
|
+
align-items: center;
|
|
19
|
+
|
|
20
|
+
mat-spinner {
|
|
21
|
+
position: absolute;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.label.loading {
|
|
25
|
+
margin-left: 30px;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.progress-bar {
|
|
31
|
+
overflow: hidden;
|
|
32
|
+
position: relative;
|
|
33
|
+
|
|
34
|
+
mat-progress-bar {
|
|
35
|
+
position: absolute;
|
|
36
|
+
bottom: 0;
|
|
37
|
+
left: 0;
|
|
38
|
+
width: 100%;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';
|
|
2
|
+
import { ThemePalette } from '@angular/material/core';
|
|
3
|
+
|
|
4
|
+
@Component({
|
|
5
|
+
selector: 'mosa-loading-button',
|
|
6
|
+
templateUrl: './loading-button.component.html',
|
|
7
|
+
styleUrls: [ './loading-button.component.scss' ],
|
|
8
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
9
|
+
})
|
|
10
|
+
export class LoadingButtonComponent {
|
|
11
|
+
|
|
12
|
+
@Input()
|
|
13
|
+
public mode: 'spinner' | 'progress-bar' = 'spinner';
|
|
14
|
+
|
|
15
|
+
@Input()
|
|
16
|
+
public loading: boolean;
|
|
17
|
+
|
|
18
|
+
@Input()
|
|
19
|
+
public disabled: boolean;
|
|
20
|
+
|
|
21
|
+
@Input()
|
|
22
|
+
public color: ThemePalette = 'primary';
|
|
23
|
+
|
|
24
|
+
@Input()
|
|
25
|
+
public buttonType: 'default' | 'raised' | 'stroked' | 'flat' | 'icon';
|
|
26
|
+
|
|
27
|
+
@Input()
|
|
28
|
+
public icon: string;
|
|
29
|
+
|
|
30
|
+
@Output()
|
|
31
|
+
// eslint-disable-next-line @angular-eslint/no-output-native
|
|
32
|
+
public click: EventEmitter<MouseEvent> = new EventEmitter<MouseEvent>();
|
|
33
|
+
|
|
34
|
+
constructor() {
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
public onClick(e: MouseEvent): void {
|
|
38
|
+
e.stopPropagation();
|
|
39
|
+
this.click.emit(e);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { CommonModule } from '@angular/common';
|
|
2
|
+
import { NgModule } from '@angular/core';
|
|
3
|
+
import { MatButtonModule } from '@angular/material/button';
|
|
4
|
+
import { MatIconModule } from '@angular/material/icon';
|
|
5
|
+
import { MatProgressBarModule } from '@angular/material/progress-bar';
|
|
6
|
+
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
|
7
|
+
import { LoadingButtonComponent } from './loading-button.component';
|
|
8
|
+
|
|
9
|
+
@NgModule({
|
|
10
|
+
declarations: [ LoadingButtonComponent ],
|
|
11
|
+
imports: [
|
|
12
|
+
CommonModule,
|
|
13
|
+
MatProgressSpinnerModule,
|
|
14
|
+
MatProgressBarModule,
|
|
15
|
+
MatButtonModule,
|
|
16
|
+
MatIconModule,
|
|
17
|
+
],
|
|
18
|
+
exports: [ LoadingButtonComponent ],
|
|
19
|
+
})
|
|
20
|
+
export class LoadingButtonModule {
|
|
21
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# Logger
|
|
2
|
+
|
|
3
|
+
The mosa logger is a tool to display messages / infos to a user. It can also be used to catch http request errors and
|
|
4
|
+
directly display the error message to the user
|
|
5
|
+
|
|
6
|
+
## Example usage
|
|
7
|
+
|
|
8
|
+
### HTML
|
|
9
|
+
|
|
10
|
+
`````html
|
|
11
|
+
<mosa-logger></mosa-logger>
|
|
12
|
+
`````
|
|
13
|
+
|
|
14
|
+
### TypeScript
|
|
15
|
+
|
|
16
|
+
````typescript
|
|
17
|
+
export class AppComponent implements OnInit {
|
|
18
|
+
|
|
19
|
+
@ViewChild(LoggerComponent)
|
|
20
|
+
public set logger(logger: LoggerComponent) {
|
|
21
|
+
this.myLoggerService.logger(logger, this.defaultLoggerConfig);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
constructor(
|
|
25
|
+
private myCoreLoggerService: CoreLoggerService,
|
|
26
|
+
private myLoggerService: LoggerService,
|
|
27
|
+
) {
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
public ngOnInit(): void {
|
|
31
|
+
// Subscribe to ui logs
|
|
32
|
+
this.defaultLoggerConfig = {
|
|
33
|
+
debug: !environment.production,
|
|
34
|
+
closeOnClick: false,
|
|
35
|
+
showDismiss: true,
|
|
36
|
+
};
|
|
37
|
+
this.myCoreLoggerService.subUiLogs()
|
|
38
|
+
.subscribe((data: ILogEvent): void => {
|
|
39
|
+
if (data) {
|
|
40
|
+
this.myLoggerService.show({
|
|
41
|
+
title: data.title,
|
|
42
|
+
msg: data.msg,
|
|
43
|
+
...data.config,
|
|
44
|
+
...this.defaultLoggerConfig as ILoggerConfig,
|
|
45
|
+
}, data.type);
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
````
|
|
51
|
+
|
|
52
|
+
## Logger features
|
|
53
|
+
|
|
54
|
+
For model definition see [ILoggerConfig](../../../../../core/src/lib/models/logger/logger-config.model.ts)
|
|
55
|
+
|
|
56
|
+
````typescript
|
|
57
|
+
// Subscribe to each log emitted in the code, or from http requests
|
|
58
|
+
this.myLoggerService.subUiLogs()
|
|
59
|
+
|
|
60
|
+
// Get error message from an object
|
|
61
|
+
this.myLoggerService.getErrorMsg(err);
|
|
62
|
+
|
|
63
|
+
// Get error title from an object
|
|
64
|
+
this.myLoggerService.getErrorTitle(err);
|
|
65
|
+
|
|
66
|
+
// Log an error
|
|
67
|
+
this.myLoggerService.logError({ msg: message });
|
|
68
|
+
|
|
69
|
+
// Log a success message
|
|
70
|
+
this.myLoggerService.logSuccess({ msg: message });
|
|
71
|
+
|
|
72
|
+
// Log a warning message
|
|
73
|
+
this.myLoggerService.logWarning({ msg: message });
|
|
74
|
+
|
|
75
|
+
// Log an info message
|
|
76
|
+
this.myLoggerService.logInfo({ msg: message });
|
|
77
|
+
|
|
78
|
+
// Any kind of log
|
|
79
|
+
this.myLoggerService.log({ msg: message });
|
|
80
|
+
|
|
81
|
+
// Any kind of log
|
|
82
|
+
this.myLoggerService.show({ msg: message }, 'default');
|
|
83
|
+
````
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
<ng-container *ngIf="loggerState$ | async as state">
|
|
2
|
+
<div #loggerElement
|
|
3
|
+
*ngFor="let log of state.logs"
|
|
4
|
+
[@slide]="log.state"
|
|
5
|
+
[class.none]="!log.state"
|
|
6
|
+
[class]="log.config.className"
|
|
7
|
+
(click)="onClickLog(log)"
|
|
8
|
+
[class.touch]="log.config.closeOnClick"
|
|
9
|
+
class="logger-element">
|
|
10
|
+
|
|
11
|
+
<div class="content">
|
|
12
|
+
<mat-icon class="icon">{{ log.icon }}</mat-icon>
|
|
13
|
+
<div>
|
|
14
|
+
<div *ngIf="log.title" class="title">{{ log.title | translate }}</div>
|
|
15
|
+
<div *ngIf="log.message" [innerHTML]="log.message | translate" class="message"></div>
|
|
16
|
+
</div>
|
|
17
|
+
</div>
|
|
18
|
+
|
|
19
|
+
<div *ngIf="log.config.action || log.config.showDismiss" class="actions">
|
|
20
|
+
<button (click)="slideOut(log.id)" *ngIf="log.config.showDismiss" class="dismiss" mat-button>
|
|
21
|
+
{{ 'mosa.commons.buttons.dismiss' | translate | uppercase }}
|
|
22
|
+
</button>
|
|
23
|
+
<button (click)="$event.stopPropagation(); callAction(log)"
|
|
24
|
+
*ngIf="log.config.action && log.config.action.label && log.config.action.callback"
|
|
25
|
+
class="action-btn" mat-button>
|
|
26
|
+
{{ log.config.action.label | translate | uppercase }}
|
|
27
|
+
</button>
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
</div>
|
|
31
|
+
</ng-container>
|
|
32
|
+
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
@import "../../styles/vars";
|
|
2
|
+
|
|
3
|
+
:host {
|
|
4
|
+
@include size(100%, 100%);
|
|
5
|
+
@include move(0, 0);
|
|
6
|
+
@include flex(true, false);
|
|
7
|
+
position: fixed;
|
|
8
|
+
z-index: 10000;
|
|
9
|
+
align-items: flex-end;
|
|
10
|
+
pointer-events: none;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.logger-element {
|
|
14
|
+
padding: 10px 15px;
|
|
15
|
+
margin: 10px 10px 0;
|
|
16
|
+
width: 350px;
|
|
17
|
+
background: $white;
|
|
18
|
+
border-radius: 4px;
|
|
19
|
+
box-shadow: 3px 3px 10px rgba($black, .3);
|
|
20
|
+
border-left: 5px solid;
|
|
21
|
+
pointer-events: all;
|
|
22
|
+
max-height: 400px;
|
|
23
|
+
|
|
24
|
+
&.touch {
|
|
25
|
+
cursor: pointer;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.content {
|
|
29
|
+
display: flex;
|
|
30
|
+
width: 100%;
|
|
31
|
+
|
|
32
|
+
.icon {
|
|
33
|
+
flex-shrink: 0;
|
|
34
|
+
margin-right: 10px;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.title {
|
|
38
|
+
font-weight: 500;
|
|
39
|
+
color: #222222;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.message {
|
|
43
|
+
@include maxLines();
|
|
44
|
+
flex: 1 auto;
|
|
45
|
+
font-size: 15px;
|
|
46
|
+
margin-top: 3px;
|
|
47
|
+
color: #222222;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.actions {
|
|
52
|
+
display: flex;
|
|
53
|
+
justify-content: flex-end;
|
|
54
|
+
margin-top: 10px;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.dismiss {
|
|
58
|
+
color: #222222;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
button:not(:first-child) {
|
|
62
|
+
margin-left: 10px;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
&.snackbar-error {
|
|
66
|
+
border-color: $danger;
|
|
67
|
+
color: $danger;
|
|
68
|
+
|
|
69
|
+
button.action-btn {
|
|
70
|
+
background-color: darken($danger, 15%);
|
|
71
|
+
color: $white;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
&.snackbar-success {
|
|
76
|
+
border-color: $success;
|
|
77
|
+
color: $success;
|
|
78
|
+
|
|
79
|
+
button.action-btn {
|
|
80
|
+
background-color: darken($success, 15%);
|
|
81
|
+
color: $white;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
&.snackbar-warning {
|
|
86
|
+
border-color: $warning;
|
|
87
|
+
color: $warning;
|
|
88
|
+
|
|
89
|
+
button.action-btn {
|
|
90
|
+
background-color: darken($warning, 10%);
|
|
91
|
+
color: $white;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
&.snackbar-info {
|
|
96
|
+
border-color: $info;
|
|
97
|
+
color: $info;
|
|
98
|
+
|
|
99
|
+
button.action-btn {
|
|
100
|
+
background-color: darken($info, 15%);
|
|
101
|
+
color: $white;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
&.snackbar-default {
|
|
106
|
+
border-color: #222222;
|
|
107
|
+
color: #222222;
|
|
108
|
+
|
|
109
|
+
button.action-btn {
|
|
110
|
+
background-color: #222222;
|
|
111
|
+
color: $white;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
@media screen and (max-width: 480px) {
|
|
117
|
+
.logger-element {
|
|
118
|
+
width: 100%;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { animate, state, style, transition, trigger } from '@angular/animations';
|
|
2
|
+
import { ChangeDetectionStrategy, Component, OnInit, QueryList, ViewChildren } from '@angular/core';
|
|
3
|
+
import { ILog, ILoggerConfig } from '@mosa-ng/core';
|
|
4
|
+
import { Observable } from 'rxjs';
|
|
5
|
+
import { ILoggerState } from '../../models/states/logger-state.model';
|
|
6
|
+
import { LoggerFacade } from '../../services/facades/logger.facade';
|
|
7
|
+
import { BaseComponent } from '../base/base.component';
|
|
8
|
+
|
|
9
|
+
@Component({
|
|
10
|
+
selector: 'mosa-logger',
|
|
11
|
+
templateUrl: './logger.component.html',
|
|
12
|
+
styleUrls: [ './logger.component.scss' ],
|
|
13
|
+
animations: [
|
|
14
|
+
trigger('slide', [
|
|
15
|
+
state('enter', style({ transform: 'translateX(0)' })),
|
|
16
|
+
transition(':leave', [
|
|
17
|
+
animate(200, style({ transform: 'translateX(120%)' })),
|
|
18
|
+
]),
|
|
19
|
+
transition(':enter', [
|
|
20
|
+
style({ transform: 'translateX(120%)' }),
|
|
21
|
+
animate(200, style({ transform: 'translateX(0)' })),
|
|
22
|
+
]),
|
|
23
|
+
]),
|
|
24
|
+
],
|
|
25
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
26
|
+
})
|
|
27
|
+
export class LoggerComponent extends BaseComponent implements OnInit {
|
|
28
|
+
|
|
29
|
+
@ViewChildren('loggerElement')
|
|
30
|
+
public elements: QueryList<HTMLElement>;
|
|
31
|
+
|
|
32
|
+
public loggerState$: Observable<ILoggerState>;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Default constructor
|
|
36
|
+
* @param myLoggerFacade
|
|
37
|
+
*/
|
|
38
|
+
constructor(
|
|
39
|
+
private readonly myLoggerFacade: LoggerFacade,
|
|
40
|
+
) {
|
|
41
|
+
super();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
public override ngOnInit(): void {
|
|
45
|
+
super.ngOnInit();
|
|
46
|
+
this.loggerState$ = this.myLoggerFacade.subState();
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
public onClickLog(log: ILog): void {
|
|
50
|
+
if (log.config.closeOnClick) {
|
|
51
|
+
this.slideOut(log.id);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Shows the snackbar
|
|
57
|
+
* @param title
|
|
58
|
+
* @param message
|
|
59
|
+
* @param type
|
|
60
|
+
* @param config
|
|
61
|
+
*/
|
|
62
|
+
public slideIn(title: string, message: string, type: string, config: ILoggerConfig): number {
|
|
63
|
+
const logs: ILog[] = [ ...this.myLoggerFacade.snapshot.logs ];
|
|
64
|
+
const i = logs.length;
|
|
65
|
+
let icon: string;
|
|
66
|
+
|
|
67
|
+
switch (type) {
|
|
68
|
+
case 'error':
|
|
69
|
+
icon = 'error';
|
|
70
|
+
break;
|
|
71
|
+
case 'warning':
|
|
72
|
+
icon = 'warning';
|
|
73
|
+
break;
|
|
74
|
+
case 'info':
|
|
75
|
+
icon = 'info';
|
|
76
|
+
break;
|
|
77
|
+
case 'success':
|
|
78
|
+
icon = 'done';
|
|
79
|
+
break;
|
|
80
|
+
case 'default':
|
|
81
|
+
icon = 'notifications';
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
logs.push({ id: i, title, message, config, state: 'enter', icon });
|
|
86
|
+
this.myLoggerFacade.updateLogs(logs);
|
|
87
|
+
return i;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Hides the log
|
|
92
|
+
* @param id
|
|
93
|
+
*/
|
|
94
|
+
public slideOut(id: number): void {
|
|
95
|
+
let logs: ILog[] = [ ...this.myLoggerFacade.snapshot.logs ];
|
|
96
|
+
if (logs.length > 0) {
|
|
97
|
+
const item = logs.find((e: ILog): boolean => e.id === id);
|
|
98
|
+
if (item) {
|
|
99
|
+
item.state = 'leave';
|
|
100
|
+
this.myLoggerFacade.updateLogs(logs);
|
|
101
|
+
setTimeout((): void => {
|
|
102
|
+
logs = [ ...this.myLoggerFacade.snapshot.logs ];
|
|
103
|
+
const index = logs.findIndex((log: ILog): boolean => log.id === item.id);
|
|
104
|
+
logs.splice(index, 1);
|
|
105
|
+
this.myLoggerFacade.updateLogs(logs);
|
|
106
|
+
}, 200);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
public callAction(log: ILog): void {
|
|
112
|
+
log.config.action.callback.call(this);
|
|
113
|
+
this.slideOut(log.id);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { CommonModule } from '@angular/common';
|
|
2
|
+
import { NgModule } from '@angular/core';
|
|
3
|
+
import { MatButtonModule } from '@angular/material/button';
|
|
4
|
+
import { MatIconModule } from '@angular/material/icon';
|
|
5
|
+
import { TranslateModule } from '@ngx-translate/core';
|
|
6
|
+
import { LoggerComponent } from './logger.component';
|
|
7
|
+
|
|
8
|
+
@NgModule({
|
|
9
|
+
declarations: [
|
|
10
|
+
LoggerComponent,
|
|
11
|
+
],
|
|
12
|
+
imports: [
|
|
13
|
+
CommonModule,
|
|
14
|
+
MatIconModule,
|
|
15
|
+
MatButtonModule,
|
|
16
|
+
TranslateModule,
|
|
17
|
+
],
|
|
18
|
+
exports: [
|
|
19
|
+
LoggerComponent,
|
|
20
|
+
],
|
|
21
|
+
})
|
|
22
|
+
export class LoggerModule {
|
|
23
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
|
2
|
+
|
|
3
|
+
@Component({
|
|
4
|
+
selector: 'mosa-skeleton-loader',
|
|
5
|
+
template: '',
|
|
6
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
7
|
+
})
|
|
8
|
+
// eslint-disable-next-line @angular-eslint/component-class-suffix
|
|
9
|
+
export class BaseSkeletonLoader {
|
|
10
|
+
|
|
11
|
+
@Input()
|
|
12
|
+
public itemCount: number;
|
|
13
|
+
|
|
14
|
+
}
|
package/src/lib/components/skeleton-loader/list-skeleton-loader/list-skeleton-loader.module.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { CommonModule } from '@angular/common';
|
|
2
|
+
import { NgModule } from '@angular/core';
|
|
3
|
+
import { MatListModule } from '@angular/material/list';
|
|
4
|
+
import { SkeletonLoaderModule } from '../skeleton-loader.module';
|
|
5
|
+
import { ListSkeletonLoader } from './list.skeleton-loader';
|
|
6
|
+
|
|
7
|
+
@NgModule({
|
|
8
|
+
declarations: [ ListSkeletonLoader ],
|
|
9
|
+
imports: [
|
|
10
|
+
CommonModule,
|
|
11
|
+
MatListModule,
|
|
12
|
+
SkeletonLoaderModule,
|
|
13
|
+
],
|
|
14
|
+
exports: [ ListSkeletonLoader ],
|
|
15
|
+
})
|
|
16
|
+
export class ListSkeletonLoaderModule {
|
|
17
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { ChangeDetectionStrategy, Component, Input, OnInit, TemplateRef } from '@angular/core';
|
|
2
|
+
import { BaseSkeletonLoader } from '../base.skeleton-loader';
|
|
3
|
+
|
|
4
|
+
@Component({
|
|
5
|
+
selector: 'mosa-list-skeleton-loader',
|
|
6
|
+
templateUrl: './list.skeleton-loader.html',
|
|
7
|
+
styleUrls: [ './list.skeleton-loader.scss' ],
|
|
8
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
9
|
+
})
|
|
10
|
+
// eslint-disable-next-line @angular-eslint/component-class-suffix
|
|
11
|
+
export class ListSkeletonLoader extends BaseSkeletonLoader implements OnInit {
|
|
12
|
+
|
|
13
|
+
@Input()
|
|
14
|
+
public content: TemplateRef<unknown>;
|
|
15
|
+
|
|
16
|
+
public items: number[] = [];
|
|
17
|
+
|
|
18
|
+
constructor() {
|
|
19
|
+
super();
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
public ngOnInit(): void {
|
|
23
|
+
this.items = Array(this.itemCount).fill(this.itemCount).map((x: number, i: number): number => i);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
}
|
|
File without changes
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { ChangeDetectionStrategy, Component, ElementRef, Input, OnInit } from '@angular/core';
|
|
2
|
+
import { Skeleton } from '../../../models/skeleton.model';
|
|
3
|
+
|
|
4
|
+
@Component({
|
|
5
|
+
selector: 'mosa-skeleton',
|
|
6
|
+
templateUrl: './skeleton.component.html',
|
|
7
|
+
styleUrls: [ './skeleton.component.scss' ],
|
|
8
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
9
|
+
})
|
|
10
|
+
export class SkeletonComponent implements OnInit {
|
|
11
|
+
|
|
12
|
+
@Input()
|
|
13
|
+
public skeleton: Skeleton;
|
|
14
|
+
|
|
15
|
+
@Input()
|
|
16
|
+
public width: number | string;
|
|
17
|
+
|
|
18
|
+
@Input()
|
|
19
|
+
public height: number | string;
|
|
20
|
+
|
|
21
|
+
@Input()
|
|
22
|
+
public randomizeOffset: number;
|
|
23
|
+
|
|
24
|
+
@Input()
|
|
25
|
+
public borderRadius: number | string;
|
|
26
|
+
|
|
27
|
+
private readonly element: HTMLElement;
|
|
28
|
+
|
|
29
|
+
constructor(
|
|
30
|
+
private readonly myElementRef: ElementRef,
|
|
31
|
+
) {
|
|
32
|
+
this.element = this.myElementRef.nativeElement;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
public ngOnInit(): void {
|
|
36
|
+
if (!this.skeleton) {
|
|
37
|
+
this.skeleton = new Skeleton({
|
|
38
|
+
width: this.width,
|
|
39
|
+
height: this.height,
|
|
40
|
+
borderRadius: this.borderRadius,
|
|
41
|
+
randomizeOffset: this.randomizeOffset,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
this.element.style.width = this.actualWidth;
|
|
45
|
+
this.element.style.height = SkeletonComponent.value(this.skeleton.height);
|
|
46
|
+
this.element.style.borderRadius = SkeletonComponent.value(this.skeleton.borderRadius);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
private get actualWidth(): string {
|
|
50
|
+
if (this.skeleton.randomizeOffset > 0 && typeof this.skeleton.width === 'number') {
|
|
51
|
+
return `${ this.skeleton.width - Math.floor(Math.random() * this.skeleton.randomizeOffset) }px`;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return SkeletonComponent.value(this.skeleton.width);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
private static value(val: number | string): string {
|
|
58
|
+
if (typeof val === 'number') {
|
|
59
|
+
return `${ val }px`;
|
|
60
|
+
}
|
|
61
|
+
return val;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { CommonModule } from '@angular/common';
|
|
2
|
+
import { NgModule } from '@angular/core';
|
|
3
|
+
import { BaseSkeletonLoader } from './base.skeleton-loader';
|
|
4
|
+
import { SkeletonComponent } from './skeleton/skeleton.component';
|
|
5
|
+
|
|
6
|
+
@NgModule({
|
|
7
|
+
declarations: [ BaseSkeletonLoader, SkeletonComponent ],
|
|
8
|
+
imports: [
|
|
9
|
+
CommonModule,
|
|
10
|
+
],
|
|
11
|
+
exports: [
|
|
12
|
+
BaseSkeletonLoader,
|
|
13
|
+
SkeletonComponent,
|
|
14
|
+
],
|
|
15
|
+
})
|
|
16
|
+
export class SkeletonLoaderModule {
|
|
17
|
+
}
|
package/src/lib/components/skeleton-loader/table-skeleton-loader/table-skeleton-loader.module.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { CommonModule } from '@angular/common';
|
|
2
|
+
import { NgModule } from '@angular/core';
|
|
3
|
+
import { MatTableModule } from '@angular/material/table';
|
|
4
|
+
import { SkeletonLoaderModule } from '../skeleton-loader.module';
|
|
5
|
+
import { TableSkeletonLoader } from './table.skeleton-loader';
|
|
6
|
+
|
|
7
|
+
@NgModule({
|
|
8
|
+
declarations: [ TableSkeletonLoader ],
|
|
9
|
+
imports: [
|
|
10
|
+
CommonModule,
|
|
11
|
+
MatTableModule,
|
|
12
|
+
SkeletonLoaderModule,
|
|
13
|
+
],
|
|
14
|
+
exports: [
|
|
15
|
+
TableSkeletonLoader,
|
|
16
|
+
],
|
|
17
|
+
})
|
|
18
|
+
export class TableSkeletonLoaderModule {
|
|
19
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<table [dataSource]="items" mat-table>
|
|
2
|
+
<ng-container *ngFor="let column of columns; let i = index;" [matColumnDef]="'column-' + i">
|
|
3
|
+
<th *matHeaderCellDef mat-header-cell>
|
|
4
|
+
<mosa-skeleton [skeleton]="column[0]"></mosa-skeleton>
|
|
5
|
+
</th>
|
|
6
|
+
<td *matCellDef="let row" mat-cell>
|
|
7
|
+
<mosa-skeleton [skeleton]="column[1]"></mosa-skeleton>
|
|
8
|
+
</td>
|
|
9
|
+
</ng-container>
|
|
10
|
+
<tr *matHeaderRowDef="displayedColumns;sticky:true" mat-header-row></tr>
|
|
11
|
+
<tr *matRowDef="let row; columns: displayedColumns;" class="row-hover" mat-row></tr>
|
|
12
|
+
</table>
|