@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.
Files changed (64) hide show
  1. package/.eslintrc.json +31 -0
  2. package/README.md +24 -0
  3. package/ng-package.json +10 -0
  4. package/package.json +12 -0
  5. package/src/lib/components/alert-widget/alert-widget.module.ts +17 -0
  6. package/src/lib/components/alert-widget/alert.widget.html +7 -0
  7. package/src/lib/components/alert-widget/alert.widget.scss +50 -0
  8. package/src/lib/components/alert-widget/alert.widget.ts +61 -0
  9. package/src/lib/components/base/base.module.ts +14 -0
  10. package/src/lib/components/base/cell-editor.base.component.ts +79 -0
  11. package/src/lib/components/cell-editor/cell-editor.component.html +6 -0
  12. package/src/lib/components/cell-editor/cell-editor.component.scss +53 -0
  13. package/src/lib/components/cell-editor/cell-editor.component.ts +115 -0
  14. package/src/lib/components/cell-editor/cell-editor.module.ts +15 -0
  15. package/src/lib/components/confirm-dialog/confirm-dialog.module.ts +19 -0
  16. package/src/lib/components/confirm-dialog/confirm.dialog.html +15 -0
  17. package/src/lib/components/confirm-dialog/confirm.dialog.scss +3 -0
  18. package/src/lib/components/confirm-dialog/confirm.dialog.ts +60 -0
  19. package/src/lib/components/loading-button/loading-button.component.html +42 -0
  20. package/src/lib/components/loading-button/loading-button.component.scss +40 -0
  21. package/src/lib/components/loading-button/loading-button.component.ts +42 -0
  22. package/src/lib/components/loading-button/loading-button.module.ts +21 -0
  23. package/src/lib/components/logger/README.md +83 -0
  24. package/src/lib/components/logger/logger.component.html +32 -0
  25. package/src/lib/components/logger/logger.component.scss +120 -0
  26. package/src/lib/components/logger/logger.component.ts +116 -0
  27. package/src/lib/components/logger/logger.module.ts +23 -0
  28. package/src/lib/components/skeleton-loader/base.skeleton-loader.ts +14 -0
  29. package/src/lib/components/skeleton-loader/list-skeleton-loader/list-skeleton-loader.module.ts +17 -0
  30. package/src/lib/components/skeleton-loader/list-skeleton-loader/list.skeleton-loader.html +5 -0
  31. package/src/lib/components/skeleton-loader/list-skeleton-loader/list.skeleton-loader.scss +0 -0
  32. package/src/lib/components/skeleton-loader/list-skeleton-loader/list.skeleton-loader.ts +26 -0
  33. package/src/lib/components/skeleton-loader/skeleton/skeleton.component.html +0 -0
  34. package/src/lib/components/skeleton-loader/skeleton/skeleton.component.scss +15 -0
  35. package/src/lib/components/skeleton-loader/skeleton/skeleton.component.ts +64 -0
  36. package/src/lib/components/skeleton-loader/skeleton-loader.module.ts +17 -0
  37. package/src/lib/components/skeleton-loader/table-skeleton-loader/table-skeleton-loader.module.ts +19 -0
  38. package/src/lib/components/skeleton-loader/table-skeleton-loader/table.skeleton-loader.html +12 -0
  39. package/src/lib/components/skeleton-loader/table-skeleton-loader/table.skeleton-loader.scss +3 -0
  40. package/src/lib/components/skeleton-loader/table-skeleton-loader/table.skeleton-loader.ts +44 -0
  41. package/src/lib/components/update-dialog/mat-update-dialog/mat-update.dialog.html +17 -0
  42. package/src/lib/components/update-dialog/mat-update-dialog/mat-update.dialog.scss +3 -0
  43. package/src/lib/components/update-dialog/mat-update-dialog/mat-update.dialog.ts +28 -0
  44. package/src/lib/components/update-dialog/update-dialog.module.ts +22 -0
  45. package/src/lib/components/update-dialog/update.dialog.ts +124 -0
  46. package/src/lib/directives/cell-editor/cell-editor.directive.module.ts +15 -0
  47. package/src/lib/directives/cell-editor/cell-editor.directive.ts +163 -0
  48. package/src/lib/directives/click-outside/click-outside.directive.module.ts +15 -0
  49. package/src/lib/directives/click-outside/click-outside.directive.ts +48 -0
  50. package/src/lib/models/confirm-dialog.model.ts +33 -0
  51. package/src/lib/models/skeleton.model.ts +19 -0
  52. package/src/lib/models/states/cell-editor-base-state.model.ts +3 -0
  53. package/src/lib/models/states/logger-state.model.ts +5 -0
  54. package/src/lib/models/table-item.model.ts +6 -0
  55. package/src/lib/models/update-config.model.ts +20 -0
  56. package/src/lib/mosa-material.module.ts +26 -0
  57. package/src/lib/services/cell-editor.service.ts +46 -0
  58. package/src/lib/services/facades/logger.facade.ts +37 -0
  59. package/src/lib/services/logger.service.ts +49 -0
  60. package/src/lib/styles/_vars.scss +71 -0
  61. package/src/public-api.ts +1 -0
  62. package/tsconfig.lib.json +14 -0
  63. package/tsconfig.lib.prod.json +10 -0
  64. package/tsconfig.spec.json +14 -0
