@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,32 @@
1
+ // @ts-check
2
+ const tseslint = require("typescript-eslint");
3
+ const rootConfig = require("../../eslint.config.js");
4
+
5
+ module.exports = tseslint.config(
6
+ ...rootConfig,
7
+ {
8
+ files: ["**/*.ts"],
9
+ rules: {
10
+ "@angular-eslint/directive-selector": [
11
+ "error",
12
+ {
13
+ type: "attribute",
14
+ prefix: "ccc",
15
+ style: "camelCase",
16
+ },
17
+ ],
18
+ "@angular-eslint/component-selector": [
19
+ "error",
20
+ {
21
+ type: "element",
22
+ prefix: "ccc",
23
+ style: "kebab-case",
24
+ },
25
+ ],
26
+ },
27
+ },
28
+ {
29
+ files: ["**/*.html"],
30
+ rules: {},
31
+ }
32
+ );
@@ -0,0 +1,11 @@
1
+ {
2
+ "$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
3
+ "dest": "../../dist/ccc-lib",
4
+ "lib": {
5
+ "entryFile": "src/index.ts"
6
+ },
7
+ "allowedNonPeerDependencies": [
8
+ "date-fns",
9
+ "date-fns-tz"
10
+ ]
11
+ }
package/package.json CHANGED
@@ -1,79 +1,18 @@
1
1
  {
2
2
  "name": "@cccteam/ccc-lib",
3
- "version": "0.0.13",
3
+ "version": "0.0.15",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git://github.com/cccteam/ccc-lib.git"
7
7
  },
8
8
  "peerDependencies": {
9
- "@angular/common": "^19.0.2",
10
- "@angular/core": "^19.0.2"
9
+ "@angular/common": "^20.0.0",
10
+ "@angular/core": "^20.0.0"
11
11
  },
12
12
  "dependencies": {
13
+ "date-fns": "^4.1.0",
14
+ "date-fns-tz": "^3.2.0",
13
15
  "tslib": "^2.3.0"
14
16
  },
