@cccteam/ccc-lib 0.0.13 → 0.0.15

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 (226) hide show
  1. package/eslint.config.js +32 -0
  2. package/ng-package.json +11 -0
  3. package/package.json +7 -68
  4. package/src/auth-authentication-guard/authentication.guard.ts +40 -0
  5. package/src/auth-authentication-guard/ng-package.json +6 -0
  6. package/src/auth-authorization-guard/authorization.guard.ts +17 -0
  7. package/src/auth-authorization-guard/ng-package.json +6 -0
  8. package/src/auth-forms/ccc-field/ccc-field.component.html +1 -0
  9. package/src/auth-forms/ccc-field/ccc-field.component.scss +0 -0
  10. package/src/auth-forms/ccc-field/ccc-field.component.spec.ts +22 -0
  11. package/src/auth-forms/ccc-field/ccc-field.component.ts +74 -0
  12. package/src/auth-forms/form-helpers.ts +39 -0
  13. package/src/auth-forms/{public-api.d.ts → index.ts} +1 -0
  14. package/src/auth-forms/ng-package.json +6 -0
  15. package/src/auth-has-permission/has-permission.directive.ts +34 -0
  16. package/src/auth-has-permission/ng-package.json +6 -0
  17. package/src/auth-service/auth.service.ts +92 -0
  18. package/src/auth-service/ng-package.json +6 -0
  19. package/src/ccc-camel-case-to-title/camel-case-to-title.pipe.ts +23 -0
  20. package/src/ccc-camel-case-to-title/index.ts +1 -0
  21. package/src/ccc-camel-case-to-title/ng-package.json +6 -0
  22. package/src/ccc-grid/ccc-grid.component.ts +155 -0
  23. package/src/ccc-grid/index.ts +3 -0
  24. package/src/ccc-grid/ng-package.json +6 -0
  25. package/src/ccc-grid/table-button/table-button.component.html +16 -0
  26. package/src/ccc-grid/table-button/table-button.component.scss +5 -0
  27. package/src/ccc-grid/table-button/table-button.component.spec.ts +22 -0
  28. package/src/ccc-grid/table-button/table-button.component.ts +49 -0
  29. package/src/ccc-resource/can-deactivate.guard.ts +41 -0
  30. package/src/ccc-resource/compound-resource/compound-resource.component.html +57 -0
  31. package/src/ccc-resource/compound-resource/compound-resource.component.scss +86 -0
  32. package/src/ccc-resource/compound-resource/compound-resource.component.spec.ts +22 -0
  33. package/src/ccc-resource/compound-resource/compound-resource.component.ts +158 -0
  34. package/src/ccc-resource/concat-fns.ts +162 -0
  35. package/src/ccc-resource/empty-readonly-field/empty-readonly-field.component.html +12 -0
  36. package/src/ccc-resource/empty-readonly-field/empty-readonly-field.component.scss +0 -0
  37. package/src/ccc-resource/empty-readonly-field/empty-readonly-field.component.spec.ts +23 -0
  38. package/src/ccc-resource/empty-readonly-field/empty-readonly-field.component.ts +17 -0
  39. package/src/ccc-resource/form-state.service.ts +24 -0
  40. package/src/ccc-resource/format-fns.ts +49 -0
  41. package/src/ccc-resource/gui-constants.ts +88 -0
  42. package/src/ccc-resource/index.ts +23 -0
  43. package/src/ccc-resource/leave-page-confirmation-modal/leave-page-confirmation-modal.component.html +8 -0
  44. package/src/ccc-resource/leave-page-confirmation-modal/leave-page-confirmation-modal.component.scss +0 -0
  45. package/src/ccc-resource/leave-page-confirmation-modal/leave-page-confirmation-modal.component.spec.ts +22 -0
  46. package/src/ccc-resource/leave-page-confirmation-modal/leave-page-confirmation-modal.component.ts +12 -0
  47. package/src/ccc-resource/ng-package.json +6 -0
  48. package/src/ccc-resource/operation-types.ts +19 -0
  49. package/src/ccc-resource/padding-element/padding-element.component.html +1 -0
  50. package/src/ccc-resource/padding-element/padding-element.component.scss +3 -0
  51. package/src/ccc-resource/padding-element/padding-element.component.spec.ts +22 -0
  52. package/src/ccc-resource/padding-element/padding-element.component.ts +20 -0
  53. package/src/ccc-resource/resource-array-view/resource-array-view.component.html +81 -0
  54. package/src/ccc-resource/resource-array-view/resource-array-view.component.scss +21 -0
  55. package/src/ccc-resource/resource-array-view/resource-array-view.component.spec.ts +22 -0
  56. package/src/ccc-resource/resource-array-view/resource-array-view.component.ts +143 -0
  57. package/src/ccc-resource/resource-base/resource-base.component.spec.ts +22 -0
  58. package/src/ccc-resource/resource-base/resource-base.component.ts +11 -0
  59. package/src/ccc-resource/resource-cache.service.ts +232 -0
  60. package/src/ccc-resource/resource-create/resource-create.component.html +31 -0
  61. package/src/ccc-resource/resource-create/resource-create.component.scss +130 -0
  62. package/src/ccc-resource/resource-create/resource-create.component.spec.ts +22 -0
  63. package/src/ccc-resource/resource-create/resource-create.component.ts +303 -0
  64. package/src/ccc-resource/resource-field/base-field.directive.ts +102 -0
  65. package/src/ccc-resource/resource-field/fields/boolean-field/boolean-field.component.html +16 -0
  66. package/src/ccc-resource/resource-field/fields/boolean-field/boolean-field.component.scss +0 -0
  67. package/src/ccc-resource/resource-field/fields/boolean-field/boolean-field.component.spec.ts +22 -0
  68. package/src/ccc-resource/resource-field/fields/boolean-field/boolean-field.component.ts +15 -0
  69. package/src/ccc-resource/resource-field/fields/computed-field/computed-field.component.html +13 -0
  70. package/src/ccc-resource/resource-field/fields/computed-field/computed-field.component.scss +0 -0
  71. package/src/ccc-resource/resource-field/fields/computed-field/computed-field.component.spec.ts +23 -0
  72. package/src/ccc-resource/resource-field/fields/computed-field/computed-field.component.ts +50 -0
  73. package/src/ccc-resource/resource-field/fields/date-field/date-field.component.html +22 -0
  74. package/src/ccc-resource/resource-field/fields/date-field/date-field.component.scss +0 -0
  75. package/src/ccc-resource/resource-field/fields/date-field/date-field.component.spec.ts +22 -0
  76. package/src/ccc-resource/resource-field/fields/date-field/date-field.component.ts +14 -0
  77. package/src/ccc-resource/resource-field/fields/enumerated-field/enumerated-field.component.html +71 -0
  78. package/src/ccc-resource/resource-field/fields/enumerated-field/enumerated-field.component.scss +9 -0
  79. package/src/ccc-resource/resource-field/fields/enumerated-field/enumerated-field.component.spec.ts +22 -0
  80. package/src/ccc-resource/resource-field/fields/enumerated-field/enumerated-field.component.ts +207 -0
  81. package/src/ccc-resource/resource-field/fields/nullboolean-field/nullboolean-field.component.html +38 -0
  82. package/src/ccc-resource/resource-field/fields/nullboolean-field/nullboolean-field.component.scss +3 -0
  83. package/src/ccc-resource/resource-field/fields/nullboolean-field/nullboolean-field.component.spec.ts +22 -0
  84. package/src/ccc-resource/resource-field/fields/nullboolean-field/nullboolean-field.component.ts +87 -0
  85. package/src/ccc-resource/resource-field/fields/number-field/number-field.component.html +23 -0
  86. package/src/ccc-resource/resource-field/fields/number-field/number-field.component.scss +6 -0
  87. package/src/ccc-resource/resource-field/fields/number-field/number-field.component.spec.ts +22 -0
  88. package/src/ccc-resource/resource-field/fields/number-field/number-field.component.ts +14 -0
  89. package/src/ccc-resource/resource-field/fields/text-field/text-field.component.html +29 -0
  90. package/src/ccc-resource/resource-field/fields/text-field/text-field.component.scss +6 -0
  91. package/src/ccc-resource/resource-field/fields/text-field/text-field.component.spec.ts +22 -0
  92. package/src/ccc-resource/resource-field/fields/text-field/text-field.component.ts +23 -0
  93. package/src/ccc-resource/resource-field/resource-field.component.html +112 -0
  94. package/src/ccc-resource/resource-field/resource-field.component.scss +7 -0
  95. package/src/ccc-resource/resource-field/resource-field.component.spec.ts +22 -0
  96. package/src/ccc-resource/resource-field/resource-field.component.ts +214 -0
  97. package/src/ccc-resource/resource-layout/resource-layout.component.html +73 -0
  98. package/src/ccc-resource/resource-layout/resource-layout.component.scss +26 -0
  99. package/src/ccc-resource/resource-layout/resource-layout.component.spec.ts +22 -0
  100. package/src/ccc-resource/resource-layout/resource-layout.component.ts +176 -0
  101. package/src/ccc-resource/resource-list/ resource-list.component.spec.ts +22 -0
  102. package/src/ccc-resource/resource-list/resource-list.component.html +27 -0
  103. package/src/ccc-resource/resource-list/resource-list.component.scss +67 -0
  104. package/src/ccc-resource/resource-list/resource-list.component.ts +376 -0
  105. package/src/ccc-resource/resource-list-create/resource-list-create.component.html +71 -0
  106. package/src/ccc-resource/resource-list-create/resource-list-create.component.scss +9 -0
  107. package/src/ccc-resource/resource-list-create/resource-list-create.component.spec.ts +22 -0
  108. package/src/ccc-resource/resource-list-create/resource-list-create.component.ts +103 -0
  109. package/src/ccc-resource/resource-resolver/resource-resolver.component.html +1 -0
  110. package/src/ccc-resource/resource-resolver/resource-resolver.component.scss +0 -0
  111. package/src/ccc-resource/resource-resolver/resource-resolver.component.spec.ts +22 -0
  112. package/src/ccc-resource/resource-resolver/resource-resolver.component.ts +69 -0
  113. package/src/ccc-resource/resource-store.service.ts +93 -0
  114. package/src/ccc-resource/resource-view/resource-view.component.html +133 -0
  115. package/src/ccc-resource/resource-view/resource-view.component.scss +150 -0
  116. package/src/ccc-resource/resource-view/resource-view.component.spec.ts +22 -0
  117. package/src/ccc-resource/resource-view/resource-view.component.ts +354 -0
  118. package/src/ccc-resource/resources-helpers.ts +262 -0
  119. package/src/ccc-resource/utils/validator-utils.ts +6 -0
  120. package/{fesm2022/cccteam-ccc-lib.mjs → src/index.ts} +32 -11
  121. package/src/internal-types/index.ts +1 -0
  122. package/src/internal-types/ng-package.json +6 -0
  123. package/src/types/auth.actions.ts +46 -0
  124. package/src/types/configs.ts +952 -0
  125. package/src/types/constants.ts +1 -0
  126. package/src/types/core.actions.ts +33 -0
  127. package/src/types/{public-api.d.ts → index.ts} +3 -0
  128. package/src/types/ng-package.json +6 -0
  129. package/src/types/notification-message.ts +20 -0
  130. package/src/types/{permissions.d.ts → permissions.ts} +9 -9
  131. package/src/types/{session-info.d.ts → session-info.ts} +4 -3
  132. package/src/types/tokens.ts +20 -0
  133. package/src/ui-alert/alert.component.html +13 -0
  134. package/src/ui-alert/alert.component.scss +48 -0
  135. package/src/ui-alert/alert.component.spec.ts +22 -0
  136. package/src/ui-alert/alert.component.ts +35 -0
  137. package/src/ui-alert/ng-package.json +6 -0
  138. package/src/ui-core-service/index.ts +1 -0
  139. package/src/ui-core-service/ng-package.json +6 -0
  140. package/src/ui-core-service/ui-core.service.ts +34 -0
  141. package/src/ui-interceptor/api.interceptor.spec.ts +16 -0
  142. package/src/ui-interceptor/api.interceptor.ts +45 -0
  143. package/src/ui-interceptor/ng-package.json +6 -0
  144. package/src/ui-notification-service/ng-package.json +6 -0
  145. package/src/ui-notification-service/notification.service.ts +59 -0
  146. package/src/ui-sidenav/ng-package.json +6 -0
  147. package/src/ui-sidenav/sidenav.component.html +60 -0
  148. package/src/ui-sidenav/sidenav.component.scss +99 -0
  149. package/src/ui-sidenav/sidenav.component.spec.ts +22 -0
  150. package/src/ui-sidenav/sidenav.component.ts +64 -0
  151. package/src/util-request-options/ng-package.json +6 -0
  152. package/src/util-request-options/request-options.ts +17 -0
  153. package/tsconfig.lib.json +13 -0
  154. package/tsconfig.lib.prod.json +11 -0
  155. package/tsconfig.spec.json +15 -0
  156. package/cccteam-ccc-lib-0.0.13.tgz +0 -0
  157. package/fesm2022/cccteam-ccc-lib-src-auth-authentication-guard.mjs +0 -44
  158. package/fesm2022/cccteam-ccc-lib-src-auth-authentication-guard.mjs.map +0 -1
  159. package/fesm2022/cccteam-ccc-lib-src-auth-authorization-guard.mjs +0 -24
  160. package/fesm2022/cccteam-ccc-lib-src-auth-authorization-guard.mjs.map +0 -1
  161. package/fesm2022/cccteam-ccc-lib-src-auth-forms.mjs +0 -118
  162. package/fesm2022/cccteam-ccc-lib-src-auth-forms.mjs.map +0 -1
  163. package/fesm2022/cccteam-ccc-lib-src-auth-has-permission.mjs +0 -51
  164. package/fesm2022/cccteam-ccc-lib-src-auth-has-permission.mjs.map +0 -1
  165. package/fesm2022/cccteam-ccc-lib-src-auth-service.mjs +0 -56
  166. package/fesm2022/cccteam-ccc-lib-src-auth-service.mjs.map +0 -1
  167. package/fesm2022/cccteam-ccc-lib-src-auth-state.mjs +0 -109
  168. package/fesm2022/cccteam-ccc-lib-src-auth-state.mjs.map +0 -1
  169. package/fesm2022/cccteam-ccc-lib-src-types.mjs +0 -137
  170. package/fesm2022/cccteam-ccc-lib-src-types.mjs.map +0 -1
  171. package/fesm2022/cccteam-ccc-lib-src-ui-alert.mjs +0 -48
  172. package/fesm2022/cccteam-ccc-lib-src-ui-alert.mjs.map +0 -1
  173. package/fesm2022/cccteam-ccc-lib-src-ui-core-state.mjs +0 -100
  174. package/fesm2022/cccteam-ccc-lib-src-ui-core-state.mjs.map +0 -1
  175. package/fesm2022/cccteam-ccc-lib-src-ui-interceptor.mjs +0 -48
  176. package/fesm2022/cccteam-ccc-lib-src-ui-interceptor.mjs.map +0 -1
  177. package/fesm2022/cccteam-ccc-lib-src-ui-notification-service.mjs +0 -57
  178. package/fesm2022/cccteam-ccc-lib-src-ui-notification-service.mjs.map +0 -1
  179. package/fesm2022/cccteam-ccc-lib-src-ui-sidenav.mjs +0 -70
  180. package/fesm2022/cccteam-ccc-lib-src-ui-sidenav.mjs.map +0 -1
  181. package/fesm2022/cccteam-ccc-lib-src-util-request-options.mjs +0 -19
  182. package/fesm2022/cccteam-ccc-lib-src-util-request-options.mjs.map +0 -1
  183. package/fesm2022/cccteam-ccc-lib.mjs.map +0 -1
  184. package/index.d.ts +0 -5
  185. package/public-api.d.ts +0 -13
  186. package/src/auth-authentication-guard/authentication.guard.d.ts +0 -3
  187. package/src/auth-authentication-guard/index.d.ts +0 -5
  188. package/src/auth-authorization-guard/authorization.guard.d.ts +0 -3
  189. package/src/auth-authorization-guard/index.d.ts +0 -5
  190. package/src/auth-forms/ccc-field/ccc-field.component.d.ts +0 -25
  191. package/src/auth-forms/form-helpers.d.ts +0 -16
  192. package/src/auth-forms/index.d.ts +0 -5
  193. package/src/auth-has-permission/has-permission.directive.d.ts +0 -12
  194. package/src/auth-has-permission/index.d.ts +0 -5
  195. package/src/auth-service/auth.service.d.ts +0 -24
  196. package/src/auth-service/index.d.ts +0 -5
  197. package/src/auth-state/auth.state.d.ts +0 -27
  198. package/src/auth-state/index.d.ts +0 -5
  199. package/src/auth-state/public-api.d.ts +0 -1
  200. package/src/types/auth.actions.d.ts +0 -41
  201. package/src/types/core.actions.d.ts +0 -31
  202. package/src/types/index.d.ts +0 -5
  203. package/src/types/notification-message.d.ts +0 -18
  204. package/src/types/tokens.d.ts +0 -13
  205. package/src/ui-alert/alert.component.d.ts +0 -13
  206. package/src/ui-alert/index.d.ts +0 -5
  207. package/src/ui-core-state/core.state.d.ts +0 -28
  208. package/src/ui-core-state/index.d.ts +0 -5
  209. package/src/ui-core-state/public-api.d.ts +0 -1
  210. package/src/ui-interceptor/api.interceptor.d.ts +0 -12
  211. package/src/ui-interceptor/index.d.ts +0 -5
  212. package/src/ui-notification-service/index.d.ts +0 -5
  213. package/src/ui-notification-service/notification.service.d.ts +0 -30
  214. package/src/ui-sidenav/index.d.ts +0 -5
  215. package/src/ui-sidenav/sidenav.component.d.ts +0 -31
  216. package/src/util-request-options/index.d.ts +0 -5
  217. package/src/util-request-options/request-options.d.ts +0 -8
  218. /package/src/auth-authentication-guard/{public-api.d.ts → index.ts} +0 -0
  219. /package/src/auth-authorization-guard/{public-api.d.ts → index.ts} +0 -0
  220. /package/src/auth-has-permission/{public-api.d.ts → index.ts} +0 -0
  221. /package/src/auth-service/{public-api.d.ts → index.ts} +0 -0
  222. /package/src/ui-alert/{public-api.d.ts → index.ts} +0 -0
  223. /package/src/ui-interceptor/{public-api.d.ts → index.ts} +0 -0
  224. /package/src/ui-notification-service/{public-api.d.ts → index.ts} +0 -0
  225. /package/src/ui-sidenav/{public-api.d.ts → index.ts} +0 -0
  226. /package/src/util-request-options/{public-api.d.ts → index.ts} +0 -0
