imng-kendo-schematics 8.115.3 → 19.12.2
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 +2 -2
- package/schematics/imng-crud/files/add-edit.component.html.template +59 -30
- package/schematics/imng-crud/files/add.component.spec.ts.template +2 -1
- package/schematics/imng-crud/files/add.component.ts.template +1 -5
- package/schematics/imng-crud/files/api.service.ts.template +2 -4
- package/schematics/imng-crud/files/base-entry.component.ts.template +12 -7
- package/schematics/imng-crud/files/crud.facade.spec.ts.template +17 -12
- package/schematics/imng-crud/files/crud.facade.ts.template +20 -10
- package/schematics/imng-crud/files/edit.component.spec.ts.template +2 -1
- package/schematics/imng-crud/files/edit.component.ts.template +2 -8
- package/schematics/imng-crud/schema.json +38 -35
- package/schematics/imng-list/files/list.component.html.template +31 -19
- package/schematics/imng-list/files/list.component.spec.ts.template +12 -7
- package/schematics/imng-list/files/list.component.ts.template +12 -9
- package/schematics/imng-list/files/list.facade.spec.ts.template +3 -6
- package/schematics/imng-list/files/list.facade.ts.template +6 -10
- package/schematics/imng-list/files/list.grid-state.ts.template +2 -1
- package/schematics/imng-list/schema.json +38 -35
- package/schematics/imng-module/files/+state/__singularizedName@dasherize__-crud.effects.ts.template +9 -9
- package/schematics/imng-module/files/+state/__singularizedName@dasherize__-list.effects.ts.template +7 -7
- package/schematics/imng-module/files/+state/__singularizedName@dasherize__.actions.ts.template +3 -2
- package/schematics/imng-module/files/+state/__singularizedName@dasherize__.feature.ts.template +15 -5
- package/schematics/imng-module/files/+state/index.ts.template +1 -2
- package/schematics/imng-module/files/__pluralizedName@dasherize__.module.ts.template +3 -1
- package/schematics/imng-module/schema.json +38 -34
- package/schematics/imng-sub-list/files/+state/__singularizedName@dasherize__.actions.ts.template +3 -1
- package/schematics/imng-sub-list/files/+state/__singularizedName@dasherize__.effects.ts.template +7 -7
- package/schematics/imng-sub-list/files/__pluralizedName@dasherize__-list/api.service.ts.template +3 -3
- package/schematics/imng-sub-list/files/__pluralizedName@dasherize__-list/list.component.html.template +12 -7
- package/schematics/imng-sub-list/files/__pluralizedName@dasherize__-list/list.component.ts.template +4 -3
- package/schematics/imng-sub-list/files/__pluralizedName@dasherize__-list/list.facade.ts.template +1 -2
- package/schematics/imng-sub-list/schema.json +42 -39
- package/schematics/shared/options.d.ts +2 -0
- package/schematics/imng-module/files/+state/__singularizedName@dasherize__.selectors.ts.template +0 -17
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "imng-kendo-schematics",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "19.12.2",
|
|
4
4
|
"description": "Angular Schematics facilitating Angular, Kendo, NGRX and imng package integration",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"build": "tsc -p tsconfig.json",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"pluralize": "^8.x",
|
|
23
23
|
"@nx/angular": ">=19.x",
|
|
24
24
|
"@angular/core": ">=18.x",
|
|
25
|
-
"jest": "
|
|
25
|
+
"jest": "*"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"@angular-devkit/core": ">=18.x",
|
|
@@ -15,9 +15,13 @@
|
|
|
15
15
|
[filterable]="true"
|
|
16
16
|
(filterChange)="handle<%= classify(swaggerProperty.name) %>Filter($event)">
|
|
17
17
|
</kendo-combobox><% if(swaggerProperty.required) { %>
|
|
18
|
-
|
|
19
|
-
<div
|
|
20
|
-
|
|
18
|
+
@if ((submitted$ | async) && formControlErrors(props.<%= swaggerProperty.snakeCaseName.toUpperCase() %>)) {
|
|
19
|
+
<div class="invalid-feedback d-block">
|
|
20
|
+
@if (formControlErrors(props.<%= swaggerProperty.snakeCaseName.toUpperCase() %>)?.[RequiredError]) {
|
|
21
|
+
<div><%= capitalize(decamelize(name)) %> <%= (swaggerProperty.startCaseName).toLowerCase() %> is required</div>
|
|
22
|
+
}
|
|
23
|
+
</div>
|
|
24
|
+
}<% } %>
|
|
21
25
|
</div><%} else if (swaggerProperty.htmlInputType === 'object' && swaggerProperty.properties.length <= 2){ %>
|
|
22
26
|
<kendo-combobox
|
|
23
27
|
id="<%= underscore(swaggerProperty.name) %>"
|
|
@@ -30,9 +34,13 @@
|
|
|
30
34
|
[filterable]="true"
|
|
31
35
|
(filterChange)="handle<%= classify(swaggerProperty.name) %>Filter($event)">
|
|
32
36
|
</kendo-combobox><% if(swaggerProperty.required) { %>
|
|
33
|
-
|
|
34
|
-
<div
|
|
35
|
-
|
|
37
|
+
@if ((submitted$ | async) && formControlErrors(props.<%= swaggerProperty.snakeCaseName.toUpperCase() %>)){
|
|
38
|
+
<div class="invalid-feedback d-block">
|
|
39
|
+
@if (formControlErrors(props.<%= swaggerProperty.snakeCaseName.toUpperCase() %>)?.[RequiredError]) {
|
|
40
|
+
<div><%= capitalize(decamelize(name)) %> <%= (swaggerProperty.startCaseName).toLowerCase() %> is required</div>
|
|
41
|
+
}
|
|
42
|
+
</div>
|
|
43
|
+
}<% } %>
|
|
36
44
|
</div><%} else if (swaggerProperty.htmlInputType === 'object'){ %>
|
|
37
45
|
<kendo-multicolumncombobox
|
|
38
46
|
id="<%= underscore(swaggerProperty.name) %>"
|
|
@@ -46,41 +54,62 @@
|
|
|
46
54
|
(filterChange)="handle<%= classify(swaggerProperty.name) %>Filter($event)"><% swaggerProperty.properties.filter(t=> t.name !== 'id' && !t.hidden).forEach(swaggerSubProperty => { %>
|
|
47
55
|
<kendo-combobox-column field="<%= camelize(swaggerSubProperty.name) %>" title="<%= swaggerSubProperty.startCaseName %>" [width]="100"></kendo-combobox-column><% }); %>
|
|
48
56
|
</kendo-multicolumncombobox><% if(swaggerProperty.required) { %>
|
|
49
|
-
|
|
50
|
-
<div
|
|
51
|
-
|
|
57
|
+
@if ((submitted$ | async) && formControlErrors(props.<%= swaggerProperty.snakeCaseName.toUpperCase() %>)) {
|
|
58
|
+
<div class="invalid-feedback d-block">
|
|
59
|
+
@if (formControlErrors(props.<%= swaggerProperty.snakeCaseName.toUpperCase() %>)?.[RequiredError]) {
|
|
60
|
+
<div><%= capitalize(decamelize(name)) %> <%= (swaggerProperty.startCaseName).toLowerCase() %> is required</div>
|
|
61
|
+
}
|
|
62
|
+
</div>
|
|
63
|
+
}<% } %>
|
|
52
64
|
</div><%} else if (swaggerProperty.htmlInputType === 'date' && swaggerProperty.required) { %>
|
|
53
|
-
<kendo-datepicker id="<%= underscore(swaggerProperty.name) %>" class="form-control" [formControlName]="props.<%= swaggerProperty.snakeCaseName.toUpperCase() %>"
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
65
|
+
<kendo-datepicker id="<%= underscore(swaggerProperty.name) %>" class="form-control" [formControlName]="props.<%= swaggerProperty.snakeCaseName.toUpperCase() %>" />
|
|
66
|
+
@if ((submitted$ | async) && formControlErrors(props.<%= swaggerProperty.snakeCaseName.toUpperCase() %>)) {
|
|
67
|
+
<div class="invalid-feedback d-block">
|
|
68
|
+
@if (formControlErrors(props.<%= swaggerProperty.snakeCaseName.toUpperCase() %>)?.[RequiredError]) {
|
|
69
|
+
<div><%= capitalize(decamelize(name)) %> <%= (swaggerProperty.startCaseName).toLowerCase() %> is required</div>
|
|
70
|
+
}
|
|
71
|
+
</div>
|
|
72
|
+
}
|
|
58
73
|
</div><%} else if (swaggerProperty.htmlInputType === 'date'){ %>
|
|
59
74
|
<kendo-datepicker id="<%= underscore(swaggerProperty.name) %>" class="form-control" [formControlName]="props.<%= swaggerProperty.snakeCaseName.toUpperCase() %>"></kendo-datepicker>
|
|
60
75
|
</div><%} else if (swaggerProperty.required && swaggerProperty.minLength) { %>
|
|
61
76
|
<input id="<%= underscore(swaggerProperty.name) %>" type="<%= swaggerProperty.htmlInputType %>" class="form-control" [formControlName]="props.<%= swaggerProperty.snakeCaseName.toUpperCase() %>" />
|
|
62
|
-
|
|
63
|
-
<div
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
77
|
+
@if ((submitted$ | async) && formControlErrors(props.<%= swaggerProperty.snakeCaseName.toUpperCase() %>)) {
|
|
78
|
+
<div class="invalid-feedback d-block">
|
|
79
|
+
@if (formControlErrors(props.<%= swaggerProperty.snakeCaseName.toUpperCase() %>)?.[RequiredError]) {
|
|
80
|
+
<div><%= capitalize(decamelize(name)) %> <%= (swaggerProperty.startCaseName).toLowerCase() %> is required</div>
|
|
81
|
+
}
|
|
82
|
+
@if (formControlErrors(props.<%= swaggerProperty.snakeCaseName.toUpperCase() %>)?.[MinLengthError]) {
|
|
83
|
+
<div>
|
|
84
|
+
<%= capitalize(decamelize(name)) %> <%= (swaggerProperty.startCaseName).toLowerCase() %> requires a min length of
|
|
85
|
+
{{formMinLengthError(props.<%= swaggerProperty.snakeCaseName.toUpperCase() %>)?.requiredLength}}, currently only
|
|
86
|
+
{{formMinLengthError(props.<%= swaggerProperty.snakeCaseName.toUpperCase() %>)?.actualLength}}.
|
|
87
|
+
</div>
|
|
88
|
+
}
|
|
68
89
|
</div>
|
|
69
|
-
|
|
90
|
+
}
|
|
70
91
|
</div><% } else if (swaggerProperty.required) { %>
|
|
71
92
|
<input id="<%= underscore(swaggerProperty.name) %>" type="<%= swaggerProperty.htmlInputType %>" class="form-control" [formControlName]="props.<%= swaggerProperty.snakeCaseName.toUpperCase() %>" />
|
|
72
|
-
|
|
73
|
-
<div
|
|
74
|
-
|
|
93
|
+
@if ((submitted$ | async) && formControlErrors(props.<%= swaggerProperty.snakeCaseName.toUpperCase() %>)) {
|
|
94
|
+
<div class="invalid-feedback d-block">
|
|
95
|
+
@if (formControlErrors(props.<%= swaggerProperty.snakeCaseName.toUpperCase() %>)?.[RequiredError]) {
|
|
96
|
+
<div><%= capitalize(decamelize(name)) %> <%= (swaggerProperty.startCaseName).toLowerCase() %> is required</div>
|
|
97
|
+
}
|
|
98
|
+
</div>
|
|
99
|
+
}
|
|
75
100
|
</div><% } else if (swaggerProperty.minLength) { %>
|
|
76
101
|
<input id="<%= underscore(swaggerProperty.name) %>" type="<%= swaggerProperty.htmlInputType %>" class="form-control" [formControlName]="props.<%= swaggerProperty.snakeCaseName.toUpperCase() %>" />
|
|
77
|
-
|
|
78
|
-
<div
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
102
|
+
@if ((submitted$ | async) && formControlErrors(props.<%= swaggerProperty.snakeCaseName.toUpperCase() %>)) {
|
|
103
|
+
<div class="invalid-feedback d-block">
|
|
104
|
+
@if (formControlErrors(props.<%= swaggerProperty.snakeCaseName.toUpperCase() %>)?.[MinLengthError]) {
|
|
105
|
+
<div>
|
|
106
|
+
<%= capitalize(decamelize(name)) %> <%= (swaggerProperty.startCaseName).toLowerCase() %> requires a min length of
|
|
107
|
+
{{formMinLengthError(props.<%= swaggerProperty.snakeCaseName.toUpperCase() %>)?.requiredLength}}, currently only
|
|
108
|
+
{{formMinLengthError(props.<%= swaggerProperty.snakeCaseName.toUpperCase() %>)?.actualLength}}.
|
|
109
|
+
</div>
|
|
110
|
+
}
|
|
82
111
|
</div>
|
|
83
|
-
|
|
112
|
+
}
|
|
84
113
|
</div><% } else{ %>
|
|
85
114
|
<input id="<%= underscore(swaggerProperty.name) %>" type="<%= swaggerProperty.htmlInputType %>" class="form-control" [formControlName]="props.<%= swaggerProperty.snakeCaseName.toUpperCase() %>" />
|
|
86
115
|
</div><% } %><% }) %>
|
|
@@ -9,7 +9,8 @@ import { mockConsoleError<% if (hasDates || hasObjects) { %>, mockConsoleGroup,
|
|
|
9
9
|
import { of } from 'rxjs';<% } %>
|
|
10
10
|
|
|
11
11
|
import { <%= classify(name) %>AddComponent } from './add.component';
|
|
12
|
-
import { <%= classify(name) %>CrudFacade } from './crud.facade'
|
|
12
|
+
import { <%= classify(name) %>CrudFacade } from './crud.facade';<% if (modelFolderLocation) { %>
|
|
13
|
+
import { I<%= classify(singularizedName) %>, createTest<%= classify(singularizedName) %>, <% swaggerObjectProperties.forEach(function(swaggerProperty, i, arr){ %>createTest<%= classify(swaggerProperty.propertyTypeName) %><% if(arr.length != i + 1) {%>, <%} }); %> } from '<%= modelFolderLocation %>';<% } %>
|
|
13
14
|
|
|
14
15
|
<% if (hasObjects) { %>export function createMock<%= classify(name) %>Facade() {
|
|
15
16
|
return {
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Component, ChangeDetectionStrategy, OnInit, OnDestroy } from '@angular/core';
|
|
2
|
-
import { <%= classify(name) %>CrudFacade } from './crud.facade';
|
|
3
2
|
import { <%= classify(name) %>BaseEntryComponent } from './base-entry.component';
|
|
4
3
|
|
|
5
4
|
@Component({
|
|
@@ -7,14 +6,11 @@ import { <%= classify(name) %>BaseEntryComponent } from './base-entry.component'
|
|
|
7
6
|
templateUrl: './add-edit.component.html',
|
|
8
7
|
styleUrls: ['./add-edit.component.scss'],
|
|
9
8
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
9
|
+
standalone: false,
|
|
10
10
|
})
|
|
11
11
|
export class <%= classify(name) %>AddComponent extends <%= classify(name) %>BaseEntryComponent implements OnInit, OnDestroy {
|
|
12
12
|
public dialogTitle = 'Add <%= classify(name) %>';
|
|
13
|
-
public active$ = this.facade.isNewActive$;
|
|
14
13
|
|
|
15
|
-
constructor(facade: <%= classify(name) %>CrudFacade) {
|
|
16
|
-
super(facade);
|
|
17
|
-
}
|
|
18
14
|
public override initForm(): void {
|
|
19
15
|
super.initForm();
|
|
20
16
|
this.addEditForm.patchValue({});
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { Injectable } from '@angular/core';
|
|
2
2
|
import { NrsrxBaseApiClientService } from 'imng-nrsrx-client-utils';
|
|
3
|
-
import { HttpClient } from '@angular/common/http';
|
|
4
3
|
import { environment } from '@env';
|
|
4
|
+
<% if (modelFolderLocation) { %>
|
|
5
|
+
import { I<%= classify(name) %>, <%= classify(name) %>Properties } from '<%= modelFolderLocation %>';<% } %>
|
|
5
6
|
|
|
6
7
|
@Injectable({
|
|
7
8
|
providedIn: 'root',
|
|
@@ -12,7 +13,4 @@ export class <%= classify(name) %>ApiService extends NrsrxBaseApiClientService<I
|
|
|
12
13
|
public override dateOnlyPropertyNames = [<% swaggerProperties.filter(t => t.format === 'date').forEach(function (swaggerProperty, index, dateProperties) { %>
|
|
13
14
|
<%= classify(singularizedName) %>Properties.<%= swaggerProperty.snakeCaseName.toUpperCase() %><% if (index + 1 < dateProperties.length) { %>,<% }}) %>];
|
|
14
15
|
<% } %>
|
|
15
|
-
constructor(http: HttpClient) {
|
|
16
|
-
super(http);
|
|
17
|
-
}
|
|
18
16
|
}
|
|
@@ -1,11 +1,16 @@
|
|
|
1
|
-
|
|
1
|
+
/* eslint-disable @angular-eslint/prefer-inject */
|
|
2
|
+
import { OnInit, Component, inject } from '@angular/core';
|
|
2
3
|
import { FormGroup } from '@angular/forms';
|
|
3
4
|
import { BaseDataEntryComponent } from 'imng-kendo-data-entry';<% if (hasObjects) { %>
|
|
4
5
|
import { BehaviorSubject, map, Observable, switchMap } from 'rxjs';<% } %>
|
|
5
6
|
|
|
6
|
-
import { <%= classify(name) %>CrudFacade } from './crud.facade'
|
|
7
|
+
import { <%= classify(name) %>CrudFacade } from './crud.facade';<% if (modelFolderLocation) { %>
|
|
8
|
+
import { <%= classify(singularizedName) %>Properties, I<%= classify(singularizedName) %>Form, <%= classify(singularizedName) %>FormGroupFac, <% swaggerObjectProperties.forEach(function(swaggerProperty, i, arr){ %>I<%= classify(swaggerProperty.propertyTypeName) %>, <%= classify(swaggerProperty.propertyTypeName) %>Properties<% if(arr.length != i + 1) {%>, <%} }); %> } from '<%= modelFolderLocation %>';<% } %>
|
|
7
9
|
|
|
8
|
-
@Component({
|
|
10
|
+
@Component({
|
|
11
|
+
template: '',
|
|
12
|
+
standalone: false,
|
|
13
|
+
})
|
|
9
14
|
export abstract class <%= classify(name) %>BaseEntryComponent extends BaseDataEntryComponent<<%= classify(name) %>CrudFacade>
|
|
10
15
|
implements OnInit {
|
|
11
16
|
public readonly props = <%= classify(name) %>Properties;<% swaggerObjectProperties.filter(t=> !t.enum).forEach(function(swaggerProperty){ %>
|
|
@@ -15,12 +20,12 @@ export abstract class <%= classify(name) %>BaseEntryComponent extends BaseDataEn
|
|
|
15
20
|
public readonly <%= camelize(swaggerProperty.pluralizedName) %>$ = new BehaviorSubject(<%= camelize(swaggerProperty.singularizedPropertyTypeName) %>Values);<% }) %>
|
|
16
21
|
public addEditForm: FormGroup<I<%= classify(name) %>Form>;
|
|
17
22
|
|
|
18
|
-
constructor(
|
|
19
|
-
super(
|
|
20
|
-
this.<%= camelize(swaggerProperty.pluralizedName) %>$ = facade.<%= camelize(swaggerProperty.pluralizedName) %>$.pipe(
|
|
23
|
+
constructor() {
|
|
24
|
+
super(inject(<%= classify(name) %>CrudFacade));<% swaggerObjectProperties.filter(t=> !t.enum).forEach(function(swaggerProperty){ %>
|
|
25
|
+
this.<%= camelize(swaggerProperty.pluralizedName) %>$ = this.facade.<%= camelize(swaggerProperty.pluralizedName) %>$.pipe(
|
|
21
26
|
switchMap(<%= camelize(swaggerProperty.pluralizedName) %> => this.<%= camelize(swaggerProperty.name) %>Filter$.pipe(
|
|
22
27
|
map(<%= camelize(swaggerProperty.name) %>Filter => <%= camelize(swaggerProperty.name) %>Filter ? <%= camelize(swaggerProperty.pluralizedName) %>
|
|
23
|
-
.filter(<%= camelize(swaggerProperty.name) %> => (<% swaggerProperty.properties.filter(f => f.name !== 'id' && f.htmlInputType !== 'object' && !f.hidden).forEach(function(swaggerSubProperty, i, arr){%>
|
|
28
|
+
.filter(<%= camelize(swaggerProperty.name) %> => (<% swaggerProperty.properties.filter(f => f.name !== 'id' && f.htmlInputType !== 'object' && f.htmlInputType !== 'checkbox' && !f.hidden).forEach(function(swaggerSubProperty, i, arr){%>
|
|
24
29
|
(<%= camelize(swaggerProperty.name) %>.<%= camelize(swaggerSubProperty.name) %> && <%= camelize(swaggerProperty.name) %>.<%= camelize(swaggerSubProperty.name) %><% if(swaggerSubProperty.format){ %>.toString()<% } %>.toLowerCase().indexOf(<%= camelize(swaggerProperty.name) %>Filter) >= 0)<% if (i + 1 != arr.length) { %> ||<% } }) %>
|
|
25
30
|
)) : <%= camelize(swaggerProperty.pluralizedName) %>
|
|
26
31
|
))));<% }) %>
|
|
@@ -5,8 +5,9 @@ import { EffectsModule } from '@ngrx/effects';
|
|
|
5
5
|
import { StoreModule, Store } from '@ngrx/store';
|
|
6
6
|
import { readFirst } from 'imng-ngrx-utils/testing';
|
|
7
7
|
import {
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
testDeleteCurrentEntity,
|
|
9
|
+
testModalStateAddAndClearCurrentEntity,
|
|
10
|
+
testModalStateEditAndClearCurrentEntity,
|
|
10
11
|
testSaveCurrentEntity,
|
|
11
12
|
testUpdateCurrentEntity,
|
|
12
13
|
} from 'imng-kendo-data-entry/testing';
|
|
@@ -15,7 +16,8 @@ import { of } from 'rxjs';
|
|
|
15
16
|
|
|
16
17
|
import { <%= camelize(pluralizedStoreName) %>Feature, <%= classify(singularizedStoreName) %>ListEffects, <%= classify(singularizedStoreName) %>CrudEffects } from '../+state';
|
|
17
18
|
import { <%= classify(name) %>CrudFacade } from './crud.facade';
|
|
18
|
-
import { <%= classify(name) %>ApiService } from './api.service'
|
|
19
|
+
import { <%= classify(name) %>ApiService } from './api.service';<% if (modelFolderLocation) { %>
|
|
20
|
+
import { createTest<%= classify(singularizedName) %> } from '<%= modelFolderLocation %>';<% } %>
|
|
19
21
|
import { environment } from '@env';
|
|
20
22
|
|
|
21
23
|
describe('<%= classify(name) %>CrudFacade', () => {
|
|
@@ -58,24 +60,27 @@ describe('<%= classify(name) %>CrudFacade', () => {
|
|
|
58
60
|
});
|
|
59
61
|
|
|
60
62
|
test('clearCurrentEntity() should set current<%= classify(name) %> to null', async () => {
|
|
61
|
-
let
|
|
62
|
-
expect(
|
|
63
|
+
let currentModalState = await readFirst(facade.currentModalState$);
|
|
64
|
+
expect(currentModalState).toBeUndefined();
|
|
63
65
|
|
|
64
66
|
facade.clearCurrentEntity();
|
|
65
|
-
|
|
67
|
+
currentModalState = await readFirst(facade.currentModalState$);
|
|
66
68
|
|
|
67
|
-
expect(
|
|
69
|
+
expect(currentModalState).toBeUndefined();
|
|
68
70
|
expect(await readFirst(store)).toMatchSnapshot();
|
|
69
71
|
});
|
|
70
72
|
|
|
71
|
-
test('
|
|
72
|
-
|
|
73
|
-
test('
|
|
74
|
-
|
|
73
|
+
test('Add Modal State And Clear CurrentEntity', async () =>
|
|
74
|
+
testModalStateAddAndClearCurrentEntity<<%= classify(name) %>CrudFacade>(facade));
|
|
75
|
+
test('Edit Modal state And Clear CurrentEntity', async () =>
|
|
76
|
+
testModalStateEditAndClearCurrentEntity<<%= classify(name) %>CrudFacade>(facade));
|
|
75
77
|
test('Save CurrentEntity', async () =>
|
|
76
78
|
testSaveCurrentEntity<<%= classify(name) %>CrudFacade>(facade, httpClient));
|
|
77
79
|
test('Update CurrentEntity', async () =>
|
|
78
|
-
testUpdateCurrentEntity<<%= classify(name) %>CrudFacade>(facade, httpClient))
|
|
80
|
+
testUpdateCurrentEntity<<%= classify(name) %>CrudFacade>(facade, httpClient));
|
|
81
|
+
test('it should handle DeleteItem', async () => {
|
|
82
|
+
await testDeleteCurrentEntity(facade, httpClient);
|
|
83
|
+
});<% swaggerObjectProperties.filter(t=> !t.enum).forEach(function(swaggerProperty){ %>
|
|
79
84
|
|
|
80
85
|
test('should load <%= classify(swaggerProperty.pluralizedName) %>', async () => {
|
|
81
86
|
facade.load<%= classify(swaggerProperty.pluralizedName) %>({});
|
|
@@ -1,21 +1,27 @@
|
|
|
1
|
-
import { Injectable } from '@angular/core';
|
|
1
|
+
import { Injectable, inject } from '@angular/core';
|
|
2
2
|
import { Store } from '@ngrx/store';
|
|
3
|
-
import { IDataEntryFacade } from 'imng-kendo-data-entry';<% if (hasObjects) { %>
|
|
3
|
+
import { IDataDeleteFacade, IDataEntryFacade } from 'imng-kendo-data-entry';<% if (hasObjects) { %>
|
|
4
4
|
import { ODataState } from 'imng-kendo-odata';<% } %>
|
|
5
|
-
|
|
5
|
+
|
|
6
|
+
import { <%= camelize(pluralizedStoreName) %>Feature, <%= camelize(singularizedStoreName) %>ActionTypes } from '../+state';<% if (modelFolderLocation) { %>
|
|
7
|
+
import { I<%= classify(singularizedName) %>, <% swaggerObjectProperties.forEach(function(swaggerProperty, i, arr){ %>I<%= classify(swaggerProperty.name) %><% if(arr.length != i + 1) {%>, <%} }); %> } from '<%= modelFolderLocation %>';<% } %>
|
|
6
8
|
|
|
7
9
|
@Injectable()
|
|
8
|
-
export class <%= classify(name) %>CrudFacade implements IDataEntryFacade<I<%= classify(name) %>> {
|
|
10
|
+
export class <%= classify(name) %>CrudFacade implements IDataEntryFacade<I<%= classify(name) %>>, IDataDeleteFacade<I<%= classify(name) %>> {
|
|
11
|
+
private readonly store = inject(Store);
|
|
12
|
+
|
|
9
13
|
loading$ = this.store.select(<%= camelize(pluralizedStoreName) %>Feature.selectLoading);
|
|
10
14
|
currentEntity$ = this.store.select(<%= camelize(pluralizedStoreName) %>Feature.selectCurrent<%= classify(name) %>);
|
|
11
|
-
|
|
12
|
-
isNewActive$ = this.store.select(<%= camelize(singularizedStoreName) %>Selectors.selectIsNew<%= classify(name) %>Active);<% swaggerObjectProperties.filter(t=> !t.enum).forEach(function(swaggerProperty){ %>
|
|
15
|
+
currentModalState$ = this.store.select(<%= camelize(pluralizedStoreName) %>Feature.selectCurrent<%= classify(singularizedName) %>ModalState);<% swaggerObjectProperties.filter(t=> !t.enum).forEach(function(swaggerProperty){ %>
|
|
13
16
|
<%= camelize(swaggerProperty.pluralizedName) %>$ = this.store.select(<%= camelize(pluralizedStoreName) %>Feature.select<%= classify(swaggerProperty.pluralizedName) %>);<% }); %>
|
|
14
17
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
18
|
+
public setCurrentEntity(item: I<%= classify(name) %>, modalState: string): void {
|
|
19
|
+
this.store.dispatch(
|
|
20
|
+
<%= camelize(singularizedStoreName) %>ActionTypes.setCurrent<%= classify(name) %>({
|
|
21
|
+
modalState,
|
|
22
|
+
entity: item,
|
|
23
|
+
}),
|
|
24
|
+
);
|
|
19
25
|
}
|
|
20
26
|
|
|
21
27
|
public clearCurrentEntity(): void {
|
|
@@ -29,6 +35,10 @@ export class <%= classify(name) %>CrudFacade implements IDataEntryFacade<I<%= cl
|
|
|
29
35
|
public updateExistingEntity(item: I<%= classify(name) %>): void {
|
|
30
36
|
this.store.dispatch(<%= camelize(singularizedStoreName) %>ActionTypes.update<%= classify(name) %>Request(item));
|
|
31
37
|
}
|
|
38
|
+
|
|
39
|
+
public deleteExistingEntity(item: I<%= classify(name) %>): void {
|
|
40
|
+
this.store.dispatch(<%= camelize(singularizedStoreName) %>ActionTypes.delete<%= classify(name) %>Request(item));
|
|
41
|
+
}
|
|
32
42
|
<% swaggerObjectProperties.filter(t=> !t.enum).forEach(function(swaggerProperty){ %>
|
|
33
43
|
public load<%= classify(swaggerProperty.pluralizedName) %>(state: ODataState): void {
|
|
34
44
|
this.store.dispatch(<%= camelize(singularizedStoreName) %>ActionTypes.load<%= classify(swaggerProperty.pluralizedName) %>Request(state));
|
|
@@ -9,7 +9,8 @@ import { of } from 'rxjs';<% } %>
|
|
|
9
9
|
import { mockConsoleError<% if (hasDates || hasObjects) { %>, mockConsoleGroup, mockConsoleWarn<% } %>, readFirst } from 'imng-ngrx-utils/testing';
|
|
10
10
|
<% if (hasObjects) { %>import { createMock<%= classify(name) %>Facade } from './add.component.spec';<% } %>
|
|
11
11
|
import { <%= classify(name) %>EditComponent } from './edit.component';
|
|
12
|
-
import { <%= classify(name) %>CrudFacade } from './crud.facade'
|
|
12
|
+
import { <%= classify(name) %>CrudFacade } from './crud.facade';<% if (modelFolderLocation) { %>
|
|
13
|
+
import { I<%= classify(singularizedName) %>, createTest<%= classify(singularizedName) %> } from '<%= modelFolderLocation %>';<% } %>
|
|
13
14
|
|
|
14
15
|
describe('<%= classify(name) %>EditComponent', () => {
|
|
15
16
|
let component: <%= classify(name) %>EditComponent;
|
|
@@ -2,26 +2,20 @@ import { Component, ChangeDetectionStrategy, OnInit, OnDestroy } from '@angular/
|
|
|
2
2
|
import { formGroupPatcher } from 'imng-kendo-data-entry';
|
|
3
3
|
|
|
4
4
|
import { <%= classify(name) %>BaseEntryComponent } from './base-entry.component';
|
|
5
|
-
import { <%= classify(name) %>CrudFacade } from './crud.facade';
|
|
6
5
|
|
|
7
6
|
@Component({
|
|
8
7
|
selector: '<%= appPrefix %>-<%= dasherize(name) %>-edit',
|
|
9
8
|
templateUrl: './add-edit.component.html',
|
|
10
9
|
styleUrls: ['./add-edit.component.scss'],
|
|
11
10
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
11
|
+
standalone: false,
|
|
12
12
|
})
|
|
13
13
|
export class <%= classify(name) %>EditComponent extends <%= classify(name) %>BaseEntryComponent implements OnInit, OnDestroy {
|
|
14
14
|
public dialogTitle = 'Edit <%= classify(name) %>';
|
|
15
|
-
public active$ = this.facade.isEditActive$;
|
|
16
15
|
|
|
17
|
-
constructor(facade: <%= classify(name) %>CrudFacade) {
|
|
18
|
-
super(facade);
|
|
19
|
-
}
|
|
20
16
|
public override initForm(): void {
|
|
21
17
|
super.initForm();
|
|
22
|
-
|
|
23
|
-
this.allSubscriptions.push(this.facade.currentEntity$.pipe(formGroupPatcher(this.addEditForm)).subscribe());
|
|
24
|
-
}
|
|
18
|
+
this.allSubscriptions.push(this.facade.currentEntity$.pipe(formGroupPatcher(this.addEditForm)).subscribe());
|
|
25
19
|
}
|
|
26
20
|
|
|
27
21
|
public save(): void {
|
|
@@ -1,38 +1,41 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
}
|
|
13
|
-
},
|
|
14
|
-
"storeName": {
|
|
15
|
-
"type": "string",
|
|
16
|
-
"description": "NGRX Feature Store name"
|
|
17
|
-
},
|
|
18
|
-
"path": {
|
|
19
|
-
"type": "string",
|
|
20
|
-
"description": "Directory where you would like the output to go"
|
|
21
|
-
},
|
|
22
|
-
"openApiJsonUrl": {
|
|
23
|
-
"type": "string",
|
|
24
|
-
"description": "URL of swagger page"
|
|
25
|
-
},
|
|
26
|
-
"openApiJsonFileName": {
|
|
27
|
-
"type": "string",
|
|
28
|
-
"description": "Relative file name and path"
|
|
29
|
-
},
|
|
30
|
-
"appPrefix": {
|
|
31
|
-
"type": "string",
|
|
32
|
-
"default": "imng",
|
|
33
|
-
"description": "Application selector prefix for components and directives."
|
|
2
|
+
"$schema": "http://json-schema.org/schema",
|
|
3
|
+
"$id": "imng-crud",
|
|
4
|
+
"type": "object",
|
|
5
|
+
"properties": {
|
|
6
|
+
"name": {
|
|
7
|
+
"type": "string",
|
|
8
|
+
"description": "Entity name",
|
|
9
|
+
"$default": {
|
|
10
|
+
"$source": "argv",
|
|
11
|
+
"index": 0
|
|
34
12
|
}
|
|
35
13
|
},
|
|
36
|
-
"
|
|
37
|
-
|
|
38
|
-
|
|
14
|
+
"storeName": {
|
|
15
|
+
"type": "string",
|
|
16
|
+
"description": "NGRX Feature Store name"
|
|
17
|
+
},
|
|
18
|
+
"path": {
|
|
19
|
+
"type": "string",
|
|
20
|
+
"description": "Directory where you would like the output to go"
|
|
21
|
+
},
|
|
22
|
+
"openApiJsonUrl": {
|
|
23
|
+
"type": "string",
|
|
24
|
+
"description": "URL of OpenApi Json document"
|
|
25
|
+
},
|
|
26
|
+
"openApiJsonFileName": {
|
|
27
|
+
"type": "string",
|
|
28
|
+
"description": "Relative file name and path of OpenApi json document"
|
|
29
|
+
},
|
|
30
|
+
"appPrefix": {
|
|
31
|
+
"type": "string",
|
|
32
|
+
"default": "imng",
|
|
33
|
+
"description": "Application selector prefix for components and directives."
|
|
34
|
+
},
|
|
35
|
+
"modelFolderLocation": {
|
|
36
|
+
"type": "string",
|
|
37
|
+
"description": "Location of the model folder (relative to the generated component root)"
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
"required": ["name", "path"]
|
|
41
|
+
}
|
|
@@ -7,14 +7,13 @@
|
|
|
7
7
|
(addItemClicked)="addItem()"
|
|
8
8
|
(reloadEntitiesClicked)="reloadEntities()"
|
|
9
9
|
(resetFiltersClicked)="resetFilters()"
|
|
10
|
-
[hasHiddenColumns$]="hasHiddenColumns$"
|
|
11
|
-
</imng-kendo-odata-grid-header>
|
|
10
|
+
[hasHiddenColumns$]="hasHiddenColumns$" />
|
|
12
11
|
</div>
|
|
13
12
|
</ng-template>
|
|
14
13
|
<kendo-grid-column [width]="75">
|
|
15
14
|
<ng-template kendoGridCellTemplate let-dataItem let-rowIndex="rowIndex">
|
|
16
15
|
<kendo-menu title="Actions">
|
|
17
|
-
<kendo-menu-item [svgIcon]="icons.
|
|
16
|
+
<kendo-menu-item [svgIcon]="icons.menu">
|
|
18
17
|
<kendo-menu-item>
|
|
19
18
|
<ng-template kendoMenuItemLinkTemplate>
|
|
20
19
|
<button
|
|
@@ -23,7 +22,7 @@
|
|
|
23
22
|
(click)="editItem(dataItem)"
|
|
24
23
|
placement="left"
|
|
25
24
|
tooltip="Edit">
|
|
26
|
-
<
|
|
25
|
+
<kendo-svgicon [icon]="icons.menu" size="xlarge"></kendo-svgicon>
|
|
27
26
|
Edit
|
|
28
27
|
</button>
|
|
29
28
|
</ng-template>
|
|
@@ -36,7 +35,7 @@
|
|
|
36
35
|
(click)="deleteItem(dataItem)"
|
|
37
36
|
placement="left"
|
|
38
37
|
tooltip="Delete">
|
|
39
|
-
<
|
|
38
|
+
<kendo-svgicon [icon]="icons.trash" size="xlarge"></kendo-svgicon>
|
|
40
39
|
Delete
|
|
41
40
|
</button>
|
|
42
41
|
</ng-template>
|
|
@@ -52,22 +51,21 @@
|
|
|
52
51
|
<%} else if (swaggerProperty.type === 'boolean') { %>
|
|
53
52
|
<kendo-grid-column [field]="props.<%= swaggerProperty.snakeCaseName.toUpperCase() %>" [width]="100" title="<%= swaggerProperty.startCaseName %>" filter="<%= swaggerProperty.filterExpression %>" [hidden]="<%= swaggerProperty.hidden %>">
|
|
54
53
|
<ng-template kendoGridCellTemplate let-dataItem>
|
|
55
|
-
|
|
56
|
-
<
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
54
|
+
@if (dataItem[props.<%= swaggerProperty.snakeCaseName.toUpperCase() %>]) {
|
|
55
|
+
<kendo-svgicon class="text-success font-weight-bolder h2" [icon]="icons.check" size="xlarge"></kendo-svgicon>
|
|
56
|
+
} @else {
|
|
57
|
+
<kendo-svgicon class="text-danger font-weight-bolder h2" [icon]="icons.cancel" size="xlarge"></kendo-svgicon>
|
|
58
|
+
}
|
|
60
59
|
</ng-template>
|
|
61
60
|
<%} else if (swaggerProperty.format === 'uuid') { %>
|
|
62
61
|
<kendo-grid-column [field]="props.<%= swaggerProperty.snakeCaseName.toUpperCase() %>" [width]="100" title="<%= swaggerProperty.startCaseName %>" filter="<%= swaggerProperty.filterExpression %>" [hidden]="<%= swaggerProperty.hidden %>">
|
|
63
62
|
<ng-template kendoGridCellTemplate let-dataItem>
|
|
64
63
|
<imng-kendo-copy
|
|
65
|
-
[displayValue]="dataItem[props
|
|
66
|
-
[copyValue]="dataItem[props.<%= swaggerProperty.snakeCaseName.toUpperCase() %>]"
|
|
67
|
-
</imng-kendo-copy>
|
|
64
|
+
[displayValue]="`${(dataItem[props.ID] | slice: 0 : 4)}.-.${(dataItem[props.ID] | slice: -4)}`"
|
|
65
|
+
[copyValue]="dataItem[props.<%= swaggerProperty.snakeCaseName.toUpperCase() %>]" />
|
|
68
66
|
</ng-template>
|
|
69
67
|
<ng-template kendoGridFilterMenuTemplate let-filter>
|
|
70
|
-
<imng-uuid-filter [filter]="filter"
|
|
68
|
+
<imng-uuid-filter [filter]="filter" />
|
|
71
69
|
</ng-template>
|
|
72
70
|
<%} else if (swaggerProperty.enum) { %>
|
|
73
71
|
<kendo-grid-column
|
|
@@ -82,7 +80,7 @@
|
|
|
82
80
|
[textField]="EnumProperties.DISPLAY_TEXT"
|
|
83
81
|
[valueField]="EnumProperties.NAME"
|
|
84
82
|
[data]="<%= camelize(swaggerProperty.pluralizedPropertyTypeName) %>"
|
|
85
|
-
[field]="props.<%= swaggerProperty.snakeCaseName.toUpperCase() %>"
|
|
83
|
+
[field]="props.<%= swaggerProperty.snakeCaseName.toUpperCase() %>" />
|
|
86
84
|
</ng-template>
|
|
87
85
|
<ng-template kendoGridCellTemplate let-dataItem>
|
|
88
86
|
{{ getEnumText(<%= camelize(swaggerProperty.pluralizedPropertyTypeName) %>, dataItem[props.<%= swaggerProperty.snakeCaseName.toUpperCase() %>]) }}
|
|
@@ -99,9 +97,23 @@
|
|
|
99
97
|
</kendo-grid-column><% }) %>
|
|
100
98
|
|
|
101
99
|
<kendo-grid-pdf [fileName]="getExportFileName('<%= classify(pluralizedName) %>')" [allPages]="false">
|
|
102
|
-
<kendo-grid-pdf-margin top="1cm" left="1cm" right="1cm" bottom="1cm"
|
|
100
|
+
<kendo-grid-pdf-margin top="1cm" left="1cm" right="1cm" bottom="1cm" />
|
|
103
101
|
</kendo-grid-pdf>
|
|
104
|
-
<kendo-grid-excel [fileName]="getExportFileName('<%= classify(pluralizedName) %>')" [fetchData]="excelData"
|
|
102
|
+
<kendo-grid-excel [fileName]="getExportFileName('<%= classify(pluralizedName) %>')" [fetchData]="excelData" />
|
|
105
103
|
</kendo-grid>
|
|
106
|
-
|
|
107
|
-
|
|
104
|
+
|
|
105
|
+
@switch (crudFacade.currentModalState$ | async) {
|
|
106
|
+
@case (modalStates.ADD) {
|
|
107
|
+
<<%= appPrefix %>-<%= dasherize(name) %>-add />
|
|
108
|
+
}
|
|
109
|
+
@case (modalStates.EDIT) {
|
|
110
|
+
<<%= appPrefix %>-<%= dasherize(name) %>-edit />
|
|
111
|
+
}
|
|
112
|
+
@case (modalStates.DELETE) {
|
|
113
|
+
<imng-data-delete-dialog
|
|
114
|
+
[facade]="crudFacade"
|
|
115
|
+
[dataItem]="crudFacade.currentEntity$ | async">
|
|
116
|
+
<div class="text-center">Are you sure you want to delete this record?</div>
|
|
117
|
+
</imng-data-delete-dialog>
|
|
118
|
+
}
|
|
119
|
+
}
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import { CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from '@angular/core';
|
|
2
2
|
import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
|
|
3
3
|
import { provideRouter } from '@angular/router';
|
|
4
|
-
import { createDataEntryMockFacade
|
|
4
|
+
import { createDataEntryMockFacade } from 'imng-kendo-data-entry/testing';
|
|
5
5
|
import { createODataGridMockFacade } from 'imng-kendo-grid-odata/testing';
|
|
6
6
|
import { provideOidcMockFacade } from 'imng-oidc-client/testing';
|
|
7
|
+
import { ModalStates } from 'imng-kendo-data-entry';
|
|
7
8
|
|
|
8
9
|
import { <%= classify(singularizedName) %>ListComponent } from './list.component';
|
|
9
10
|
import { <%= classify(singularizedName) %>ListFacade } from './list.facade';
|
|
10
11
|
import { <%= classify(singularizedName) %>CrudFacade } from '../<%= dasherize(pluralizedName) %>-crud';
|
|
11
|
-
import { <%= camelize(singularizedName) %>Routes } from '../<%= dasherize(pluralizedName) %>.routing'
|
|
12
|
+
import { <%= camelize(singularizedName) %>Routes } from '../<%= dasherize(pluralizedName) %>.routing';<% if (modelFolderLocation) { %>
|
|
13
|
+
import { createTest<%= classify(name) %> } from '<%= modelFolderLocation %>';<% } %>
|
|
12
14
|
|
|
13
15
|
describe('<%= classify(singularizedName) %>ListComponent', () => {
|
|
14
16
|
let component: <%= classify(singularizedName) %>ListComponent;
|
|
@@ -21,7 +23,7 @@ describe('<%= classify(singularizedName) %>ListComponent', () => {
|
|
|
21
23
|
declarations: [<%= classify(singularizedName) %>ListComponent],
|
|
22
24
|
imports: [],
|
|
23
25
|
providers: [
|
|
24
|
-
{ provide: <%= classify(singularizedName) %>ListFacade, useValue: createODataGridMockFacade(
|
|
26
|
+
{ provide: <%= classify(singularizedName) %>ListFacade, useValue: createODataGridMockFacade() },
|
|
25
27
|
{ provide: <%= classify(singularizedName) %>CrudFacade, useValue: createDataEntryMockFacade() },
|
|
26
28
|
provideRouter(<%= camelize(singularizedName) %>Routes),
|
|
27
29
|
provideOidcMockFacade(),
|
|
@@ -60,20 +62,23 @@ describe('<%= classify(singularizedName) %>ListComponent', () => {
|
|
|
60
62
|
test('it should handle AddItem', () => {
|
|
61
63
|
component.addItem();
|
|
62
64
|
expect(crudFacade.setCurrentEntity).toHaveBeenCalledTimes(1);
|
|
63
|
-
expect(crudFacade.setCurrentEntity).toHaveBeenCalledWith({});
|
|
65
|
+
expect(crudFacade.setCurrentEntity).toHaveBeenCalledWith({}, ModalStates.ADD);
|
|
64
66
|
});
|
|
65
67
|
|
|
66
68
|
test('it should handle EditItem', () => {
|
|
67
69
|
const item = createTest<%= classify(singularizedName) %>();
|
|
68
70
|
component.editItem(item);
|
|
69
71
|
expect(crudFacade.setCurrentEntity).toHaveBeenCalledTimes(1);
|
|
70
|
-
expect(crudFacade.setCurrentEntity).toHaveBeenCalledWith(item);
|
|
72
|
+
expect(crudFacade.setCurrentEntity).toHaveBeenCalledWith(item, ModalStates.EDIT);
|
|
71
73
|
});
|
|
72
74
|
|
|
73
75
|
test('it should handle DeleteItem', () => {
|
|
74
76
|
const item = createTest<%= classify(singularizedName) %>();
|
|
75
77
|
component.deleteItem(item);
|
|
76
|
-
expect(
|
|
77
|
-
expect(
|
|
78
|
+
expect(crudFacade.setCurrentEntity).toHaveBeenCalledTimes(1);
|
|
79
|
+
expect(crudFacade.setCurrentEntity).toHaveBeenCalledWith(
|
|
80
|
+
item,
|
|
81
|
+
ModalStates.DELETE,
|
|
82
|
+
);
|
|
78
83
|
});
|
|
79
84
|
});
|