@smartsoft001/crud-shell-angular 2.76.0 → 2.80.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 (75) hide show
  1. package/fesm2022/smartsoft001-crud-shell-angular.mjs +2840 -0
  2. package/fesm2022/smartsoft001-crud-shell-angular.mjs.map +1 -0
  3. package/index.d.ts +632 -0
  4. package/package.json +18 -3
  5. package/.storybook/addons.js +0 -1
  6. package/.storybook/config.js +0 -5
  7. package/.storybook/tsconfig.json +0 -8
  8. package/.storybook/webpack.config.js +0 -7
  9. package/jest.config.ts +0 -38
  10. package/ng-package.json +0 -7
  11. package/project.json +0 -49
  12. package/src/index.ts +0 -13
  13. package/src/lib/+state/crud.facade.ts +0 -82
  14. package/src/lib/+state/crud.methods.ts +0 -258
  15. package/src/lib/+state/crud.store.ts +0 -77
  16. package/src/lib/components/components.module.ts +0 -58
  17. package/src/lib/components/export/export.component.ts +0 -69
  18. package/src/lib/components/filter/base/base.component.ts +0 -175
  19. package/src/lib/components/filter/check/check.component.scss +0 -25
  20. package/src/lib/components/filter/check/check.component.ts +0 -72
  21. package/src/lib/components/filter/date/date.component.html +0 -30
  22. package/src/lib/components/filter/date/date.component.ts +0 -70
  23. package/src/lib/components/filter/date-time/date-time.component.html +0 -62
  24. package/src/lib/components/filter/date-time/date-time.component.ts +0 -56
  25. package/src/lib/components/filter/date-with-edit/date-with-edit.component.html +0 -109
  26. package/src/lib/components/filter/date-with-edit/date-with-edit.component.ts +0 -70
  27. package/src/lib/components/filter/filter.component.html +0 -52
  28. package/src/lib/components/filter/filter.component.ts +0 -34
  29. package/src/lib/components/filter/flag/flag.component.ts +0 -55
  30. package/src/lib/components/filter/index.ts +0 -9
  31. package/src/lib/components/filter/int/int.component.html +0 -74
  32. package/src/lib/components/filter/int/int.component.ts +0 -57
  33. package/src/lib/components/filter/radio/radio.component.ts +0 -74
  34. package/src/lib/components/filter/text/text.component.ts +0 -46
  35. package/src/lib/components/filters/filters.component.scss +0 -150
  36. package/src/lib/components/filters/filters.component.ts +0 -157
  37. package/src/lib/components/filters-config/filters-config.component.ts +0 -69
  38. package/src/lib/components/group/group.component.ts +0 -93
  39. package/src/lib/components/index.ts +0 -7
  40. package/src/lib/components/multiselect/multiselect.component.html +0 -41
  41. package/src/lib/components/multiselect/multiselect.component.scss +0 -125
  42. package/src/lib/components/multiselect/multiselect.component.ts +0 -104
  43. package/src/lib/crud-full.module.ts +0 -51
  44. package/src/lib/crud.config.ts +0 -79
  45. package/src/lib/crud.module.ts +0 -72
  46. package/src/lib/factories/list-pagination/list-pagination.factory.ts +0 -77
  47. package/src/lib/models/index.ts +0 -1
  48. package/src/lib/models/interfaces.ts +0 -34
  49. package/src/lib/pages/index.ts +0 -6
  50. package/src/lib/pages/item/base/base.component.ts +0 -54
  51. package/src/lib/pages/item/item.component.ts +0 -513
  52. package/src/lib/pages/item/standard/standard.component.scss +0 -0
  53. package/src/lib/pages/item/standard/standard.component.ts +0 -50
  54. package/src/lib/pages/list/base/base.component.ts +0 -29
  55. package/src/lib/pages/list/list.component.stories.ts +0 -77
  56. package/src/lib/pages/list/list.component.ts +0 -438
  57. package/src/lib/pages/list/standard/standard.component.ts +0 -42
  58. package/src/lib/pipes/form-options/form-options.pipe.ts +0 -61
  59. package/src/lib/pipes/index.ts +0 -2
  60. package/src/lib/pipes/pipes.module.ts +0 -9
  61. package/src/lib/providers/model-possibilities/model-possibilities.provider.ts +0 -19
  62. package/src/lib/services/crud/crud.service.spec.ts +0 -303
  63. package/src/lib/services/crud/crud.service.ts +0 -178
  64. package/src/lib/services/list-group/list-group.service.spec.ts +0 -87
  65. package/src/lib/services/list-group/list-group.service.ts +0 -65
  66. package/src/lib/services/page/page.service.spec.ts +0 -143
  67. package/src/lib/services/page/page.service.ts +0 -44
  68. package/src/lib/services/search/search.service.spec.ts +0 -134
  69. package/src/lib/services/search/search.service.ts +0 -42
  70. package/test-setup.ts +0 -0
  71. package/tsconfig.json +0 -13
  72. package/tsconfig.lib.json +0 -31
  73. package/tsconfig.lib.prod.json +0 -11
  74. package/tsconfig.spec.json +0 -10
  75. package/tslint.json +0 -10