@@ -0,0 +1,162 @@
1
+ export const concatFunctions = {
2
+ 'space-concat': spaceConcat,
3
+ 'hyphen-concat': hyphenConcat,
4
+ 'space-hyphen-concat': spaceHyphenConcat,
5
+ 'hyphen-space-concat': hyphenSpaceConcat,
6
+ };
7
+
8
+ /**
9
+ * Concatenates the strings corresponding to the given keys in the resource,
10
+ * using a space separator.
11
+ * @param resource A record mapping keys to string values.
12
+ * @param args Keys of the resource to concatenate.
13
+ * @returns Concatenated string.
14
+ * @example
15
+ * const resource = { foo: 'foo', bar: 'bar', baz: 'baz' };
16
+ * spaceConcat(resource, 'foo', 'bar', 'baz'); // returns 'foo bar baz'
17
+ */
18
+ export function spaceConcat(resource: Record<string, string>, ...args: string[]): string {
19
+ if (args.length === 0) return '';
20
+ if (args.length === 1) return resource[args[0] ?? ''] ?? '';
21
+ return args.map((arg) => resource[arg] ?? '').join(' ');
22
+ }
23
+
24
+ /**
25
+ * Concatenates the strings corresponding to the given keys in the resource,
26
+ * using a hyphen separator.
27
+ * @param resource A record mapping keys to string values.
28
+ * @param args Keys of the resource to concatenate.
29
+ * @returns Concatenated string.
30
+ * @example
31
+ * const resource = { foo: 'foo', bar: 'bar', baz: 'baz' };
32
+ * hyphenConcat(resource, 'foo', 'bar', 'baz'); // returns 'foo - bar - baz'
33
+ */
34
+ export function hyphenConcat(resource: Record<string, string>, ...args: string[]): string {
35
+ if (args.length === 0) return '';
36
+ if (args.length === 1) return resource[args[0] ?? ''] ?? '';
37
+ return args.map((arg) => resource[arg] ?? '').join(' - ');
38
+ }
39
+
40
+ /**
41
+ * Concatenates the given strings so that all but the last are joined with a space,
42
+ * and the last string is appended with a " - " separator.
43
+ * @param resource A mapping of keys to string values.
44
+ * @param args Keys of strings to concatenate.
45
+ * @returns Concatenated string.
46
+ * @example spaceHyphenConcat(resource, 'foo', 'bar', 'baz') => 'foo bar - baz'
47
+ */
48
+ export function spaceHyphenConcat(resource: Record<string, string>, ...args: string[]): string {
49
+ if (args.length === 0) return '';
50
+ if (args.length === 1) return resource[args[0] || ''] || '';
51
+
52
+ const initialPart = args
53
+ .slice(0, -1)
54
+ .map((arg) => resource[arg] || '')
55
+ .join(' ');
56
+
57
+ const lastPart = resource[args[args.length - 1] || ''] || '';
58
+
59
+ return `${initialPart} - ${lastPart}`;
60
+ }
61
+
62
+ /**
63
+ * Concatenates the given strings so that all but the first are joined with a space,
64
+ * and the first string is appended with a " - " separator.
65
+ * @param resource A mapping of keys to string values.
66
+ * @param args Keys of strings to concatenate.
67
+ * @returns Concatenated string.
68
+ * @example spaceHyphenConcat(resource, 'foo', 'bar', 'baz') => 'foo - bar baz'
69
+ */
70
+ export function hyphenSpaceConcat(resource: Record<string, string>, ...args: string[]): string {
71
+ if (args.length === 0) return '';
72
+ if (args.length === 1) return resource[args[0] || ''] || '';
73
+
74
+ const initialPart = args[0] !== undefined ? resource[args[0]] || '' : '';
75
+
76
+ const lastPart = args
77
+ .slice(1, args.length)
78
+ .map((arg) => resource[arg] || '')
79
+ .join(' ');
80
+
81
+ return `${initialPart} - ${lastPart}`;
82
+ }
83
+
84
+ /**
85
+ * Concatenates the strings using a space separator.
86
+ * @param args Strings to concatenate.
87
+ * @returns Concatenated string.
88
+ * @example
89
+ * spaceConcatWithoutResource(['foo', 'bar', 'baz']); // returns 'foo bar baz'
90
+ */
91
+ export function spaceConcatWithoutResource(args: string[]): string {
92
+ if (args.length === 0) return '';
93
+ if (args.length === 1) return args[0] ?? '';
94
+ return args.map((arg) => arg ?? '').join(' ');
95
+ }
96
+
97
+ /**
98
+ * Concatenates the strings using a hyphen separator.
99
+ * @param args Strings to concatenate.
100
+ * @returns Concatenated string.
101
+ * @example
102
+ * hyphenConcatWithoutResource(['foo', 'bar', 'baz']); // returns 'foo - bar - baz'
103
+ */
104
+ export function hyphenConcatWithoutResource(args: string[]): string {
105
+ if (args.length === 0) return '';
106
+ if (args.length === 1) return args[0] || '';
107
+ return args.join(' - ');
108
+ }
109
+
110
+ /**
111
+ * Concatenates the given strings so that all but the last are joined with a space,
112
+ * and the last string is appended with a " - " separator.
113
+ * @param args Strings to concatenate.
114
+ * @returns Concatenated string.
115
+ * @example spaceHyphenConcatWithoutResource(['foo', 'bar', 'baz']) => 'foo bar - baz'
116
+ */
117
+ export function spaceHyphenConcatWithoutResource(args: string[]): string {
118
+ if (args.length === 0) return '';
119
+ if (args.length === 1) return args[0] || '';
120
+
121
+ const initialPart = args
122
+ .slice(0, -1)
123
+ .map((arg) => arg || '')
124
+ .join(' ');
125
+
126
+ const lastPart = args[args.length - 1] || '';
127
+
128
+ return `${initialPart} - ${lastPart}`;
129
+ }
130
+
131
+ /**
132
+ * Concatenates the given strings so that all but the first are joined with a space,
133
+ * and the first string is appended with a " - " separator.
134
+ * @param args Strings to concatenate.
135
+ * @returns Concatenated string.
136
+ * @example hyphenSpaceConcatWithoutResource(['foo', 'bar', 'baz']) => 'foo - bar baz'
137
+ */
138
+ export function hyphenSpaceConcatWithoutResource(args: string[]): string {
139
+ if (args.length === 0) return '';
140
+ if (args.length === 1) return args[0] || '';
141
+
142
+ const initialPart = args[0] || '';
143
+
144
+ const lastPart = args
145
+ .slice(1, args.length)
146
+ .map((arg) => arg || '')
147
+ .join(' ');
148
+
149
+ return `${initialPart} - ${lastPart}`;
150
+ }
151
+
152
+ /**
153
+ * Concatenates the given strings without any space,
154
+ * @param args Strings to concatenate.
155
+ * @returns Concatenated string.
156
+ * @example noSpaceConcatWithoutResource(['foo', 'bar', 'baz']) => 'foobarbaz'
157
+ */
158
+ export function noSpaceConcatWithoutResource(args: string[]): string {
159
+ if (args.length === 0) return '';
160
+ if (args.length === 1) return args[0] || '';
161
+ return args.join('');
162
+ }
@@ -0,0 +1,12 @@
1
+ <div class="readonly-field">
2
+ <mat-form-field class="field" [subscriptSizing]="'dynamic'">
3
+ <mat-label>{{ label() }}</mat-label>
4
+ <input
5
+ matInput
6
+ (keydown.enter)="$event.preventDefault()"
7
+ [readonly]="true"
8
+ type="text"
9
+ [value]="displayValue"
10
+ id="{{ label() }}-readonly-input-text" />
11
+ </mat-form-field>
12
+ </div>
@@ -0,0 +1,23 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+
3
+ import { EmptyReadonlyFieldComponent } from './empty-readonly-field.component';
4
+
5
+ describe('EmptyReadonlyFieldComponent', () => {
6
+ let component: EmptyReadonlyFieldComponent;
7
+ let fixture: ComponentFixture<EmptyReadonlyFieldComponent>;
8
+
9
+ beforeEach(async () => {
10
+ await TestBed.configureTestingModule({
11
+ imports: [EmptyReadonlyFieldComponent]
12
+ })
13
+ .compileComponents();
14
+
15
+ fixture = TestBed.createComponent(EmptyReadonlyFieldComponent);
16
+ component = fixture.componentInstance;
17
+ fixture.detectChanges();
18
+ });
19
+
20
+ it('should create', () => {
21
+ expect(component).toBeTruthy();
22
+ });
23
+ });
@@ -0,0 +1,17 @@
1
+ import { Component, 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 { defaultEmptyFieldValue } from '@cccteam/ccc-lib/src/types';
6
+
7
+ @Component({
8
+ selector: 'ccc-empty-readonly-field',
9
+ imports: [MatFormFieldModule, MatButtonModule, MatInputModule],
10
+ templateUrl: './empty-readonly-field.component.html',
11
+ styleUrl: './empty-readonly-field.component.scss',
12
+ })
13
+ export class EmptyReadonlyFieldComponent {
14
+ label = input.required<string>();
15
+
16
+ displayValue = defaultEmptyFieldValue;
17
+ }
@@ -0,0 +1,24 @@
1
+ import { computed, Injectable, signal } from '@angular/core';
2
+
3
+ @Injectable({
4
+ providedIn: 'root',
5
+ })
6
+ export class FormStateService {
7
+ dirtyForms = signal(0);
8
+
9
+ incrementDirtyForms(): void {
10
+ this.dirtyForms.set(this.dirtyForms() + 1);
11
+ }
12
+
13
+ decrementDirtyForms(): void {
14
+ this.dirtyForms.set(this.dirtyForms() - 1);
15
+ }
16
+
17
+ resetDirtyForms(): void {
18
+ this.dirtyForms.set(0);
19
+ }
20
+
21
+ isDirty = computed(() => {
22
+ return this.dirtyForms() > 0;
23
+ });
24
+ }
@@ -0,0 +1,49 @@
1
+ import { FormatType } from '@cccteam/ccc-lib/src/types';
2
+ import { format, isValid, parseISO } from 'date-fns';
3
+
4
+ export type FormatterFn = (value: string) => string;
5
+
6
+ export const simpleSlashDateFormatter = (value: string): string => {
7
+ if (!value) return '';
8
+ const parsedDate = parseISO(value.toString());
9
+
10
+ if (isValid(parsedDate)) {
11
+ return format(parsedDate, 'M/d/yyyy');
12
+ }
13
+
14
+ console.error('Applying simpleSlashDateFormatter to invalid date value:', value);
15
+ return value.toString();
16
+ };
17
+
18
+ export const ValueFormatters: Record<FormatType, FormatterFn> = {
19
+ ['simpleSlashDateFormat']: simpleSlashDateFormatter,
20
+ };
21
+
22
+ export function applyFormatting(formatString: string, value: string): string {
23
+ if (!value) return '';
24
+ if (formatString in ValueFormatters) {
25
+ return ValueFormatters[formatString as FormatType](value);
26
+ }
27
+
28
+ //default to formatting as a date with provided format string
29
+ const parsedDate = parseISO(value.toString());
30
+
31
+ if (isValid(parsedDate)) {
32
+ return format(parsedDate, formatString);
33
+ }
34
+
35
+ return value.toString();
36
+ }
37
+
38
+ export function formatDateString(formatString: string, value: string): string {
39
+ if (!value) return '';
40
+
41
+ //default to formatting as a date with provided format string
42
+ const parsedDate = parseISO(value.toString());
43
+
44
+ if (isValid(parsedDate)) {
45
+ return format(parsedDate, formatString);
46
+ }
47
+
48
+ return value.toString();
49
+ }
@@ -0,0 +1,88 @@
1
+ import { AbstractControl, ValidationErrors, Validators } from '@angular/forms';
2
+ import { ConfigElement, ResourceValidatorFn } from '@cccteam/ccc-lib/src/types';
3
+ import { isDate } from 'date-fns';
4
+ import { formatInTimeZone } from 'date-fns-tz';
5
+ import { isNumber } from 'lodash-es';
6
+ import { createResourceValidator } from './utils/validator-utils';
7
+
8
+ export const maxConfigElementRecursionDepth = 240;
9
+ export const maxLayoutNestingDepth = 48;
10
+
11
+ /** Returns a flat array of nested elements by recursively traversing
12
+ * through the elements graph */
13
+ export const flattenElements: (elements: ConfigElement[], depth?: number) => ConfigElement[] = (
14
+ elements: ConfigElement[],
15
+ depth = 0,
16
+ ) => {
17
+ depth++;
18
+ if (!elements || elements.length === 0 || depth > maxConfigElementRecursionDepth) {
19
+ return [];
20
+ }
21
+ return elements.reduce((acc, element) => {
22
+ if (element.type === 'section') {
23
+ return acc.concat(element, flattenElements(element.children, depth));
24
+ }
25
+ return acc.concat(element);
26
+ }, [] as ConfigElement[]);
27
+ };
28
+
29
+ export const civildateCoercion = (value: string): Date => {
30
+ if (value === undefined || value === '') {
31
+ return new Date(value);
32
+ }
33
+ return new Date(formatInTimeZone(new Date(value), 'UTC', 'yyyy-MM-dd HH:mm:ss'));
34
+ };
35
+
36
+ const currentOrFutureDateValidator = (control: AbstractControl): ValidationErrors | null => {
37
+ if (!control.value) {
38
+ return null; // Let "REQUIRED" validator handle empty values
39
+ }
40
+
41
+ if (!isDate(control.value)) {
42
+ return { errorMsg: 'Value must be a valid date' };
43
+ }
44
+
45
+ const selectedDate = new Date(control.value);
46
+ const today = new Date();
47
+ today.setHours(0, 0, 0, 0);
48
+
49
+ if (selectedDate >= today) {
50
+ return null;
51
+ }
52
+
53
+ return { errorMsg: 'Date must be greater than or equal to the current date' };
54
+ };
55
+
56
+ const positiveNumberValidator = (control: AbstractControl): ValidationErrors | null => {
57
+ if (!control.value && control.value !== 0) {
58
+ return null; // Let "REQUIRED" validator handle "empty" values
59
+ }
60
+
61
+ if (isNumber(control.value) && control.value > 0) {
62
+ return null;
63
+ }
64
+
65
+ return { errorMsg: 'Value must be a positive number' };
66
+ };
67
+
68
+ /**
69
+ * This object stores every possible validator used across the application
70
+ * Add all validators that are used in configs to this object
71
+ *
72
+ * Available validators that may be added: min, max, required, requiredTrue,
73
+ * email, minLength, maxLength, pattern, nullValidator
74
+ */
75
+ export const resourceValidators = Object.freeze({
76
+ REQUIRED: createResourceValidator(Validators.required),
77
+ EMAIL: createResourceValidator(Validators.email),
78
+ CURRENT_OR_FUTURE_DATE: createResourceValidator(currentOrFutureDateValidator),
79
+ POSITIVE_NUMBER: createResourceValidator(positiveNumberValidator),
80
+
81
+ // Add any additional validators here. They may be defined in
82
+ // a different file if they are too large. E.g.:
83
+ // MIN_LENGTH_3: createResourceValidator(Validators.minLength(3)),
84
+ });
85
+
86
+ export const validatorsPresent = (control: AbstractControl, validatorResources: ResourceValidatorFn[]): boolean => {
87
+ return validatorResources.every((validator) => control.hasValidator(validator));
88
+ };
@@ -0,0 +1,23 @@
1
+ export * from './can-deactivate.guard';
2
+ export * from './compound-resource/compound-resource.component';
3
+ export * from './concat-fns';
4
+ export * from './empty-readonly-field/empty-readonly-field.component';
5
+ export * from './form-state.service';
6
+ export * from './format-fns';
7
+ export * from './gui-constants';
8
+ export * from './leave-page-confirmation-modal/leave-page-confirmation-modal.component';
9
+ export * from './padding-element/padding-element.component';
10
+ export * from './resource-array-view/resource-array-view.component';
11
+ export * from './resource-base/resource-base.component';
12
+ export * from './resource-cache.service';
13
+ export * from './resource-create/resource-create.component';
14
+ export * from './resource-field/base-field.directive';
15
+ export * from './resource-field/resource-field.component';
16
+ export * from './resource-layout/resource-layout.component';
17
+ export * from './resource-list-create/resource-list-create.component';
18
+ export * from './resource-list/resource-list.component';
19
+ export * from './resource-resolver/resource-resolver.component';
20
+ export * from './resource-store.service';
21
+ export * from './resource-view/resource-view.component';
22
+ export * from './resources-helpers';
23
+
@@ -0,0 +1,8 @@
1
+ <div mat-dialog-title>You have unsaved changes, are you sure you want to leave?</div>
2
+ <mat-dialog-content>
3
+ <p>Any unsaved changes will be lost.</p>
4
+ </mat-dialog-content>
5
+ <mat-dialog-actions align="end">
6
+ <button mat-raised-button color="warn" [mat-dialog-close]="false">Cancel</button>
7
+ <button mat-raised-button color="accent" [mat-dialog-close]="true">Confirm</button>
8
+ </mat-dialog-actions>
@@ -0,0 +1,22 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+
3
+ import { LeavePageConfirmationModalComponent } from './leave-page-confirmation-modal.component';
4
+
5
+ describe('LeavePageConfirmationModalComponent', () => {
6
+ let component: LeavePageConfirmationModalComponent;
7
+ let fixture: ComponentFixture<LeavePageConfirmationModalComponent>;
8
+
9
+ beforeEach(async () => {
10
+ await TestBed.configureTestingModule({
11
+ imports: [LeavePageConfirmationModalComponent],
12
+ }).compileComponents();
13
+
14
+ fixture = TestBed.createComponent(LeavePageConfirmationModalComponent);
15
+ component = fixture.componentInstance;
16
+ fixture.detectChanges();
17
+ });
18
+
19
+ it('should create', () => {
20
+ expect(component).toBeTruthy();
21
+ });
22
+ });
@@ -0,0 +1,12 @@
1
+ import { Component } from '@angular/core';
2
+ import { MatButtonModule } from '@angular/material/button';
3
+ import { MatDialogActions, MatDialogModule } from '@angular/material/dialog';
4
+ import { MatFormFieldModule } from '@angular/material/form-field';
5
+
6
+ @Component({
7
+ selector: 'ccc-leave-page-confirmation-modal',
8
+ imports: [MatDialogModule, MatFormFieldModule, MatDialogActions, MatButtonModule],
9
+ templateUrl: './leave-page-confirmation-modal.component.html',
10
+ styleUrls: ['./leave-page-confirmation-modal.component.scss'],
11
+ })
12
+ export class LeavePageConfirmationModalComponent {}
@@ -0,0 +1,6 @@
1
+ {
2
+ "$schema": "../../../../node_modules/ng-packagr/ng-package.schema.json",
3
+ "lib": {
4
+ "entryFile": "./index.ts"
5
+ }
6
+ }
@@ -0,0 +1,19 @@
1
+ export type PatchOperation = 'add' | 'patch' | 'remove';
2
+
3
+ export interface Operation {
4
+ op: PatchOperation;
5
+ value?: Record<string, unknown>;
6
+ path: string;
7
+ }
8
+
9
+ export interface CreateOperation extends Operation {
10
+ op: 'add';
11
+ }
12
+
13
+ export interface UpdateOperation extends Operation {
14
+ op: 'patch';
15
+ }
16
+
17
+ export interface DeleteOperation extends Operation {
18
+ op: 'remove';
19
+ }
@@ -0,0 +1 @@
1
+ <div class="padding-container"></div>
@@ -0,0 +1,3 @@
1
+ .padding-container {
2
+ height: 52px;
3
+ }
@@ -0,0 +1,22 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+
3
+ import { PaddingElementComponent } from './padding-element.component';
4
+
5
+ describe('PaddingElementComponent', () => {
6
+ let component: PaddingElementComponent;
7
+ let fixture: ComponentFixture<PaddingElementComponent>;
8
+
9
+ beforeEach(async () => {
10
+ await TestBed.configureTestingModule({
11
+ imports: [PaddingElementComponent],
12
+ }).compileComponents();
13
+
14
+ fixture = TestBed.createComponent(PaddingElementComponent);
15
+ component = fixture.componentInstance;
16
+ fixture.detectChanges();
17
+ });
18
+
19
+ it('should create', () => {
20
+ expect(component).toBeTruthy();
21
+ });
22
+ });
@@ -0,0 +1,20 @@
1
+ import { Component, HostBinding, input, OnInit } from '@angular/core';
2
+ import { PaddingElement } from '@cccteam/ccc-lib/src/types';
3
+
4
+ @Component({
5
+ selector: 'ccc-padding-element',
6
+ imports: [],
7
+ templateUrl: './padding-element.component.html',
8
+ styleUrls: ['./padding-element.component.scss'],
9
+ })
10
+ export class PaddingElementComponent implements OnInit {
11
+ paddingElement = input.required<PaddingElement>();
12
+
13
+ @HostBinding('class') class = 'col-6';
14
+
15
+ ngOnInit(): void {
16
+ if (this.paddingElement().cols) {
17
+ this.class = 'col-' + this.paddingElement()?.cols;
18
+ }
19
+ }
20
+ }
@@ -0,0 +1,81 @@
1
+ @if (resourceConfig().title !== '') {
2
+ <div class="resource-array-view">
3
+ <mat-expansion-panel
4
+ #expPanel
5
+ [@.disabled]="true"
6
+ [disabled]="!resourceConfig().collapsible"
7
+ [expanded]="!resourceConfig().collapsible">
8
+ <mat-expansion-panel-header>
9
+ @if (resourceConfig().title) {
10
+ <mat-panel-title>
11
+ <h1 class="title">
12
+ {{ resourceConfig().title }}
13
+ </h1>
14
+ </mat-panel-title>
15
+ }
16
+ @if (showCreateButton()) {
17
+ <button
18
+ mat-icon-button
19
+ class="exp-panel-add-element-btn"
20
+ color="accent"
21
+ (click)="createResource($event)"
22
+ [matTooltip]="resourceConfig().createButtonLabel"
23
+ matTooltipPosition="above">
24
+ <mat-icon color="accent">add_circle</mat-icon>
25
+ </button>
26
+ }
27
+ </mat-expansion-panel-header>
28
+
29
+ @if (!resourceConfig().collapsible && !resourceConfig().title) {
30
+ <div class="no-title-exp-panel-padding"></div>
31
+ }
32
+
33
+ @if (createMode()) {
34
+ <ccc-resource-create
35
+ [resourceConfig]="createConfig()"
36
+ [parentData]="parentData()"
37
+ (complete)="onCreateCompleted()">
38
+ </ccc-resource-create>
39
+ }
40
+ @for (resource of store.listData(); track resource['id']; let i = $index) {
41
+ @let resourceId = (resource[resourceConfig().connectorField] || resource['id']) + '';
42
+
43
+ @if (parentData() && resourceConfig().iteratedConfig && resourceId && i + 1 <= resourceConfig().limit) {
44
+ <ng-container *ngComponentOutlet="compoundResourceComponent().componentType;
45
+ inputs: {
46
+ uuid: resourceId,
47
+ parentData: parentData(),
48
+ isArrayChild: true,
49
+ resourceConfig: resourceConfig().iteratedConfig
50
+ }">
51
+ </ng-container>
52
+ }
53
+ }
54
+
55
+ @if (store.listData().length === 0) {
56
+ <div>No records found</div>
57
+ }
58
+ </mat-expansion-panel>
59
+ </div>
60
+ } @else {
61
+ @if (createMode()) {
62
+ <ccc-resource-create [resourceConfig]="createConfig()" [parentData]="parentData()" (complete)="onCreateCompleted()">
63
+ </ccc-resource-create>
64
+ }
65
+ @for (resource of store.listData(); track resource['id']; let i = $index) {
66
+ @if (parentData() && resourceConfig().iteratedConfig && resource['id'] && i + 1 <= resourceConfig().limit) {
67
+ <ng-container *ngComponentOutlet="compoundResourceComponent().componentType;
68
+ inputs: {
69
+ uuid: resource['id'] + '',
70
+ parentData: parentData(),
71
+ isArrayChild: true,
72
+ resourceConfig: resourceConfig().iteratedConfig
73
+ }">
74
+ </ng-container>
75
+ }
76
+ }
77
+
78
+ @if (store.listData().length === 0) {
79
+ <div>No records found</div>
80
+ }
81
+ }
@@ -0,0 +1,21 @@
1
+ .resource-array-view {
2
+ display: flex;
3
+ flex-direction: column;
4
+ min-height: 36px;
5
+ padding: 10px 0 0 0;
6
+ }
7
+
8
+ .title {
9
+ display: flex;
10
+ align-items: center;
11
+ flex-shrink: 0;
12
+ }
13
+
14
+ .exp-panel-add-element-btn {
15
+ margin-right: 10px;
16
+ transform: scale(1.2);
17
+ }
18
+
19
+ .no-title-exp-panel-padding {
20
+ padding: 10px;
21
+ }
@@ -0,0 +1,22 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+
3
+ import { ResourceArrayViewComponent } from './resource-array-view.component';
4
+
5
+ xdescribe('ResourceArrayViewComponent', () => {
6
+ let component: ResourceArrayViewComponent;
7
+ let fixture: ComponentFixture<ResourceArrayViewComponent>;
8
+
9
+ beforeEach(async () => {
10
+ await TestBed.configureTestingModule({
11
+ imports: [ResourceArrayViewComponent],
12
+ }).compileComponents();
13
+
14
+ fixture = TestBed.createComponent(ResourceArrayViewComponent);
15
+ component = fixture.componentInstance;
16
+ fixture.detectChanges();
17
+ });
18
+
19
+ it('should create', () => {
20
+ expect(component).toBeTruthy();
21
+ });
22
+ });