15
- "sideEffects": false,
16
- "module": "fesm2022/cccteam-ccc-lib.mjs",
17
- "typings": "index.d.ts",
18
- "exports": {
19
- "./package.json": {
20
- "default": "./package.json"
21
- },
22
- ".": {
23
- "types": "./index.d.ts",
24
- "default": "./fesm2022/cccteam-ccc-lib.mjs"
25
- },
26
- "./src/auth-authentication-guard": {
27
- "types": "./src/auth-authentication-guard/index.d.ts",
28
- "default": "./fesm2022/cccteam-ccc-lib-src-auth-authentication-guard.mjs"
29
- },
30
- "./src/auth-forms": {
31
- "types": "./src/auth-forms/index.d.ts",
32
- "default": "./fesm2022/cccteam-ccc-lib-src-auth-forms.mjs"
33
- },
34
- "./src/auth-has-permission": {
35
- "types": "./src/auth-has-permission/index.d.ts",
36
- "default": "./fesm2022/cccteam-ccc-lib-src-auth-has-permission.mjs"
37
- },
38
- "./src/auth-authorization-guard": {
39
- "types": "./src/auth-authorization-guard/index.d.ts",
40
- "default": "./fesm2022/cccteam-ccc-lib-src-auth-authorization-guard.mjs"
41
- },
42
- "./src/auth-service": {
43
- "types": "./src/auth-service/index.d.ts",
44
- "default": "./fesm2022/cccteam-ccc-lib-src-auth-service.mjs"
45
- },
46
- "./src/auth-state": {
47
- "types": "./src/auth-state/index.d.ts",
48
- "default": "./fesm2022/cccteam-ccc-lib-src-auth-state.mjs"
49
- },
50
- "./src/types": {
51
- "types": "./src/types/index.d.ts",
52
- "default": "./fesm2022/cccteam-ccc-lib-src-types.mjs"
53
- },
54
- "./src/ui-alert": {
55
- "types": "./src/ui-alert/index.d.ts",
56
- "default": "./fesm2022/cccteam-ccc-lib-src-ui-alert.mjs"
57
- },
58
- "./src/ui-core-state": {
59
- "types": "./src/ui-core-state/index.d.ts",
60
- "default": "./fesm2022/cccteam-ccc-lib-src-ui-core-state.mjs"
61
- },
62
- "./src/ui-interceptor": {
63
- "types": "./src/ui-interceptor/index.d.ts",
64
- "default": "./fesm2022/cccteam-ccc-lib-src-ui-interceptor.mjs"
65
- },
66
- "./src/ui-notification-service": {
67
- "types": "./src/ui-notification-service/index.d.ts",
68
- "default": "./fesm2022/cccteam-ccc-lib-src-ui-notification-service.mjs"
69
- },
70
- "./src/ui-sidenav": {
71
- "types": "./src/ui-sidenav/index.d.ts",
72
- "default": "./fesm2022/cccteam-ccc-lib-src-ui-sidenav.mjs"
73
- },
74
- "./src/util-request-options": {
75
- "types": "./src/util-request-options/index.d.ts",
76
- "default": "./fesm2022/cccteam-ccc-lib-src-util-request-options.mjs"
77
- }
78
- }
79
- }
17
+ "sideEffects": false
18
+ }
@@ -0,0 +1,40 @@
1
+ import { inject } from '@angular/core';
2
+ import { ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
3
+ import { AuthService } from '@cccteam/ccc-lib/src/auth-service';
4
+ import { BASE_URL } from '@cccteam/ccc-lib/src/types';
5
+ import { Observable, of } from 'rxjs';
6
+ import { catchError, map } from 'rxjs/operators';
7
+
8
+ export const AuthenticationGuard = (
9
+ route: ActivatedRouteSnapshot,
10
+ routerState: RouterStateSnapshot,
11
+ ): Observable<boolean> => {
12
+ const authService = inject(AuthService);
13
+ const baseUrl = inject(BASE_URL);
14
+
15
+ const authenticate = (): void => {
16
+ const url = routerState.url;
17
+ const absoluteUrl = baseUrl + (!url.toString().startsWith('/') ? '/' + url : url);
18
+ const encodedUrl = encodeURIComponent(absoluteUrl);
19
+ window.location.href = `${authService.loginRoute()}?returnUrl=${encodedUrl}`;
20
+ };
21
+
22
+ if (authService.authenticated()) {
23
+ return of(true);
24
+ }
25
+
26
+ return authService.checkUserSession().pipe(
27
+ map((sessionInfo) => {
28
+ if (sessionInfo?.authenticated) {
29
+ return true;
30
+ }
31
+
32
+ authenticate();
33
+ return false;
34
+ }),
35
+ catchError(() => {
36
+ authenticate();
37
+ return of(false);
38
+ }),
39
+ );
40
+ };
@@ -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,17 @@
1
+ import { computed, inject, Signal } from '@angular/core';
2
+ import { ActivatedRouteSnapshot, Router } from '@angular/router';
3
+ import { AuthService } from '@cccteam/ccc-lib/src/auth-service';
4
+
5
+ export const AuthorizationGuard = (route: ActivatedRouteSnapshot): Signal<boolean> => {
6
+ const router = inject(Router);
7
+ const auth = inject(AuthService);
8
+ return computed(() => {
9
+ const hasPermission = auth.hasPermission(route.data['scope']);
10
+ if (hasPermission) {
11
+ return true;
12
+ } else {
13
+ router.navigate(['/']);
14
+ return false;
15
+ }
16
+ });
17
+ };
@@ -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 @@
1
+ <p>ccc-field works!</p>
@@ -0,0 +1,22 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+
3
+ import { CccInputFieldComponent } from './ccc-field.component';
4
+
5
+ describe('CccFieldComponent', () => {
6
+ let component: CccInputFieldComponent;
7
+ let fixture: ComponentFixture<CccInputFieldComponent>;
8
+
9
+ beforeEach(async () => {
10
+ await TestBed.configureTestingModule({
11
+ imports: [CccInputFieldComponent],
12
+ }).compileComponents();
13
+
14
+ fixture = TestBed.createComponent(CccInputFieldComponent);
15
+ component = fixture.componentInstance;
16
+ fixture.detectChanges();
17
+ });
18
+
19
+ it('should create', () => {
20
+ expect(component).toBeTruthy();
21
+ });
22
+ });
@@ -0,0 +1,74 @@
1
+ import { Component, computed, inject, input, OnInit, signal, Signal } from '@angular/core';
2
+ import { MatFormFieldModule } from '@angular/material/form-field';
3
+ import { MatInputModule } from '@angular/material/input';
4
+ import { AuthService } from '@cccteam/ccc-lib/src/auth-service';
5
+ import { Domain, ReadPermission, Resource, UpdatePermission } from '@cccteam/ccc-lib/src/types';
6
+
7
+ export enum InputMode {
8
+ Read = 'read',
9
+ Edit = 'edit',
10
+ }
11
+
12
+ @Component({
13
+ selector: 'ccc-input-field',
14
+ imports: [MatFormFieldModule, MatInputModule],
15
+ template: `
16
+ <mat-form-field [class]="className()">
17
+ <mat-label>{{ name() }}</mat-label>
18
+ <input matInput [disabled]="mode() === inputMode.Edit && canEdit()" [value]="value()" />
19
+ </mat-form-field>
20
+ `,
21
+ styleUrl: './ccc-field.component.scss',
22
+ })
23
+ export class CccInputFieldComponent implements OnInit {
24
+ auth = inject(AuthService);
25
+ className = input();
26
+ mode = input.required<InputMode>();
27
+ resource = input.required<Resource>();
28
+ domain = input.required<Domain>();
29
+ value = input.required();
30
+ name = input.required<string>();
31
+
32
+ inputMode = InputMode;
33
+
34
+ canEdit: Signal<boolean> = signal(false);
35
+ canEditSelector = false;
36
+
37
+ canRead: Signal<boolean> = signal(false);
38
+ canReadSelector = false;
39
+
40
+ ngOnInit(): void {
41
+ this.canEditSelector = this.auth.hasPermission({
42
+ resource: this.resource(),
43
+ permission: ReadPermission,
44
+ domain: this.domain(),
45
+ });
46
+ this.canReadSelector = this.auth.hasPermission({
47
+ resource: this.resource(),
48
+ permission: UpdatePermission,
49
+ domain: this.domain(),
50
+ });
51
+
52
+ this.canRead = computed(() => {
53
+ const res = this.resource();
54
+ if (!res) {
55
+ return false;
56
+ }
57
+ if (AuthService.requiresPermission(this.resource(), ReadPermission)) {
58
+ return this.canReadSelector;
59
+ }
60
+ return false;
61
+ });
62
+
63
+ this.canEdit = computed(() => {
64
+ const res = this.resource();
65
+ if (!res) {
66
+ return false;
67
+ }
68
+ if (AuthService.requiresPermission(this.resource(), UpdatePermission)) {
69
+ return this.canEditSelector;
70
+ }
71
+ return false;
72
+ });
73
+ }
74
+ }
@@ -0,0 +1,39 @@
1
+ import { FormArray, FormGroup } from '@angular/forms';
2
+ import { isEqual } from 'lodash-es';
3
+
4
+ /**
5
+ * Accepts a FormGroup and compares it to an object to return the dirty form values
6
+ * as a sparse object
7
+ * @param form - FormGroup
8
+ * @param compareData - object to compare form values against
9
+ * @returns Partial<T>
10
+ * @example sparseFormData<UserCreate>(this.userForm, initUser)
11
+ */
12
+ export function sparseFormData<T>(form: FormGroup, compareData: T): T {
13
+ const sparseFormData: T = {} as T;
14
+
15
+ for (const [key, control] of Object.entries(form.controls)) {
16
+ const controlValue = control.value;
17
+ const compareValue = compareData[key as keyof T];
18
+
19
+ if (!isEqual(controlValue, compareValue)) {
20
+ sparseFormData[key as keyof T] = controlValue as T[keyof T];
21
+ }
22
+ }
23
+
24
+ return sparseFormData;
25
+ }
26
+
27
+ /**
28
+ * Accepts a FormArray and removes empty strings
29
+ * @param formArray - FormArray
30
+ * @returns FormArray
31
+ */
32
+ export function cleanStringFormArray(formArray: FormArray): FormArray {
33
+ for (let i = formArray.controls.length - 1; i >= 0; i--) {
34
+ if (formArray.at(i).value === '') {
35
+ formArray.removeAt(i);
36
+ }
37
+ }
38
+ return formArray;
39
+ }
@@ -1,2 +1,3 @@
1
1
  export * from './ccc-field/ccc-field.component';
2
2
  export * from './form-helpers';
3
+
@@ -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,34 @@
1
+ import { Directive, Input, TemplateRef, ViewContainerRef, effect, inject, signal } from '@angular/core';
2
+ import { AuthService } from '@cccteam/ccc-lib/src/auth-service';
3
+ import { PermissionScope } from '@cccteam/ccc-lib/src/types';
4
+
5
+ @Directive({
6
+ selector: '[cccHasPermission]',
7
+ standalone: true,
8
+ })
9
+ export class HasPermissionDirective {
10
+ private auth = inject(AuthService);
11
+ private templateRef = inject(TemplateRef<unknown>);
12
+ private viewContainer = inject(ViewContainerRef);
13
+
14
+ private scope = signal<PermissionScope | undefined>(undefined);
15
+
16
+ @Input()
17
+ set cccHasPermission(scope: PermissionScope) {
18
+ this.scope.set(scope);
19
+ }
20
+
21
+ constructor() {
22
+ effect(() => {
23
+ const scope = this.scope();
24
+
25
+ if (this.auth.hasPermission(scope) && this.auth.authenticated()) {
26
+ if (!this.viewContainer.get(0)) {
27
+ this.viewContainer.createEmbeddedView(this.templateRef);
28
+ }
29
+ } else {
30
+ this.viewContainer.clear();
31
+ }
32
+ });
33
+ }
34
+ }
@@ -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,92 @@
1
+ import { HttpClient } from '@angular/common/http';
2
+ import { inject, Inject, Injectable, signal } from '@angular/core';
3
+ import {
4
+ API_URL,
5
+ Permission,
6
+ PERMISSION_REQUIRED,
7
+ PermissionScope,
8
+ Resource,
9
+ SessionInfo,
10
+ } from '@cccteam/ccc-lib/src/types';
11
+ import { errorOptions } from '@cccteam/ccc-lib/src/util-request-options';
12
+ import { map, Observable, tap } from 'rxjs';
13
+
14
+ const routes = {
15
+ login: (rootUrl: string): string => `${rootUrl}/user/login`,
16
+ session: (rootUrl: string): string => `${rootUrl}/user/session`,
17
+ };
18
+
19
+ @Injectable({
20
+ providedIn: 'root',
21
+ })
22
+ export class AuthService {
23
+ http = inject(HttpClient);
24
+ private authenticatedSignal = signal(false);
25
+ private sessionInfoSignal = signal({} as SessionInfo);
26
+
27
+ redirectUrl = signal('');
28
+ authenticated = this.authenticatedSignal.asReadonly();
29
+ sessionInfo = this.sessionInfoSignal.asReadonly();
30
+
31
+ constructor(@Inject(API_URL) private apiUrl: string) {
32
+ this.initializePermissionFn();
33
+ }
34
+
35
+ private static permissionFn: (resource: Resource, permission: Permission) => boolean;
36
+
37
+ hasPermission(scope?: PermissionScope): boolean {
38
+ if (!scope) return true;
39
+ const resourcePermissions = this.sessionInfo().permissions?.[scope.domain]?.[scope.resource];
40
+ return Array.isArray(resourcePermissions) && resourcePermissions.includes(scope.permission);
41
+ }
42
+
43
+ static requiresPermission(resource: Resource, permission: Permission): boolean {
44
+ if (!AuthService.permissionFn) {
45
+ throw new Error(
46
+ `AuthState has not been initialized. Ensure AuthState is provided in your module or instantiated at least once.`,
47
+ );
48
+ }
49
+ return AuthService.permissionFn(resource, permission);
50
+ }
51
+
52
+ private initializePermissionFn(): void {
53
+ if (!AuthService.permissionFn) {
54
+ AuthService.permissionFn = inject(PERMISSION_REQUIRED);
55
+ }
56
+ }
57
+
58
+ /**
59
+ * Logs a user out.
60
+ *
61
+ * @returns Observable with a boolean indicating whether they were logged out.
62
+ */
63
+ logout(): Observable<boolean> {
64
+ return this.http
65
+ .delete(routes.session(this.apiUrl), errorOptions(false))
66
+ .pipe(map(() => true))
67
+ .pipe(
68
+ tap(() => {
69
+ this.authenticatedSignal.set(false);
70
+ this.sessionInfoSignal.set({} as SessionInfo);
71
+ }),
72
+ );
73
+ }
74
+
75
+ /**
76
+ * Checks a user's session with the server.
77
+ *
78
+ * @returns Observable with the user session info
79
+ */
80
+ checkUserSession(): Observable<SessionInfo> {
81
+ return this.http.get<SessionInfo>(routes.session(this.apiUrl), errorOptions(false)).pipe(
82
+ tap((sessionInfo) => {
83
+ this.authenticatedSignal.set(!!sessionInfo?.authenticated);
84
+ this.sessionInfoSignal.set(sessionInfo);
85
+ }),
86
+ );
87
+ }
88
+
89
+ loginRoute(): string {
90
+ return routes.login(this.apiUrl);
91
+ }
92
+ }
@@ -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,23 @@
1
+ import { Pipe, PipeTransform } from '@angular/core';
2
+
3
+ @Pipe({
4
+ name: 'camelCaseToTitle',
5
+ })
6
+ export class CamelCaseToTitlePipe implements PipeTransform {
7
+ transform(value: string): string {
8
+ if (!value) {
9
+ return value;
10
+ }
11
+
12
+ if (value === value.toUpperCase() && !/[0-9]/.test(value)) {
13
+ return value;
14
+ }
15
+
16
+ let transformed = value.replace(/([A-Z])/g, ' $1');
17
+ transformed = transformed.replace(/([a-zA-Z])([0-9])/g, '$1 $2');
18
+ transformed = transformed.trim();
19
+ transformed = transformed.charAt(0).toUpperCase() + transformed.slice(1);
20
+
21
+ return transformed;
22
+ }
23
+ }
@@ -0,0 +1 @@
1
+ export * from './camel-case-to-title.pipe';
@@ -0,0 +1,6 @@
1
+ {
2
+ "$schema": "../../../../node_modules/ng-packagr/ng-package.schema.json",
3
+ "lib": {
4
+ "entryFile": "index.ts"
5
+ }
6
+ }