@@ -1,438 +0,0 @@
1
- import { NgTemplateOutlet } from '@angular/common';
2
- import {
3
- ChangeDetectorRef,
4
- Component,
5
- ComponentFactory,
6
- computed,
7
- inject,
8
- Injector,
9
- input,
10
- OnDestroy,
11
- OnInit,
12
- Signal,
13
- TemplateRef,
14
- viewChild,
15
- viewChildren,
16
- ViewContainerRef,
17
- WritableSignal,
18
- } from '@angular/core';
19
- import { Router } from '@angular/router';
20
- import { Subject } from 'rxjs';
21
-
22
- import {
23
- CreateDynamicComponent,
24
- DynamicComponentLoader,
25
- DynamicContentDirective,
26
- HardwareService,
27
- IIconButtonOptions,
28
- IListOptions,
29
- IPageOptions,
30
- ListMode,
31
- MenuService,
32
- PageComponent,
33
- } from '@smartsoft001/angular';
34
- import { IEntity } from '@smartsoft001/domain-core';
35
- import {
36
- getModelFieldsWithOptions,
37
- getModelOptions,
38
- IFieldEditMetadata,
39
- IFieldListMetadata,
40
- } from '@smartsoft001/models';
41
- import { SpecificationService } from '@smartsoft001/utils';
42
-
43
- import { CrudFacade } from '../../+state/crud.facade';
44
- import { ExportComponent } from '../../components';
45
- import { FiltersComponent } from '../../components';
46
- import { MultiselectComponent } from '../../components';
47
- import { CrudFullConfig } from '../../crud.config';
48
- import { CrudListPageBaseComponent } from './base/base.component';
49
- import { CrudListPaginationFactory } from '../../factories/list-pagination/list-pagination.factory';
50
- import { ICrudFilter } from '../../models';
51
- import { ListStandardComponent } from './standard/standard.component';
52
- import { PageService } from '../../services/page/page.service';
53
- import { CrudSearchService } from '../../services/search/search.service';
54
-
55
- @Component({
56
- selector: 'smart-crud-list-page',
57
- imports: [PageComponent, ListStandardComponent, NgTemplateOutlet],
58
- template: `
59
- @if (filter()) {
60
- <smart-page [options]="pageOptions()">
61
- <div #topTpl></div>
62
-
63
- @if (template() === 'default') {
64
- <smart-crud-list-standard-page [listOptions]="listOptions()">
65
- <ng-container [ngTemplateOutlet]="contentTpl"></ng-container>
66
- </smart-crud-list-standard-page>
67
- }
68
- <ng-template #contentTpl>
69
- <ng-content></ng-content>
70
- </ng-template>
71
- <div class="dynamic-content"></div>
72
- </smart-page>
73
- }
74
- `,
75
- })
76
- export class ListComponent<T extends IEntity<string>>
77
- extends CreateDynamicComponent<CrudListPageBaseComponent<any>>(
78
- 'crud-list-page',
79
- )
80
- implements OnInit, OnDestroy
81
- {
82
- private facade = inject(CrudFacade<T>);
83
- private router = inject(Router);
84
- private dynamicComponentLoader = inject(DynamicComponentLoader<T>);
85
- private injector = inject(Injector);
86
- private cd = inject(ChangeDetectorRef);
87
- private menuService = inject(MenuService);
88
- private hardwareService = inject(HardwareService);
89
- private paginationFacade = inject(CrudListPaginationFactory<T>);
90
- private pageService = inject(PageService<T>);
91
- public config = inject(CrudFullConfig<T>);
92
- private searchService = inject(CrudSearchService);
93
-
94
- private _cleanMultiSelected$ = new Subject<void>();
95
-
96
- pageOptions: Signal<IPageOptions>;
97
- listOptions: WritableSignal<IListOptions<T>>;
98
- links: { next; prev };
99
-
100
- filter: Signal<ICrudFilter> = this.facade.filter;
101
-
102
- topTpl = viewChild<ViewContainerRef>('topTpl');
103
-
104
- contentTpl = viewChild<TemplateRef<any>>('contentTpl');
105
-
106
- dynamicContents = viewChildren<DynamicContentDirective>(
107
- DynamicContentDirective,
108
- );
109
-
110
- constructor() {
111
- super();
112
-
113
- this.links = this.facade.links();
114
- }
115
-
116
- refreshProperties(): void {
117
- this.baseComponentRef.setInput('listOptions', this.listOptions());
118
- }
119
-
120
- async ngOnInit(): Promise<void> {
121
- this.pageService.checkPermissions();
122
-
123
- const options = getModelOptions(this.config.type);
124
-
125
- let newFilter = null;
126
-
127
- if (this.config.list?.resetQuery === 'beforeInit') {
128
- newFilter = {
129
- query: this.config.baseQuery ? [...this.config.baseQuery] : [],
130
- paginationMode: this.config.list.paginationMode,
131
- limit: this.config.pagination ? this.config.pagination.limit : null,
132
- offset: this.config.pagination ? 0 : null,
133
- sortBy: this.config.sort ? this.config.sort['default'] : null,
134
- sortDesc: this.config.sort ? this.config.sort['defaultDesc'] : null,
135
- ...this.searchService.filter,
136
- };
137
- } else if (this.filter()) {
138
- newFilter = this.filter();
139
- } else {
140
- newFilter = {
141
- paginationMode: this.config.list.paginationMode,
142
- limit: this.searchService.filter?.limit
143
- ? this.searchService.filter.limit
144
- : this.config.pagination
145
- ? this.config.pagination.limit
146
- : null,
147
- offset:
148
- this.searchService.filter?.offset ||
149
- this.searchService.filter?.offset === 0
150
- ? this.searchService.filter.offset
151
- : this.config.pagination
152
- ? 0
153
- : null,
154
- sortBy: this.searchService.filter?.sortBy
155
- ? this.searchService.filter.sortBy
156
- : this.config.sort
157
- ? this.config.sort['default']
158
- : null,
159
- sortDesc: this.searchService.filter?.sortDesc
160
- ? this.searchService.filter.sortDesc
161
- : this.config.sort
162
- ? this.config.sort['defaultDesc']
163
- : null,
164
- query: this.config.baseQuery ? [...this.config.baseQuery] : [],
165
- ...this.searchService.filter,
166
- };
167
- }
168
-
169
- this.facade.read(newFilter);
170
-
171
- const endButtons = this.getEndButtons();
172
-
173
- this.pageOptions = computed(() => ({
174
- title: this.config.title,
175
- search: this.config.search
176
- ? {
177
- text: computed(() => this.filter().searchText ?? null),
178
- set: (txt) => {
179
- if (txt !== this.filter().searchText)
180
- this.facade.read({
181
- ...this.filter(),
182
- searchText: txt,
183
- offset: 0,
184
- });
185
- },
186
- }
187
- : null,
188
- endButtons: endButtons,
189
- }));
190
-
191
- const compiledComponents =
192
- await this.dynamicComponentLoader.getComponentsWithFactories({
193
- components: [
194
- ...(this.config.details &&
195
- this.config.details['components'] &&
196
- this.config.details['components'].top
197
- ? [this.config.details['components'].top]
198
- : []),
199
- ...(this.config.details &&
200
- this.config.details['components'] &&
201
- this.config.details['components'].bottom
202
- ? [this.config.details['components'].bottom]
203
- : []),
204
- ...(this.config.list &&
205
- this.config.list['components'] &&
206
- this.config.list['components'].top
207
- ? [this.config.list['components'].top]
208
- : []),
209
- ],
210
- });
211
-
212
- this.listOptions.set({
213
- provider: {
214
- getData: (filter): void => {
215
- const global = {
216
- ...this.filter(),
217
- ...filter,
218
- };
219
- this.facade.read(global);
220
- },
221
- onChangeMultiSelected: async (list) => {
222
- if (list.length && !this.menuService.openedEnd) {
223
- await this.menuService.openEnd({
224
- injector: this.injector,
225
- component: MultiselectComponent,
226
- });
227
- } else if (!list.length && this.menuService.openedEnd) {
228
- await this.menuService.closeEnd();
229
- }
230
-
231
- this.facade.multiSelect(list);
232
- },
233
- list: this.facade.list,
234
- loading: this.facade.loading,
235
- onCleanMultiSelected$: this._cleanMultiSelected$,
236
- },
237
- cellPipe: this.config.list ? this.config.list.cellPipe : null,
238
- mode: this.config.list?.mode,
239
- type: this.config.type,
240
- details: this.config.details
241
- ? {
242
- provider: {
243
- getData: (id) => {
244
- this.facade.select(id);
245
- },
246
- clearData: () => {
247
- this.facade.unselect();
248
- },
249
- item: this.facade.selected,
250
- loading: this.facade.loading,
251
- },
252
- componentFactories: {
253
- top:
254
- this.config.details &&
255
- this.config.details['components'] &&
256
- this.config.details['components'].top
257
- ? compiledComponents.find(
258
- (cc) =>
259
- cc.component === this.config.details['components'].top,
260
- ).factory
261
- : null,
262
- bottom:
263
- this.config.details &&
264
- this.config.details['components'] &&
265
- this.config.details['components'].bottom
266
- ? compiledComponents.find(
267
- (cc) =>
268
- cc.component ===
269
- this.config.details['components'].bottom,
270
- ).factory
271
- : null,
272
- },
273
- }
274
- : null,
275
- item:
276
- !!this.config.edit || this.config.details
277
- ? {
278
- options: {
279
- routingPrefix: '/' + this.router.routerState.snapshot.url + '/',
280
- edit: !!this.config.edit,
281
- },
282
- }
283
- : null,
284
- remove: this.config.remove
285
- ? {
286
- provider: {
287
- invoke: (id) => this.facade.delete(id),
288
- check: (item: T) => {
289
- return options?.remove?.enabled
290
- ? SpecificationService.valid(item, options?.remove?.enabled)
291
- : true;
292
- },
293
- },
294
- }
295
- : null,
296
- pagination: await this.paginationFacade.create({
297
- mode: this.config.list.paginationMode,
298
- limit: this.config.pagination.limit,
299
- provider: {
300
- getFilter: () => {
301
- return this.filter();
302
- },
303
- getLinks: () => this.links,
304
- },
305
- }),
306
- sort: this.config.sort,
307
- });
308
-
309
- this.cd.detectChanges();
310
-
311
- this.initCloseMenu();
312
- this.initTopComponent(compiledComponents);
313
-
314
- this.refreshDynamicInstance();
315
- }
316
-
317
- private initCloseMenu() {
318
- this.router.events.pipe(this.takeUntilDestroy).subscribe(async () => {
319
- await this.clear();
320
- });
321
- }
322
-
323
- private async clear() {
324
- await this.menuService.closeEnd();
325
-
326
- this.listOptions.update((val) => ({
327
- ...val,
328
- select: null,
329
- }));
330
-
331
- this.facade.multiSelect([]);
332
- }
333
-
334
- private getEndButtons(): Array<IIconButtonOptions> {
335
- const fieldsWithOptions = getModelFieldsWithOptions(new this.config.type());
336
- const modelOptions = getModelOptions(this.config.type);
337
-
338
- const showFilters =
339
- fieldsWithOptions.some(
340
- (x) => (x.options?.list as IFieldListMetadata)?.filter,
341
- ) || modelOptions?.filters?.length;
342
-
343
- const showMultiEdit =
344
- this.config.list?.components?.multi ||
345
- (this.config.edit &&
346
- fieldsWithOptions.some(
347
- (x) => (x.options?.update as IFieldEditMetadata)?.multi,
348
- ) &&
349
- !this.hardwareService.isMobile &&
350
- (!this.config?.list?.mode ||
351
- this.config?.list?.mode === ListMode.desktop));
352
-
353
- return [
354
- ...(showMultiEdit
355
- ? [
356
- {
357
- icon: 'checkbox-outline',
358
- text: 'multi',
359
- handler: () => {
360
- this.facade.multiSelect([]);
361
- this._cleanMultiSelected$.next();
362
-
363
- setTimeout(async () => {
364
- this.listOptions.update((val) => ({
365
- ...val,
366
- select: val.select === 'multi' ? null : 'multi',
367
- }));
368
- if (this.menuService.openedEnd)
369
- await this.menuService.closeEnd();
370
- this.cd.detectChanges();
371
- });
372
- },
373
- },
374
- ]
375
- : []),
376
- ...(showFilters
377
- ? [
378
- {
379
- icon: 'filter-outline',
380
- text: 'filters',
381
- handler: async () => {
382
- await this.menuService.openEnd({
383
- injector: this.injector,
384
- component: FiltersComponent,
385
- });
386
- },
387
- },
388
- ]
389
- : []),
390
- ...(this.config.add
391
- ? [
392
- {
393
- icon: 'add',
394
- text: 'add',
395
- handler: () => {
396
- this.router.navigate([
397
- '/' + this.router.routerState.snapshot.url + '/add',
398
- ]);
399
- },
400
- },
401
- ]
402
- : []),
403
- ...(this.config.export
404
- ? [
405
- {
406
- text: 'export',
407
- icon: 'download-outline',
408
- type: 'popover' as const,
409
- component: ExportComponent,
410
- },
411
- ]
412
- : []),
413
- ...(this.config.buttons ? this.config.buttons : []),
414
- ];
415
- }
416
-
417
- private initTopComponent(
418
- compiledComponents: {
419
- component: any;
420
- factory: ComponentFactory<any>;
421
- }[],
422
- ) {
423
- const factory =
424
- this.config.list &&
425
- this.config.list['components'] &&
426
- this.config.list['components'].top
427
- ? compiledComponents.find(
428
- (cc) => cc.component === this.config.list['components'].top,
429
- ).factory
430
- : null;
431
-
432
- setTimeout(() => {
433
- if (factory && !this.topTpl().get(0)) {
434
- this.topTpl().createComponent(factory);
435
- }
436
- });
437
- }
438
- }
@@ -1,42 +0,0 @@
1
- import { Component, computed, inject, Signal } from '@angular/core';
2
-
3
- import { ListComponent } from '@smartsoft001/angular';
4
- import { IEntity } from '@smartsoft001/domain-core';
5
-
6
- import { CrudFacade } from '../../../+state/crud.facade';
7
- import { FiltersConfigComponent, GroupComponent } from '../../../components';
8
- import { CrudFullConfig } from '../../../crud.config';
9
- import { CrudListGroupService } from '../../../services/list-group/list-group.service';
10
- import { CrudListPageBaseComponent } from '../base/base.component';
11
-
12
- @Component({
13
- selector: 'smart-crud-list-standard-page',
14
- template: `
15
- <smart-crud-filters-config></smart-crud-filters-config>
16
- @let groups = config.list?.groups;
17
- @if (listOptions) {
18
- <smart-list
19
- [hidden]="groups && !isSearch()"
20
- [options]="listOptions()"
21
- ></smart-list>
22
- }
23
- @if (groups && !isSearch()) {
24
- <smart-crud-group
25
- [groups]="groups"
26
- [listOptions]="listOptions()"
27
- ></smart-crud-group>
28
- }
29
- `,
30
- imports: [FiltersConfigComponent, ListComponent, GroupComponent],
31
- providers: [CrudListGroupService],
32
- })
33
- export class ListStandardComponent<
34
- T extends IEntity<string>,
35
- > extends CrudListPageBaseComponent<T> {
36
- private readonly facade = inject(CrudFacade<T>);
37
- public readonly config = inject(CrudFullConfig<T>);
38
-
39
- isSearch: Signal<boolean> = computed(
40
- () => !!this.facade.filter()?.searchText,
41
- );
42
- }
@@ -1,61 +0,0 @@
1
- import { inject, Pipe, PipeTransform, Type } from '@angular/core';
2
-
3
- import { IFormOptions, InputBaseComponent } from '@smartsoft001/angular';
4
- import { IEntity } from '@smartsoft001/domain-core';
5
-
6
- import { CRUD_MODEL_POSSIBILITIES_PROVIDER } from '../../providers/model-possibilities/model-possibilities.provider';
7
-
8
- @Pipe({
9
- name: 'smartFormOptions',
10
- })
11
- export class FormOptionsPipe<T extends IEntity<string>>
12
- implements PipeTransform
13
- {
14
- private modelPossibilitiesProvider = inject(
15
- CRUD_MODEL_POSSIBILITIES_PROVIDER,
16
- );
17
-
18
- transform(
19
- item: T,
20
- mode: string,
21
- type: any,
22
- uniqueProvider?: (values: Record<keyof T, any>) => Promise<boolean>,
23
- inputComponents?: { [key: string]: Type<InputBaseComponent<any>> },
24
- ): IFormOptions<T> {
25
- if (!mode || !type) return null;
26
-
27
- let possibilities = {};
28
-
29
- if (type && this.modelPossibilitiesProvider) {
30
- possibilities = this.modelPossibilitiesProvider.get(type);
31
- }
32
-
33
- if (mode === 'create') {
34
- return {
35
- mode: 'create',
36
- possibilities,
37
- inputComponents,
38
- uniqueProvider,
39
- model: new type(),
40
- show: true,
41
- };
42
- } else {
43
- const model = new type();
44
-
45
- if (item) {
46
- Object.keys(item).forEach((key) => {
47
- model[key] = item[key];
48
- });
49
- }
50
-
51
- return {
52
- mode: mode,
53
- uniqueProvider,
54
- possibilities: possibilities,
55
- inputComponents,
56
- model: model,
57
- show: true,
58
- };
59
- }
60
- }
61
- }
@@ -1,2 +0,0 @@
1
- export * from './pipes.module';
2
- export * from './form-options/form-options.pipe';
@@ -1,9 +0,0 @@
1
- import { NgModule } from '@angular/core';
2
-
3
- import { FormOptionsPipe } from './form-options/form-options.pipe';
4
-
5
- @NgModule({
6
- exports: [FormOptionsPipe],
7
- imports: [FormOptionsPipe],
8
- })
9
- export class CrudPipesModule {}
@@ -1,19 +0,0 @@
1
- import { InjectionToken } from '@angular/core';
2
- import { Observable } from 'rxjs';
3
-
4
- /**
5
- * @deprecated - please, use IModelPossibilitiesProvider from @smartsoft001/angular
6
- */
7
- export abstract class ICrudModelPossibilitiesProvider {
8
- abstract get<T>(type: any): {
9
- [key: string]: Observable<{ id: any; text: string }[]>;
10
- };
11
- }
12
-
13
- /**
14
- * @deprecated - please, use MODEL_POSSIBILITIES_PROVIDER from @smartsoft001/angular
15
- */
16
- export const CRUD_MODEL_POSSIBILITIES_PROVIDER =
17
- new InjectionToken<ICrudModelPossibilitiesProvider>(
18
- 'CRUD_MODEL_POSSIBILITIES_PROVIDER',
19
- );