@cccteam/ccc-lib 0.0.15 → 0.0.16

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 (221) hide show
  1. package/README.md +38 -13
  2. package/fesm2022/cccteam-ccc-lib-src-auth-authentication-guard.mjs +36 -0
  3. package/fesm2022/cccteam-ccc-lib-src-auth-authentication-guard.mjs.map +1 -0
  4. package/fesm2022/cccteam-ccc-lib-src-auth-authorization-guard.mjs +25 -0
  5. package/fesm2022/cccteam-ccc-lib-src-auth-authorization-guard.mjs.map +1 -0
  6. package/fesm2022/cccteam-ccc-lib-src-auth-forms.mjs +83 -0
  7. package/fesm2022/cccteam-ccc-lib-src-auth-forms.mjs.map +1 -0
  8. package/fesm2022/cccteam-ccc-lib-src-auth-has-permission.mjs +44 -0
  9. package/fesm2022/cccteam-ccc-lib-src-auth-has-permission.mjs.map +1 -0
  10. package/fesm2022/cccteam-ccc-lib-src-auth-service.mjs +82 -0
  11. package/fesm2022/cccteam-ccc-lib-src-auth-service.mjs.map +1 -0
  12. package/fesm2022/cccteam-ccc-lib-src-ccc-camel-case-to-title.mjs +33 -0
  13. package/fesm2022/cccteam-ccc-lib-src-ccc-camel-case-to-title.mjs.map +1 -0
  14. package/fesm2022/cccteam-ccc-lib-src-ccc-grid.mjs +256 -0
  15. package/fesm2022/cccteam-ccc-lib-src-ccc-grid.mjs.map +1 -0
  16. package/fesm2022/cccteam-ccc-lib-src-ccc-resource.mjs +3129 -0
  17. package/fesm2022/cccteam-ccc-lib-src-ccc-resource.mjs.map +1 -0
  18. package/fesm2022/cccteam-ccc-lib-src-forms.mjs +79 -0
  19. package/fesm2022/cccteam-ccc-lib-src-forms.mjs.map +1 -0
  20. package/fesm2022/cccteam-ccc-lib-src-internal-types.mjs +6 -0
  21. package/fesm2022/cccteam-ccc-lib-src-internal-types.mjs.map +1 -0
  22. package/fesm2022/cccteam-ccc-lib-src-types.mjs +431 -0
  23. package/fesm2022/cccteam-ccc-lib-src-types.mjs.map +1 -0
  24. package/fesm2022/cccteam-ccc-lib-src-ui-alert.mjs +48 -0
  25. package/fesm2022/cccteam-ccc-lib-src-ui-alert.mjs.map +1 -0
  26. package/fesm2022/cccteam-ccc-lib-src-ui-core-service.mjs +41 -0
  27. package/fesm2022/cccteam-ccc-lib-src-ui-core-service.mjs.map +1 -0
  28. package/fesm2022/cccteam-ccc-lib-src-ui-idle-service.mjs +157 -0
  29. package/fesm2022/cccteam-ccc-lib-src-ui-idle-service.mjs.map +1 -0
  30. package/fesm2022/cccteam-ccc-lib-src-ui-interceptor.mjs +50 -0
  31. package/fesm2022/cccteam-ccc-lib-src-ui-interceptor.mjs.map +1 -0
  32. package/fesm2022/cccteam-ccc-lib-src-ui-notification-service.mjs +63 -0
  33. package/fesm2022/cccteam-ccc-lib-src-ui-notification-service.mjs.map +1 -0
  34. package/fesm2022/cccteam-ccc-lib-src-ui-sidenav.mjs +60 -0
  35. package/fesm2022/cccteam-ccc-lib-src-ui-sidenav.mjs.map +1 -0
  36. package/fesm2022/cccteam-ccc-lib-src-util-request-options.mjs +19 -0
  37. package/fesm2022/cccteam-ccc-lib-src-util-request-options.mjs.map +1 -0
  38. package/fesm2022/cccteam-ccc-lib.mjs +4444 -0
  39. package/fesm2022/cccteam-ccc-lib.mjs.map +1 -0
  40. package/package.json +88 -5
  41. package/types/cccteam-ccc-lib-src-auth-authentication-guard.d.ts +6 -0
  42. package/types/cccteam-ccc-lib-src-auth-authorization-guard.d.ts +6 -0
  43. package/types/cccteam-ccc-lib-src-auth-forms.d.ts +28 -0
  44. package/types/cccteam-ccc-lib-src-auth-has-permission.d.ts +15 -0
  45. package/types/cccteam-ccc-lib-src-auth-service.d.ts +38 -0
  46. package/types/cccteam-ccc-lib-src-ccc-camel-case-to-title.d.ts +10 -0
  47. package/types/cccteam-ccc-lib-src-ccc-grid.d.ts +35 -0
  48. package/types/cccteam-ccc-lib-src-ccc-resource.d.ts +674 -0
  49. package/types/cccteam-ccc-lib-src-forms.d.ts +27 -0
  50. package/types/cccteam-ccc-lib-src-types.d.ts +934 -0
  51. package/types/cccteam-ccc-lib-src-ui-alert.d.ts +16 -0
  52. package/types/cccteam-ccc-lib-src-ui-core-service.d.ts +20 -0
  53. package/types/cccteam-ccc-lib-src-ui-idle-service.d.ts +49 -0
  54. package/types/cccteam-ccc-lib-src-ui-interceptor.d.ts +16 -0
  55. package/types/cccteam-ccc-lib-src-ui-notification-service.d.ts +33 -0
  56. package/types/cccteam-ccc-lib-src-ui-sidenav.d.ts +33 -0
  57. package/types/cccteam-ccc-lib-src-util-request-options.d.ts +12 -0
  58. package/types/cccteam-ccc-lib.d.ts +1877 -0
  59. package/eslint.config.js +0 -32
  60. package/ng-package.json +0 -11
  61. package/src/auth-authentication-guard/authentication.guard.ts +0 -40
  62. package/src/auth-authentication-guard/index.ts +0 -1
  63. package/src/auth-authentication-guard/ng-package.json +0 -6
  64. package/src/auth-authorization-guard/authorization.guard.ts +0 -17
  65. package/src/auth-authorization-guard/index.ts +0 -1
  66. package/src/auth-authorization-guard/ng-package.json +0 -6
  67. package/src/auth-forms/ccc-field/ccc-field.component.html +0 -1
  68. package/src/auth-forms/ccc-field/ccc-field.component.scss +0 -0
  69. package/src/auth-forms/ccc-field/ccc-field.component.spec.ts +0 -22
  70. package/src/auth-forms/ccc-field/ccc-field.component.ts +0 -74
  71. package/src/auth-forms/form-helpers.ts +0 -39
  72. package/src/auth-forms/index.ts +0 -3
  73. package/src/auth-forms/ng-package.json +0 -6
  74. package/src/auth-has-permission/has-permission.directive.ts +0 -34
  75. package/src/auth-has-permission/index.ts +0 -1
  76. package/src/auth-has-permission/ng-package.json +0 -6
  77. package/src/auth-service/auth.service.ts +0 -92
  78. package/src/auth-service/index.ts +0 -1
  79. package/src/auth-service/ng-package.json +0 -6
  80. package/src/ccc-camel-case-to-title/camel-case-to-title.pipe.ts +0 -23
  81. package/src/ccc-camel-case-to-title/index.ts +0 -1
  82. package/src/ccc-camel-case-to-title/ng-package.json +0 -6
  83. package/src/ccc-grid/ccc-grid.component.ts +0 -155
  84. package/src/ccc-grid/index.ts +0 -3
  85. package/src/ccc-grid/ng-package.json +0 -6
  86. package/src/ccc-grid/table-button/table-button.component.html +0 -16
  87. package/src/ccc-grid/table-button/table-button.component.scss +0 -5
  88. package/src/ccc-grid/table-button/table-button.component.spec.ts +0 -22
  89. package/src/ccc-grid/table-button/table-button.component.ts +0 -49
  90. package/src/ccc-resource/can-deactivate.guard.ts +0 -41
  91. package/src/ccc-resource/compound-resource/compound-resource.component.html +0 -57
  92. package/src/ccc-resource/compound-resource/compound-resource.component.scss +0 -86
  93. package/src/ccc-resource/compound-resource/compound-resource.component.spec.ts +0 -22
  94. package/src/ccc-resource/compound-resource/compound-resource.component.ts +0 -158
  95. package/src/ccc-resource/concat-fns.ts +0 -162
  96. package/src/ccc-resource/empty-readonly-field/empty-readonly-field.component.html +0 -12
  97. package/src/ccc-resource/empty-readonly-field/empty-readonly-field.component.scss +0 -0
  98. package/src/ccc-resource/empty-readonly-field/empty-readonly-field.component.spec.ts +0 -23
  99. package/src/ccc-resource/empty-readonly-field/empty-readonly-field.component.ts +0 -17
  100. package/src/ccc-resource/form-state.service.ts +0 -24
  101. package/src/ccc-resource/format-fns.ts +0 -49
  102. package/src/ccc-resource/gui-constants.ts +0 -88
  103. package/src/ccc-resource/index.ts +0 -23
  104. package/src/ccc-resource/leave-page-confirmation-modal/leave-page-confirmation-modal.component.html +0 -8
  105. package/src/ccc-resource/leave-page-confirmation-modal/leave-page-confirmation-modal.component.scss +0 -0
  106. package/src/ccc-resource/leave-page-confirmation-modal/leave-page-confirmation-modal.component.spec.ts +0 -22
  107. package/src/ccc-resource/leave-page-confirmation-modal/leave-page-confirmation-modal.component.ts +0 -12
  108. package/src/ccc-resource/ng-package.json +0 -6
  109. package/src/ccc-resource/operation-types.ts +0 -19
  110. package/src/ccc-resource/padding-element/padding-element.component.html +0 -1
  111. package/src/ccc-resource/padding-element/padding-element.component.scss +0 -3
  112. package/src/ccc-resource/padding-element/padding-element.component.spec.ts +0 -22
  113. package/src/ccc-resource/padding-element/padding-element.component.ts +0 -20
  114. package/src/ccc-resource/resource-array-view/resource-array-view.component.html +0 -81
  115. package/src/ccc-resource/resource-array-view/resource-array-view.component.scss +0 -21
  116. package/src/ccc-resource/resource-array-view/resource-array-view.component.spec.ts +0 -22
  117. package/src/ccc-resource/resource-array-view/resource-array-view.component.ts +0 -143
  118. package/src/ccc-resource/resource-base/resource-base.component.spec.ts +0 -22
  119. package/src/ccc-resource/resource-base/resource-base.component.ts +0 -11
  120. package/src/ccc-resource/resource-cache.service.ts +0 -232
  121. package/src/ccc-resource/resource-create/resource-create.component.html +0 -31
  122. package/src/ccc-resource/resource-create/resource-create.component.scss +0 -130
  123. package/src/ccc-resource/resource-create/resource-create.component.spec.ts +0 -22
  124. package/src/ccc-resource/resource-create/resource-create.component.ts +0 -303
  125. package/src/ccc-resource/resource-field/base-field.directive.ts +0 -102
  126. package/src/ccc-resource/resource-field/fields/boolean-field/boolean-field.component.html +0 -16
  127. package/src/ccc-resource/resource-field/fields/boolean-field/boolean-field.component.scss +0 -0
  128. package/src/ccc-resource/resource-field/fields/boolean-field/boolean-field.component.spec.ts +0 -22
  129. package/src/ccc-resource/resource-field/fields/boolean-field/boolean-field.component.ts +0 -15
  130. package/src/ccc-resource/resource-field/fields/computed-field/computed-field.component.html +0 -13
  131. package/src/ccc-resource/resource-field/fields/computed-field/computed-field.component.scss +0 -0
  132. package/src/ccc-resource/resource-field/fields/computed-field/computed-field.component.spec.ts +0 -23
  133. package/src/ccc-resource/resource-field/fields/computed-field/computed-field.component.ts +0 -50
  134. package/src/ccc-resource/resource-field/fields/date-field/date-field.component.html +0 -22
  135. package/src/ccc-resource/resource-field/fields/date-field/date-field.component.scss +0 -0
  136. package/src/ccc-resource/resource-field/fields/date-field/date-field.component.spec.ts +0 -22
  137. package/src/ccc-resource/resource-field/fields/date-field/date-field.component.ts +0 -14
  138. package/src/ccc-resource/resource-field/fields/enumerated-field/enumerated-field.component.html +0 -71
  139. package/src/ccc-resource/resource-field/fields/enumerated-field/enumerated-field.component.scss +0 -9
  140. package/src/ccc-resource/resource-field/fields/enumerated-field/enumerated-field.component.spec.ts +0 -22
  141. package/src/ccc-resource/resource-field/fields/enumerated-field/enumerated-field.component.ts +0 -207
  142. package/src/ccc-resource/resource-field/fields/nullboolean-field/nullboolean-field.component.html +0 -38
  143. package/src/ccc-resource/resource-field/fields/nullboolean-field/nullboolean-field.component.scss +0 -3
  144. package/src/ccc-resource/resource-field/fields/nullboolean-field/nullboolean-field.component.spec.ts +0 -22
  145. package/src/ccc-resource/resource-field/fields/nullboolean-field/nullboolean-field.component.ts +0 -87
  146. package/src/ccc-resource/resource-field/fields/number-field/number-field.component.html +0 -23
  147. package/src/ccc-resource/resource-field/fields/number-field/number-field.component.scss +0 -6
  148. package/src/ccc-resource/resource-field/fields/number-field/number-field.component.spec.ts +0 -22
  149. package/src/ccc-resource/resource-field/fields/number-field/number-field.component.ts +0 -14
  150. package/src/ccc-resource/resource-field/fields/text-field/text-field.component.html +0 -29
  151. package/src/ccc-resource/resource-field/fields/text-field/text-field.component.scss +0 -6
  152. package/src/ccc-resource/resource-field/fields/text-field/text-field.component.spec.ts +0 -22
  153. package/src/ccc-resource/resource-field/fields/text-field/text-field.component.ts +0 -23
  154. package/src/ccc-resource/resource-field/resource-field.component.html +0 -112
  155. package/src/ccc-resource/resource-field/resource-field.component.scss +0 -7
  156. package/src/ccc-resource/resource-field/resource-field.component.spec.ts +0 -22
  157. package/src/ccc-resource/resource-field/resource-field.component.ts +0 -214
  158. package/src/ccc-resource/resource-layout/resource-layout.component.html +0 -73
  159. package/src/ccc-resource/resource-layout/resource-layout.component.scss +0 -26
  160. package/src/ccc-resource/resource-layout/resource-layout.component.spec.ts +0 -22
  161. package/src/ccc-resource/resource-layout/resource-layout.component.ts +0 -176
  162. package/src/ccc-resource/resource-list/ resource-list.component.spec.ts +0 -22
  163. package/src/ccc-resource/resource-list/resource-list.component.html +0 -27
  164. package/src/ccc-resource/resource-list/resource-list.component.scss +0 -67
  165. package/src/ccc-resource/resource-list/resource-list.component.ts +0 -376
  166. package/src/ccc-resource/resource-list-create/resource-list-create.component.html +0 -71
  167. package/src/ccc-resource/resource-list-create/resource-list-create.component.scss +0 -9
  168. package/src/ccc-resource/resource-list-create/resource-list-create.component.spec.ts +0 -22
  169. package/src/ccc-resource/resource-list-create/resource-list-create.component.ts +0 -103
  170. package/src/ccc-resource/resource-resolver/resource-resolver.component.html +0 -1
  171. package/src/ccc-resource/resource-resolver/resource-resolver.component.scss +0 -0
  172. package/src/ccc-resource/resource-resolver/resource-resolver.component.spec.ts +0 -22
  173. package/src/ccc-resource/resource-resolver/resource-resolver.component.ts +0 -69
  174. package/src/ccc-resource/resource-store.service.ts +0 -93
  175. package/src/ccc-resource/resource-view/resource-view.component.html +0 -133
  176. package/src/ccc-resource/resource-view/resource-view.component.scss +0 -150
  177. package/src/ccc-resource/resource-view/resource-view.component.spec.ts +0 -22
  178. package/src/ccc-resource/resource-view/resource-view.component.ts +0 -354
  179. package/src/ccc-resource/resources-helpers.ts +0 -262
  180. package/src/ccc-resource/utils/validator-utils.ts +0 -6
  181. package/src/index.ts +0 -44
  182. package/src/internal-types/ng-package.json +0 -6
  183. package/src/types/auth.actions.ts +0 -46
  184. package/src/types/configs.ts +0 -952
  185. package/src/types/constants.ts +0 -1
  186. package/src/types/core.actions.ts +0 -33
  187. package/src/types/index.ts +0 -9
  188. package/src/types/ng-package.json +0 -6
  189. package/src/types/notification-message.ts +0 -20
  190. package/src/types/permissions.ts +0 -17
  191. package/src/types/session-info.ts +0 -10
  192. package/src/types/tokens.ts +0 -20
  193. package/src/ui-alert/alert.component.html +0 -13
  194. package/src/ui-alert/alert.component.scss +0 -48
  195. package/src/ui-alert/alert.component.spec.ts +0 -22
  196. package/src/ui-alert/alert.component.ts +0 -35
  197. package/src/ui-alert/index.ts +0 -1
  198. package/src/ui-alert/ng-package.json +0 -6
  199. package/src/ui-core-service/index.ts +0 -1
  200. package/src/ui-core-service/ng-package.json +0 -6
  201. package/src/ui-core-service/ui-core.service.ts +0 -34
  202. package/src/ui-interceptor/api.interceptor.spec.ts +0 -16
  203. package/src/ui-interceptor/api.interceptor.ts +0 -45
  204. package/src/ui-interceptor/index.ts +0 -1
  205. package/src/ui-interceptor/ng-package.json +0 -6
  206. package/src/ui-notification-service/index.ts +0 -1
  207. package/src/ui-notification-service/ng-package.json +0 -6
  208. package/src/ui-notification-service/notification.service.ts +0 -59
  209. package/src/ui-sidenav/index.ts +0 -1
  210. package/src/ui-sidenav/ng-package.json +0 -6
  211. package/src/ui-sidenav/sidenav.component.html +0 -60
  212. package/src/ui-sidenav/sidenav.component.scss +0 -99
  213. package/src/ui-sidenav/sidenav.component.spec.ts +0 -22
  214. package/src/ui-sidenav/sidenav.component.ts +0 -64
  215. package/src/util-request-options/index.ts +0 -1
  216. package/src/util-request-options/ng-package.json +0 -6
  217. package/src/util-request-options/request-options.ts +0 -17
  218. package/tsconfig.lib.json +0 -13
  219. package/tsconfig.lib.prod.json +0 -11
  220. package/tsconfig.spec.json +0 -15
  221. /package/{src/internal-types/index.ts → types/cccteam-ccc-lib-src-internal-types.d.ts} +0 -0
