@lenne.tech/ng-base 13.6.5 → 13.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (193) hide show
  1. package/base-components/base-components.module.d.ts +8 -3
  2. package/base-components/components/breadcrumb/breadcrumb.component.d.ts +10 -0
  3. package/base-components/components/checkbox/checkbox.component.d.ts +1 -1
  4. package/base-components/components/loading-bar/loading-bar.component.d.ts +5 -0
  5. package/base-components/components/select/select.component.d.ts +2 -1
  6. package/base-components/components/skeleton-loader/skeleton-loader.component.d.ts +10 -0
  7. package/base-components/components/tags/tags.component.d.ts +33 -0
  8. package/base-components/components/toast/toast.component.d.ts +18 -0
  9. package/base-components/public-api.d.ts +5 -0
  10. package/base-prototype/base-prototype.module.d.ts +6 -5
  11. package/base-prototype/pages/forgot-password/forgot-password.component.d.ts +7 -2
  12. package/base-prototype/pages/login/login.component.d.ts +8 -2
  13. package/base-prototype/pages/register/register.component.d.ts +8 -2
  14. package/esm2020/base-components/base-components.module.mjs +23 -3
  15. package/esm2020/base-components/components/breadcrumb/breadcrumb.component.mjs +17 -0
  16. package/esm2020/base-components/components/checkbox/checkbox.component.mjs +3 -3
  17. package/esm2020/base-components/components/input/input.component.mjs +3 -3
  18. package/esm2020/base-components/components/loading-bar/loading-bar.component.mjs +11 -0
  19. package/esm2020/base-components/components/select/select.component.mjs +6 -3
  20. package/esm2020/base-components/components/skeleton-loader/skeleton-loader.component.mjs +33 -0
  21. package/esm2020/base-components/components/tags/tags.component.mjs +85 -0
  22. package/esm2020/base-components/components/toast/toast.component.mjs +61 -0
  23. package/esm2020/base-components/public-api.mjs +6 -1
  24. package/esm2020/base-prototype/base-prototype.module.mjs +5 -4
  25. package/esm2020/base-prototype/pages/forgot-password/forgot-password.component.mjs +30 -9
  26. package/esm2020/base-prototype/pages/login/login.component.mjs +46 -9
  27. package/esm2020/base-prototype/pages/register/register.component.mjs +45 -11
  28. package/esm2020/public-api.mjs +1 -42
  29. package/esm2020/shared/classes/auth.class.mjs +16 -0
  30. package/esm2020/shared/classes/basic-user.class.mjs +51 -0
  31. package/esm2020/shared/classes/graphql-enum.class.mjs +9 -0
  32. package/esm2020/shared/classes/graphql-meta.class.mjs +171 -0
  33. package/esm2020/shared/classes/graphql-type.class.mjs +13 -0
  34. package/esm2020/shared/classes/helper.class.mjs +304 -0
  35. package/esm2020/shared/classes/standard.class.mjs +40 -0
  36. package/esm2020/{src → shared}/enums/comparison-operator.enum.mjs +1 -1
  37. package/esm2020/shared/enums/graphql-request-type.enum.mjs +10 -0
  38. package/esm2020/shared/enums/logical-operator.enum.mjs +10 -0
  39. package/esm2020/shared/enums/skeleton-type.enum.mjs +7 -0
  40. package/esm2020/shared/enums/sort-order.enum.mjs +6 -0
  41. package/esm2020/shared/enums/toast-type.enum.mjs +7 -0
  42. package/esm2020/shared/functions/ws-client.function.mjs +39 -0
  43. package/esm2020/shared/interfaces/base-module-config.interface.mjs +3 -0
  44. package/esm2020/shared/interfaces/breadcrumb.interface.mjs +2 -0
  45. package/esm2020/shared/interfaces/can-component-deactivate.interface.mjs +2 -0
  46. package/esm2020/shared/interfaces/combined-filter-input.interface.mjs +2 -0
  47. package/esm2020/shared/interfaces/field-object.interface.mjs +2 -0
  48. package/esm2020/shared/interfaces/field.interface.mjs +2 -0
  49. package/esm2020/shared/interfaces/filter-input.interface.mjs +2 -0
  50. package/esm2020/shared/interfaces/find-args.interface.mjs +2 -0
  51. package/esm2020/shared/interfaces/graphql-fields-object.interface.mjs +2 -0
  52. package/esm2020/shared/interfaces/graphql-options.interface.mjs +2 -0
  53. package/esm2020/shared/interfaces/graphql-plus-options.interfacen.mjs +2 -0
  54. package/esm2020/shared/interfaces/graphql-type-collection.interface.mjs +2 -0
  55. package/esm2020/shared/interfaces/single-filter-input.interface.mjs +2 -0
  56. package/esm2020/shared/interfaces/sort-input.interface.mjs +2 -0
  57. package/esm2020/shared/interfaces/time-components.interface.mjs +2 -0
  58. package/esm2020/shared/interfaces/toast.interface.mjs +2 -0
  59. package/esm2020/shared/lenne.tech-ng-base-shared.mjs +5 -0
  60. package/esm2020/shared/public-api.mjs +57 -0
  61. package/esm2020/shared/services/auth.service.mjs +71 -0
  62. package/esm2020/shared/services/breadcrumb.service.mjs +68 -0
  63. package/esm2020/shared/services/forms.service.mjs +25 -0
  64. package/esm2020/shared/services/graphql-meta.service.mjs +123 -0
  65. package/esm2020/shared/services/graphql-plus.service.mjs +84 -0
  66. package/esm2020/shared/services/graphql.service.mjs +441 -0
  67. package/esm2020/shared/services/image.service.mjs +102 -0
  68. package/esm2020/shared/services/loader.service.mjs +29 -0
  69. package/esm2020/shared/services/scroll.service.mjs +179 -0
  70. package/esm2020/shared/services/storage.service.mjs +132 -0
  71. package/esm2020/shared/services/toast.service.mjs +41 -0
  72. package/esm2020/shared/services/user.service.mjs +82 -0
  73. package/esm2020/shared/services/ws.service.mjs +16 -0
  74. package/esm2020/shared/types/graphql-fields.type.mjs +2 -0
  75. package/esm2020/shared/types/storage.type.mjs +2 -0
  76. package/esm2020/shared/validators/match.validator.mjs +19 -0
  77. package/esm2020/src/base.module.mjs +14 -11
  78. package/esm2020/src/directives/match-height.directive.mjs +2 -2
  79. package/esm2020/src/factories/apollo-options.factory.mjs +14 -12
  80. package/esm2020/src/guards/auth.guard.mjs +3 -3
  81. package/esm2020/src/guards/can-deactivate.guard.mjs +1 -1
  82. package/esm2020/src/guards/logout.guard.mjs +2 -2
  83. package/esm2020/src/services/theme.service.mjs +2 -2
  84. package/fesm2015/lenne.tech-ng-base-base-components.mjs +218 -9
  85. package/fesm2015/lenne.tech-ng-base-base-components.mjs.map +1 -1
  86. package/fesm2015/lenne.tech-ng-base-base-prototype.mjs +113 -22
  87. package/fesm2015/lenne.tech-ng-base-base-prototype.mjs.map +1 -1
  88. package/fesm2015/lenne.tech-ng-base-shared.mjs +1995 -0
  89. package/fesm2015/lenne.tech-ng-base-shared.mjs.map +1 -0
  90. package/fesm2015/lenne.tech-ng-base.mjs +57 -1799
  91. package/fesm2015/lenne.tech-ng-base.mjs.map +1 -1
  92. package/fesm2020/lenne.tech-ng-base-base-components.mjs +218 -9
  93. package/fesm2020/lenne.tech-ng-base-base-components.mjs.map +1 -1
  94. package/fesm2020/lenne.tech-ng-base-base-prototype.mjs +111 -22
  95. package/fesm2020/lenne.tech-ng-base-base-prototype.mjs.map +1 -1
  96. package/fesm2020/lenne.tech-ng-base-shared.mjs +2055 -0
  97. package/fesm2020/lenne.tech-ng-base-shared.mjs.map +1 -0
  98. package/fesm2020/lenne.tech-ng-base.mjs +57 -1854
  99. package/fesm2020/lenne.tech-ng-base.mjs.map +1 -1
  100. package/package.json +10 -2
  101. package/public-api.d.ts +0 -36
  102. package/shared/classes/auth.class.d.ts +9 -0
  103. package/{src → shared}/classes/basic-user.class.d.ts +0 -0
  104. package/{src → shared}/classes/graphql-enum.class.d.ts +0 -0
  105. package/{src → shared}/classes/graphql-meta.class.d.ts +0 -0
  106. package/{src → shared}/classes/graphql-type.class.d.ts +0 -0
  107. package/{src → shared}/classes/helper.class.d.ts +0 -0
  108. package/{src → shared}/classes/standard.class.d.ts +0 -0
  109. package/{src → shared}/enums/comparison-operator.enum.d.ts +0 -0
  110. package/{src → shared}/enums/graphql-request-type.enum.d.ts +0 -0
  111. package/{src → shared}/enums/logical-operator.enum.d.ts +0 -0
  112. package/shared/enums/skeleton-type.enum.d.ts +5 -0
  113. package/{src → shared}/enums/sort-order.enum.d.ts +0 -0
  114. package/shared/enums/toast-type.enum.d.ts +5 -0
  115. package/shared/functions/ws-client.function.d.ts +5 -0
  116. package/{src → shared}/interfaces/base-module-config.interface.d.ts +1 -1
  117. package/shared/interfaces/breadcrumb.interface.d.ts +4 -0
  118. package/{src → shared}/interfaces/can-component-deactivate.interface.d.ts +0 -0
  119. package/{src → shared}/interfaces/combined-filter-input.interface.d.ts +0 -0
  120. package/{src → shared}/interfaces/field-object.interface.d.ts +0 -0
  121. package/{src → shared}/interfaces/field.interface.d.ts +0 -0
  122. package/{src → shared}/interfaces/filter-input.interface.d.ts +0 -0
  123. package/{src → shared}/interfaces/find-args.interface.d.ts +0 -0
  124. package/{src → shared}/interfaces/graphql-fields-object.interface.d.ts +0 -0
  125. package/{src → shared}/interfaces/graphql-options.interface.d.ts +0 -0
  126. package/{src → shared}/interfaces/graphql-plus-options.interfacen.d.ts +0 -0
  127. package/{src → shared}/interfaces/graphql-type-collection.interface.d.ts +0 -0
  128. package/{src → shared}/interfaces/single-filter-input.interface.d.ts +0 -0
  129. package/{src → shared}/interfaces/sort-input.interface.d.ts +0 -0
  130. package/shared/interfaces/time-components.interface.d.ts +6 -0
  131. package/shared/interfaces/toast.interface.d.ts +8 -0
  132. package/shared/lenne.tech-ng-base-shared.d.ts +5 -0
  133. package/shared/package.json +10 -0
  134. package/shared/public-api.d.ts +49 -0
  135. package/{src → shared}/services/auth.service.d.ts +0 -0
  136. package/shared/services/breadcrumb.service.d.ts +32 -0
  137. package/{src → shared}/services/forms.service.d.ts +0 -1
  138. package/{src → shared}/services/graphql-meta.service.d.ts +0 -0
  139. package/{src → shared}/services/graphql-plus.service.d.ts +0 -0
  140. package/{src → shared}/services/graphql.service.d.ts +0 -0
  141. package/{src → shared}/services/image.service.d.ts +0 -0
  142. package/{src → shared}/services/loader.service.d.ts +0 -0
  143. package/{src → shared}/services/scroll.service.d.ts +0 -0
  144. package/{src → shared}/services/storage.service.d.ts +0 -0
  145. package/shared/services/toast.service.d.ts +15 -0
  146. package/shared/services/user.service.d.ts +42 -0
  147. package/{src → shared}/services/ws.service.d.ts +2 -2
  148. package/{src → shared}/types/graphql-fields.type.d.ts +0 -0
  149. package/{src → shared}/types/storage.type.d.ts +0 -0
  150. package/shared/validators/match.validator.d.ts +4 -0
  151. package/src/base.module.d.ts +4 -2
  152. package/src/directives/match-height.directive.d.ts +1 -1
  153. package/src/factories/apollo-options.factory.d.ts +1 -3
  154. package/src/guards/auth.guard.d.ts +1 -2
  155. package/src/guards/can-deactivate.guard.d.ts +1 -1
  156. package/src/guards/logout.guard.d.ts +1 -1
  157. package/src/services/theme.service.d.ts +1 -1
  158. package/esm2020/src/classes/basic-user.class.mjs +0 -51
  159. package/esm2020/src/classes/graphql-enum.class.mjs +0 -9
  160. package/esm2020/src/classes/graphql-meta.class.mjs +0 -171
  161. package/esm2020/src/classes/graphql-type.class.mjs +0 -13
  162. package/esm2020/src/classes/helper.class.mjs +0 -304
  163. package/esm2020/src/classes/standard.class.mjs +0 -40
  164. package/esm2020/src/enums/graphql-request-type.enum.mjs +0 -10
  165. package/esm2020/src/enums/logical-operator.enum.mjs +0 -10
  166. package/esm2020/src/enums/sort-order.enum.mjs +0 -6
  167. package/esm2020/src/interfaces/base-module-config.interface.mjs +0 -3
  168. package/esm2020/src/interfaces/can-component-deactivate.interface.mjs +0 -2
  169. package/esm2020/src/interfaces/combined-filter-input.interface.mjs +0 -2
  170. package/esm2020/src/interfaces/field-object.interface.mjs +0 -2
  171. package/esm2020/src/interfaces/field.interface.mjs +0 -2
  172. package/esm2020/src/interfaces/filter-input.interface.mjs +0 -2
  173. package/esm2020/src/interfaces/find-args.interface.mjs +0 -2
  174. package/esm2020/src/interfaces/graphql-fields-object.interface.mjs +0 -2
  175. package/esm2020/src/interfaces/graphql-options.interface.mjs +0 -2
  176. package/esm2020/src/interfaces/graphql-plus-options.interfacen.mjs +0 -2
  177. package/esm2020/src/interfaces/graphql-type-collection.interface.mjs +0 -2
  178. package/esm2020/src/interfaces/single-filter-input.interface.mjs +0 -2
  179. package/esm2020/src/interfaces/sort-input.interface.mjs +0 -2
  180. package/esm2020/src/services/auth.service.mjs +0 -71
  181. package/esm2020/src/services/forms.service.mjs +0 -26
  182. package/esm2020/src/services/graphql-meta.service.mjs +0 -123
  183. package/esm2020/src/services/graphql-plus.service.mjs +0 -84
  184. package/esm2020/src/services/graphql.service.mjs +0 -441
  185. package/esm2020/src/services/image.service.mjs +0 -102
  186. package/esm2020/src/services/loader.service.mjs +0 -29
  187. package/esm2020/src/services/scroll.service.mjs +0 -179
  188. package/esm2020/src/services/storage.service.mjs +0 -132
  189. package/esm2020/src/services/ws.service.mjs +0 -17
  190. package/esm2020/src/types/graphql-fields.type.mjs +0 -2
  191. package/esm2020/src/types/storage.type.mjs +0 -2
  192. package/esm2020/src/validators/must-match.validator.mjs +0 -22
  193. package/src/validators/must-match.validator.d.ts +0 -6
