imng-kendo-schematics 8.115.1 → 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.
Files changed (34) hide show
  1. package/package.json +2 -2
  2. package/schematics/imng-crud/files/add-edit.component.html.template +59 -30
  3. package/schematics/imng-crud/files/add.component.spec.ts.template +2 -1
  4. package/schematics/imng-crud/files/add.component.ts.template +1 -5
  5. package/schematics/imng-crud/files/api.service.ts.template +2 -4
  6. package/schematics/imng-crud/files/base-entry.component.ts.template +12 -7
  7. package/schematics/imng-crud/files/crud.facade.spec.ts.template +17 -12
  8. package/schematics/imng-crud/files/crud.facade.ts.template +20 -10
  9. package/schematics/imng-crud/files/edit.component.spec.ts.template +2 -1
  10. package/schematics/imng-crud/files/edit.component.ts.template +2 -8
  11. package/schematics/imng-crud/schema.json +38 -35
  12. package/schematics/imng-list/files/list.component.html.template +31 -19
  13. package/schematics/imng-list/files/list.component.spec.ts.template +12 -7
  14. package/schematics/imng-list/files/list.component.ts.template +12 -9
  15. package/schematics/imng-list/files/list.facade.spec.ts.template +3 -6
  16. package/schematics/imng-list/files/list.facade.ts.template +6 -10
  17. package/schematics/imng-list/files/list.grid-state.ts.template +2 -1
  18. package/schematics/imng-list/schema.json +38 -35
  19. package/schematics/imng-module/files/+state/__singularizedName@dasherize__-crud.effects.ts.template +9 -9
  20. package/schematics/imng-module/files/+state/__singularizedName@dasherize__-list.effects.ts.template +7 -7
  21. package/schematics/imng-module/files/+state/__singularizedName@dasherize__.actions.ts.template +3 -2
  22. package/schematics/imng-module/files/+state/__singularizedName@dasherize__.feature.ts.template +15 -5
  23. package/schematics/imng-module/files/+state/index.ts.template +1 -2
  24. package/schematics/imng-module/files/__pluralizedName@dasherize__.module.ts.template +3 -1
  25. package/schematics/imng-module/schema.json +38 -34
  26. package/schematics/imng-sub-list/files/+state/__singularizedName@dasherize__.actions.ts.template +3 -1
  27. package/schematics/imng-sub-list/files/+state/__singularizedName@dasherize__.effects.ts.template +7 -7
  28. package/schematics/imng-sub-list/files/__pluralizedName@dasherize__-list/api.service.ts.template +3 -3
  29. package/schematics/imng-sub-list/files/__pluralizedName@dasherize__-list/list.component.html.template +12 -7
  30. package/schematics/imng-sub-list/files/__pluralizedName@dasherize__-list/list.component.ts.template +4 -3
  31. package/schematics/imng-sub-list/files/__pluralizedName@dasherize__-list/list.facade.ts.template +1 -2
  32. package/schematics/imng-sub-list/schema.json +42 -39
  33. package/schematics/shared/options.d.ts +2 -0
  34. 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": "8.115.1",
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": ">=29.x"
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
- <div *ngIf="(submitted$ | async) && formControlErrors(props.<%= swaggerProperty.snakeCaseName.toUpperCase() %>)" class="invalid-feedback d-block">
19
- <div *ngIf="formControlErrors(props.<%= swaggerProperty.snakeCaseName.toUpperCase() %>)?.[RequiredError]"><%= capitalize(decamelize(name)) %> <%= (swaggerProperty.startCaseName).toLowerCase() %> is required</div>
20
- </div><% } %>
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
- <div *ngIf="(submitted$ | async) && formControlErrors(props.<%= swaggerProperty.snakeCaseName.toUpperCase() %>)" class="invalid-feedback d-block">
34
- <div *ngIf="formControlErrors(props.<%= swaggerProperty.snakeCaseName.toUpperCase() %>)?.[RequiredError]"><%= capitalize(decamelize(name)) %> <%= (swaggerProperty.startCaseName).toLowerCase() %> is required</div>
35
- </div><% } %>
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
- <div *ngIf="(submitted$ | async) && formControlErrors(props.<%= swaggerProperty.snakeCaseName.toUpperCase() %>)" class="invalid-feedback d-block">
50
- <div *ngIf="formControlErrors(props.<%= swaggerProperty.snakeCaseName.toUpperCase() %>)?.[RequiredError]"><%= capitalize(decamelize(name)) %> <%= (swaggerProperty.startCaseName).toLowerCase() %> is required</div>
51
- </div><% } %>
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
- </kendo-datepicker>
55
- <div *ngIf="(submitted$ | async) && formControlErrors(props.<%= swaggerProperty.snakeCaseName.toUpperCase() %>)" class="invalid-feedback d-block">
56
- <div *ngIf="formControlErrors(props.<%= swaggerProperty.snakeCaseName.toUpperCase() %>)?.[RequiredError]"><%= capitalize(decamelize(name)) %> <%= (swaggerProperty.startCaseName).toLowerCase() %> is required</div>
57
- </div>
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
- <div *ngIf="(submitted$ | async) && formControlErrors(props.<%= swaggerProperty.snakeCaseName.toUpperCase() %>)" class="invalid-feedback d-block">
63
- <div *ngIf="formControlErrors(props.<%= swaggerProperty.snakeCaseName.toUpperCase() %>)?.[RequiredError]"><%= capitalize(decamelize(name)) %> <%= (swaggerProperty.startCaseName).toLowerCase() %> is required</div>
64
- <div *ngIf="formControlErrors(props.<%= swaggerProperty.snakeCaseName.toUpperCase() %>)?.[MinLengthError]">
65
- <%= capitalize(decamelize(name)) %> <%= (swaggerProperty.startCaseName).toLowerCase() %> requires a min length of
66
- {{formMinLengthError(props.<%= swaggerProperty.snakeCaseName.toUpperCase() %>)?.requiredLength}}, currently only
67
- {{formMinLengthError(props.<%= swaggerProperty.snakeCaseName.toUpperCase() %>)?.actualLength}}.
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
- </div>
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
- <div *ngIf="(submitted$ | async) && formControlErrors(props.<%= swaggerProperty.snakeCaseName.toUpperCase() %>)" class="invalid-feedback d-block">
73
- <div *ngIf="formControlErrors(props.<%= swaggerProperty.snakeCaseName.toUpperCase() %>)?.[RequiredError]"><%= capitalize(decamelize(name)) %> <%= (swaggerProperty.startCaseName).toLowerCase() %> is required</div>
74
- </div>
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
- <div *ngIf="(submitted$ | async) && formControlErrors(props.<%= swaggerProperty.snakeCaseName.toUpperCase() %>)" class="invalid-feedback d-block">
78
- <div *ngIf="formControlErrors(props.<%= swaggerProperty.snakeCaseName.toUpperCase() %>)?.[MinLengthError]">
79
- <%= capitalize(decamelize(name)) %> <%= (swaggerProperty.startCaseName).toLowerCase() %> requires a min length of
80
- {{formMinLengthError(props.<%= swaggerProperty.snakeCaseName.toUpperCase() %>)?.requiredLength}}, currently only
81
- {{formMinLengthError(props.<%= swaggerProperty.snakeCaseName.toUpperCase() %>)?.actualLength}}.
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
- </div>
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
- import { OnInit, Component } from '@angular/core';
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({ template: '' })
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(facade: <%= classify(name) %>CrudFacade) {
19
- super(facade);<% swaggerObjectProperties.filter(t=> !t.enum).forEach(function(swaggerProperty){ %>
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
- testAddSetAndClearCurrentEntity,
9
- testEditSetAndClearCurrentEntity,
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 isNewActive = await readFirst(facade.isNewActive$);
62
- expect(isNewActive).toBeFalsy();
63
+ let currentModalState = await readFirst(facade.currentModalState$);
64
+ expect(currentModalState).toBeUndefined();
63
65
 
64
66
  facade.clearCurrentEntity();
65
- isNewActive = await readFirst(facade.isNewActive$);
67
+ currentModalState = await readFirst(facade.currentModalState$);
66
68
 
67
- expect(isNewActive).toBeFalsy();
69
+ expect(currentModalState).toBeUndefined();
68
70
  expect(await readFirst(store)).toMatchSnapshot();
69
71
  });
70
72
 
71
- test('New Entity Set And Clear CurrentEntity', async () =>
72
- testAddSetAndClearCurrentEntity<<%= classify(name) %>CrudFacade>(facade));
73
- test('Existing Entity Set And Clear CurrentEntity', async () =>
74
- testEditSetAndClearCurrentEntity<<%= classify(name) %>CrudFacade>(facade));
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));<% swaggerObjectProperties.filter(t=> !t.enum).forEach(function(swaggerProperty){ %>
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
- import { <%= camelize(pluralizedStoreName) %>Feature, <%= camelize(singularizedStoreName) %>Selectors, <%= camelize(singularizedStoreName) %>ActionTypes } from '../+state';
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
- isEditActive$ = this.store.select(<%= camelize(singularizedStoreName) %>Selectors.selectIsEdit<%= classify(name) %>Active);
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
- constructor(private readonly store: Store) {}
16
-
17
- public setCurrentEntity(item: I<%= classify(name) %>): void {
18
- this.store.dispatch(<%= camelize(singularizedStoreName) %>ActionTypes.setCurrent<%= classify(name) %>(item));
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
- if (this.addEditForm) {
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
- "$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
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
- "required": ["name", "path"]
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 icon="menu">
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
- <span class="k-icon k-i-edit"></span>
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
- <span class="k-icon k-i-delete"></span>
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
- <div *ngIf="dataItem[props.<%= swaggerProperty.snakeCaseName.toUpperCase() %>]">
56
- <span class="text-success font-weight-bolder h2" tooltip="<%= swaggerProperty.startCaseName %>">
57
- <span class="k-icon k-i-check-circle start-50"></span>
58
- </span>
59
- </div>
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.<%= swaggerProperty.snakeCaseName.toUpperCase() %>] | slice:0:5"
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"></imng-uuid-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() %>"></imng-multi-select-filter>
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"></kendo-grid-pdf-margin>
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"></kendo-grid-excel>
102
+ <kendo-grid-excel [fileName]="getExportFileName('<%= classify(pluralizedName) %>')" [fetchData]="excelData" />
105
103
  </kendo-grid>
106
- <<%= appPrefix %>-<%= dasherize(name) %>-add *ngIf="crudFacade.isNewActive$ | async"></<%= appPrefix %>-<%= dasherize(name) %>-add>
107
- <<%= appPrefix %>-<%= dasherize(name) %>-edit *ngIf="crudFacade.isEditActive$ | async"></<%= appPrefix %>-<%= dasherize(name) %>-edit>
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, createDataDeleteMockFacade } from 'imng-kendo-data-entry/testing';
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(createDataDeleteMockFacade()) },
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(listFacade.deleteExistingEntity).toHaveBeenCalledTimes(1);
77
- expect(listFacade.deleteExistingEntity).toHaveBeenCalledWith(item);
78
+ expect(crudFacade.setCurrentEntity).toHaveBeenCalledTimes(1);
79
+ expect(crudFacade.setCurrentEntity).toHaveBeenCalledWith(
80
+ item,
81
+ ModalStates.DELETE,
82
+ );
78
83
  });
79
84
  });