@@ -1,303 +0,0 @@
1
- import {
2
- ChangeDetectionStrategy,
3
- Component,
4
- computed,
5
- DestroyRef,
6
- effect,
7
- inject,
8
- input,
9
- OnInit,
10
- output,
11
- signal,
12
- } from '@angular/core';
13
- import { takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop';
14
- import { FormControl, FormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms';
15
- import { MatButtonModule } from '@angular/material/button';
16
- import { MatDividerModule } from '@angular/material/divider';
17
- import { MatIconModule } from '@angular/material/icon';
18
- import { MatInputModule } from '@angular/material/input';
19
- import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
20
- import { ActivatedRoute, Data, Router, RouterModule } from '@angular/router';
21
- import { CamelCaseToTitlePipe } from '@cccteam/ccc-lib/src/ccc-camel-case-to-title';
22
- import {
23
- ChildResourceConfig,
24
- DataType,
25
- FieldElement,
26
- ListViewConfig,
27
- RecordData,
28
- Resource,
29
- RESOURCE_META,
30
- ResourceMeta,
31
- RootConfig,
32
- ViewConfig,
33
- } from '@cccteam/ccc-lib/src/types';
34
- import { NotificationService } from '@cccteam/ccc-lib/src/ui-notification-service';
35
- import { tap } from 'rxjs';
36
- import { FormStateService } from '../form-state.service';
37
- import { flattenElements } from '../gui-constants';
38
- import { CreateOperation } from '../operation-types';
39
- import { ResourceCacheService } from '../resource-cache.service';
40
- import { ResourceLayoutComponent } from '../resource-layout/resource-layout.component';
41
- import { ResourceStore } from '../resource-store.service';
42
- import { cleanStringForm, metadataTypeCoercion } from '../resources-helpers';
43
-
44
- @Component({
45
- selector: 'ccc-resource-create',
46
- imports: [
47
- FormsModule,
48
- ReactiveFormsModule,
49
- MatInputModule,
50
- RouterModule,
51
- MatButtonModule,
52
- MatIconModule,
53
- MatProgressSpinnerModule,
54
- MatDividerModule,
55
- ResourceLayoutComponent,
56
- ],
57
- templateUrl: './resource-create.component.html',
58
- styleUrl: './resource-create.component.scss',
59
- changeDetection: ChangeDetectionStrategy.OnPush,
60
- providers: [ResourceStore],
61
- })
62
- export class ResourceCreateComponent implements OnInit {
63
- activatedRoute = inject(ActivatedRoute);
64
- notifications = inject(NotificationService);
65
- store = inject(ResourceStore);
66
- cache = inject(ResourceCacheService);
67
- router = inject(Router);
68
- destroyRef = inject(DestroyRef);
69
- formState = inject(FormStateService);
70
- resourceMeta = inject(RESOURCE_META);
71
-
72
- routeData = toSignal<Data>(this.activatedRoute.data);
73
-
74
- isDirty = signal(false);
75
- submitted = signal<boolean>(false);
76
- complete = output<boolean>();
77
- resourceConfig = input<ChildResourceConfig>();
78
- parentData = input<RecordData>({});
79
- loadCreatedResource = input<boolean>(false);
80
-
81
- rootConfig = computed(() => {
82
- return this.activatedRoute.snapshot.data['config'] as RootConfig;
83
- });
84
-
85
- config = computed(() => {
86
- const inputConfig = this.resourceConfig() as ViewConfig;
87
- if (inputConfig !== undefined) {
88
- return inputConfig;
89
- }
90
- return this.rootConfig().parentConfig as ListViewConfig;
91
- });
92
-
93
- indentTitle = computed(() => {
94
- if (this.config().collapsible || this.resourceConfig() === undefined) {
95
- return false;
96
- }
97
-
98
- return true;
99
- });
100
-
101
- form = computed(() => {
102
- const meta = this.store.resourceMeta();
103
- const fg = new FormGroup({});
104
- const allElements = flattenElements(this.config().elements);
105
-
106
- for (const field of meta.fields || []) {
107
- if (fg.get(field.fieldName)) {
108
- continue;
109
- }
110
-
111
- let control = new FormControl<DataType>('');
112
- if (field.displayType === 'boolean') {
113
- control = new FormControl<boolean>(false);
114
- }
115
-
116
- const findElement = allElements.find((element) => element.type === 'field' && element.name === field.fieldName);
117
- const fieldConfig = findElement as FieldElement | undefined;
118
- if (!fieldConfig) {
119
- continue;
120
- }
121
- const fieldDefault = fieldConfig.default;
122
- if (field.displayType === 'boolean') {
123
- const booleanDefaultValue =
124
- fieldDefault?.type == 'static' && typeof fieldDefault?.value === 'boolean' ? fieldDefault.value : null;
125
- if (booleanDefaultValue === null) {
126
- console.error(
127
- `Default value for boolean field, ${field.fieldName}, is null, add a default value to the config`,
128
- );
129
- }
130
- control = new FormControl<boolean | null>(booleanDefaultValue);
131
- }
132
-
133
- if (fieldDefault?.type === 'foreignKey' && this.parentData()) {
134
- const parentValue = this.parentData()[fieldDefault.parentId];
135
- if (parentValue !== undefined) {
136
- control.setValue(parentValue);
137
- }
138
- } else if (fieldDefault?.type == 'static') {
139
- const staticDefault = fieldDefault;
140
- if (staticDefault.value) {
141
- control.setValue(staticDefault.value);
142
- }
143
- }
144
-
145
- if (fieldConfig.validators.length > 0) {
146
- control.setValidators(fieldConfig.validators);
147
- }
148
-
149
- if (field.required && !control.hasValidator(Validators.required)) {
150
- control.setValidators([Validators.required]);
151
- }
152
- fg.addControl(field.fieldName, control);
153
- }
154
- return fg;
155
- });
156
-
157
- route = computed(() => {
158
- const meta = this.store.resourceMeta();
159
- if (!meta) return '';
160
- return meta.consolidatedRoute || meta.route;
161
- });
162
-
163
- primaryKeys = computed(() => {
164
- const meta = this.store.resourceMeta() as ResourceMeta;
165
- if (!meta) return [];
166
- return meta.fields
167
- .filter((field) => field.primaryKey)
168
- .sort((a, b) => a.primaryKey!.ordinalPosition - b.primaryKey!.ordinalPosition);
169
- });
170
-
171
- hasRequiredPrimaryKey = computed(() => {
172
- const meta = this.store.resourceMeta() as ResourceMeta;
173
- if (!meta) {
174
- return false;
175
- }
176
- return meta.fields.some((field) => field.primaryKey && field.required);
177
- });
178
-
179
- primaryKeyPath = computed(() => {
180
- const meta = this.store.resourceMeta();
181
- const isConsolidated = meta.consolidatedRoute !== undefined;
182
- const pathPrefix = isConsolidated ? '/' + meta.route : '';
183
- const keyPath = this.primaryKeys()
184
- .map((field) => this.form().get(field.fieldName)?.value)
185
- .join('/');
186
-
187
- if (keyPath === '' && pathPrefix === '') {
188
- return '/';
189
- }
190
-
191
- if (keyPath === '') {
192
- return pathPrefix;
193
- }
194
-
195
- return pathPrefix + '/' + keyPath;
196
- });
197
-
198
- camelCaseToTitlePipe = new CamelCaseToTitlePipe();
199
-
200
- ngOnInit(): void {
201
- if (this.resourceMeta(this.config().primaryResource as Resource)) {
202
- this.store.resourceName.set(this.config().primaryResource as Resource);
203
- this.store.resourceMeta.set(this.resourceMeta(this.config().primaryResource as Resource));
204
- }
205
- }
206
-
207
- saveForm(): void {
208
- if (!this.form().valid) {
209
- this.submitted.set(true);
210
- this.form().markAllAsTouched();
211
- const formElement = document.getElementById('resource-form');
212
- const invalidField = formElement?.querySelector('.mdc-text-field--invalid');
213
- if (invalidField) {
214
- invalidField.scrollIntoView({ behavior: 'smooth' });
215
- }
216
- return;
217
- }
218
-
219
- const resourceMeta = this.store.resourceMeta();
220
- if (!resourceMeta) return;
221
-
222
- const cleanedForm = cleanStringForm<Record<string, string>>(this.form());
223
- if (cleanedForm === undefined || cleanedForm === null) {
224
- return;
225
- }
226
- const coercedCleanedData = metadataTypeCoercion(cleanedForm, this.store.resourceMeta());
227
-
228
- const cleanedDataWithoutPrimaryKeys = Object.fromEntries(
229
- Object.entries(coercedCleanedData).filter(
230
- ([key]) => !this.primaryKeys().some((field) => field.fieldName === key),
231
- ),
232
- );
233
-
234
- const createPatch: CreateOperation = {
235
- op: 'add',
236
- value: cleanedDataWithoutPrimaryKeys,
237
- path: this.primaryKeyPath(),
238
- };
239
-
240
- this.cache
241
- .createPatch(createPatch, this.route(), this.store.resourceName())
242
- .pipe(
243
- tap((response) => {
244
- this.formState.decrementDirtyForms();
245
-
246
- if (!response) {
247
- this.complete.emit(true);
248
- return;
249
- }
250
- const navigationRoutes = this.config().createNavigation;
251
- const createIds = (response[this.store.resourceRoute()] as string[]) || [];
252
- if (this.loadCreatedResource() && createIds.length === 1) {
253
- let route = this.rootConfig().routeData.route;
254
- if (this.parentData() || !route) {
255
- route = resourceMeta.route;
256
- }
257
- if (navigationRoutes.length === 0) {
258
- this.router.navigate([route, createIds[0]]);
259
- } else {
260
- if (createIds[0]) {
261
- navigationRoutes.push(createIds[0]);
262
- }
263
- this.router.navigate(navigationRoutes);
264
- }
265
- } else {
266
- this.complete.emit(true);
267
- }
268
- }),
269
- )
270
- .subscribe();
271
- }
272
-
273
- cancelForm(): void {
274
- if (this.form().dirty) {
275
- this.formState.decrementDirtyForms();
276
- }
277
- this.complete.emit(true);
278
- }
279
-
280
- constructor() {
281
- effect(() => {
282
- console.debug('USAGE | New FormGroup subscription for: ', this.config().title);
283
-
284
- this.form()
285
- .valueChanges.pipe(
286
- tap(() => {
287
- const dirty = this.form().dirty;
288
-
289
- if (dirty !== this.isDirty()) {
290
- this.isDirty.set(dirty);
291
- if (dirty) {
292
- this.formState.incrementDirtyForms();
293
- } else {
294
- this.formState.decrementDirtyForms();
295
- }
296
- }
297
- }),
298
- takeUntilDestroyed(this.destroyRef),
299
- )
300
- .subscribe();
301
- });
302
- }
303
- }
@@ -1,102 +0,0 @@
1
- import { computed, Directive, inject, Injector, input, signal } from '@angular/core';
2
- import { FormGroup } from '@angular/forms';
3
- import { DataType, FieldElement, FieldMeta, Meta, RecordData, RESOURCE_META, RPCFieldMeta } from '@cccteam/ccc-lib/src/types';
4
- import { ResourceCacheService } from '../resource-cache.service';
5
- import { isUUID } from '../resources-helpers';
6
-
7
- /*
8
- * Base class for all resource input components.
9
- */
10
- @Directive()
11
- export abstract class BaseInputComponent {
12
- injector = inject(Injector);
13
- cache = inject(ResourceCacheService);
14
- resourceMeta = inject(RESOURCE_META);
15
-
16
- meta = input.required<Meta>();
17
- pristineValue = input<DataType | null>();
18
- editMode = input.required<'edit' | 'view'>();
19
- showField = input<boolean>();
20
- fieldConfig = input.required<FieldElement>();
21
- fieldClass = input<string>();
22
- fieldMeta = input.required<FieldMeta | RPCFieldMeta>();
23
- form = input.required<FormGroup>();
24
- relatedData = input<RecordData>();
25
-
26
- /**
27
- * Resets the field back to its pristine value.
28
- */
29
- reset(): void {
30
- const control = this.form().get(this.fieldConfig().name as string);
31
- if (control) {
32
- control.setValue(this.pristineValue());
33
- control.markAsPristine();
34
- }
35
- }
36
-
37
- prefixString = computed(() => {
38
- const relatedData = this.relatedData();
39
-
40
- let builtPrefix = '';
41
- this.fieldConfig().prefixes.forEach((prefix) => {
42
- if (typeof prefix === 'string') {
43
- builtPrefix += prefix;
44
- } else if ('resource' in prefix) {
45
- if (!relatedData || !relatedData[prefix.id]) return;
46
- const id = relatedData[prefix.id];
47
- if (typeof id !== 'string') return;
48
- if (!id || !isUUID(id)) return;
49
- const prefixResourceMeta = this.resourceMeta(prefix.resource);
50
- const resource = this.cache
51
- .registerView(signal(prefixResourceMeta.route), signal(prefix.resource), signal(id))
52
- ?.value();
53
- if (resource && prefix.field in resource) {
54
- builtPrefix += resource[prefix.field];
55
- }
56
- } else if ('field' in prefix) {
57
- if (relatedData) {
58
- const fieldValue = relatedData[prefix.field];
59
- builtPrefix += fieldValue ? fieldValue : '';
60
- }
61
- }
62
- });
63
- return builtPrefix;
64
- });
65
-
66
- suffixString = computed(() => {
67
- const relatedData = this.relatedData();
68
-
69
- let builtSuffix = '';
70
- this.fieldConfig().suffixes.forEach((suffix) => {
71
- if (typeof suffix === 'string') {
72
- builtSuffix += suffix;
73
- } else if ('resource' in suffix) {
74
- if (!relatedData || !relatedData[suffix.id]) return;
75
- const id = relatedData[suffix.id];
76
- if (typeof id !== 'string') return;
77
- if (!id || !isUUID(id)) return;
78
- const suffixResourceMeta = this.resourceMeta(suffix.resource);
79
- const resource = this.cache
80
- .registerView(signal(suffixResourceMeta.route), signal(suffix.resource), signal(id))
81
- ?.value();
82
- if (resource && suffix.field in resource) {
83
- builtSuffix += resource[suffix.field];
84
- }
85
- } else if ('field' in suffix) {
86
- if (relatedData) {
87
- const fieldValue = relatedData[suffix.field];
88
- builtSuffix += fieldValue ? fieldValue : '';
89
- }
90
- }
91
- });
92
- return builtSuffix;
93
- });
94
-
95
- floatLabel = computed(() => {
96
- if (this.fieldConfig().prefixes.length > 0 || this.fieldConfig().suffixes.length > 0) {
97
- return 'always';
98
- } else {
99
- return 'auto';
100
- }
101
- });
102
- }
@@ -1,16 +0,0 @@
1
- @if (showField()) {
2
- <ng-container [formGroup]="form()">
3
- <div [class.readonly-field]="editMode() === 'view'">
4
- <mat-checkbox
5
- class="field checkbox {{ fieldClass() }}"
6
- [formControlName]="fieldConfig().name"
7
- (keydown.enter)="$event.preventDefault()">
8
- {{ fieldConfig().label }}
9
- </mat-checkbox>
10
- </div>
11
- </ng-container>
12
- } @else {
13
- <ng-container [formGroup]="form()">
14
- <input type="hidden" [formControlName]="fieldConfig().name" />
15
- </ng-container>
16
- }
@@ -1,22 +0,0 @@
1
- import { ComponentFixture, TestBed } from '@angular/core/testing';
2
-
3
- import { BooleanFieldComponent } from './boolean-field.component';
4
-
5
- xdescribe('BooleanFieldComponent', () => {
6
- let component: BooleanFieldComponent;
7
- let fixture: ComponentFixture<BooleanFieldComponent>;
8
-
9
- beforeEach(async () => {
10
- await TestBed.configureTestingModule({
11
- imports: [BooleanFieldComponent],
12
- }).compileComponents();
13
-
14
- fixture = TestBed.createComponent(BooleanFieldComponent);
15
- component = fixture.componentInstance;
16
- fixture.detectChanges();
17
- });
18
-
19
- it('should create', () => {
20
- expect(component).toBeTruthy();
21
- });
22
- });
@@ -1,15 +0,0 @@
1
- import { Component } from '@angular/core';
2
- import { ReactiveFormsModule } from '@angular/forms';
3
- import { MatCheckboxModule } from '@angular/material/checkbox';
4
- import { MatDatepickerModule } from '@angular/material/datepicker';
5
- import { MatFormFieldModule } from '@angular/material/form-field';
6
- import { MatInputModule } from '@angular/material/input';
7
- import { BaseInputComponent } from '../../base-field.directive';
8
-
9
- @Component({
10
- selector: 'ccc-boolean-field',
11
- imports: [MatFormFieldModule, MatInputModule, MatDatepickerModule, ReactiveFormsModule, MatCheckboxModule],
12
- templateUrl: './boolean-field.component.html',
13
- styleUrl: './boolean-field.component.scss',
14
- })
15
- export class BooleanFieldComponent extends BaseInputComponent {}
@@ -1,13 +0,0 @@
1
- @if (showField()) {
2
- <div class="readonly-field">
3
- <mat-form-field class="field {{ fieldClass() }}" [subscriptSizing]="'dynamic'">
4
- <mat-label>{{ fieldConfig().label }}</mat-label>
5
- <input
6
- matInput
7
- (keydown.enter)="$event.preventDefault()"
8
- [readonly]="true"
9
- type="text"
10
- [value]="computedValue()" />
11
- </mat-form-field>
12
- </div>
13
- }
@@ -1,23 +0,0 @@
1
- import { ComponentFixture, TestBed } from '@angular/core/testing';
2
-
3
- import { ComputedFieldComponent } from './computed-field.component';
4
-
5
- describe('ComputedFieldComponent', () => {
6
- let component: ComputedFieldComponent;
7
- let fixture: ComponentFixture<ComputedFieldComponent>;
8
-
9
- beforeEach(async () => {
10
- await TestBed.configureTestingModule({
11
- imports: [ComputedFieldComponent]
12
- })
13
- .compileComponents();
14
-
15
- fixture = TestBed.createComponent(ComputedFieldComponent);
16
- component = fixture.componentInstance;
17
- fixture.detectChanges();
18
- });
19
-
20
- it('should create', () => {
21
- expect(component).toBeTruthy();
22
- });
23
- });
@@ -1,50 +0,0 @@
1
- import { Component, computed, effect, HostBinding, input } from '@angular/core';
2
- import { MatButtonModule } from '@angular/material/button';
3
- import { MatFormFieldModule } from '@angular/material/form-field';
4
- import { MatInputModule } from '@angular/material/input';
5
- import { ComputedDisplayFieldElement, RecordData } from '@cccteam/ccc-lib/src/types';
6
-
7
- @Component({
8
- selector: 'ccc-computed-field',
9
- imports: [MatFormFieldModule, MatButtonModule, MatInputModule],
10
- templateUrl: './computed-field.component.html',
11
- styleUrl: './computed-field.component.scss',
12
- })
13
- export class ComputedFieldComponent {
14
- fieldConfig = input.required<ComputedDisplayFieldElement>();
15
- fieldClass = input<string>();
16
- formDataState = input<RecordData>();
17
-
18
- computedValue = computed(() => {
19
- try {
20
- return this.fieldConfig().calculatedValue(this.formDataState());
21
- } catch (e) {
22
- console.error('Failed to calculate value for computed field: ', this.fieldConfig().label);
23
- console.error(e);
24
- return '';
25
- }
26
- });
27
-
28
- showField = computed(() => {
29
- const shouldRender = this.fieldConfig().shouldRender;
30
- if (typeof shouldRender === 'boolean') {
31
- return shouldRender;
32
- }
33
-
34
- try {
35
- return shouldRender(this.formDataState());
36
- } catch (e) {
37
- console.error('Failed to calculate value for should Render function for field: ', this.fieldConfig().label);
38
- console.error(e);
39
- return true;
40
- }
41
- });
42
-
43
- @HostBinding('class') class = '';
44
-
45
- constructor() {
46
- effect(() => {
47
- this.class = this.showField() ? 'col-' + this.fieldConfig()?.cols : 'hidden-field';
48
- });
49
- }
50
- }
@@ -1,22 +0,0 @@
1
- @if (showField()) {
2
- <div [class.readonly-field]="editMode() === 'view'">
3
- <mat-form-field class="field {{ fieldClass() }}" [formGroup]="form()" [subscriptSizing]="'dynamic'">
4
- <mat-label>{{ fieldConfig().label }}</mat-label>
5
- <input
6
- matInput
7
- [readonly]="editMode() === 'view'"
8
- [matDatepicker]="picker"
9
- type="text"
10
- (keydown.enter)="$event.preventDefault()"
11
- [formControlName]="fieldConfig().name" />
12
- @if (editMode() === 'edit') {
13
- <mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
14
- }
15
- <mat-datepicker #picker></mat-datepicker>
16
- </mat-form-field>
17
- </div>
18
- } @else {
19
- <ng-container [formGroup]="form()">
20
- <input type="hidden" [formControlName]="fieldConfig().name" />
21
- </ng-container>
22
- }
@@ -1,22 +0,0 @@
1
- import { ComponentFixture, TestBed } from '@angular/core/testing';
2
-
3
- import { DateFieldComponent } from './date-field.component';
4
-
5
- xdescribe('DateFieldComponent', () => {
6
- let component: DateFieldComponent;
7
- let fixture: ComponentFixture<DateFieldComponent>;
8
-
9
- beforeEach(async () => {
10
- await TestBed.configureTestingModule({
11
- imports: [DateFieldComponent],
12
- }).compileComponents();
13
-
14
- fixture = TestBed.createComponent(DateFieldComponent);
15
- component = fixture.componentInstance;
16
- fixture.detectChanges();
17
- });
18
-
19
- it('should create', () => {
20
- expect(component).toBeTruthy();
21
- });
22
- });
@@ -1,14 +0,0 @@
1
- import { Component } from '@angular/core';
2
- import { ReactiveFormsModule } from '@angular/forms';
3
- import { MatDatepickerModule } from '@angular/material/datepicker';
4
- import { MatFormFieldModule } from '@angular/material/form-field';
5
- import { MatInputModule } from '@angular/material/input';
6
- import { BaseInputComponent } from '../../base-field.directive';
7
-
8
- @Component({
9
- selector: 'ccc-date-field',
10
- imports: [MatFormFieldModule, MatInputModule, MatDatepickerModule, ReactiveFormsModule],
11
- templateUrl: './date-field.component.html',
12
- styleUrl: './date-field.component.scss',
13
- })
14
- export class DateFieldComponent extends BaseInputComponent {}