@@ -0,0 +1,2055 @@
1
+ import * as i0 from '@angular/core';
2
+ import { InjectionToken, Injectable, Inject } from '@angular/core';
3
+ import { BehaviorSubject, of, throwError, Observable, map as map$1, filter } from 'rxjs';
4
+ import * as i1 from 'apollo-angular';
5
+ import { gql } from 'apollo-angular';
6
+ import { buildClientSchema, getIntrospectionQuery } from 'graphql';
7
+ import { map } from 'rxjs/operators';
8
+ import { FormControl, FormGroup } from '@angular/forms';
9
+ import * as i1$1 from '@angular/router';
10
+ import { NavigationEnd } from '@angular/router';
11
+ import { createClient } from 'graphql-ws';
12
+
13
+ /**
14
+ * Helper class
15
+ */
16
+ class Helper {
17
+ /**
18
+ * Simple filter function for plain objects
19
+ */
20
+ static filter(objects, filter) {
21
+ return (objects?.filter((element) => {
22
+ for (const [key, value] of Object.entries(filter)) {
23
+ if (Array.isArray(element[key])) {
24
+ for (const item of element[key]) {
25
+ if (!element[key].includs(value)) {
26
+ return false;
27
+ }
28
+ }
29
+ }
30
+ else if (element[key] !== value) {
31
+ return false;
32
+ }
33
+ }
34
+ return true;
35
+ }) || []);
36
+ }
37
+ /**
38
+ * Convert to a url/uri conform string
39
+ * Only:
40
+ * - lower case
41
+ * - chars, numbers and hyphens
42
+ */
43
+ static urlString(str, options = {}) {
44
+ // Config
45
+ const config = {
46
+ allowAll: false,
47
+ ...options,
48
+ };
49
+ // To string
50
+ str = str + '';
51
+ // Trim
52
+ str = str.trim();
53
+ // Lower case
54
+ str = str.toLowerCase();
55
+ if (!config.allowAll) {
56
+ // Replace spaces
57
+ str = str.trim().replace(/\s+/g, '-');
58
+ // Replace some special chars
59
+ str = str.replace('ä', 'ae');
60
+ str = str.replace('ö', 'oe');
61
+ str = str.replace('ü', 'ue');
62
+ str = str.replace('ß', 'ss');
63
+ // Remove other special chars
64
+ str = str.replace(/[^a-zA-Z0-9-]/g, '');
65
+ }
66
+ // Return url conform string
67
+ return encodeURI(str);
68
+ }
69
+ /**
70
+ * Simple map function
71
+ */
72
+ static map(source, target, options = {}) {
73
+ // Set config
74
+ const config = {
75
+ funcAllowed: false,
76
+ dateStringToDate: true,
77
+ ...options,
78
+ };
79
+ // Check source
80
+ if (!source || typeof source !== 'object' || Array.isArray(source)) {
81
+ return target;
82
+ }
83
+ // Update properties
84
+ for (const key of Object.keys(target)) {
85
+ if (source[key] !== undefined && (config.funcAllowed || typeof (source[key] !== 'function'))) {
86
+ if (typeof source[key] === 'string' && config.dateStringToDate) {
87
+ if (Array.isArray(config.dateStringToDate)) {
88
+ if (config.dateStringToDate.includes(key)) {
89
+ target[key] = Helper.parseDate(source[key]);
90
+ }
91
+ }
92
+ else {
93
+ target[key] = Helper.parseDate(source[key]);
94
+ }
95
+ }
96
+ else {
97
+ target[key] = source[key];
98
+ }
99
+ }
100
+ }
101
+ // Return target
102
+ return target;
103
+ }
104
+ /**
105
+ * Create Object or Objects of specified type with specified data
106
+ */
107
+ static maps(data, targetClass) {
108
+ // Check data
109
+ if (!data || typeof data !== 'object') {
110
+ return undefined;
111
+ }
112
+ // Check array
113
+ if (!Array.isArray(data)) {
114
+ data = [data];
115
+ }
116
+ // Map
117
+ return data.map((item) => {
118
+ return targetClass.map(item);
119
+ });
120
+ }
121
+ /**
122
+ * Get plain parameter
123
+ */
124
+ static getPlainParameter(parameter) {
125
+ if (!parameter) {
126
+ return parameter;
127
+ }
128
+ return parameter?.split('?')?.shift()?.split('#')?.shift();
129
+ }
130
+ /**
131
+ * Get ID of an url parameter
132
+ */
133
+ static getParameterId(parameter) {
134
+ if (!parameter) {
135
+ return parameter;
136
+ }
137
+ return Helper.getPlainParameter(parameter)?.split('-').pop();
138
+ }
139
+ /**
140
+ * Delay
141
+ */
142
+ static delay(ms) {
143
+ const promise = new Promise((resolve) => setTimeout(resolve, ms));
144
+ return promise;
145
+ }
146
+ /**
147
+ * Deep freeze
148
+ * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze#What_is_shallow_freeze
149
+ */
150
+ static deepFreeze(object, preparedObjects = []) {
151
+ // Prevent infinit regress
152
+ if (preparedObjects.includes(object)) {
153
+ return object;
154
+ }
155
+ preparedObjects.push(object);
156
+ // Retrieve the property names defined on object
157
+ const propNames = Object.getOwnPropertyNames(object);
158
+ // Freeze properties before freezing self
159
+ for (const name of propNames) {
160
+ const value = object[name];
161
+ if (value && typeof value === 'object') {
162
+ Helper.deepFreeze(value, preparedObjects);
163
+ }
164
+ }
165
+ return Object.freeze(object);
166
+ }
167
+ /**
168
+ * Generates an unique identifier with 24 characters
169
+ */
170
+ static getUID() {
171
+ let dt = new Date().getTime();
172
+ const uuid = 'xxxxxxxxxxxxxxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
173
+ // eslint-disable-next-line no-bitwise
174
+ const r = (dt + Math.random() * 16) % 16 | 0;
175
+ dt = Math.floor(dt / 16);
176
+ // eslint-disable-next-line no-bitwise
177
+ return (c === 'x' ? r : (r & 0x3) | 0x8).toString(16);
178
+ });
179
+ return uuid;
180
+ }
181
+ /**
182
+ * Parse date string to date object
183
+ */
184
+ static parseDate(dateString) {
185
+ const reISO = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*))(?:Z|(\+|-)([\d|:]*))?$/;
186
+ const reMsAjax = /^\/Date\((d|-|.*)\)[\/|\\]$/;
187
+ if (typeof dateString === 'string') {
188
+ const isoExec = reISO.exec(dateString);
189
+ if (isoExec) {
190
+ return new Date(dateString);
191
+ }
192
+ const msAjaxExec = reMsAjax.exec(dateString);
193
+ if (msAjaxExec) {
194
+ const cleaned = msAjaxExec[1].split(/[-+,.]/);
195
+ return new Date(cleaned[0] ? +cleaned[0] : 0 - +cleaned[1]);
196
+ }
197
+ }
198
+ return dateString;
199
+ }
200
+ /**
201
+ * Get browser name and version
202
+ */
203
+ static getBrowser() {
204
+ const userAgent = navigator.userAgent;
205
+ let data = userAgent.match(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i) || [];
206
+ let version;
207
+ if (/trident/i.test(data[1])) {
208
+ version = /\brv[ :]+(\d+)/g.exec(userAgent) || [];
209
+ return { name: 'IE', version: version[1] || '' };
210
+ }
211
+ if (data[1] === 'Chrome') {
212
+ version = userAgent.match(/\bOPR|Edge\/(\d+)/);
213
+ if (version != null) {
214
+ return { name: 'Opera', version: version[1] };
215
+ }
216
+ }
217
+ data = data[2] ? [data[1], data[2]] : [navigator.appName, navigator.appVersion, '-?'];
218
+ version = userAgent.match(/version\/(\d+)/i);
219
+ if (version !== null) {
220
+ data.splice(1, 1, version[1]);
221
+ }
222
+ return {
223
+ name: data[0],
224
+ version: data[1],
225
+ };
226
+ }
227
+ /**
228
+ * Whether first parameter is a deep subset of second parameter
229
+ * Hint: functions will be ignored
230
+ */
231
+ static isSubset(a, b) {
232
+ // Equal
233
+ if (a === b) {
234
+ return true;
235
+ }
236
+ // Different type
237
+ if (typeof a !== typeof b) {
238
+ return false;
239
+ }
240
+ // Process array
241
+ if (Array.isArray(a)) {
242
+ for (const [key, value] of Object.entries(a)) {
243
+ if (Helper.isSubset(value, b[key])) {
244
+ return false;
245
+ }
246
+ }
247
+ return true;
248
+ }
249
+ // Process object
250
+ if (typeof a === 'object') {
251
+ const plain = JSON.parse(JSON.stringify(a));
252
+ for (const [key, value] of Object.entries(plain)) {
253
+ if (Helper.isSubset(value, b[key])) {
254
+ return false;
255
+ }
256
+ }
257
+ return true;
258
+ }
259
+ // Else
260
+ return true;
261
+ }
262
+ /**
263
+ * Whether parameters are equal (have equal properties)
264
+ * Hint: functions will be ignored
265
+ */
266
+ static isEqual(a, b) {
267
+ return Helper.isSubset(a, b) && Helper.isSubset(b, a);
268
+ }
269
+ /**
270
+ * First level difference of two objects
271
+ * Hint: functions will be ignored and when an array or an object is different the hole array or object will used as property value
272
+ *
273
+ * @returns Record<string, any> Object with properties from first object
274
+ */
275
+ static getDiff(a, b, clone = true) {
276
+ const result = {};
277
+ let firstObject = a;
278
+ if (clone) {
279
+ firstObject = JSON.parse(JSON.stringify(a));
280
+ }
281
+ for (const [key, value] of Object.entries(firstObject)) {
282
+ if (!Helper.isSubset(value, b[key])) {
283
+ result[key] = value;
284
+ }
285
+ }
286
+ return result;
287
+ }
288
+ /**
289
+ * Check if propertie is type of HTMLCollection or NodeList
290
+ * See https://stackoverflow.com/a/7238344
291
+ *
292
+ * @param nodes
293
+ */
294
+ static isNodeList(nodes) {
295
+ try {
296
+ const stringRepr = Object.prototype.toString.call(nodes);
297
+ return (typeof nodes === 'object' &&
298
+ /^\[object (HTMLCollection|NodeList|Object)\]$/.test(stringRepr) &&
299
+ typeof nodes.length === 'number' &&
300
+ (nodes.length === 0 || (typeof nodes[0] === 'object' && nodes[0].nodeType > 0)));
301
+ }
302
+ catch (e) {
303
+ return false;
304
+ }
305
+ }
306
+ static arrayBufferToBase64(buffer) {
307
+ let binary = '';
308
+ const bytes = new Uint8Array(buffer);
309
+ const len = bytes.byteLength;
310
+ for (let i = 0; i < len; i++) {
311
+ binary += String.fromCharCode(bytes[i]);
312
+ }
313
+ return `data:image/*;base64, ${window.btoa(binary)}`;
314
+ }
315
+ }
316
+
317
+ /**
318
+ * Standard class
319
+ * Other classes should extend the Standard class, if they offer own functions
320
+ * If the extended class uses object properties with own map functions, it should implement its own map function
321
+ */
322
+ class Standard {
323
+ /**
324
+ * Static map method
325
+ */
326
+ static map(data, item = new this()) {
327
+ return item.map(data);
328
+ }
329
+ /**
330
+ * Map data into an object
331
+ */
332
+ map(data) {
333
+ return Helper.map(data, this);
334
+ }
335
+ /**
336
+ * Clone object (and map additional data)
337
+ */
338
+ clone(mapData) {
339
+ const current = JSON.parse(JSON.stringify(this));
340
+ if (mapData) {
341
+ Object.assign(current, mapData);
342
+ }
343
+ return new this.constructor().map(current);
344
+ }
345
+ /**
346
+ * Compare this with another object
347
+ * Hint: functions will be ignored and when an array or an object is different the hole array or object will used as property value
348
+ *
349
+ * @return Record<string, any> with properties of this object which are different
350
+ */
351
+ getDiff(compare, clone = true) {
352
+ return Helper.getDiff(this, compare, clone);
353
+ }
354
+ }
355
+
356
+ /**
357
+ * User class
358
+ */
359
+ class BasicUser extends Standard {
360
+ constructor() {
361
+ super(...arguments);
362
+ this.id = undefined;
363
+ this.email = undefined;
364
+ this.firstName = undefined;
365
+ this.lastName = undefined;
366
+ this.roles = [];
367
+ this.username = undefined;
368
+ }
369
+ // ===================================================================================================================
370
+ // Methods
371
+ // ===================================================================================================================
372
+ /**
373
+ * Mapping
374
+ */
375
+ map(data) {
376
+ Helper.map(data, this);
377
+ return this;
378
+ }
379
+ /**
380
+ * Checks whether the user has at least one of the required roles
381
+ */
382
+ hasRole(roles) {
383
+ if (typeof roles === 'string') {
384
+ roles = [roles];
385
+ }
386
+ if (!this.roles || this.roles.length < 1) {
387
+ return false;
388
+ }
389
+ return !roles || roles.length < 1 ? true : this.roles.some((role) => roles.includes(role));
390
+ }
391
+ /**
392
+ * Checks whether the user has all required roles
393
+ */
394
+ hasAllRoles(roles) {
395
+ if (typeof roles === 'string') {
396
+ roles = [roles];
397
+ }
398
+ if (!this.roles || this.roles.length < 1) {
399
+ return false;
400
+ }
401
+ return !roles ? true : roles.every((role) => this.roles.includes(role));
402
+ }
403
+ }
404
+
405
+ /**
406
+ * GraphQL enum
407
+ */
408
+ class GraphQLEnum {
409
+ constructor(value) {
410
+ this.value = value;
411
+ }
412
+ }
413
+
414
+ /**
415
+ * GraphQL type
416
+ */
417
+ class GraphQLType extends Standard {
418
+ constructor() {
419
+ super(...arguments);
420
+ this.type = '';
421
+ this.isEnum = false;
422
+ this.validEnums = [];
423
+ }
424
+ }
425
+
426
+ /**
427
+ * GraphQL meta
428
+ */
429
+ class GraphQLMeta {
430
+ /**
431
+ * Integrate schema
432
+ */
433
+ constructor(schema) {
434
+ this.schema = schema;
435
+ // Frozen caches
436
+ this.args = {};
437
+ this.fields = {};
438
+ if (!schema) {
439
+ throw Error('Missing schema');
440
+ }
441
+ }
442
+ /**
443
+ * Get arguments of GraphQL function
444
+ */
445
+ getArgs(functionName, options = {}) {
446
+ const { cache, freeze, type } = {
447
+ cache: true,
448
+ freeze: true,
449
+ type: undefined,
450
+ ...options,
451
+ };
452
+ // Get cache
453
+ if (cache && freeze) {
454
+ const args = this.args[functionName + type];
455
+ if (args) {
456
+ return args;
457
+ }
458
+ }
459
+ const func = this.getFunction(functionName, { type });
460
+ const result = {};
461
+ if (func?.args) {
462
+ func.args.forEach((item) => {
463
+ result[item.name] = this.getDeepType(item.type);
464
+ });
465
+ }
466
+ // Set cache
467
+ if (freeze) {
468
+ this.args[functionName + type] = Helper.deepFreeze(result);
469
+ }
470
+ return result;
471
+ }
472
+ /**
473
+ * Get fields of GraphQL function
474
+ */
475
+ getFields(functionName, options = {}) {
476
+ const { cache, freeze, type } = {
477
+ cache: true,
478
+ freeze: true,
479
+ type: undefined,
480
+ ...options,
481
+ };
482
+ // Get cache
483
+ if (cache && freeze) {
484
+ const args = this.fields[functionName + type];
485
+ if (args) {
486
+ return args;
487
+ }
488
+ }
489
+ const func = this.getFunction(functionName, options);
490
+ const result = this.getDeepType(func.type);
491
+ // Set cache
492
+ if (freeze) {
493
+ this.fields[functionName + type] = Helper.deepFreeze(result);
494
+ }
495
+ return result;
496
+ }
497
+ /**
498
+ * Get GraphQL function
499
+ */
500
+ getFunction(name, options = {}) {
501
+ // Set config
502
+ const config = {
503
+ ...options,
504
+ };
505
+ // Init possible functions
506
+ let functions = {};
507
+ // If function type is set
508
+ if (config.type) {
509
+ const graphQLType = config.type.charAt(0).toUpperCase() + config.type.slice(1);
510
+ const type = this.schema.getType(graphQLType);
511
+ if (type) {
512
+ functions = type.getFields();
513
+ }
514
+ }
515
+ // If function type is not set
516
+ else {
517
+ ['Subscription', 'Mutation', 'Query'].forEach((item) => {
518
+ const type = this.schema.getType(item);
519
+ if (type) {
520
+ functions = {
521
+ ...functions,
522
+ ...(type.getFields() || {}),
523
+ };
524
+ }
525
+ });
526
+ }
527
+ // Get function via name
528
+ return functions[name];
529
+ }
530
+ /**
531
+ * Get type
532
+ */
533
+ getType(name) {
534
+ return this.schema.getType(name);
535
+ }
536
+ /**
537
+ * Get deep type data
538
+ */
539
+ getDeepType(type, prepared = new WeakMap()) {
540
+ // Check type
541
+ if (!type) {
542
+ return type;
543
+ }
544
+ // Infinite regress protection
545
+ const preparedObject = {};
546
+ // Check prepared
547
+ if (typeof type === 'object') {
548
+ const preparedType = prepared.get(type);
549
+ if (preparedType) {
550
+ return preparedType;
551
+ }
552
+ // Set prepared
553
+ prepared.set(type, preparedObject);
554
+ }
555
+ // Search deeper
556
+ if (type.ofType) {
557
+ const ofTypeResult = this.getDeepType(type.ofType, prepared);
558
+ Object.assign(preparedObject, ofTypeResult);
559
+ return ofTypeResult;
560
+ }
561
+ // Process fields
562
+ if (type._fields) {
563
+ const result = {};
564
+ for (const [key, value] of Object.entries(type._fields)) {
565
+ result[key] = this.getDeepType(value, prepared);
566
+ }
567
+ Object.assign(preparedObject, result);
568
+ return result;
569
+ }
570
+ // Get type name
571
+ if (type.type) {
572
+ const typeResult = this.getDeepType(type.type, prepared);
573
+ Object.assign(preparedObject, typeResult);
574
+ return typeResult;
575
+ }
576
+ // Initialize GraphQLType
577
+ const graphqlType = GraphQLType.map({
578
+ type: type.name,
579
+ });
580
+ // Set enum values
581
+ if (!!type._values) {
582
+ graphqlType.isEnum = true;
583
+ for (const [key, value] of Object.entries(type._nameLookup)) {
584
+ if (!value.isDeprecated) {
585
+ graphqlType.validEnums.push(key);
586
+ }
587
+ }
588
+ }
589
+ // Finish
590
+ prepared.set(type, graphqlType);
591
+ return graphqlType;
592
+ }
593
+ }
594
+
595
+ class Auth extends Standard {
596
+ constructor() {
597
+ super(...arguments);
598
+ this.token = undefined;
599
+ this.user = undefined;
600
+ }
601
+ map(data) {
602
+ Helper.map(data, this);
603
+ this.user = data?.user ? BasicUser.map(data.user) : this.user;
604
+ return this;
605
+ }
606
+ }
607
+
608
+ const BASE_MODULE_CONFIG = new InjectionToken('BASE_MODULE_CONFIG');
609
+
610
+ /**
611
+ * Storage service for local data storage
612
+ */
613
+ class StorageService {
614
+ /**
615
+ * Initializations
616
+ */
617
+ constructor(moduleConfig) {
618
+ this.moduleConfig = moduleConfig;
619
+ /**
620
+ * Storage
621
+ */
622
+ this.storage = null;
623
+ /**
624
+ * Prefix for storage keys
625
+ */
626
+ this.prefix = '';
627
+ // Set storage
628
+ const type = moduleConfig.storageType ? moduleConfig.storageType : 'local';
629
+ if (window[type + 'Storage']) {
630
+ this.storage = window[type + 'Storage'];
631
+ }
632
+ // Set prefix
633
+ this.prefix = '';
634
+ if (moduleConfig.prefix) {
635
+ this.prefix += moduleConfig.prefix + '_';
636
+ }
637
+ if (moduleConfig.version) {
638
+ this.prefix += moduleConfig.version + '_';
639
+ }
640
+ }
641
+ /**
642
+ * Save itemKeys
643
+ *
644
+ * If you want to save one item, use itemKeys and value parameters like these:
645
+ * save('KEY_OF_THE_ITEM', ITEM)
646
+ *
647
+ * If you want to save multiple items, use itemKeys only (value parameter will be ignored):
648
+ * save({'KEY_OF_ITEM_1': ITEM_1, 'KEY_OF_ITEM_2': ITEM_2, ...})
649
+ */
650
+ save(itemKeys, value) {
651
+ // Check local storage
652
+ if (!this.storage) {
653
+ return false;
654
+ }
655
+ // Check item keys and value
656
+ if (!itemKeys ||
657
+ (typeof itemKeys === 'object' && !Object.keys(itemKeys).length) ||
658
+ (typeof itemKeys === 'string' && value === undefined)) {
659
+ return false;
660
+ }
661
+ if (typeof itemKeys === 'object') {
662
+ for (const [itemKey, itemValue] of Object.entries(itemKeys)) {
663
+ this.storage.setItem(this.prefix + itemKey, JSON.stringify(itemValue));
664
+ }
665
+ return true;
666
+ }
667
+ this.storage.setItem(this.prefix + itemKeys, JSON.stringify(value));
668
+ return true;
669
+ }
670
+ /**
671
+ * Load items via key(s)
672
+ */
673
+ load(itemKeys) {
674
+ // Check local storage
675
+ if (!this.storage) {
676
+ return;
677
+ }
678
+ // Check item keys
679
+ if (!itemKeys || (Array.isArray(itemKeys) && !itemKeys.length)) {
680
+ return null;
681
+ }
682
+ if (Array.isArray(itemKeys)) {
683
+ const back = {};
684
+ itemKeys.forEach((itemKey) => {
685
+ const loadedItem = this.storage.getItem(this.prefix + itemKey);
686
+ if (loadedItem) {
687
+ back[itemKey] = JSON.parse(loadedItem);
688
+ }
689
+ else {
690
+ back[itemKey] = null;
691
+ }
692
+ });
693
+ return back;
694
+ }
695
+ let value = this.storage.getItem(this.prefix + itemKeys);
696
+ if (value) {
697
+ value = JSON.parse(value);
698
+ }
699
+ return value;
700
+ }
701
+ /**
702
+ * Remove item from storage
703
+ *
704
+ * @param itemKeys keys or key to remove
705
+ */
706
+ remove(itemKeys) {
707
+ // Check local storage
708
+ if (!this.storage) {
709
+ return false;
710
+ }
711
+ if (Array.isArray(itemKeys)) {
712
+ itemKeys.forEach((key) => {
713
+ this.storage.removeItem(this.prefix + key);
714
+ });
715
+ return true;
716
+ }
717
+ this.storage.removeItem(this.prefix + itemKeys);
718
+ return true;
719
+ }
720
+ /**
721
+ * Clear local storage
722
+ */
723
+ reset() {
724
+ this.storage.clear();
725
+ }
726
+ }
727
+ StorageService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.3", ngImport: i0, type: StorageService, deps: [{ token: BASE_MODULE_CONFIG }], target: i0.ɵɵFactoryTarget.Injectable });
728
+ StorageService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.3.3", ngImport: i0, type: StorageService, providedIn: 'root' });
729
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.3", ngImport: i0, type: StorageService, decorators: [{
730
+ type: Injectable,
731
+ args: [{
732
+ providedIn: 'root',
733
+ }]
734
+ }], ctorParameters: function () { return [{ type: undefined, decorators: [{
735
+ type: Inject,
736
+ args: [BASE_MODULE_CONFIG]
737
+ }] }]; } });
738
+
739
+ class WsService {
740
+ reconnect() {
741
+ this.client?.restart();
742
+ }
743
+ }
744
+ WsService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.3", ngImport: i0, type: WsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
745
+ WsService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.3.3", ngImport: i0, type: WsService, providedIn: 'root' });
746
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.3", ngImport: i0, type: WsService, decorators: [{
747
+ type: Injectable,
748
+ args: [{
749
+ providedIn: 'root',
750
+ }]
751
+ }] });
752
+
753
+ /**
754
+ * Authentication service
755
+ */
756
+ class AuthService {
757
+ /**
758
+ * Constructor
759
+ */
760
+ constructor(moduleConfig, storageService, wsService) {
761
+ this.moduleConfig = moduleConfig;
762
+ this.storageService = storageService;
763
+ this.wsService = wsService;
764
+ // Subjects
765
+ this._currentUser = new BehaviorSubject(null);
766
+ this._token = new BehaviorSubject(null);
767
+ this.token = this.storageService.load('token');
768
+ this.currentUser = this.storageService.load('currentUser');
769
+ }
770
+ /**
771
+ * Logout
772
+ */
773
+ logout() {
774
+ this.storageService.remove(['token', 'currentUser']);
775
+ this.currentUser = null;
776
+ this.token = null;
777
+ }
778
+ // #################################################################
779
+ // Current User
780
+ // #################################################################
781
+ get currentUser() {
782
+ return this._currentUser.value;
783
+ }
784
+ set currentUser(user) {
785
+ this._currentUser.next(user);
786
+ this.storageService.save('currentUser', user);
787
+ }
788
+ get currentUserObservable() {
789
+ return this._currentUser.asObservable();
790
+ }
791
+ // #################################################################
792
+ // Token
793
+ // #################################################################
794
+ get token() {
795
+ return this._token.value;
796
+ }
797
+ set token(token) {
798
+ this._token.next(token);
799
+ this.storageService.save('token', token);
800
+ this.wsService.reconnect();
801
+ }
802
+ get tokenObservable() {
803
+ return this._token.asObservable();
804
+ }
805
+ }
806
+ AuthService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.3", ngImport: i0, type: AuthService, deps: [{ token: BASE_MODULE_CONFIG }, { token: StorageService }, { token: WsService }], target: i0.ɵɵFactoryTarget.Injectable });
807
+ AuthService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.3.3", ngImport: i0, type: AuthService, providedIn: 'root' });
808
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.3", ngImport: i0, type: AuthService, decorators: [{
809
+ type: Injectable,
810
+ args: [{
811
+ providedIn: 'root',
812
+ }]
813
+ }], ctorParameters: function () { return [{ type: undefined, decorators: [{
814
+ type: Inject,
815
+ args: [BASE_MODULE_CONFIG]
816
+ }] }, { type: StorageService }, { type: WsService }]; } });
817
+
818
+ /**
819
+ * GraphQL request type enum
820
+ */
821
+ var GraphQLRequestType;
822
+ (function (GraphQLRequestType) {
823
+ GraphQLRequestType["QUERY"] = "query";
824
+ GraphQLRequestType["MUTATION"] = "mutation";
825
+ GraphQLRequestType["SUBSCRIPTION"] = "subscription";
826
+ })(GraphQLRequestType || (GraphQLRequestType = {}));
827
+
828
+ /**
829
+ * GraphQL meta service
830
+ *
831
+ * For collecting meta information of the GraphQL API
832
+ */
833
+ class GraphQLMetaService {
834
+ /**
835
+ * Include services
836
+ */
837
+ constructor(apollo) {
838
+ this.apollo = apollo;
839
+ }
840
+ /**
841
+ * Getter of introspectionQuery
842
+ */
843
+ get introspectionQuery() {
844
+ return JSON.parse(JSON.stringify(this._introspectionQuery));
845
+ }
846
+ /**
847
+ * Get schema for API
848
+ * See https://www.apollographql.com/blog/three-ways-to-represent-your-graphql-schema-a41f4175100d
849
+ */
850
+ getSchema(options = {}) {
851
+ // Get configurations
852
+ const config = {
853
+ cache: true,
854
+ freeze: true,
855
+ ...options,
856
+ };
857
+ // Use caching
858
+ if (config.cache) {
859
+ if (config.freeze && this._frozenSchema) {
860
+ return of(this._frozenSchema);
861
+ }
862
+ if (this._introspectionQuery) {
863
+ return of(buildClientSchema(this.introspectionQuery));
864
+ }
865
+ if (config.freeze && this._frozenSchemaObservable) {
866
+ return this._frozenSchemaObservable;
867
+ }
868
+ else if (!config.freeze && this._schemaObservable) {
869
+ return this._schemaObservable;
870
+ }
871
+ }
872
+ // Request schema from server
873
+ const observable = this.apollo
874
+ .query({
875
+ query: gql(getIntrospectionQuery({ descriptions: false })),
876
+ })
877
+ .pipe(map((schema) => {
878
+ // Cache introspectionQuery
879
+ this._introspectionQuery = schema.data;
880
+ // Convert schema to GraphQLSchema
881
+ this._frozenSchema = Helper.deepFreeze(buildClientSchema(this.introspectionQuery));
882
+ // Return GraphQLSchema
883
+ if (config.freeze) {
884
+ return this._frozenSchema;
885
+ }
886
+ return buildClientSchema(schema.data);
887
+ }));
888
+ // Set observables
889
+ if (config.freeze) {
890
+ this._frozenSchemaObservable = observable;
891
+ }
892
+ else {
893
+ this._schemaObservable = observable;
894
+ }
895
+ // Return result
896
+ return observable;
897
+ }
898
+ /**
899
+ * Get meta for API
900
+ * See https://www.apollographql.com/blog/three-ways-to-represent-your-graphql-schema-a41f4175100d
901
+ */
902
+ getMeta(options = {}) {
903
+ // Get configurations
904
+ const config = {
905
+ cache: true,
906
+ log: false,
907
+ ...options,
908
+ };
909
+ // Use caching
910
+ if (config.cache) {
911
+ if (this._meta) {
912
+ return of(this._meta);
913
+ }
914
+ else if (this._metaObservable) {
915
+ return this._metaObservable;
916
+ }
917
+ }
918
+ // Request schema from server
919
+ const observable = this.getSchema(options).pipe(map((schema) => {
920
+ // Log
921
+ if (config.log) {
922
+ console.log({ schema });
923
+ }
924
+ this._meta = new GraphQLMeta(schema);
925
+ return this._meta;
926
+ }));
927
+ // Set observables
928
+ this._metaObservable = observable;
929
+ // Return result
930
+ return observable;
931
+ }
932
+ }
933
+ GraphQLMetaService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.3", ngImport: i0, type: GraphQLMetaService, deps: [{ token: i1.Apollo }], target: i0.ɵɵFactoryTarget.Injectable });
934
+ GraphQLMetaService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.3.3", ngImport: i0, type: GraphQLMetaService, providedIn: 'root' });
935
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.3", ngImport: i0, type: GraphQLMetaService, decorators: [{
936
+ type: Injectable,
937
+ args: [{
938
+ providedIn: 'root',
939
+ }]
940
+ }], ctorParameters: function () { return [{ type: i1.Apollo }]; } });
941
+
942
+ /**
943
+ * GraphQL service
944
+ */
945
+ class GraphQLService {
946
+ /**
947
+ * Include services
948
+ */
949
+ constructor(apollo, graphQLMetaService) {
950
+ this.apollo = apollo;
951
+ this.graphQLMetaService = graphQLMetaService;
952
+ }
953
+ /**
954
+ * GraphQL request
955
+ */
956
+ graphQl(graphql, options = {}) {
957
+ // Check arguments
958
+ if (!graphql) {
959
+ throwError('Missing graphql argument');
960
+ }
961
+ // Get config
962
+ const config = {
963
+ arguments: null,
964
+ fields: null,
965
+ log: false,
966
+ model: null,
967
+ type: GraphQLRequestType.QUERY,
968
+ ...options,
969
+ };
970
+ // Convert class to Object for arguments
971
+ if (typeof config.arguments === 'function') {
972
+ config.arguments = new config.arguments();
973
+ }
974
+ // Convert class to Object for fields
975
+ if (typeof config.fields === 'function') {
976
+ config.fields = new config.fields();
977
+ }
978
+ // Log
979
+ if (config.log) {
980
+ console.log({ config });
981
+ }
982
+ // Send request
983
+ return new Observable((subscriber) => {
984
+ // Get meta
985
+ this.graphQLMetaService.getMeta({ log: config.log }).subscribe((meta) => {
986
+ // Prepare fields
987
+ let fields;
988
+ let allowedFields;
989
+ // Log meta
990
+ if (config.log) {
991
+ console.log({ meta });
992
+ }
993
+ if (config.fields) {
994
+ allowedFields = meta.getFields(graphql, { type: config.type });
995
+ // Log meta
996
+ if (config.log) {
997
+ console.log({ allowedFields });
998
+ }
999
+ const fieldsData = this.prepareFields(config.fields, {
1000
+ allowed: allowedFields,
1001
+ });
1002
+ // Log fields data
1003
+ if (config.log) {
1004
+ fieldsData.usedFields.sort();
1005
+ fieldsData.schemaFields.sort();
1006
+ const filtered = fieldsData.schemaFields.filter((field) => !fieldsData.usedFields.includes(field));
1007
+ const unused = this.graphQLTypeCollectionToStringArray(allowedFields).filter((field) => !fieldsData.usedFields.includes(field));
1008
+ console.log({ fieldsData, filtered, unused });
1009
+ }
1010
+ fields = fieldsData.fieldsString;
1011
+ }
1012
+ if (fields && !fields.startsWith('{')) {
1013
+ fields = '{' + fields + '\n}';
1014
+ }
1015
+ // Log fields
1016
+ if (config.log) {
1017
+ console.log({ fields });
1018
+ }
1019
+ // Get allowed args
1020
+ const allowedArgs = meta.getArgs(graphql, { type: config.type });
1021
+ // Log allowed args
1022
+ if (config.log) {
1023
+ console.log({ allowedArgs });
1024
+ }
1025
+ const argsData = this.prepareArguments(config.arguments, {
1026
+ allowed: allowedArgs,
1027
+ });
1028
+ // Log args data
1029
+ if (config.log) {
1030
+ argsData.usedArgs.sort();
1031
+ argsData.schemaArgs.sort();
1032
+ const filtered = argsData.schemaArgs.filter((field) => !argsData.usedArgs.includes(field));
1033
+ const unused = this.graphQLTypeCollectionToStringArray(allowedArgs)
1034
+ .sort()
1035
+ .filter((field) => !argsData.usedArgs.includes(field));
1036
+ console.log({ argsData, filtered, unused });
1037
+ }
1038
+ const args = argsData?.argsString || '';
1039
+ // Log
1040
+ if (config.log) {
1041
+ console.log({ graphQL: graphql, args, fields, type: config.type });
1042
+ }
1043
+ // Prepare request
1044
+ const documentNode = fields
1045
+ ? gql(config.type + '{\n' + graphql + args + fields + '\n}')
1046
+ : gql(config.type + '{\n' + graphql + args + '\n}');
1047
+ // Log
1048
+ if (config.log) {
1049
+ console.log({ documentNode });
1050
+ }
1051
+ const request = {};
1052
+ request[config.type] = documentNode;
1053
+ // Log
1054
+ if (config.log) {
1055
+ console.log({ request });
1056
+ }
1057
+ let func;
1058
+ if (config.type === GraphQLRequestType.MUTATION) {
1059
+ func = 'mutate';
1060
+ request[config.type] = documentNode;
1061
+ }
1062
+ else if (config.type === GraphQLRequestType.SUBSCRIPTION) {
1063
+ func = 'subscribe';
1064
+ request.query = documentNode;
1065
+ }
1066
+ else {
1067
+ func = config.type;
1068
+ request[config.type] = documentNode;
1069
+ }
1070
+ this.apollo[func](request).subscribe((result) => {
1071
+ const data = result?.data?.[graphql] !== undefined ? result.data[graphql] : result;
1072
+ // Direct data
1073
+ if (!config.model) {
1074
+ subscriber.next(data);
1075
+ }
1076
+ // Map data as array
1077
+ else if (Array.isArray(data)) {
1078
+ subscriber.next(data.map((item) => {
1079
+ return config.model.map(item);
1080
+ }));
1081
+ }
1082
+ // Map data
1083
+ else {
1084
+ subscriber.next(config.model.map(data));
1085
+ }
1086
+ if (config.type !== GraphQLRequestType.SUBSCRIPTION) {
1087
+ // Done
1088
+ subscriber.complete();
1089
+ }
1090
+ }, (error) => {
1091
+ subscriber.error(error);
1092
+ subscriber.complete();
1093
+ });
1094
+ });
1095
+ });
1096
+ }
1097
+ /**
1098
+ * Get fields / args from IGraphQLTypeCollection
1099
+ */
1100
+ graphQLTypeCollectionToStringArray(collection, current = '', result = [], cacheNode = []) {
1101
+ if (collection) {
1102
+ if (collection instanceof GraphQLType) {
1103
+ result.push(current);
1104
+ }
1105
+ else {
1106
+ if (current?.includes('.')) {
1107
+ cacheNode.push(current.split('.')[1]);
1108
+ }
1109
+ else if (current) {
1110
+ cacheNode.push(current);
1111
+ }
1112
+ for (const key of Object.keys(collection)) {
1113
+ if (current === key || cacheNode.includes(key)) {
1114
+ continue;
1115
+ }
1116
+ this.graphQLTypeCollectionToStringArray(collection[key], current ? current + '.' + key : key, result, cacheNode);
1117
+ }
1118
+ }
1119
+ }
1120
+ return result;
1121
+ }
1122
+ /**
1123
+ * Prepare arguments for GraphQL request
1124
+ */
1125
+ prepareArguments(args, options = {}) {
1126
+ // Init config variables
1127
+ const { allowed, level, parent, schemaArgs, usedArgs } = {
1128
+ allowed: null,
1129
+ level: 1,
1130
+ parent: '',
1131
+ schemaArgs: [],
1132
+ usedArgs: [],
1133
+ ...options,
1134
+ };
1135
+ // Check args
1136
+ if (args === undefined || args === null) {
1137
+ return { argsString: '', schemaArgs, usedArgs };
1138
+ }
1139
+ // Init args
1140
+ const result = [];
1141
+ // Process array
1142
+ if (Array.isArray(args)) {
1143
+ const allowedKeys = allowed ? Object.keys(allowed) : null;
1144
+ for (const item of args) {
1145
+ let key = null;
1146
+ if (allowed) {
1147
+ if (allowed.length < 1) {
1148
+ break;
1149
+ }
1150
+ key = allowedKeys?.shift();
1151
+ }
1152
+ // Process value
1153
+ result.push(this.prepareArguments(item, {
1154
+ allowed: key ? allowed[key] : null,
1155
+ level: level + 1,
1156
+ parent: parent + key + '.',
1157
+ schemaArgs,
1158
+ usedArgs,
1159
+ }).argsString);
1160
+ }
1161
+ // Encapsulation of the array result
1162
+ if (result.length) {
1163
+ // Complete result, encapsulated via round brackets
1164
+ if (level === 1) {
1165
+ return { argsString: '(' + result.join(', ') + ')', schemaArgs, usedArgs };
1166
+ }
1167
+ // Deeper result part, encapsulated via square brackets
1168
+ else {
1169
+ return { argsString: '[' + result.join(', ') + ']', schemaArgs, usedArgs };
1170
+ }
1171
+ }
1172
+ }
1173
+ // Process object
1174
+ else if (typeof args === 'object') {
1175
+ // Check object is empty
1176
+ if (args && Object.keys(args).length === 0 && Object.getPrototypeOf(args) === Object.prototype) {
1177
+ return { argsString: '{}', schemaArgs, usedArgs };
1178
+ }
1179
+ // Process all object entries
1180
+ for (const [key, value] of Object.entries(args)) {
1181
+ // Init data for current entry
1182
+ const currentKey = parent + key;
1183
+ schemaArgs.push(currentKey);
1184
+ // If the allowed key handling is enabled and the current key is not included in the list of allowed keys,
1185
+ // the current key will be skipped
1186
+ if (allowed && !allowed[key]) {
1187
+ continue;
1188
+ }
1189
+ // Skip value if not exists
1190
+ if (value === undefined || value === null) {
1191
+ continue;
1192
+ }
1193
+ // Add current key to metadata
1194
+ usedArgs.push(currentKey);
1195
+ // Process GraphQLEnum
1196
+ if (value instanceof GraphQLEnum) {
1197
+ result.push(key + ':' + value.value);
1198
+ continue;
1199
+ }
1200
+ // Process array
1201
+ else if (Array.isArray(value)) {
1202
+ result.push(key +
1203
+ ': [' +
1204
+ value.map((item) => this.prepareArguments(item, {
1205
+ allowed: allowed[key],
1206
+ level: level + 1,
1207
+ parent: currentKey + '.',
1208
+ schemaArgs,
1209
+ usedArgs,
1210
+ }).argsString) +
1211
+ ']');
1212
+ continue;
1213
+ }
1214
+ // Prepare additional result string
1215
+ let additionalResult = key + ': ';
1216
+ // Value is a date object
1217
+ if (typeof value === 'object' && Object.prototype.toString.call(value) === '[object Date]') {
1218
+ additionalResult += `"""${value.toString()}"""`;
1219
+ }
1220
+ // Value is a string
1221
+ else if (typeof value === 'string') {
1222
+ // Enum (doesn't need quotation marks)
1223
+ if (allowed[key].isEnum) {
1224
+ additionalResult += value;
1225
+ }
1226
+ // String
1227
+ else {
1228
+ additionalResult += `"""${value.replace(/"/g, '\\"')}"""`;
1229
+ }
1230
+ }
1231
+ // Value is a simple boolean or a number
1232
+ else if (typeof value === 'boolean' || typeof value === 'number') {
1233
+ additionalResult += value;
1234
+ }
1235
+ // Others
1236
+ else {
1237
+ additionalResult += this.prepareArguments(value, {
1238
+ allowed: allowed[key],
1239
+ level: level + 1,
1240
+ parent: currentKey + '.',
1241
+ schemaArgs,
1242
+ usedArgs,
1243
+ }).argsString;
1244
+ }
1245
+ // Push deeper part into result array
1246
+ result.push(additionalResult);
1247
+ }
1248
+ // Encapsulation of the object result
1249
+ if (result.length) {
1250
+ // Complete result, encapsulated via round brackets
1251
+ if (level === 1) {
1252
+ return { argsString: '(' + result.join(', ') + ')', schemaArgs, usedArgs };
1253
+ }
1254
+ // Deeper result part, encapsulated via curly brackets
1255
+ else {
1256
+ return { argsString: '{' + result.join(', ') + '}', schemaArgs, usedArgs };
1257
+ }
1258
+ }
1259
+ }
1260
+ // Prepare and process other / unknown values as JSON
1261
+ else {
1262
+ return { argsString: JSON.stringify(args), schemaArgs, usedArgs };
1263
+ }
1264
+ }
1265
+ /**
1266
+ * Prepare fields for GraphQL request
1267
+ */
1268
+ prepareFields(fields, options = {}) {
1269
+ // Config
1270
+ const { allowed, parent, schemaFields, spaces, tab, usedFields } = {
1271
+ allowed: null,
1272
+ parent: '',
1273
+ schemaFields: [],
1274
+ spaces: 2,
1275
+ tab: 1,
1276
+ usedFields: [],
1277
+ ...options,
1278
+ };
1279
+ // Init fields string
1280
+ let fieldsString = '';
1281
+ // Check fields
1282
+ if (!fields) {
1283
+ return { fieldsString, schemaFields, usedFields };
1284
+ }
1285
+ // Process string
1286
+ if (typeof fields === 'string') {
1287
+ if (allowed &&
1288
+ ((typeof allowed === 'string' && allowed !== fields) || (typeof allowed === 'object' && !allowed[fields]))) {
1289
+ return { fieldsString, schemaFields, usedFields };
1290
+ }
1291
+ return { fieldsString: '\n' + ' '.repeat(spaces).repeat(tab) + fields, schemaFields, usedFields };
1292
+ }
1293
+ // Process array
1294
+ else if (Array.isArray(fields)) {
1295
+ for (const item of fields) {
1296
+ if (typeof item === 'object') {
1297
+ fieldsString =
1298
+ fieldsString +
1299
+ this.prepareFields(item, {
1300
+ allowed,
1301
+ parent,
1302
+ spaces,
1303
+ schemaFields,
1304
+ tab: tab + 1,
1305
+ usedFields,
1306
+ }).fieldsString;
1307
+ continue;
1308
+ }
1309
+ const currentPath = parent + item;
1310
+ schemaFields.push(currentPath);
1311
+ if (allowed && !allowed?.[item]) {
1312
+ continue;
1313
+ }
1314
+ usedFields.push(currentPath);
1315
+ fieldsString =
1316
+ fieldsString +
1317
+ this.prepareFields(item, {
1318
+ allowed: typeof allowed?.[item] === 'object' && !(allowed?.[item] instanceof GraphQLType) ? allowed?.[item] : item,
1319
+ parent: currentPath + '.',
1320
+ spaces,
1321
+ schemaFields,
1322
+ tab: tab + 1,
1323
+ usedFields,
1324
+ }).fieldsString;
1325
+ }
1326
+ }
1327
+ // Process object
1328
+ else if (typeof fields === 'object') {
1329
+ for (const [key, val] of Object.entries(fields)) {
1330
+ const currentPath = parent + key;
1331
+ schemaFields.push(currentPath);
1332
+ if (allowed && !allowed[key]) {
1333
+ continue;
1334
+ }
1335
+ usedFields.push(currentPath);
1336
+ if (typeof val !== 'object' || !Object.keys(val).length) {
1337
+ fieldsString = fieldsString + '\n' + ' '.repeat(spaces).repeat(tab) + key;
1338
+ }
1339
+ else {
1340
+ fieldsString =
1341
+ fieldsString +
1342
+ '\n' +
1343
+ ' '.repeat(spaces).repeat(tab) +
1344
+ key +
1345
+ ' ' +
1346
+ '{' +
1347
+ this.prepareFields(val, {
1348
+ allowed: typeof allowed?.[key] === 'object' && !(allowed?.[key] instanceof GraphQLType) ? allowed?.[key] : key,
1349
+ parent: currentPath + '.',
1350
+ spaces,
1351
+ schemaFields,
1352
+ tab: tab + 1,
1353
+ usedFields,
1354
+ }).fieldsString +
1355
+ '\n' +
1356
+ ' '.repeat(spaces).repeat(tab) +
1357
+ '}';
1358
+ }
1359
+ }
1360
+ }
1361
+ // Return result
1362
+ return { fieldsString, schemaFields, usedFields };
1363
+ }
1364
+ }
1365
+ GraphQLService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.3", ngImport: i0, type: GraphQLService, deps: [{ token: i1.Apollo }, { token: GraphQLMetaService }], target: i0.ɵɵFactoryTarget.Injectable });
1366
+ GraphQLService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.3.3", ngImport: i0, type: GraphQLService, providedIn: 'root' });
1367
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.3", ngImport: i0, type: GraphQLService, decorators: [{
1368
+ type: Injectable,
1369
+ args: [{
1370
+ providedIn: 'root',
1371
+ }]
1372
+ }], ctorParameters: function () { return [{ type: i1.Apollo }, { type: GraphQLMetaService }]; } });
1373
+
1374
+ /**
1375
+ * Loader service for loading indication
1376
+ */
1377
+ class LoaderService {
1378
+ constructor() {
1379
+ this.isLoading = new BehaviorSubject(false);
1380
+ }
1381
+ start() {
1382
+ this.isLoading.next(true);
1383
+ }
1384
+ stop() {
1385
+ this.isLoading.next(false);
1386
+ }
1387
+ getAsObservable() {
1388
+ return this.isLoading.asObservable();
1389
+ }
1390
+ }
1391
+ LoaderService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.3", ngImport: i0, type: LoaderService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1392
+ LoaderService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.3.3", ngImport: i0, type: LoaderService, providedIn: 'root' });
1393
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.3", ngImport: i0, type: LoaderService, decorators: [{
1394
+ type: Injectable,
1395
+ args: [{
1396
+ providedIn: 'root',
1397
+ }]
1398
+ }] });
1399
+
1400
+ /**
1401
+ * GraphQL plus service, for extra error handling and loading indication
1402
+ */
1403
+ class GraphQLPlusService extends GraphQLService {
1404
+ /**
1405
+ * Include services
1406
+ */
1407
+ constructor(apollo, graphqlMetaService, loaderService) {
1408
+ super(apollo, graphqlMetaService);
1409
+ this.apollo = apollo;
1410
+ this.graphqlMetaService = graphqlMetaService;
1411
+ this.loaderService = loaderService;
1412
+ }
1413
+ graphQl(graphql, options = {}) {
1414
+ this.handleLoader('start', options);
1415
+ return new Observable((subscriber) => {
1416
+ super.graphQl(graphql, options).subscribe((response) => {
1417
+ if (response && response.errors) {
1418
+ this.handleError(response.errors, options.excludedErrors);
1419
+ subscriber.error(response);
1420
+ this.handleLoader('stop', options);
1421
+ subscriber.complete();
1422
+ }
1423
+ subscriber.next(response);
1424
+ this.handleLoader('stop', options);
1425
+ if (options.type !== GraphQLRequestType.SUBSCRIPTION) {
1426
+ subscriber.complete();
1427
+ }
1428
+ }, (error) => {
1429
+ if (!options.ignoreErrors) {
1430
+ this.handleError(error, options.excludedErrors);
1431
+ }
1432
+ subscriber.error(error);
1433
+ this.handleLoader('stop', options);
1434
+ subscriber.complete();
1435
+ });
1436
+ });
1437
+ }
1438
+ handleLoader(state, options) {
1439
+ if (options.loading) {
1440
+ if (state === 'start') {
1441
+ this.loaderService.start();
1442
+ }
1443
+ else if (state === 'stop') {
1444
+ this.loaderService.stop();
1445
+ }
1446
+ }
1447
+ }
1448
+ handleError(error, excludedErrors = null) {
1449
+ if (excludedErrors) {
1450
+ if (Array.isArray(excludedErrors)) {
1451
+ excludedErrors.forEach((excludedError) => {
1452
+ if (error.message.includes(excludedError.toLowerCase())) {
1453
+ return;
1454
+ }
1455
+ });
1456
+ }
1457
+ else if (error.message.toLowerCase().includes(excludedErrors?.toLowerCase())) {
1458
+ return;
1459
+ }
1460
+ }
1461
+ this.displayError(error);
1462
+ }
1463
+ displayError(error) {
1464
+ console.error(error);
1465
+ }
1466
+ }
1467
+ GraphQLPlusService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.3", ngImport: i0, type: GraphQLPlusService, deps: [{ token: i1.Apollo }, { token: GraphQLMetaService }, { token: LoaderService }], target: i0.ɵɵFactoryTarget.Injectable });
1468
+ GraphQLPlusService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.3.3", ngImport: i0, type: GraphQLPlusService, providedIn: 'root' });
1469
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.3", ngImport: i0, type: GraphQLPlusService, decorators: [{
1470
+ type: Injectable,
1471
+ args: [{
1472
+ providedIn: 'root',
1473
+ }]
1474
+ }], ctorParameters: function () { return [{ type: i1.Apollo }, { type: GraphQLMetaService }, { type: LoaderService }]; } });
1475
+
1476
+ class FormsService {
1477
+ validateAllFormFields(formGroup) {
1478
+ Object.keys(formGroup.controls).forEach((field) => {
1479
+ const control = formGroup.get(field);
1480
+ if (control instanceof FormControl) {
1481
+ control.markAsTouched({ onlySelf: true });
1482
+ }
1483
+ else if (control instanceof FormGroup) {
1484
+ this.validateAllFormFields(control);
1485
+ }
1486
+ });
1487
+ }
1488
+ }
1489
+ FormsService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.3", ngImport: i0, type: FormsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1490
+ FormsService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.3.3", ngImport: i0, type: FormsService, providedIn: 'root' });
1491
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.3", ngImport: i0, type: FormsService, decorators: [{
1492
+ type: Injectable,
1493
+ args: [{
1494
+ providedIn: 'root',
1495
+ }]
1496
+ }] });
1497
+
1498
+ class UserService extends GraphQLPlusService {
1499
+ constructor(apollo, graphqlMetaService, loaderService, authService) {
1500
+ super(apollo, graphqlMetaService, loaderService);
1501
+ this.apollo = apollo;
1502
+ this.graphqlMetaService = graphqlMetaService;
1503
+ this.loaderService = loaderService;
1504
+ this.authService = authService;
1505
+ }
1506
+ /**
1507
+ * Login
1508
+ *
1509
+ * @param input
1510
+ */
1511
+ login(input) {
1512
+ return this.graphQl('signIn', {
1513
+ arguments: { input },
1514
+ fields: ['token', { user: ['id', 'firstName', 'lastName', 'email', 'roles'] }],
1515
+ type: GraphQLRequestType.QUERY,
1516
+ loading: true,
1517
+ }).pipe(map$1((response) => {
1518
+ this.authService.token = response.token;
1519
+ this.authService.currentUser = BasicUser.map(response.user);
1520
+ return Auth.map({
1521
+ token: response.token,
1522
+ user: BasicUser.map(response.user),
1523
+ });
1524
+ }));
1525
+ }
1526
+ /**
1527
+ * Register
1528
+ *
1529
+ * @param input
1530
+ */
1531
+ register(input) {
1532
+ return this.graphQl('signUp', {
1533
+ arguments: { input },
1534
+ fields: ['token', { user: ['id', 'firstName', 'lastName', 'email', 'roles'] }],
1535
+ type: GraphQLRequestType.MUTATION,
1536
+ loading: true,
1537
+ }).pipe(map$1((response) => {
1538
+ this.authService.token = response.token;
1539
+ this.authService.currentUser = BasicUser.map(response.user);
1540
+ return Auth.map({
1541
+ token: response.token,
1542
+ user: BasicUser.map(response.user),
1543
+ });
1544
+ }));
1545
+ }
1546
+ /**
1547
+ * Request password reset mail
1548
+ *
1549
+ * @param email
1550
+ */
1551
+ requestPasswordResetMail(email) {
1552
+ return this.graphQl('requestPasswordResetMail', {
1553
+ arguments: { email },
1554
+ fields: [],
1555
+ type: GraphQLRequestType.QUERY,
1556
+ loading: true,
1557
+ });
1558
+ }
1559
+ }
1560
+ UserService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.3", ngImport: i0, type: UserService, deps: [{ token: i1.Apollo }, { token: GraphQLMetaService }, { token: LoaderService }, { token: AuthService }], target: i0.ɵɵFactoryTarget.Injectable });
1561
+ UserService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.3.3", ngImport: i0, type: UserService, providedIn: 'root' });
1562
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.3", ngImport: i0, type: UserService, decorators: [{
1563
+ type: Injectable,
1564
+ args: [{
1565
+ providedIn: 'root',
1566
+ }]
1567
+ }], ctorParameters: function () { return [{ type: i1.Apollo }, { type: GraphQLMetaService }, { type: LoaderService }, { type: AuthService }]; } });
1568
+
1569
+ /**
1570
+ * Image service
1571
+ */
1572
+ class ImageService {
1573
+ /**
1574
+ * Preaload images (for lazy handling)
1575
+ *
1576
+ * @param options
1577
+ * @protected
1578
+ */
1579
+ preLoadImages(options) {
1580
+ // Init configuration
1581
+ const config = {
1582
+ doneFunnction: undefined,
1583
+ elements: document,
1584
+ regExp: undefined,
1585
+ ...options,
1586
+ };
1587
+ return new Promise((resolve) => {
1588
+ // Convert element(s) into array
1589
+ if (!Array.isArray(config.elements)) {
1590
+ // NodeList or HTMLCollection
1591
+ if (Helper.isNodeList(config.elements)) {
1592
+ config.elements = Array.from(config.elements);
1593
+ }
1594
+ // Single element
1595
+ else {
1596
+ config.elements = [config.elements];
1597
+ }
1598
+ }
1599
+ // Init loading
1600
+ const promises = [];
1601
+ // Get all images
1602
+ let images = [];
1603
+ config.elements.forEach((element) => {
1604
+ images = images.concat(Array.from(element.getElementsByTagName('img')));
1605
+ });
1606
+ // Prepare images
1607
+ for (let image of images) {
1608
+ const src = image.getAttribute('src');
1609
+ // Check if changes are necessary and possible
1610
+ if ((image.complete && image.naturalHeight !== 0) || // already laoded
1611
+ !src || // Image has no src
1612
+ config.regExp?.test(src) // Test if src matches regular expression
1613
+ ) {
1614
+ continue;
1615
+ }
1616
+ // Replace lazy loading image with immediately loading image
1617
+ if (image.getAttribute('loading') === 'lazy') {
1618
+ const newImage = document.createElement('img');
1619
+ Array.from(image.attributes).forEach((attr) => {
1620
+ if (attr.name !== 'loading' && attr.name !== 'src') {
1621
+ newImage.setAttribute(attr.name, attr.value);
1622
+ }
1623
+ });
1624
+ image.replaceWith(newImage);
1625
+ image = newImage;
1626
+ }
1627
+ // Wait for laoding
1628
+ promises.push(this.loadImage(image, src));
1629
+ }
1630
+ // Wait until all images loaded
1631
+ Promise.all(promises)
1632
+ .catch((e) => console.error('Error during image loading', e))
1633
+ .finally(async () => {
1634
+ // Return result
1635
+ let result;
1636
+ if (config.doneFunnction) {
1637
+ result = await config.doneFunction();
1638
+ }
1639
+ resolve(result);
1640
+ });
1641
+ });
1642
+ }
1643
+ /**
1644
+ * Load image for image element
1645
+ *
1646
+ * @param imageElement
1647
+ * @param src
1648
+ * @protected
1649
+ */
1650
+ async loadImage(imageElement, src) {
1651
+ src = src || imageElement.src;
1652
+ return new Promise((resolve, reject) => {
1653
+ imageElement.onload = () => resolve(imageElement);
1654
+ imageElement.onerror = reject;
1655
+ imageElement.src = src;
1656
+ });
1657
+ }
1658
+ }
1659
+ ImageService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.3", ngImport: i0, type: ImageService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1660
+ ImageService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.3.3", ngImport: i0, type: ImageService, providedIn: 'root' });
1661
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.3", ngImport: i0, type: ImageService, decorators: [{
1662
+ type: Injectable,
1663
+ args: [{
1664
+ providedIn: 'root',
1665
+ }]
1666
+ }] });
1667
+
1668
+ /**
1669
+ * Scroll service for autoscroll to specific fragments
1670
+ */
1671
+ class ScrollService {
1672
+ /**
1673
+ * Initializer
1674
+ */
1675
+ constructor(router, moduleConfig, imageService) {
1676
+ this.router = router;
1677
+ this.moduleConfig = moduleConfig;
1678
+ this.imageService = imageService;
1679
+ /**
1680
+ * Is a scroll listener set
1681
+ *
1682
+ * @protected
1683
+ */
1684
+ this.scrollListener = false;
1685
+ /**
1686
+ * Current scroll timer;
1687
+ *
1688
+ * @protected
1689
+ */
1690
+ this.scrollTimer = -1;
1691
+ const config = {
1692
+ scrollDetectionOffset: 200,
1693
+ scrollOffset: 100,
1694
+ scrollSamplingRate: 100,
1695
+ ...moduleConfig,
1696
+ };
1697
+ this.detectionOffset = config.scrollDetectionOffset;
1698
+ this.scrollOffset = config.scrollOffset;
1699
+ this.scrollSamplingRate = config.scrollSamplingRate;
1700
+ }
1701
+ /**
1702
+ * Scroll to structureElement with specific ID
1703
+ */
1704
+ async scrollTo(id, options = {}) {
1705
+ // Prepare config
1706
+ const config = {
1707
+ checkUrl: false,
1708
+ loadImagesBefore: true,
1709
+ resetStyles: false,
1710
+ setOverflow: true,
1711
+ stopPropagation: true,
1712
+ ...options,
1713
+ };
1714
+ // Check current URL
1715
+ if (config.checkUrl && this.router.url !== '/' && !this.router.url.startsWith('/#')) {
1716
+ await this.router.navigate(['/'], { fragment: id });
1717
+ return !config.stopPropagation;
1718
+ }
1719
+ // Check if target element exits
1720
+ const el = document.getElementById(id);
1721
+ if (!el) {
1722
+ console.error('Missing scroll element with ID:', id);
1723
+ return !config.stopPropagation;
1724
+ }
1725
+ // Check if body overflow is visible
1726
+ // This is necessary for scroll handling
1727
+ const body = document.querySelector('body');
1728
+ let undoOverflowChanges = false;
1729
+ const scrollBodyStyles = JSON.parse(JSON.stringify(window.getComputedStyle(body)));
1730
+ if (config.setOverflow && (scrollBodyStyles.overflowX !== 'visible' || scrollBodyStyles.overflowY !== 'visible')) {
1731
+ // Set body overflow to visible
1732
+ console.warn('Style of body element for overflowX and overflowY will be set to "visible" for scrolling!');
1733
+ body.style.overflowX = 'visible';
1734
+ body.style.overflowY = 'visible';
1735
+ undoOverflowChanges = true;
1736
+ }
1737
+ // Load images before scrolling (once)
1738
+ if (config.loadImagesBefore) {
1739
+ await this.imageService.preLoadImages();
1740
+ }
1741
+ // Get get bounding rect of target element
1742
+ const cords = el.getBoundingClientRect();
1743
+ // Scroll to element
1744
+ window.scrollBy({ top: cords.top - this.scrollOffset, behavior: 'smooth' });
1745
+ await this.scrollDone({
1746
+ doneFunction: () => {
1747
+ // Undo changes
1748
+ if (undoOverflowChanges && config.resetStyles) {
1749
+ body.style.overflowX = scrollBodyStyles.overflowX;
1750
+ body.style.overflowY = scrollBodyStyles.overflowY;
1751
+ console.warn('Original style of body element for overflowX and overflowY is set.');
1752
+ }
1753
+ },
1754
+ });
1755
+ // Return stop propagation configuration
1756
+ return !config.stopPropagation;
1757
+ }
1758
+ /**
1759
+ * Get last active structureElement
1760
+ */
1761
+ getLastActiveElement(list) {
1762
+ const currentScrollPosition = window.scrollY;
1763
+ const elementsWithId = document.querySelectorAll('[id]');
1764
+ let lastId = null;
1765
+ let lastPosition = 0 - this.detectionOffset - 1;
1766
+ elementsWithId.forEach((element) => {
1767
+ const cords = element.getBoundingClientRect();
1768
+ const top = cords.top + window.pageYOffset - this.detectionOffset;
1769
+ if ((!list || !list.length || list.includes(element.id)) && // In list
1770
+ top < currentScrollPosition && // In active area
1771
+ lastPosition < top // Higher than the last one
1772
+ ) {
1773
+ lastId = element.id;
1774
+ lastPosition = top;
1775
+ }
1776
+ });
1777
+ return lastId;
1778
+ }
1779
+ /**
1780
+ * Check if ID is active
1781
+ */
1782
+ isActive(id, list, isFirst) {
1783
+ const lastActiveElement = this.getLastActiveElement(list);
1784
+ return id === lastActiveElement || (lastActiveElement === null && isFirst);
1785
+ }
1786
+ /**
1787
+ * Scroll done promise
1788
+ */
1789
+ async scrollDone(options = {}) {
1790
+ // Init configuration
1791
+ const config = {
1792
+ doneFunction: undefined,
1793
+ ...options,
1794
+ };
1795
+ // Wait for scroll done
1796
+ await this.scrollDoneDetection();
1797
+ // Get result
1798
+ if (config.doneFunction) {
1799
+ return config.doneFunction();
1800
+ }
1801
+ }
1802
+ /**
1803
+ * Scroll done detecton
1804
+ *
1805
+ * @protected
1806
+ */
1807
+ scrollDoneDetection() {
1808
+ // Return current scroll promise (Singelton)
1809
+ if (this.scrollPromise) {
1810
+ return this.scrollPromise;
1811
+ }
1812
+ // Create current scroll promise
1813
+ this.scrollPromise = new Promise((resolve) => {
1814
+ this.scrollPromiseResolve = resolve;
1815
+ if (this.scrollTimer !== -1) {
1816
+ window.clearTimeout(this.scrollTimer);
1817
+ }
1818
+ this.scrollTimer = window.setTimeout(() => {
1819
+ window.removeEventListener('scroll', this.scrollDoneDetection.bind(this));
1820
+ this.scrollPromise = undefined;
1821
+ resolve();
1822
+ }, this.scrollSamplingRate);
1823
+ });
1824
+ // Lisitening to scroll event;
1825
+ window.addEventListener('scroll', this.scrollDoneDetection.bind(this));
1826
+ // Return promise
1827
+ return this.scrollPromise;
1828
+ }
1829
+ }
1830
+ ScrollService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.3", ngImport: i0, type: ScrollService, deps: [{ token: i1$1.Router }, { token: BASE_MODULE_CONFIG }, { token: ImageService }], target: i0.ɵɵFactoryTarget.Injectable });
1831
+ ScrollService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.3.3", ngImport: i0, type: ScrollService, providedIn: 'root' });
1832
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.3", ngImport: i0, type: ScrollService, decorators: [{
1833
+ type: Injectable,
1834
+ args: [{
1835
+ providedIn: 'root',
1836
+ }]
1837
+ }], ctorParameters: function () { return [{ type: i1$1.Router }, { type: undefined, decorators: [{
1838
+ type: Inject,
1839
+ args: [BASE_MODULE_CONFIG]
1840
+ }] }, { type: ImageService }]; } });
1841
+
1842
+ class ToastService {
1843
+ constructor() {
1844
+ this.toastsObservables = new BehaviorSubject([]);
1845
+ }
1846
+ get toastsAsObservable() {
1847
+ return this.toastsObservables.asObservable();
1848
+ }
1849
+ /**
1850
+ * Show new toast
1851
+ *
1852
+ * @param toast
1853
+ * @param duration
1854
+ */
1855
+ show(toast, duration) {
1856
+ const value = this.toastsObservables.value;
1857
+ value.push(toast);
1858
+ this.toastsObservables.next(value);
1859
+ if (duration) {
1860
+ setTimeout(() => {
1861
+ const currentToasts = this.toastsObservables.value;
1862
+ const foundIndex = currentToasts.findIndex((e) => e.id === toast.id);
1863
+ if (foundIndex > -1) {
1864
+ currentToasts.splice(foundIndex, 1);
1865
+ this.toastsObservables.next(currentToasts);
1866
+ }
1867
+ }, duration);
1868
+ }
1869
+ }
1870
+ }
1871
+ ToastService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.3", ngImport: i0, type: ToastService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1872
+ ToastService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.3.3", ngImport: i0, type: ToastService, providedIn: 'root' });
1873
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.3", ngImport: i0, type: ToastService, decorators: [{
1874
+ type: Injectable,
1875
+ args: [{
1876
+ providedIn: 'root',
1877
+ }]
1878
+ }] });
1879
+
1880
+ class BreadcrumbService {
1881
+ constructor(router) {
1882
+ this.router = router;
1883
+ this._breadcrumbs = new BehaviorSubject([]);
1884
+ this.subscribeToRouteChanges();
1885
+ }
1886
+ set breadcrumbs(value) {
1887
+ this._breadcrumbs.next(value);
1888
+ }
1889
+ get breadcrumbsObservable() {
1890
+ return this._breadcrumbs.asObservable();
1891
+ }
1892
+ /**
1893
+ * Subscribe to route changes and add element to breadcrumb
1894
+ */
1895
+ subscribeToRouteChanges() {
1896
+ this.router.events.pipe(filter((event) => event instanceof NavigationEnd)).subscribe((event) => {
1897
+ const root = this.router.routerState.snapshot.root;
1898
+ const breadcrumbs = [];
1899
+ this.addBreadcrumb(root, [], breadcrumbs);
1900
+ this.breadcrumbs = breadcrumbs;
1901
+ });
1902
+ }
1903
+ /**
1904
+ * Add element to breadcrumb
1905
+ *
1906
+ * @param route
1907
+ * @param parentUrl
1908
+ * @param breadcrumbs
1909
+ * @private
1910
+ */
1911
+ addBreadcrumb(route, parentUrl, breadcrumbs) {
1912
+ if (route) {
1913
+ const routeUrl = parentUrl.concat(route.url.map((url) => url.path));
1914
+ if (route.data?.breadcrumb) {
1915
+ const breadcrumb = {
1916
+ label: this.getLabel(route.data),
1917
+ url: '/' + routeUrl.join('/'),
1918
+ };
1919
+ breadcrumbs.push(breadcrumb);
1920
+ }
1921
+ this.addBreadcrumb(route.firstChild, routeUrl, breadcrumbs);
1922
+ }
1923
+ }
1924
+ /**
1925
+ * Get label for breadcrumb
1926
+ *
1927
+ * @param data
1928
+ * @private
1929
+ */
1930
+ getLabel(data) {
1931
+ return typeof data.breadcrumb === 'function' ? data.breadcrumb(data) : data.breadcrumb;
1932
+ }
1933
+ }
1934
+ BreadcrumbService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.3", ngImport: i0, type: BreadcrumbService, deps: [{ token: i1$1.Router }], target: i0.ɵɵFactoryTarget.Injectable });
1935
+ BreadcrumbService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.3.3", ngImport: i0, type: BreadcrumbService, providedIn: 'root' });
1936
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.3", ngImport: i0, type: BreadcrumbService, decorators: [{
1937
+ type: Injectable,
1938
+ args: [{
1939
+ providedIn: 'root',
1940
+ }]
1941
+ }], ctorParameters: function () { return [{ type: i1$1.Router }]; } });
1942
+
1943
+ /**
1944
+ * Comparison operator enum
1945
+ */
1946
+ var ComparisonOperatorEnum;
1947
+ (function (ComparisonOperatorEnum) {
1948
+ ComparisonOperatorEnum["EQ"] = "EQ";
1949
+ ComparisonOperatorEnum["GT"] = "GT";
1950
+ ComparisonOperatorEnum["GTE"] = "GTE";
1951
+ ComparisonOperatorEnum["IN"] = "IN";
1952
+ ComparisonOperatorEnum["LT"] = "LT";
1953
+ ComparisonOperatorEnum["LTE"] = "LTE";
1954
+ ComparisonOperatorEnum["NE"] = "NE";
1955
+ ComparisonOperatorEnum["NIN"] = "NIN";
1956
+ ComparisonOperatorEnum["REGEX"] = "REGEX";
1957
+ })(ComparisonOperatorEnum || (ComparisonOperatorEnum = {}));
1958
+
1959
+ /**
1960
+ * Logical operator enum
1961
+ */
1962
+ var LogicalOperatorEnum;
1963
+ (function (LogicalOperatorEnum) {
1964
+ LogicalOperatorEnum["AND"] = "AND";
1965
+ LogicalOperatorEnum["NOR"] = "NOR";
1966
+ LogicalOperatorEnum["OR"] = "OR";
1967
+ })(LogicalOperatorEnum || (LogicalOperatorEnum = {}));
1968
+
1969
+ var SortOrderEnum;
1970
+ (function (SortOrderEnum) {
1971
+ SortOrderEnum["ASC"] = "ASC";
1972
+ SortOrderEnum["DESC"] = "DESC";
1973
+ })(SortOrderEnum || (SortOrderEnum = {}));
1974
+
1975
+ var ToastType;
1976
+ (function (ToastType) {
1977
+ ToastType["ERROR"] = "error";
1978
+ ToastType["WARNING"] = "warning";
1979
+ ToastType["INFO"] = "info";
1980
+ })(ToastType || (ToastType = {}));
1981
+
1982
+ var SkeletonType;
1983
+ (function (SkeletonType) {
1984
+ SkeletonType["LINE"] = "LINE";
1985
+ SkeletonType["RECTANGLE"] = "RECTANGLE";
1986
+ SkeletonType["AVATAR"] = "AVATAR";
1987
+ })(SkeletonType || (SkeletonType = {}));
1988
+
1989
+ class Validation {
1990
+ static match(controlName, checkControlName) {
1991
+ return (controls) => {
1992
+ const control = controls.get(controlName);
1993
+ const checkControl = controls.get(checkControlName);
1994
+ if (checkControl?.errors && !checkControl.errors?.matching) {
1995
+ return null;
1996
+ }
1997
+ if (control?.value !== checkControl?.value) {
1998
+ controls.get(checkControlName)?.setErrors({ matching: true });
1999
+ return { matching: true };
2000
+ }
2001
+ else {
2002
+ return null;
2003
+ }
2004
+ };
2005
+ }
2006
+ }
2007
+
2008
+ function createRestartableClient(options) {
2009
+ let restartRequested = false;
2010
+ let restart = () => {
2011
+ restartRequested = true;
2012
+ };
2013
+ const { on = undefined } = options;
2014
+ const client = createClient({
2015
+ ...options,
2016
+ on: {
2017
+ ...on,
2018
+ connected: (socket) => {
2019
+ // @ts-ignore
2020
+ on?.connected?.(socket);
2021
+ restart = () => {
2022
+ if (socket.readyState === WebSocket.OPEN) {
2023
+ // if the socket is still open for the restart, do the restart
2024
+ socket.close(4205, 'Client Restart');
2025
+ }
2026
+ else {
2027
+ // otherwise the socket might've closed, indicate that you want
2028
+ // a restart on the next connected event
2029
+ restartRequested = true;
2030
+ }
2031
+ };
2032
+ // just in case you were eager to restart
2033
+ if (restartRequested) {
2034
+ restartRequested = false;
2035
+ restart();
2036
+ }
2037
+ },
2038
+ },
2039
+ });
2040
+ return {
2041
+ ...client,
2042
+ restart: () => restart(),
2043
+ };
2044
+ }
2045
+
2046
+ /**
2047
+ * Exports for public API
2048
+ */
2049
+
2050
+ /**
2051
+ * Generated bundle index. Do not edit.
2052
+ */
2053
+
2054
+ export { Auth, AuthService, BASE_MODULE_CONFIG, BasicUser, BreadcrumbService, ComparisonOperatorEnum, FormsService, GraphQLEnum, GraphQLMeta, GraphQLMetaService, GraphQLPlusService, GraphQLRequestType, GraphQLService, GraphQLType, Helper, ImageService, LoaderService, LogicalOperatorEnum, ScrollService, SkeletonType, SortOrderEnum, Standard, StorageService, ToastService, ToastType, UserService, Validation, WsService, createRestartableClient };
2055
+ //# sourceMappingURL=lenne.tech-ng-base-shared.mjs.map