@@ -0,0 +1,44 @@
1
+ import { ChangeDetectionStrategy, Component, Input, OnInit } from '@angular/core';
2
+ import { Skeleton } from '../../../models/skeleton.model';
3
+ import { BaseSkeletonLoader } from '../base.skeleton-loader';
4
+
5
+ @Component({
6
+ selector: 'mosa-table-skeleton-loader',
7
+ templateUrl: './table.skeleton-loader.html',
8
+ styleUrls: [ './table.skeleton-loader.scss' ],
9
+ changeDetection: ChangeDetectionStrategy.OnPush,
10
+ })
11
+ // eslint-disable-next-line @angular-eslint/component-class-suffix
12
+ export class TableSkeletonLoader extends BaseSkeletonLoader implements OnInit {
13
+
14
+ @Input()
15
+ public columns: Skeleton[][];
16
+
17
+ public items: Skeleton[][] = [];
18
+ public displayedColumns: string[] = [];
19
+
20
+ constructor() {
21
+ super();
22
+ }
23
+
24
+ public ngOnInit(): void {
25
+ for (let i = 0; i < this.columns.length; i++) {
26
+ this.displayedColumns.push(`column-${ i }`);
27
+ }
28
+
29
+ for (let i = 0; i < this.itemCount; i++) {
30
+ const skeletons: Skeleton[] = [];
31
+ for (let j = 0; j < this.displayedColumns.length; j++) {
32
+ const skeleton = this.columns[ j ][ 1 ];
33
+ skeletons.push(new Skeleton({
34
+ width: skeleton.width,
35
+ height: skeleton.height,
36
+ borderRadius: skeleton.borderRadius,
37
+ randomizeOffset: skeleton.randomizeOffset,
38
+ }));
39
+ }
40
+ this.items.push(skeletons);
41
+ }
42
+ }
43
+
44
+ }
@@ -0,0 +1,17 @@
1
+ <h1 class="active" mat-dialog-title>{{ config.title | translate }}</h1>
2
+ <div mat-dialog-content>
3
+ {{ config.message | translate }}
4
+ </div>
5
+ <div mat-dialog-actions>
6
+ <button (click)="close(0)" [class.cancel-btn]="config.showIgnore" mat-stroked-button>
7
+ {{ 'mosa.commons.buttons.cancel' | translate | uppercase }}
8
+ </button>
9
+ <button (click)="close(1)" *ngIf="config.showIgnore" color="primary" mat-stroked-button>
10
+ {{ 'mosa.commons.buttons.ignoreFor' | translate: {
11
+ duration: config.ignoreTimeout | mosaDuration: 'auto' | async | uppercase
12
+ } | uppercase }}
13
+ </button>
14
+ <button mat-flat-button color="primary" (click)="close(2)">
15
+ {{ 'mosa.commons.buttons.reloadNow' | translate | uppercase}}
16
+ </button>
17
+ </div>
@@ -0,0 +1,3 @@
1
+ .cancel-btn {
2
+ margin-right: auto;
3
+ }
@@ -0,0 +1,28 @@
1
+ import { Component, Inject, OnInit } from '@angular/core';
2
+ import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
3
+ import { IUpdateConfig, UpdateDialogResult } from '../../../models/update-config.model';
4
+ import { BaseComponent } from '../../base/base.component';
5
+
6
+ @Component({
7
+ selector: 'mosa-mat-update-dialog',
8
+ templateUrl: './mat-update.dialog.html',
9
+ styleUrls: [ './mat-update.dialog.scss' ],
10
+ })
11
+ export class MatUpdateDialog extends BaseComponent implements OnInit {
12
+
13
+ constructor(
14
+ private readonly myMatDialogRef: MatDialogRef<MatUpdateDialog>,
15
+ @Inject(MAT_DIALOG_DATA) public readonly config: IUpdateConfig,
16
+ ) {
17
+ super();
18
+ }
19
+
20
+ public override ngOnInit(): void {
21
+ super.ngOnInit();
22
+ }
23
+
24
+ public close(result: UpdateDialogResult): void {
25
+ this.myMatDialogRef.close(result);
26
+ }
27
+
28
+ }
@@ -0,0 +1,22 @@
1
+ import { CommonModule } from '@angular/common';
2
+ import { NgModule } from '@angular/core';
3
+ import { TranslateModule } from '@ngx-translate/core';
4
+ import { MatUpdateDialog } from './mat-update-dialog/mat-update.dialog';
5
+ import { UpdateDialog } from './update.dialog';
6
+ import { MatDialogModule } from '@angular/material/dialog';
7
+ import { MatButtonModule } from '@angular/material/button';
8
+ import { MosaDurationPipeModule } from '@mosa-ng/core';
9
+
10
+ @NgModule({
11
+ declarations: [ UpdateDialog, MatUpdateDialog ],
12
+ imports: [
13
+ CommonModule,
14
+ MatDialogModule,
15
+ MatButtonModule,
16
+ MosaDurationPipeModule,
17
+ TranslateModule,
18
+ ],
19
+ exports: [ UpdateDialog ],
20
+ })
21
+ export class UpdateDialogModule {
22
+ }
@@ -0,0 +1,124 @@
1
+ import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
2
+ import { MatDialog } from '@angular/material/dialog';
3
+ import { ApiService, isNullOrEmpty } from '@mosa-ng/core';
4
+ import { firstValueFrom, timer } from 'rxjs';
5
+ import { IUpdateConfig, IVersion, UpdateDialogResult } from '../../models/update-config.model';
6
+ import { MatUpdateDialog } from './mat-update-dialog/mat-update.dialog';
7
+
8
+ @Component({
9
+ selector: 'mosa-update-dialog',
10
+ template: '',
11
+ changeDetection: ChangeDetectionStrategy.OnPush,
12
+ })
13
+ export class UpdateDialog {
14
+
15
+ // eslint-disable-next-line @angular-eslint/no-input-rename
16
+ @Input('config')
17
+ public set updateConfig(config: IUpdateConfig) {
18
+ if (config) {
19
+ if (!config.versionPath) {
20
+ console.warn('LoggerService: No version path was provided. This field is required!');
21
+ return;
22
+ }
23
+
24
+ if (!config.localStorageKey) {
25
+ config.localStorageKey = 'mosaApplicationVersion';
26
+ }
27
+
28
+ if (!config.ignoreTimeout) {
29
+ config.ignoreTimeout = 30000;
30
+ }
31
+
32
+ if (!config.refreshInterval) {
33
+ config.refreshInterval = 15000;
34
+ }
35
+
36
+ if (!config.title) {
37
+ config.title = 'mosa.components.updateDialog.title';
38
+ }
39
+
40
+ if (!config.message) {
41
+ config.message = 'mosa.components.updateDialog.message';
42
+ }
43
+
44
+ this.config = config;
45
+ this.end();
46
+ this.start();
47
+ } else {
48
+ console.warn('LoggerService: Cannot check for version. No config was provided.');
49
+ }
50
+ }
51
+
52
+ private firstLoad: boolean = true;
53
+
54
+ private blocked: boolean;
55
+ private interval: NodeJS.Timeout;
56
+ private config: IUpdateConfig;
57
+
58
+ constructor(
59
+ private readonly myApiService: ApiService,
60
+ private readonly myMatDialog: MatDialog,
61
+ ) {
62
+ }
63
+
64
+ private start(): void {
65
+ if (this.interval) {
66
+ this.end();
67
+ }
68
+ void this.checkForUpdate();
69
+ this.interval = setInterval((): Promise<void> => this.checkForUpdate(), this.config.refreshInterval);
70
+ }
71
+
72
+ private openDialog(version: IVersion): void {
73
+ this.myMatDialog
74
+ .open(MatUpdateDialog, {
75
+ width: '600px',
76
+ data: this.config,
77
+ })
78
+ .afterClosed()
79
+ .subscribe((result: UpdateDialogResult): void => {
80
+ switch (result) {
81
+ case UpdateDialogResult.cancel:
82
+ this.end();
83
+ this.blocked = true;
84
+ break;
85
+ case UpdateDialogResult.ignore:
86
+ timer(this.config.ignoreTimeout).subscribe((): void => {
87
+ this.openDialog(version);
88
+ });
89
+ break;
90
+ case UpdateDialogResult.reload:
91
+ window.location.reload();
92
+ window.localStorage.setItem(this.config.localStorageKey, JSON.stringify(version));
93
+ break;
94
+ }
95
+ });
96
+ }
97
+
98
+ private async checkForUpdate(): Promise<void> {
99
+ if (!this.blocked) {
100
+ const localStorageVersion: string = window.localStorage.getItem(this.config.localStorageKey);
101
+ let localVersion: IVersion = { version: '0.0.0', timestamp: 0 };
102
+ if (!isNullOrEmpty(localStorageVersion)) {
103
+ localVersion = JSON.parse(localStorageVersion);
104
+ }
105
+ const data: IVersion = await firstValueFrom(this.myApiService.get(this.config.versionPath));
106
+ if (this.firstLoad) {
107
+ window.localStorage.setItem(this.config.localStorageKey, JSON.stringify(data));
108
+ this.firstLoad = false;
109
+ return;
110
+ }
111
+ if (data.version !== localVersion.version) {
112
+ this.blocked = true;
113
+ this.end();
114
+ this.openDialog(data);
115
+ }
116
+ }
117
+ }
118
+
119
+ private end(): void {
120
+ clearInterval(this.interval);
121
+ this.interval = null;
122
+ }
123
+
124
+ }
@@ -0,0 +1,15 @@
1
+ import { CommonModule } from '@angular/common';
2
+ import { NgModule } from '@angular/core';
3
+ import { CellEditorDirective } from './cell-editor.directive';
4
+
5
+ @NgModule({
6
+ declarations: [ CellEditorDirective ],
7
+ imports: [
8
+ CommonModule,
9
+ ],
10
+ exports: [
11
+ CellEditorDirective,
12
+ ],
13
+ })
14
+ export class CellEditorDirectiveModule {
15
+ }
@@ -0,0 +1,163 @@
1
+ import { ContentChild, Directive, ElementRef, HostListener, OnInit } from '@angular/core';
2
+ import { CellEditorComponent } from '../../components/cell-editor/cell-editor.component';
3
+ import { CellEditorService } from '../../services/cell-editor.service';
4
+
5
+ @Directive({
6
+ selector: 'td[mosaCellEditor]',
7
+ })
8
+ export class CellEditorDirective implements OnInit {
9
+
10
+ @ContentChild(CellEditorComponent)
11
+ private readonly cellEditor: CellEditorComponent;
12
+
13
+ constructor(
14
+ private readonly myElementRef: ElementRef<HTMLElement>,
15
+ private readonly myCellEditorService: CellEditorService,
16
+ ) {
17
+ }
18
+
19
+ @HostListener('keydown.escape', [ '$event' ])
20
+ public onEscapeKeyDown(e: KeyboardEvent): void {
21
+ e.preventDefault();
22
+ this.cellEditor.toOutput();
23
+ }
24
+
25
+ @HostListener('keydown.tab', [ '$event' ])
26
+ @HostListener('keydown.shift.tab', [ '$event' ])
27
+ @HostListener('keydown.meta.tab', [ '$event' ])
28
+ public onShiftKeyDown(e: KeyboardEvent): void {
29
+ e.preventDefault();
30
+ if (e.shiftKey) {
31
+ this.moveToCell(e, false);
32
+ } else {
33
+ this.moveToCell(e, true);
34
+ }
35
+ }
36
+
37
+ @HostListener('keydown.enter', [ '$event' ])
38
+ public onEnterKeyDown(e: KeyboardEvent): void {
39
+ e.preventDefault();
40
+ if (this.myCellEditorService.isEditingCellValid()) {
41
+ this.moveToNextRowCell(e);
42
+ }
43
+ }
44
+
45
+ @HostListener('click', [ '$event' ])
46
+ public onClick(e: MouseEvent): void {
47
+ e.preventDefault();
48
+ this.myCellEditorService.updateEditingCell(this.cellEditor);
49
+ this.cellEditor.cellClick.emit();
50
+ }
51
+
52
+ public ngOnInit(): void {
53
+ this.myElementRef.nativeElement.classList.add('editable-cell');
54
+ }
55
+
56
+ private moveToNextRowCell(e: KeyboardEvent): void {
57
+ const currentCell: Element = this.cellEditor?.element?.parentElement;
58
+ if (!currentCell) {
59
+ return;
60
+ }
61
+
62
+ let columnDefClass: string = '';
63
+ currentCell.classList.forEach((className: string): void => {
64
+ const found: boolean = className.indexOf('mat-column-') > -1;
65
+ if (found) {
66
+ columnDefClass = className;
67
+ }
68
+ });
69
+
70
+ const targetCell: HTMLElement = this.findNextRowEditableColumn(currentCell, columnDefClass);
71
+ this.cellEditor.toOutput(true);
72
+ CellEditorDirective.executeMove(e, targetCell);
73
+ }
74
+
75
+ private findNextRowEditableColumn(row: Element, matColumnClassName: string): HTMLElement {
76
+ const nextRow: Element = row.parentElement?.nextElementSibling;
77
+ if (!nextRow) {
78
+ return null;
79
+ }
80
+
81
+ const column: Element = nextRow.getElementsByClassName(matColumnClassName)[ 0 ];
82
+ return column?.classList.contains('editable-cell') ?
83
+ column.firstChild as HTMLElement :
84
+ this.findNextRowEditableColumn(nextRow, matColumnClassName);
85
+ }
86
+
87
+ private findNextEditableColumn(cell: HTMLElement): HTMLElement {
88
+ let nextCell: HTMLElement = cell.parentElement?.nextElementSibling as HTMLElement;
89
+
90
+ if (!nextCell) {
91
+ const nextRow: HTMLElement = cell.parentElement.parentElement.nextElementSibling as HTMLElement;
92
+ if (nextRow) {
93
+ nextCell = nextRow.firstElementChild as HTMLElement;
94
+ }
95
+ }
96
+
97
+ if (nextCell) {
98
+ return nextCell.classList.contains('editable-cell') ?
99
+ nextCell.firstChild as HTMLElement :
100
+ this.findNextEditableColumn(nextCell);
101
+ } else {
102
+ return null;
103
+ }
104
+ }
105
+
106
+ private findPreviousEditableColumn(cell: HTMLElement): HTMLElement {
107
+ let prevCell: HTMLElement = cell.previousElementSibling as HTMLElement;
108
+
109
+ if (!prevCell) {
110
+ const previousRow: HTMLElement = cell.parentElement.previousElementSibling as HTMLElement;
111
+ if (previousRow) {
112
+ prevCell = previousRow.lastElementChild as HTMLElement;
113
+ }
114
+ }
115
+
116
+ if (prevCell) {
117
+ return prevCell.classList.contains('editable-cell') ?
118
+ prevCell.firstChild as HTMLElement :
119
+ this.findPreviousEditableColumn(prevCell);
120
+ } else {
121
+ return null;
122
+ }
123
+ }
124
+
125
+ private moveToCell(event: KeyboardEvent, nextCell: boolean): void {
126
+ const currentCell: HTMLElement = this.cellEditor.element;
127
+ if (this.cellEditor.element != null) {
128
+ const targetCell: HTMLElement = nextCell ?
129
+ this.findNextEditableColumn(currentCell) :
130
+ this.findPreviousEditableColumn(currentCell);
131
+ if (this.myCellEditorService.isEditingCellValid()) {
132
+ this.cellEditor.toOutput(true);
133
+ targetCell?.click();
134
+ }
135
+ CellEditorDirective.executeMove(event, targetCell);
136
+ }
137
+ }
138
+
139
+ private static invokeElementMethod(element: HTMLElement, methodName: string, args?: unknown[]): void {
140
+ // eslint-disable-next-line prefer-spread
141
+ (element[ methodName as keyof HTMLElement ] as Function).apply(element, args);
142
+ }
143
+
144
+ private static executeMove(e: KeyboardEvent, targetCell: HTMLElement): void {
145
+ e.preventDefault();
146
+ // If datepicker is opened, remove cdk-overlay from dom
147
+ const element: Element = e.composedPath()[ 0 ] as Element;
148
+ if (element.className.indexOf('td-input-date') > -1) {
149
+ const cdkOverlayContainer: Element = document.getElementsByClassName('cdk-overlay-container')[ 0 ];
150
+ const cdkBackdrop: HTMLElement = cdkOverlayContainer.getElementsByClassName('cdk-overlay-backdrop')[ 0 ] as HTMLElement;
151
+ if (cdkBackdrop != null) {
152
+ CellEditorDirective.invokeElementMethod(cdkBackdrop, 'click');
153
+ }
154
+ cdkOverlayContainer.innerHTML = '';
155
+ }
156
+
157
+ CellEditorDirective.invokeElementMethod(e.target as HTMLElement, 'blur');
158
+ if (targetCell != null) {
159
+ CellEditorDirective.invokeElementMethod(targetCell, 'click');
160
+ }
161
+ }
162
+
163
+ }
@@ -0,0 +1,15 @@
1
+ import { CommonModule } from '@angular/common';
2
+ import { NgModule } from '@angular/core';
3
+ import { ClickOutsideDirective } from './click-outside.directive';
4
+
5
+ @NgModule({
6
+ declarations: [
7
+ ClickOutsideDirective,
8
+ ],
9
+ imports: [
10
+ CommonModule,
11
+ ],
12
+ exports: [ ClickOutsideDirective ],
13
+ })
14
+ export class ClickOutsideDirectiveModule {
15
+ }
@@ -0,0 +1,48 @@
1
+ import { Directive, ElementRef, EventEmitter, HostListener, Input, Output } from '@angular/core';
2
+
3
+ @Directive({
4
+ // eslint-disable-next-line @angular-eslint/directive-selector
5
+ selector: '[clickOutside]',
6
+ })
7
+ export class ClickOutsideDirective {
8
+
9
+ @Output()
10
+ public clickOutside: EventEmitter<[ HTMLElement, HTMLElement ]> = new EventEmitter<[ HTMLElement, HTMLElement ]>();
11
+
12
+ @Input()
13
+ public enableWhiteListing: boolean;
14
+
15
+ constructor(
16
+ private readonly elementRef: ElementRef,
17
+ ) {
18
+ }
19
+
20
+ @HostListener('document:click', [ '$event.target' ])
21
+ private onClick(targetElement: HTMLElement): void {
22
+ const clickedInside = this.elementRef.nativeElement.contains(targetElement);
23
+ const whiteListedClass = 'whitelisted';
24
+ if (!clickedInside) {
25
+ if (this.enableWhiteListing) {
26
+ const isWhiteListed = targetElement.classList.contains(whiteListedClass)
27
+ || ClickOutsideDirective.getClosest(targetElement, whiteListedClass)
28
+ || ClickOutsideDirective.getClosest(targetElement, 'cdk-overlay-container');
29
+ if (!isWhiteListed) {
30
+ this.clickOutside.emit([ this.elementRef.nativeElement, targetElement ]);
31
+ }
32
+ } else {
33
+ this.clickOutside.emit([ this.elementRef.nativeElement, targetElement ]);
34
+ }
35
+ }
36
+ }
37
+
38
+ private static getClosest(el: HTMLElement, selector: string): HTMLElement {
39
+ while (el) {
40
+ if (el.classList.contains(selector)) {
41
+ return el;
42
+ }
43
+ el = el.parentElement;
44
+ }
45
+ return null;
46
+ }
47
+
48
+ }
@@ -0,0 +1,33 @@
1
+ // eslint-disable-next-line max-classes-per-file
2
+ export enum ConfirmDialogResult {
3
+ confirmed,
4
+ denied,
5
+ cancelled,
6
+ }
7
+
8
+ export class ConfirmDialogAction {
9
+ public icon: string;
10
+ public visible: boolean;
11
+ public label: string;
12
+
13
+ constructor(label: string, visible?: boolean) {
14
+ this.label = label;
15
+ this.visible = visible;
16
+ }
17
+ }
18
+
19
+ export class ConfirmDialogData {
20
+ public title: string;
21
+ public message: string;
22
+ public cancel: ConfirmDialogAction;
23
+ public confirm: ConfirmDialogAction;
24
+ public deny: ConfirmDialogAction;
25
+
26
+ constructor(title?: string, message?: string, cancel?: ConfirmDialogAction, confirm?: ConfirmDialogAction, deny?: ConfirmDialogAction) {
27
+ this.title = title;
28
+ this.message = message;
29
+ this.cancel = cancel;
30
+ this.confirm = confirm;
31
+ this.deny = deny;
32
+ }
33
+ }
@@ -0,0 +1,19 @@
1
+ import { isNullOrEmpty, isNumber, isZeroOrHigher } from '@mosa-ng/core';
2
+
3
+ export class Skeleton {
4
+ public width?: number | string;
5
+ public height?: number | string;
6
+ public borderRadius?: number | string;
7
+ public randomizeOffset?: number;
8
+
9
+ constructor(skeleton?: Skeleton) {
10
+ this.width = isZeroOrHigher(skeleton?.width) ? skeleton?.width : 100;
11
+ this.height = isZeroOrHigher(skeleton?.height) ? skeleton?.height : 15;
12
+ if ((isNumber(skeleton?.borderRadius) && isZeroOrHigher(skeleton?.borderRadius)) ||
13
+ (typeof skeleton?.borderRadius === 'string' && !isNullOrEmpty(skeleton?.borderRadius))) {
14
+ this.borderRadius = skeleton.borderRadius;
15
+ }
16
+ this.borderRadius = this.borderRadius || 4;
17
+ this.randomizeOffset = skeleton?.randomizeOffset || 0;
18
+ }
19
+ }
@@ -0,0 +1,3 @@
1
+ export interface ICellEditorBaseState {
2
+ loading: boolean;
3
+ }
@@ -0,0 +1,5 @@
1
+ import { ILog } from '@mosa-ng/core';
2
+
3
+ export interface ILoggerState {
4
+ logs: ILog[];
5
+ }
@@ -0,0 +1,6 @@
1
+ export interface ITableItem<T> {
2
+ changedRowKeys: string[];
3
+ rowOriginalData: T;
4
+ }
5
+
6
+ export type TableItem<T> = ITableItem<T> & T;
@@ -0,0 +1,20 @@
1
+ export interface IUpdateConfig {
2
+ refreshInterval?: number;
3
+ ignoreTimeout?: number;
4
+ localStorageKey?: string;
5
+ versionPath: string;
6
+ showIgnore?: boolean;
7
+ title?: string;
8
+ message?: string;
9
+ }
10
+
11
+ export interface IVersion {
12
+ version: string;
13
+ timestamp: number;
14
+ }
15
+
16
+ export enum UpdateDialogResult {
17
+ cancel,
18
+ ignore,
19
+ reload,
20
+ }
@@ -0,0 +1,26 @@
1
+ import { CommonModule } from '@angular/common';
2
+ import { APP_INITIALIZER, ModuleWithProviders, NgModule } from '@angular/core';
3
+ import { AssetsI18nLoaderService } from '@mosa-ng/core';
4
+
5
+ export function initI18n(i18n: AssetsI18nLoaderService): () => Promise<void> {
6
+ return () => i18n.init(null, 'mosa');
7
+ }
8
+
9
+ @NgModule({
10
+ declarations: [],
11
+ imports: [
12
+ CommonModule,
13
+ ],
14
+ })
15
+ export class MosaMaterialModule {
16
+
17
+ public static forRoot(): ModuleWithProviders<MosaMaterialModule> {
18
+ return {
19
+ ngModule: MosaMaterialModule,
20
+ providers: [
21
+ { provide: APP_INITIALIZER, useFactory: initI18n, deps: [ AssetsI18nLoaderService ], multi: true },
22
+ ],
23
+ };
24
+ }
25
+
26
+ }
@@ -0,0 +1,46 @@
1
+ import { Injectable } from '@angular/core';
2
+ import { CellEditorComponent } from '../components/cell-editor/cell-editor.component';
3
+
4
+ @Injectable({
5
+ providedIn: 'root',
6
+ })
7
+ export class CellEditorService {
8
+
9
+ public cellEditor: CellEditorComponent;
10
+
11
+ private documentEditListener: (e: MouseEvent) => void;
12
+
13
+ constructor() {
14
+ }
15
+
16
+ public updateEditingCell(cellEditor: CellEditorComponent): void {
17
+ if (cellEditor !== this.cellEditor) {
18
+ this.cellEditor?.toOutput(true);
19
+ }
20
+ this.cellEditor = cellEditor;
21
+ this.cellEditor.toInput();
22
+ this.bindDocumentEditListener();
23
+ }
24
+
25
+ public bindDocumentEditListener(): void {
26
+ if (!this.documentEditListener) {
27
+ this.documentEditListener = (e: MouseEvent): void => {
28
+ e.preventDefault();
29
+ const target: HTMLElement = e.target as HTMLElement;
30
+ const mosaCellEditor: HTMLElement = target.closest('mosa-cell-editor');
31
+ if (this.cellEditor && mosaCellEditor !== this.cellEditor.element && !target.classList.contains('cell-output')) {
32
+ this.documentEditListener = null;
33
+ this.cellEditor.toOutput(true);
34
+ this.cellEditor = null;
35
+ document.removeEventListener('click', this.documentEditListener);
36
+ }
37
+ };
38
+
39
+ document.addEventListener('click', this.documentEditListener);
40
+ }
41
+ }
42
+
43
+ public isEditingCellValid(): boolean {
44
+ return this.cellEditor?.element != null && Array.from(this.cellEditor.element.querySelectorAll('.ng-invalid')).length === 0;
45
+ }
46
+ }