@sinequa/atomic-angular 0.0.140

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 (174) hide show
  1. package/assets/tailwind.css +248 -0
  2. package/esm2022/lib/assistant/index.mjs +2 -0
  3. package/esm2022/lib/assistant/signalR.web.service.mjs +81 -0
  4. package/esm2022/lib/components/dropdown.mjs +127 -0
  5. package/esm2022/lib/components/index.mjs +5 -0
  6. package/esm2022/lib/components/menu/index.mjs +3 -0
  7. package/esm2022/lib/components/menu/menu-item.mjs +22 -0
  8. package/esm2022/lib/components/menu/menu.mjs +99 -0
  9. package/esm2022/lib/components/metadata/index.mjs +2 -0
  10. package/esm2022/lib/components/metadata/metadata.component.mjs +65 -0
  11. package/esm2022/lib/components/theme/index.mjs +3 -0
  12. package/esm2022/lib/components/theme/theme-selector.component.mjs +67 -0
  13. package/esm2022/lib/components/theme/theme-toggle.component.mjs +67 -0
  14. package/esm2022/lib/directives/index.mjs +5 -0
  15. package/esm2022/lib/directives/infinite-scroll.directive.mjs +47 -0
  16. package/esm2022/lib/directives/select-article-on-click.directive.mjs +39 -0
  17. package/esm2022/lib/directives/show-bookmark.directive.mjs +55 -0
  18. package/esm2022/lib/directives/theme-provider.directive.mjs +31 -0
  19. package/esm2022/lib/guards/auth.guard.mjs +27 -0
  20. package/esm2022/lib/guards/index.mjs +3 -0
  21. package/esm2022/lib/guards/initialization.guard.mjs +41 -0
  22. package/esm2022/lib/interceptors/audit.interceptor.mjs +23 -0
  23. package/esm2022/lib/interceptors/auth.interceptor.mjs +49 -0
  24. package/esm2022/lib/interceptors/body.interceptor.mjs +24 -0
  25. package/esm2022/lib/interceptors/error.interceptor.mjs +35 -0
  26. package/esm2022/lib/interceptors/index.mjs +7 -0
  27. package/esm2022/lib/interceptors/toast.interceptor.mjs +27 -0
  28. package/esm2022/lib/models/aggregation.mjs +2 -0
  29. package/esm2022/lib/models/article-metadata.mjs +2 -0
  30. package/esm2022/lib/models/autocomplete.mjs +2 -0
  31. package/esm2022/lib/models/custom-json.mjs +2 -0
  32. package/esm2022/lib/models/filter-dropdown.mjs +2 -0
  33. package/esm2022/lib/models/index.mjs +7 -0
  34. package/esm2022/lib/models/user-settings.mjs +2 -0
  35. package/esm2022/lib/pipes/highlight-word.pipe.mjs +33 -0
  36. package/esm2022/lib/pipes/index.mjs +3 -0
  37. package/esm2022/lib/pipes/source-icon.pipe.mjs +43 -0
  38. package/esm2022/lib/providers/eager-provider.mjs +24 -0
  39. package/esm2022/lib/providers/index.mjs +2 -0
  40. package/esm2022/lib/public-api.mjs +19 -0
  41. package/esm2022/lib/resolvers/index.mjs +2 -0
  42. package/esm2022/lib/resolvers/query-name-resolver.mjs +14 -0
  43. package/esm2022/lib/resources/index.mjs +2 -0
  44. package/esm2022/lib/resources/themes.mjs +53 -0
  45. package/esm2022/lib/services/application.service.mjs +245 -0
  46. package/esm2022/lib/services/autocomplete.service.mjs +85 -0
  47. package/esm2022/lib/services/drawer/backdrop.service.mjs +23 -0
  48. package/esm2022/lib/services/drawer/drawer-stack.service.mjs +152 -0
  49. package/esm2022/lib/services/drawer/drawer.service.mjs +38 -0
  50. package/esm2022/lib/services/index.mjs +12 -0
  51. package/esm2022/lib/services/label.service.mjs +161 -0
  52. package/esm2022/lib/services/navigation.service.mjs +59 -0
  53. package/esm2022/lib/services/saved-searches.service.mjs +75 -0
  54. package/esm2022/lib/services/search.service.mjs +89 -0
  55. package/esm2022/lib/services/selection-history.service.mjs +92 -0
  56. package/esm2022/lib/services/selection.service.mjs +87 -0
  57. package/esm2022/lib/stores/aggregations.store.mjs +62 -0
  58. package/esm2022/lib/stores/app.store.mjs +265 -0
  59. package/esm2022/lib/stores/application.store.mjs +93 -0
  60. package/esm2022/lib/stores/index.mjs +9 -0
  61. package/esm2022/lib/stores/principal.store.mjs +47 -0
  62. package/esm2022/lib/stores/query-params.store.mjs +208 -0
  63. package/esm2022/lib/stores/selection.store.mjs +46 -0
  64. package/esm2022/lib/stores/theme.store.mjs +116 -0
  65. package/esm2022/lib/stores/user-settings.store.mjs +272 -0
  66. package/esm2022/lib/tokens/highlights.mjs +32 -0
  67. package/esm2022/lib/tokens/index.mjs +2 -0
  68. package/esm2022/lib/utils/debounced-signal.mjs +38 -0
  69. package/esm2022/lib/utils/index.mjs +8 -0
  70. package/esm2022/lib/utils/inline-worker.mjs +40 -0
  71. package/esm2022/lib/utils/query.mjs +58 -0
  72. package/esm2022/lib/utils/routes.mjs +28 -0
  73. package/esm2022/lib/utils/tailwind-utils.mjs +6 -0
  74. package/esm2022/lib/utils/theme-body-hook.mjs +18 -0
  75. package/esm2022/lib/utils/theme-registry.mjs +6 -0
  76. package/esm2022/lib/web-services/aggregations.service.mjs +104 -0
  77. package/esm2022/lib/web-services/app.service.mjs +48 -0
  78. package/esm2022/lib/web-services/audit.service.mjs +122 -0
  79. package/esm2022/lib/web-services/index.mjs +10 -0
  80. package/esm2022/lib/web-services/json-method-plugin.service.mjs +54 -0
  81. package/esm2022/lib/web-services/preview.service.mjs +327 -0
  82. package/esm2022/lib/web-services/principal.service.mjs +46 -0
  83. package/esm2022/lib/web-services/query.service.mjs +123 -0
  84. package/esm2022/lib/web-services/text-chunck.service.mjs +46 -0
  85. package/esm2022/public-api.mjs +5 -0
  86. package/esm2022/sinequa-atomic-angular.mjs +5 -0
  87. package/fesm2022/sinequa-atomic-angular.mjs +4204 -0
  88. package/fesm2022/sinequa-atomic-angular.mjs.map +1 -0
  89. package/index.d.ts +5 -0
  90. package/lib/assistant/index.d.ts +1 -0
  91. package/lib/assistant/signalR.web.service.d.ts +46 -0
  92. package/lib/components/dropdown.d.ts +50 -0
  93. package/lib/components/index.d.ts +4 -0
  94. package/lib/components/menu/index.d.ts +2 -0
  95. package/lib/components/menu/menu-item.d.ts +8 -0
  96. package/lib/components/menu/menu.d.ts +24 -0
  97. package/lib/components/metadata/index.d.ts +1 -0
  98. package/lib/components/metadata/metadata.component.d.ts +24 -0
  99. package/lib/components/theme/index.d.ts +2 -0
  100. package/lib/components/theme/theme-selector.component.d.ts +70 -0
  101. package/lib/components/theme/theme-toggle.component.d.ts +10 -0
  102. package/lib/directives/index.d.ts +4 -0
  103. package/lib/directives/infinite-scroll.directive.d.ts +30 -0
  104. package/lib/directives/select-article-on-click.directive.d.ts +14 -0
  105. package/lib/directives/show-bookmark.directive.d.ts +52 -0
  106. package/lib/directives/theme-provider.directive.d.ts +20 -0
  107. package/lib/guards/auth.guard.d.ts +7 -0
  108. package/lib/guards/index.d.ts +2 -0
  109. package/lib/guards/initialization.guard.d.ts +20 -0
  110. package/lib/interceptors/audit.interceptor.d.ts +13 -0
  111. package/lib/interceptors/auth.interceptor.d.ts +14 -0
  112. package/lib/interceptors/body.interceptor.d.ts +11 -0
  113. package/lib/interceptors/error.interceptor.d.ts +9 -0
  114. package/lib/interceptors/index.d.ts +5 -0
  115. package/lib/interceptors/toast.interceptor.d.ts +13 -0
  116. package/lib/models/aggregation.d.ts +12 -0
  117. package/lib/models/article-metadata.d.ts +5 -0
  118. package/lib/models/autocomplete.d.ts +5 -0
  119. package/lib/models/custom-json.d.ts +58 -0
  120. package/lib/models/filter-dropdown.d.ts +10 -0
  121. package/lib/models/index.d.ts +6 -0
  122. package/lib/models/user-settings.d.ts +32 -0
  123. package/lib/pipes/highlight-word.pipe.d.ts +22 -0
  124. package/lib/pipes/index.d.ts +2 -0
  125. package/lib/pipes/source-icon.pipe.d.ts +54 -0
  126. package/lib/providers/eager-provider.d.ts +11 -0
  127. package/lib/providers/index.d.ts +1 -0
  128. package/lib/public-api.d.ts +15 -0
  129. package/lib/resolvers/index.d.ts +1 -0
  130. package/lib/resolvers/query-name-resolver.d.ts +9 -0
  131. package/lib/resources/index.d.ts +1 -0
  132. package/lib/resources/themes.d.ts +51 -0
  133. package/lib/services/application.service.d.ts +178 -0
  134. package/lib/services/autocomplete.service.d.ts +91 -0
  135. package/lib/services/drawer/backdrop.service.d.ts +9 -0
  136. package/lib/services/drawer/drawer-stack.service.d.ts +70 -0
  137. package/lib/services/drawer/drawer.service.d.ts +15 -0
  138. package/lib/services/index.d.ts +11 -0
  139. package/lib/services/label.service.d.ts +117 -0
  140. package/lib/services/navigation.service.d.ts +33 -0
  141. package/lib/services/saved-searches.service.d.ts +145 -0
  142. package/lib/services/search.service.d.ts +155 -0
  143. package/lib/services/selection-history.service.d.ts +50 -0
  144. package/lib/services/selection.service.d.ts +127 -0
  145. package/lib/stores/aggregations.store.d.ts +50 -0
  146. package/lib/stores/app.store.d.ts +208 -0
  147. package/lib/stores/application.store.d.ts +106 -0
  148. package/lib/stores/index.d.ts +8 -0
  149. package/lib/stores/principal.store.d.ts +53 -0
  150. package/lib/stores/query-params.store.d.ts +187 -0
  151. package/lib/stores/selection.store.d.ts +62 -0
  152. package/lib/stores/theme.store.d.ts +55 -0
  153. package/lib/stores/user-settings.store.d.ts +161 -0
  154. package/lib/tokens/highlights.d.ts +8 -0
  155. package/lib/tokens/index.d.ts +1 -0
  156. package/lib/utils/debounced-signal.d.ts +25 -0
  157. package/lib/utils/index.d.ts +7 -0
  158. package/lib/utils/inline-worker.d.ts +11 -0
  159. package/lib/utils/query.d.ts +26 -0
  160. package/lib/utils/routes.d.ts +16 -0
  161. package/lib/utils/tailwind-utils.d.ts +2 -0
  162. package/lib/utils/theme-body-hook.d.ts +6 -0
  163. package/lib/utils/theme-registry.d.ts +3 -0
  164. package/lib/web-services/aggregations.service.d.ts +60 -0
  165. package/lib/web-services/app.service.d.ts +30 -0
  166. package/lib/web-services/audit.service.d.ts +75 -0
  167. package/lib/web-services/index.d.ts +9 -0
  168. package/lib/web-services/json-method-plugin.service.d.ts +41 -0
  169. package/lib/web-services/preview.service.d.ts +295 -0
  170. package/lib/web-services/principal.service.d.ts +28 -0
  171. package/lib/web-services/query.service.d.ts +29 -0
  172. package/lib/web-services/text-chunck.service.d.ts +22 -0
  173. package/package.json +28 -0
  174. package/public-api.d.ts +1 -0
@@ -0,0 +1,245 @@
1
+ import { computed, inject, Injectable, InjectionToken } from '@angular/core';
2
+ import { ActivatedRoute, Router } from '@angular/router';
3
+ import { getState } from '@ngrx/signals';
4
+ import { toast } from 'ngx-sonner';
5
+ import { globalConfig, labels, login, setGlobalConfig } from '@sinequa/atomic';
6
+ import { AuthGuard, InitializationGuard } from '../guards';
7
+ import { AppStore } from '../stores/app.store';
8
+ import { PrincipalStore } from '../stores/principal.store';
9
+ import { UserSettingsStore } from '../stores/user-settings.store';
10
+ import { AppService } from '../web-services/app.service';
11
+ import { AuditService } from '../web-services/audit.service';
12
+ import { ApplicationStore } from '../stores/application.store';
13
+ import * as i0 from "@angular/core";
14
+ export const ROUTE_COMPONENTS = new InjectionToken('ROUTE_COMPONENTS', { factory: () => [] });
15
+ export class ApplicationService {
16
+ constructor() {
17
+ this.userSettingsStore = inject(UserSettingsStore);
18
+ this.principalStore = inject(PrincipalStore);
19
+ this.appService = inject(AppService);
20
+ this.appStore = inject(AppStore);
21
+ this.applicationStore = inject(ApplicationStore);
22
+ this.route = inject(ActivatedRoute);
23
+ this.router = inject(Router);
24
+ this.auditService = inject(AuditService);
25
+ this.components = inject(ROUTE_COMPONENTS);
26
+ this.defaultComponent = computed(() => this.components.find(c => c.path === 'all')?.component);
27
+ this.defaultLayoutComponent = computed(() => this.components.find(c => c.isRoot)?.component);
28
+ }
29
+ /**
30
+ * Registers a list of components.
31
+ *
32
+ * * For each path, the corresponding component is registered.
33
+ * * The default component is the component registered with the path 'all'.
34
+ * * The default layout component is the component registered with the isLayout flag set to true.
35
+ * * If no layout component is registered, the default layout component is the default component.
36
+ * * If no default component is registered, the default component is the first component in the list.
37
+ *
38
+ * Those components will be used to create the routes.
39
+ *
40
+ * @deprecated use the ROUTE_COMPONENTS injection token instead
41
+ *
42
+ * @param components - An array of ComponentMapping objects to be registered.
43
+ */
44
+ register(components) {
45
+ this.components = [...components];
46
+ }
47
+ /**
48
+ * Authenticates the user with the provided credentials, initializes and creates routes.  
49
+ * * in case of failure, it rejects with an error message.
50
+ * * in case of success, it resolves with `true`, shows a toast notification to welcome the user,
51
+ * and updates the application state to ready.
52
+ *
53
+ * @param {Credentials} [credentials] - The user's login credentials.
54
+ * @returns {Promise<boolean>} - A promise that resolves to `true` if login is successful,
55
+ * or rejects with an error message if login fails.
56
+ * @throws {Error} - Throws an error if the login process fails.
57
+ */
58
+ async autoLogin({ credentials, withCreateRoutes = true } = {}) {
59
+ const { useCredentialsOrSSO } = globalConfig;
60
+ try {
61
+ const authenticated = await login(credentials);
62
+ if (authenticated) {
63
+ await this.initAndCreateRoutes(withCreateRoutes).catch((error) => {
64
+ console.warn('Error initializing the application (authenticated)', error);
65
+ return Promise.reject(error);
66
+ });
67
+ // Show a toast notification to welcome the user
68
+ // and the application is ready to use
69
+ const { fullName, name } = getState(this.principalStore).principal;
70
+ toast(`Welcome back ${fullName || name}!`, { duration: 2000 });
71
+ this.applicationStore.updateReadyState();
72
+ return Promise.resolve(true);
73
+ }
74
+ else {
75
+ return Promise.reject('Login failed');
76
+ }
77
+ }
78
+ catch (error) {
79
+ console.error('Error logging in', error);
80
+ if (useCredentialsOrSSO) {
81
+ await this.initAndCreateRoutes(withCreateRoutes).catch((error) => {
82
+ console.warn('Error initializing the application (useCredentialsOrSSO)', error);
83
+ setGlobalConfig({ useCredentials: true });
84
+ return Promise.reject(error);
85
+ });
86
+ setGlobalConfig({ useSSO: true });
87
+ // Show a toast notification to welcome the user
88
+ // and the application is ready to use
89
+ const { fullName, name } = getState(this.principalStore).principal;
90
+ toast(`Welcome back ${fullName || name}!`, { duration: 2000 });
91
+ this.applicationStore.updateReadyState();
92
+ return Promise.resolve(true);
93
+ }
94
+ else {
95
+ return Promise.reject(error);
96
+ }
97
+ }
98
+ }
99
+ /**
100
+ * Initializes the application.
101
+ * - Fetches the application configuration.
102
+ * - Sets the fetched application configuration in the app store.
103
+ * - Loads the user settings and logs the state of the user settings store.
104
+ */
105
+ async init() {
106
+ // Fetch the application configuration
107
+ await this.appStore.initialize();
108
+ console.log("appStore", getState(this.appStore));
109
+ // Load the principal (user information)
110
+ await this.principalStore.initialize();
111
+ console.log("principalStore", getState(this.principalStore));
112
+ // Load the user settings
113
+ await this.userSettingsStore.initialize();
114
+ console.log("userSettingsStore", getState(this.userSettingsStore));
115
+ // Labels access
116
+ const service = (this.appStore.getWebServiceByType('labels'));
117
+ if (!service) {
118
+ this.applicationStore.updateHasLabelsAccess(false);
119
+ return;
120
+ }
121
+ try {
122
+ const rights = await labels.getUserRights();
123
+ this.applicationStore.updateHasLabelsAccess(rights.canEditPublicLabels || rights.canManagePublicLabels);
124
+ }
125
+ catch (error) {
126
+ console.log("labels.canHandleLabels failure - error: ", error);
127
+ this.applicationStore.updateHasLabelsAccess(false);
128
+ }
129
+ }
130
+ /**
131
+ * Initializes the application and creates routes.
132
+ *
133
+ * This method performs the following actions:
134
+ * 1. Calls the `init` method to initialize the application.
135
+ * 2. Calls the `createRoutes` method to set up the application routes.
136
+ * 3. Notifies the audit service of a login event.
137
+ *
138
+ * @returns {Promise<void>} A promise that resolves when the initialization and route creation are complete.
139
+ */
140
+ async initAndCreateRoutes(withCreateRoutes = true) {
141
+ // throw an error if no components are registered and withCreateRoutes is true
142
+ // components are required to create the routes
143
+ if (withCreateRoutes && !this.components.length)
144
+ throw new Error('No components registered');
145
+ await this.init();
146
+ if (withCreateRoutes) {
147
+ this.createRoutes();
148
+ }
149
+ }
150
+ /**
151
+ * Creates dynamic routes based on the application's queries and custom JSON configurations.
152
+ *
153
+ * This method performs the following steps:
154
+ * 1. Retrieves the queries and custom JSON data from the application state.
155
+ * 2. Maps the queries to an array of objects containing query names and tabs.
156
+ * 3. Throws an error if no queries are found.
157
+ * 4. Retrieves route data from custom JSONs or falls back to default data.
158
+ * 5. Creates routes for each tab in each query, or uses the query name if no tabs are found.
159
+ * 6. Removes the current search route from the router configuration.
160
+ * 7. Creates child routes based on the provided routes data or the first query's tabs.
161
+ * 8. Updates the search route with the new child routes.
162
+ * 9. Resets the router configuration with the new routes.
163
+ *
164
+ * @throws {Error} If no queries are found.
165
+ */
166
+ createRoutes() {
167
+ // Now we can create the dynamic routes based on the queries's tabs
168
+ const { queries, data: custom, customJSONs = [] } = getState(this.appStore);
169
+ // contains an array of objects with the query name and the tabs
170
+ const queriesMap = Object.entries(queries).map(([key, value]) => ({ key, ...value }));
171
+ // ! if no queries are found, throw an error
172
+ if (!queriesMap.length) {
173
+ throw new Error('No queries found');
174
+ }
175
+ // Retrieves the routes data from the custom JSONs array or fall back to the default data (custom json).
176
+ let { data: cjRoutes } = Array.isArray(customJSONs) ? customJSONs?.find((c => c.name === 'routes')) || {} : { data: custom?.['routes'] };
177
+ // check if cjRoutes is an array and not an object to avoid errors
178
+ if (cjRoutes && !Array.isArray(cjRoutes)) {
179
+ cjRoutes = undefined;
180
+ }
181
+ const routes = (cjRoutes || custom?.['routes']);
182
+ // take only first query
183
+ const firstQuery = queriesMap[0];
184
+ // We need to create a route for each tab in each query
185
+ // if a query has no tabs, we create a route with the query name as the tab name
186
+ const firstQueryConfig = { tabs: firstQuery.tabSearch.tabs || [{ name: firstQuery.name }] };
187
+ // We need to remove the current search route from the router config
188
+ // the route exists in the router config because it was created in the app-routing.module.ts and we need it
189
+ // to be able to navigate to the search page. We will recreate it with the new tabs
190
+ const currentConfig = this.router.config.filter(route => route.path !== 'search');
191
+ let children = [];
192
+ // if the routes data is provided, we create the children routes based on the routes data
193
+ if (routes) {
194
+ // update routes pathDisplayName with the query display name when not provided
195
+ // for each path we need to find the corresponding query and tab in the firstQuery object
196
+ // and create a child route with the query name and tab name
197
+ const displayNamesMap = firstQuery.tabSearch.tabs.reduce((acc, tab) => {
198
+ acc[tab.name] = { display: tab.display };
199
+ return acc;
200
+ }, {});
201
+ children = routes.map((route) => {
202
+ return ({
203
+ path: route.path,
204
+ component: this.components.find(c => c.path === route.path)?.component || this.defaultComponent(),
205
+ data: {
206
+ queryName: route.wsName || firstQuery.name,
207
+ display: route.pathDisplayName || displayNamesMap[route.wsQueryTab]?.display || route.path,
208
+ wsQueryTab: route.wsQueryTab,
209
+ iconClass: route.icon
210
+ }
211
+ });
212
+ });
213
+ }
214
+ else {
215
+ // if the routes data is not provided, we create the children routes based on the first query's tabs
216
+ // create the children routes for the search route
217
+ children = firstQueryConfig.tabs.map(tab => ({
218
+ path: tab.name,
219
+ component: this.components.find(c => c.path === tab.name)?.component || this.defaultComponent(),
220
+ data: { queryName: firstQuery.name, display: tab.display || tab.name }
221
+ }));
222
+ }
223
+ const searchPath = this.router.config.find(route => route.path === 'search')
224
+ || {
225
+ path: 'search',
226
+ component: this.components.find(c => c.path === 'search')?.component || this.defaultLayoutComponent(),
227
+ canActivate: [AuthGuard(), InitializationGuard()],
228
+ children: []
229
+ };
230
+ searchPath.component = this.components.find(c => c.path === 'search')?.component || this.defaultLayoutComponent();
231
+ searchPath.children = [...children, { path: '**', redirectTo: 'all', pathMatch: 'full' }];
232
+ const newConfig = [searchPath, ...currentConfig];
233
+ // finally we reset the router config with the new routes
234
+ this.router.resetConfig(newConfig);
235
+ }
236
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: ApplicationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
237
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: ApplicationService, providedIn: 'root' }); }
238
+ }
239
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: ApplicationService, decorators: [{
240
+ type: Injectable,
241
+ args: [{
242
+ providedIn: 'root'
243
+ }]
244
+ }] });
245
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBwbGljYXRpb24uc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2F0b21pYy1hbmd1bGFyL3NyYy9saWIvc2VydmljZXMvYXBwbGljYXRpb24uc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sRUFBRSxVQUFVLEVBQUUsY0FBYyxFQUFnQixNQUFNLGVBQWUsQ0FBQztBQUMzRixPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ3pELE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDekMsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLFlBQVksQ0FBQztBQUVuQyxPQUFPLEVBQXNCLFlBQVksRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLGVBQWUsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBRW5HLE9BQU8sRUFBRSxTQUFTLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDM0QsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQy9DLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUMzRCxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQztBQUNsRSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFDekQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBQzdELE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLDZCQUE2QixDQUFDOztBQUUvRCxNQUFNLENBQUMsTUFBTSxnQkFBZ0IsR0FBRyxJQUFJLGNBQWMsQ0FBcUIsa0JBQWtCLEVBQUUsRUFBRSxPQUFPLEVBQUUsR0FBRyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztBQVdsSCxNQUFNLE9BQU8s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RSxRQUFRO2dCQUNkLFNBQVMsRUFBRSxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLEtBQUssUUFBUSxDQUFDLEVBQUUsU0FBUyxJQUFJLElBQUksQ0FBQyxzQkFBc0IsRUFBRTtnQkFDckcsV0FBVyxFQUFFLENBQUMsU0FBUyxFQUFFLEVBQUUsbUJBQW1CLEVBQUUsQ0FBQztnQkFDakQsUUFBUSxFQUFFLEVBQUU7YUFDYixDQUFDO1FBRUYsVUFBVSxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLEtBQUssUUFBUSxDQUFDLEVBQUUsU0FBUyxJQUFJLElBQUksQ0FBQyxzQkFBc0IsRUFBRSxDQUFDO1FBQ2xILFVBQVUsQ0FBQyxRQUFRLEdBQUcsQ0FBQyxHQUFHLFFBQVEsRUFBRSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUUsTUFBTSxFQUFFLENBQUMsQ0FBQztRQUUxRixNQUFNLFNBQVMsR0FBRyxDQUFDLFVBQVUsRUFBRSxHQUFHLGFBQWEsQ0FBQyxDQUFDO1FBQ2pELHlEQUF5RDtRQUN6RCxJQUFJLENBQUMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUNyQyxDQUFDOzhHQXZQVSxrQkFBa0I7a0hBQWxCLGtCQUFrQixjQUZqQixNQUFNOzsyRkFFUCxrQkFBa0I7a0JBSDlCLFVBQVU7bUJBQUM7b0JBQ1YsVUFBVSxFQUFFLE1BQU07aUJBQ25CIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgY29tcHV0ZWQsIGluamVjdCwgSW5qZWN0YWJsZSwgSW5qZWN0aW9uVG9rZW4sIHNpZ25hbCwgVHlwZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQWN0aXZhdGVkUm91dGUsIFJvdXRlciB9IGZyb20gJ0Bhbmd1bGFyL3JvdXRlcic7XG5pbXBvcnQgeyBnZXRTdGF0ZSB9IGZyb20gJ0BuZ3J4L3NpZ25hbHMnO1xuaW1wb3J0IHsgdG9hc3QgfSBmcm9tICduZ3gtc29ubmVyJztcblxuaW1wb3J0IHsgQ0NBcHAsIENyZWRlbnRpYWxzLCBnbG9iYWxDb25maWcsIGxhYmVscywgbG9naW4sIHNldEdsb2JhbENvbmZpZyB9IGZyb20gJ0BzaW5lcXVhL2F0b21pYyc7XG5cbmltcG9ydCB7IEF1dGhHdWFyZCwgSW5pdGlhbGl6YXRpb25HdWFyZCB9IGZyb20gJy4uL2d1YXJkcyc7XG5pbXBvcnQgeyBBcHBTdG9yZSB9IGZyb20gJy4uL3N0b3Jlcy9hcHAuc3RvcmUnO1xuaW1wb3J0IHsgUHJpbmNpcGFsU3RvcmUgfSBmcm9tICcuLi9zdG9yZXMvcHJpbmNpcGFsLnN0b3JlJztcbmltcG9ydCB7IFVzZXJTZXR0aW5nc1N0b3JlIH0gZnJvbSAnLi4vc3RvcmVzL3VzZXItc2V0dGluZ3Muc3RvcmUnO1xuaW1wb3J0IHsgQXBwU2VydmljZSB9IGZyb20gJy4uL3dlYi1zZXJ2aWNlcy9hcHAuc2VydmljZSc7XG5pbXBvcnQgeyBBdWRpdFNlcnZpY2UgfSBmcm9tICcuLi93ZWItc2VydmljZXMvYXVkaXQuc2VydmljZSc7XG5pbXBvcnQgeyBBcHBsaWNhdGlvblN0b3JlIH0gZnJvbSAnLi4vc3RvcmVzL2FwcGxpY2F0aW9uLnN0b3JlJztcblxuZXhwb3J0IGNvbnN0IFJPVVRFX0NPTVBPTkVOVFMgPSBuZXcgSW5qZWN0aW9uVG9rZW48Q29tcG9uZW50TWFwcGluZ1tdPignUk9VVEVfQ09NUE9ORU5UUycsIHsgZmFjdG9yeTogKCkgPT4gW10gfSk7XG5cbmV4cG9ydCB0eXBlIENvbXBvbmVudE1hcHBpbmcgPSB7XG4gIHBhdGg6IHN0cmluZyxcbiAgY29tcG9uZW50OiBUeXBlPHVua25vd24+XG4gIGlzUm9vdD86IGJvb2xlYW5cbn07XG5cbkBJbmplY3RhYmxlKHtcbiAgcHJvdmlkZWRJbjogJ3Jvb3QnXG59KVxuZXhwb3J0IGNsYXNzIEFwcGxpY2F0aW9uU2VydmljZSB7XG5cbiAgdXNlclNldHRpbmdzU3RvcmUgPSBpbmplY3QoVXNlclNldHRpbmdzU3RvcmUpO1xuICBwcmluY2lwYWxTdG9yZSA9IGluamVjdChQcmluY2lwYWxTdG9yZSk7XG5cbiAgYXBwU2VydmljZSA9IGluamVjdChBcHBTZXJ2aWNlKTtcbiAgYXBwU3RvcmUgPSBpbmplY3QoQXBwU3RvcmUpO1xuICBhcHBsaWNhdGlvblN0b3JlID0gaW5qZWN0KEFwcGxpY2F0aW9uU3RvcmUpO1xuXG4gIHJvdXRlID0gaW5qZWN0KEFjdGl2YXRlZFJvdXRlKTtcbiAgcm91dGVyID0gaW5qZWN0KFJvdXRlcik7XG5cbiAgYXVkaXRTZXJ2aWNlID0gaW5qZWN0KEF1ZGl0U2VydmljZSk7XG5cbiAgY29tcG9uZW50cyA9IGluamVjdChST1VURV9DT01QT05FTlRTKTtcbiAgZGVmYXVsdENvbXBvbmVudCA9IGNvbXB1dGVkKCgpID0+IHRoaXMuY29tcG9uZW50cy5maW5kKGMgPT4gYy5wYXRoID09PSAnYWxsJyk/LmNvbXBvbmVudCk7XG4gIGRlZmF1bHRMYXlvdXRDb21wb25lbnQgPSBjb21wdXRlZCgoKSA9PiB0aGlzLmNvbXBvbmVudHMuZmluZChjID0+IGMuaXNSb290KT8uY29tcG9uZW50KTtcblxuICAvKipcbiAgICogUmVnaXN0ZXJzIGEgbGlzdCBvZiBjb21wb25lbnRzLlxuICAgKlxuICAgKiAqIEZvciBlYWNoIHBhdGgsIHRoZSBjb3JyZXNwb25kaW5nIGNvbXBvbmVudCBpcyByZWdpc3RlcmVkLlxuICAgKiAqIFRoZSBkZWZhdWx0IGNvbXBvbmVudCBpcyB0aGUgY29tcG9uZW50IHJlZ2lzdGVyZWQgd2l0aCB0aGUgcGF0aCAnYWxsJy5cbiAgICogKiBUaGUgZGVmYXVsdCBsYXlvdXQgY29tcG9uZW50IGlzIHRoZSBjb21wb25lbnQgcmVnaXN0ZXJlZCB3aXRoIHRoZSBpc0xheW91dCBmbGFnIHNldCB0byB0cnVlLlxuICAgKiAqIElmIG5vIGxheW91dCBjb21wb25lbnQgaXMgcmVnaXN0ZXJlZCwgdGhlIGRlZmF1bHQgbGF5b3V0IGNvbXBvbmVudCBpcyB0aGUgZGVmYXVsdCBjb21wb25lbnQuXG4gICAqICogSWYgbm8gZGVmYXVsdCBjb21wb25lbnQgaXMgcmVnaXN0ZXJlZCwgdGhlIGRlZmF1bHQgY29tcG9uZW50IGlzIHRoZSBmaXJzdCBjb21wb25lbnQgaW4gdGhlIGxpc3QuXG4gICAqXG4gICAqIFRob3NlIGNvbXBvbmVudHMgd2lsbCBiZSB1c2VkIHRvIGNyZWF0ZSB0aGUgcm91dGVzLlxuICAgKlxuICAgKiBAZGVwcmVjYXRlZCB1c2UgdGhlIFJPVVRFX0NPTVBPTkVOVFMgaW5qZWN0aW9uIHRva2VuIGluc3RlYWRcbiAgICpcbiAgICogQHBhcmFtIGNvbXBvbmVudHMgLSBBbiBhcnJheSBvZiBDb21wb25lbnRNYXBwaW5nIG9iamVjdHMgdG8gYmUgcmVnaXN0ZXJlZC5cbiAgICovXG4gIHJlZ2lzdGVyKGNvbXBvbmVudHM6IENvbXBvbmVudE1hcHBpbmdbXSkge1xuICAgIHRoaXMuY29tcG9uZW50cyA9IFsuLi5jb21wb25lbnRzXTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBdXRoZW50aWNhdGVzIHRoZSB1c2VyIHdpdGggdGhlIHByb3ZpZGVkIGNyZWRlbnRpYWxzLCBpbml0aWFsaXplcyBhbmQgY3JlYXRlcyByb3V0ZXMuJm5ic3A7Jm5ic3A7XG4gICAqICogaW4gY2FzZSBvZiBmYWlsdXJlLCBpdCByZWplY3RzIHdpdGggYW4gZXJyb3IgbWVzc2FnZS5cbiAgICogKiBpbiBjYXNlIG9mIHN1Y2Nlc3MsIGl0IHJlc29sdmVzIHdpdGggYHRydWVgLCBzaG93cyBhIHRvYXN0IG5vdGlmaWNhdGlvbiB0byB3ZWxjb21lIHRoZSB1c2VyLFxuICAgKiBhbmQgdXBkYXRlcyB0aGUgYXBwbGljYXRpb24gc3RhdGUgdG8gcmVhZHkuXG4gICAqXG4gICAqIEBwYXJhbSB7Q3JlZGVudGlhbHN9IFtjcmVkZW50aWFsc10gLSBUaGUgdXNlcidzIGxvZ2luIGNyZWRlbnRpYWxzLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxib29sZWFuPn0gLSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB0byBgdHJ1ZWAgaWYgbG9naW4gaXMgc3VjY2Vzc2Z1bCxcbiAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3IgcmVqZWN0cyB3aXRoIGFuIGVycm9yIG1lc3NhZ2UgaWYgbG9naW4gZmFpbHMuXG4gICAqIEB0aHJvd3Mge0Vycm9yfSAtIFRocm93cyBhbiBlcnJvciBpZiB0aGUgbG9naW4gcHJvY2VzcyBmYWlscy5cbiAgICovXG4gIGFzeW5jIGF1dG9Mb2dpbih7IGNyZWRlbnRpYWxzLCB3aXRoQ3JlYXRlUm91dGVzID0gdHJ1ZSB9OiB7IGNyZWRlbnRpYWxzPzogQ3JlZGVudGlhbHM7IHdpdGhDcmVhdGVSb3V0ZXM/OiBib29sZWFuOyB9ID0ge30pOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICBjb25zdCB7IHVzZUNyZWRlbnRpYWxzT3JTU08gfSA9IGdsb2JhbENvbmZpZztcbiAgICB0cnkge1xuICAgICAgY29uc3QgYXV0aGVudGljYXRlZCA9IGF3YWl0IGxvZ2luKGNyZWRlbnRpYWxzKTtcbiAgICAgIGlmIChhdXRoZW50aWNhdGVkKSB7XG4gICAgICAgIGF3YWl0IHRoaXMuaW5pdEFuZENyZWF0ZVJvdXRlcyh3aXRoQ3JlYXRlUm91dGVzKS5jYXRjaCgoZXJyb3IpID0+IHtcbiAgICAgICAgICBjb25zb2xlLndhcm4oJ0Vycm9yIGluaXRpYWxpemluZyB0aGUgYXBwbGljYXRpb24gKGF1dGhlbnRpY2F0ZWQpJywgZXJyb3IpO1xuICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChlcnJvcik7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIFNob3cgYSB0b2FzdCBub3RpZmljYXRpb24gdG8gd2VsY29tZSB0aGUgdXNlclxuICAgICAgICAvLyBhbmQgdGhlIGFwcGxpY2F0aW9uIGlzIHJlYWR5IHRvIHVzZVxuICAgICAgICBjb25zdCB7IGZ1bGxOYW1lLCBuYW1lIH0gPSBnZXRTdGF0ZSh0aGlzLnByaW5jaXBhbFN0b3JlKS5wcmluY2lwYWw7XG4gICAgICAgIHRvYXN0KGBXZWxjb21lIGJhY2sgJHtmdWxsTmFtZSB8fCBuYW1lfSFgLCB7IGR1cmF0aW9uOiAyMDAwIH0pXG4gICAgICAgIHRoaXMuYXBwbGljYXRpb25TdG9yZS51cGRhdGVSZWFkeVN0YXRlKCk7XG5cbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh0cnVlKTtcbiAgICAgIH1cbiAgICAgIGVsc2Uge1xuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoJ0xvZ2luIGZhaWxlZCcpO1xuICAgICAgfVxuICAgIH1cbiAgICBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIGxvZ2dpbmcgaW4nLCBlcnJvcik7XG4gICAgICBpZiAodXNlQ3JlZGVudGlhbHNPclNTTykge1xuICAgICAgICBhd2FpdCB0aGlzLmluaXRBbmRDcmVhdGVSb3V0ZXMod2l0aENyZWF0ZVJvdXRlcykuY2F0Y2goKGVycm9yKSA9PiB7XG4gICAgICAgICAgY29uc29sZS53YXJuKCdFcnJvciBpbml0aWFsaXppbmcgdGhlIGFwcGxpY2F0aW9uICh1c2VDcmVkZW50aWFsc09yU1NPKScsIGVycm9yKTtcbiAgICAgICAgICBzZXRHbG9iYWxDb25maWcoeyB1c2VDcmVkZW50aWFsczogdHJ1ZSB9KTtcbiAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoZXJyb3IpO1xuICAgICAgICB9KVxuXG4gICAgICAgIHNldEdsb2JhbENvbmZpZyh7IHVzZVNTTzogdHJ1ZSB9KTtcbiAgICAgICAgLy8gU2hvdyBhIHRvYXN0IG5vdGlmaWNhdGlvbiB0byB3ZWxjb21lIHRoZSB1c2VyXG4gICAgICAgIC8vIGFuZCB0aGUgYXBwbGljYXRpb24gaXMgcmVhZHkgdG8gdXNlXG4gICAgICAgIGNvbnN0IHsgZnVsbE5hbWUsIG5hbWUgfSA9IGdldFN0YXRlKHRoaXMucHJpbmNpcGFsU3RvcmUpLnByaW5jaXBhbDtcbiAgICAgICAgdG9hc3QoYFdlbGNvbWUgYmFjayAke2Z1bGxOYW1lIHx8IG5hbWV9IWAsIHsgZHVyYXRpb246IDIwMDAgfSlcbiAgICAgICAgdGhpcy5hcHBsaWNhdGlvblN0b3JlLnVwZGF0ZVJlYWR5U3RhdGUoKTtcblxuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHRydWUpO1xuICAgICAgfVxuICAgICAgZWxzZSB7XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChlcnJvcik7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEluaXRpYWxpemVzIHRoZSBhcHBsaWNhdGlvbi5cbiAgICogLSBGZXRjaGVzIHRoZSBhcHBsaWNhdGlvbiBjb25maWd1cmF0aW9uLlxuICAgKiAtIFNldHMgdGhlIGZldGNoZWQgYXBwbGljYXRpb24gY29uZmlndXJhdGlvbiBpbiB0aGUgYXBwIHN0b3JlLlxuICAgKiAtIExvYWRzIHRoZSB1c2VyIHNldHRpbmdzIGFuZCBsb2dzIHRoZSBzdGF0ZSBvZiB0aGUgdXNlciBzZXR0aW5ncyBzdG9yZS5cbiAgICovXG4gIGFzeW5jIGluaXQoKSB7XG4gICAgLy8gRmV0Y2ggdGhlIGFwcGxpY2F0aW9uIGNvbmZpZ3VyYXRpb25cbiAgICBhd2FpdCB0aGlzLmFwcFN0b3JlLmluaXRpYWxpemUoKTtcbiAgICBjb25zb2xlLmxvZyhcImFwcFN0b3JlXCIsIGdldFN0YXRlKHRoaXMuYXBwU3RvcmUpKTtcblxuICAgIC8vIExvYWQgdGhlIHByaW5jaXBhbCAodXNlciBpbmZvcm1hdGlvbilcbiAgICBhd2FpdCB0aGlzLnByaW5jaXBhbFN0b3JlLmluaXRpYWxpemUoKVxuICAgIGNvbnNvbGUubG9nKFwicHJpbmNpcGFsU3RvcmVcIiwgZ2V0U3RhdGUodGhpcy5wcmluY2lwYWxTdG9yZSkpXG5cbiAgICAvLyBMb2FkIHRoZSB1c2VyIHNldHRpbmdzXG4gICAgYXdhaXQgdGhpcy51c2VyU2V0dGluZ3NTdG9yZS5pbml0aWFsaXplKCk7XG4gICAgY29uc29sZS5sb2coXCJ1c2VyU2V0dGluZ3NTdG9yZVwiLCBnZXRTdGF0ZSh0aGlzLnVzZXJTZXR0aW5nc1N0b3JlKSlcblxuICAgIC8vIExhYmVscyBhY2Nlc3NcbiAgICBjb25zdCBzZXJ2aWNlID0gKHRoaXMuYXBwU3RvcmUuZ2V0V2ViU2VydmljZUJ5VHlwZSgnbGFiZWxzJykpO1xuICAgIGlmICghc2VydmljZSkge1xuICAgICAgdGhpcy5hcHBsaWNhdGlvblN0b3JlLnVwZGF0ZUhhc0xhYmVsc0FjY2VzcyhmYWxzZSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRyeSB7XG4gICAgICBjb25zdCByaWdodHMgPSBhd2FpdCBsYWJlbHMuZ2V0VXNlclJpZ2h0cygpO1xuICAgICAgdGhpcy5hcHBsaWNhdGlvblN0b3JlLnVwZGF0ZUhhc0xhYmVsc0FjY2VzcyhyaWdodHMuY2FuRWRpdFB1YmxpY0xhYmVscyB8fCByaWdodHMuY2FuTWFuYWdlUHVibGljTGFiZWxzKTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgY29uc29sZS5sb2coXCJsYWJlbHMuY2FuSGFuZGxlTGFiZWxzIGZhaWx1cmUgLSBlcnJvcjogXCIsIGVycm9yKTtcbiAgICAgIHRoaXMuYXBwbGljYXRpb25TdG9yZS51cGRhdGVIYXNMYWJlbHNBY2Nlc3MoZmFsc2UpO1xuICAgIH1cbiAgfVxuXG5cbiAgLyoqXG4gICAqIEluaXRpYWxpemVzIHRoZSBhcHBsaWNhdGlvbiBhbmQgY3JlYXRlcyByb3V0ZXMuXG4gICAqXG4gICAqIFRoaXMgbWV0aG9kIHBlcmZvcm1zIHRoZSBmb2xsb3dpbmcgYWN0aW9uczpcbiAgICogMS4gQ2FsbHMgdGhlIGBpbml0YCBtZXRob2QgdG8gaW5pdGlhbGl6ZSB0aGUgYXBwbGljYXRpb24uXG4gICAqIDIuIENhbGxzIHRoZSBgY3JlYXRlUm91dGVzYCBtZXRob2QgdG8gc2V0IHVwIHRoZSBhcHBsaWNhdGlvbiByb3V0ZXMuXG4gICAqIDMuIE5vdGlmaWVzIHRoZSBhdWRpdCBzZXJ2aWNlIG9mIGEgbG9naW4gZXZlbnQuXG4gICAqXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIHRoZSBpbml0aWFsaXphdGlvbiBhbmQgcm91dGUgY3JlYXRpb24gYXJlIGNvbXBsZXRlLlxuICAgKi9cbiAgYXN5bmMgaW5pdEFuZENyZWF0ZVJvdXRlcyh3aXRoQ3JlYXRlUm91dGVzID0gdHJ1ZSkge1xuICAgIC8vIHRocm93IGFuIGVycm9yIGlmIG5vIGNvbXBvbmVudHMgYXJlIHJlZ2lzdGVyZWQgYW5kIHdpdGhDcmVhdGVSb3V0ZXMgaXMgdHJ1ZVxuICAgIC8vIGNvbXBvbmVudHMgYXJlIHJlcXVpcmVkIHRvIGNyZWF0ZSB0aGUgcm91dGVzXG4gICAgaWYgKHdpdGhDcmVhdGVSb3V0ZXMgJiYgIXRoaXMuY29tcG9uZW50cy5sZW5ndGgpIHRocm93IG5ldyBFcnJvcignTm8gY29tcG9uZW50cyByZWdpc3RlcmVkJyk7XG5cbiAgICBhd2FpdCB0aGlzLmluaXQoKTtcbiAgICBpZiAod2l0aENyZWF0ZVJvdXRlcykge1xuICAgICAgdGhpcy5jcmVhdGVSb3V0ZXMoKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBkeW5hbWljIHJvdXRlcyBiYXNlZCBvbiB0aGUgYXBwbGljYXRpb24ncyBxdWVyaWVzIGFuZCBjdXN0b20gSlNPTiBjb25maWd1cmF0aW9ucy5cbiAgICpcbiAgICogVGhpcyBtZXRob2QgcGVyZm9ybXMgdGhlIGZvbGxvd2luZyBzdGVwczpcbiAgICogMS4gUmV0cmlldmVzIHRoZSBxdWVyaWVzIGFuZCBjdXN0b20gSlNPTiBkYXRhIGZyb20gdGhlIGFwcGxpY2F0aW9uIHN0YXRlLlxuICAgKiAyLiBNYXBzIHRoZSBxdWVyaWVzIHRvIGFuIGFycmF5IG9mIG9iamVjdHMgY29udGFpbmluZyBxdWVyeSBuYW1lcyBhbmQgdGFicy5cbiAgICogMy4gVGhyb3dzIGFuIGVycm9yIGlmIG5vIHF1ZXJpZXMgYXJlIGZvdW5kLlxuICAgKiA0LiBSZXRyaWV2ZXMgcm91dGUgZGF0YSBmcm9tIGN1c3RvbSBKU09OcyBvciBmYWxscyBiYWNrIHRvIGRlZmF1bHQgZGF0YS5cbiAgICogNS4gQ3JlYXRlcyByb3V0ZXMgZm9yIGVhY2ggdGFiIGluIGVhY2ggcXVlcnksIG9yIHVzZXMgdGhlIHF1ZXJ5IG5hbWUgaWYgbm8gdGFicyBhcmUgZm91bmQuXG4gICAqIDYuIFJlbW92ZXMgdGhlIGN1cnJlbnQgc2VhcmNoIHJvdXRlIGZyb20gdGhlIHJvdXRlciBjb25maWd1cmF0aW9uLlxuICAgKiA3LiBDcmVhdGVzIGNoaWxkIHJvdXRlcyBiYXNlZCBvbiB0aGUgcHJvdmlkZWQgcm91dGVzIGRhdGEgb3IgdGhlIGZpcnN0IHF1ZXJ5J3MgdGFicy5cbiAgICogOC4gVXBkYXRlcyB0aGUgc2VhcmNoIHJvdXRlIHdpdGggdGhlIG5ldyBjaGlsZCByb3V0ZXMuXG4gICAqIDkuIFJlc2V0cyB0aGUgcm91dGVyIGNvbmZpZ3VyYXRpb24gd2l0aCB0aGUgbmV3IHJvdXRlcy5cbiAgICpcbiAgICogQHRocm93cyB7RXJyb3J9IElmIG5vIHF1ZXJpZXMgYXJlIGZvdW5kLlxuICAgKi9cbiAgcHJpdmF0ZSBjcmVhdGVSb3V0ZXMoKSB7XG4gICAgLy8gTm93IHdlIGNhbiBjcmVhdGUgdGhlIGR5bmFtaWMgcm91dGVzIGJhc2VkIG9uIHRoZSBxdWVyaWVzJ3MgdGFic1xuICAgIGNvbnN0IHsgcXVlcmllcywgZGF0YTogY3VzdG9tLCBjdXN0b21KU09OcyA9IFtdIH0gPSBnZXRTdGF0ZSh0aGlzLmFwcFN0b3JlKSBhcyBDQ0FwcDtcblxuICAgIC8vIGNvbnRhaW5zIGFuIGFycmF5IG9mIG9iamVjdHMgd2l0aCB0aGUgcXVlcnkgbmFtZSBhbmQgdGhlIHRhYnNcbiAgICBjb25zdCBxdWVyaWVzTWFwID0gT2JqZWN0LmVudHJpZXMocXVlcmllcykubWFwKChba2V5LCB2YWx1ZV0pID0+ICh7IGtleSwgLi4udmFsdWUgfSkpO1xuXG4gICAgLy8gISBpZiBubyBxdWVyaWVzIGFyZSBmb3VuZCwgdGhyb3cgYW4gZXJyb3JcbiAgICBpZiAoIXF1ZXJpZXNNYXAubGVuZ3RoKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIHF1ZXJpZXMgZm91bmQnKTtcbiAgICB9XG5cbiAgICAvLyBSZXRyaWV2ZXMgdGhlIHJvdXRlcyBkYXRhIGZyb20gdGhlIGN1c3RvbSBKU09OcyBhcnJheSBvciBmYWxsIGJhY2sgdG8gdGhlIGRlZmF1bHQgZGF0YSAoY3VzdG9tIGpzb24pLlxuICAgIGxldCB7IGRhdGE6IGNqUm91dGVzIH0gPSBBcnJheS5pc0FycmF5KGN1c3RvbUpTT05zKSA/IGN1c3RvbUpTT05zPy5maW5kKChjID0+IGMubmFtZSA9PT0gJ3JvdXRlcycpKSB8fCB7fSA6IHsgZGF0YTogY3VzdG9tPy5bJ3JvdXRlcyddIH07XG4gICAgLy8gY2hlY2sgaWYgY2pSb3V0ZXMgaXMgYW4gYXJyYXkgYW5kIG5vdCBhbiBvYmplY3QgdG8gYXZvaWQgZXJyb3JzXG4gICAgaWYgKGNqUm91dGVzICYmICFBcnJheS5pc0FycmF5KGNqUm91dGVzKSkge1xuICAgICAgY2pSb3V0ZXMgPSB1bmRlZmluZWQ7XG4gICAgfVxuICAgIGNvbnN0IHJvdXRlcyA9IChjalJvdXRlcyB8fCBjdXN0b20/Llsncm91dGVzJ10pIGFzIHsgcGF0aDogc3RyaW5nLCB3c05hbWU6IHN0cmluZywgd3NRdWVyeVRhYjogc3RyaW5nLCBwYXRoRGlzcGxheU5hbWU6IHN0cmluZywgaWNvbjogc3RyaW5nIH1bXTtcblxuICAgIC8vIHRha2Ugb25seSBmaXJzdCBxdWVyeVxuICAgIGNvbnN0IGZpcnN0UXVlcnkgPSBxdWVyaWVzTWFwWzBdO1xuXG4gICAgLy8gV2UgbmVlZCB0byBjcmVhdGUgYSByb3V0ZSBmb3IgZWFjaCB0YWIgaW4gZWFjaCBxdWVyeVxuICAgIC8vIGlmIGEgcXVlcnkgaGFzIG5vIHRhYnMsIHdlIGNyZWF0ZSBhIHJvdXRlIHdpdGggdGhlIHF1ZXJ5IG5hbWUgYXMgdGhlIHRhYiBuYW1lXG4gICAgY29uc3QgZmlyc3RRdWVyeUNvbmZpZyA9IHsgdGFiczogZmlyc3RRdWVyeS50YWJTZWFyY2gudGFicyB8fCBbeyBuYW1lOiBmaXJzdFF1ZXJ5Lm5hbWUgfV0gfTtcblxuICAgIC8vIFdlIG5lZWQgdG8gcmVtb3ZlIHRoZSBjdXJyZW50IHNlYXJjaCByb3V0ZSBmcm9tIHRoZSByb3V0ZXIgY29uZmlnXG4gICAgLy8gdGhlIHJvdXRlIGV4aXN0cyBpbiB0aGUgcm91dGVyIGNvbmZpZyBiZWNhdXNlIGl0IHdhcyBjcmVhdGVkIGluIHRoZSBhcHAtcm91dGluZy5tb2R1bGUudHMgYW5kIHdlIG5lZWQgaXRcbiAgICAvLyB0byBiZSBhYmxlIHRvIG5hdmlnYXRlIHRvIHRoZSBzZWFyY2ggcGFnZS4gV2Ugd2lsbCByZWNyZWF0ZSBpdCB3aXRoIHRoZSBuZXcgdGFic1xuICAgIGNvbnN0IGN1cnJlbnRDb25maWcgPSB0aGlzLnJvdXRlci5jb25maWcuZmlsdGVyKHJvdXRlID0+IHJvdXRlLnBhdGggIT09ICdzZWFyY2gnKTtcblxuICAgIGxldCBjaGlsZHJlbiA9IFtdO1xuXG4gICAgLy8gaWYgdGhlIHJvdXRlcyBkYXRhIGlzIHByb3ZpZGVkLCB3ZSBjcmVhdGUgdGhlIGNoaWxkcmVuIHJvdXRlcyBiYXNlZCBvbiB0aGUgcm91dGVzIGRhdGFcbiAgICBpZiAocm91dGVzKSB7XG4gICAgICAvLyB1cGRhdGUgcm91dGVzIHBhdGhEaXNwbGF5TmFtZSB3aXRoIHRoZSBxdWVyeSBkaXNwbGF5IG5hbWUgd2hlbiBub3QgcHJvdmlkZWRcbiAgICAgIC8vIGZvciBlYWNoIHBhdGggd2UgbmVlZCB0byBmaW5kIHRoZSBjb3JyZXNwb25kaW5nIHF1ZXJ5IGFuZCB0YWIgaW4gdGhlIGZpcnN0UXVlcnkgb2JqZWN0XG4gICAgICAvLyBhbmQgY3JlYXRlIGEgY2hpbGQgcm91dGUgd2l0aCB0aGUgcXVlcnkgbmFtZSBhbmQgdGFiIG5hbWVcbiAgICAgIGNvbnN0IGRpc3BsYXlOYW1lc01hcCA9IGZpcnN0UXVlcnkudGFiU2VhcmNoLnRhYnMucmVkdWNlKChhY2MsIHRhYikgPT4ge1xuICAgICAgICBhY2NbdGFiLm5hbWVdID0geyBkaXNwbGF5OiB0YWIuZGlzcGxheSB9O1xuICAgICAgICByZXR1cm4gYWNjO1xuICAgICAgfSwge30gYXMgUmVjb3JkPHN0cmluZywgeyBkaXNwbGF5OiBzdHJpbmcgfT4pO1xuXG4gICAgICBjaGlsZHJlbiA9IHJvdXRlcy5tYXAoKHJvdXRlKSA9PiB7XG4gICAgICAgIHJldHVybiAoe1xuICAgICAgICAgIHBhdGg6IHJvdXRlLnBhdGgsXG4gICAgICAgICAgY29tcG9uZW50OiB0aGlzLmNvbXBvbmVudHMuZmluZChjID0+IGMucGF0aCA9PT0gcm91dGUucGF0aCk/LmNvbXBvbmVudCB8fCB0aGlzLmRlZmF1bHRDb21wb25lbnQoKSxcbiAgICAgICAgICBkYXRhOiB7XG4gICAgICAgICAgICBxdWVyeU5hbWU6IHJvdXRlLndzTmFtZSB8fCBmaXJzdFF1ZXJ5Lm5hbWUsXG4gICAgICAgICAgICBkaXNwbGF5OiByb3V0ZS5wYXRoRGlzcGxheU5hbWUgfHwgZGlzcGxheU5hbWVzTWFwW3JvdXRlLndzUXVlcnlUYWJdPy5kaXNwbGF5IHx8IHJvdXRlLnBhdGgsXG4gICAgICAgICAgICB3c1F1ZXJ5VGFiOiByb3V0ZS53c1F1ZXJ5VGFiLFxuICAgICAgICAgICAgaWNvbkNsYXNzOiByb3V0ZS5pY29uXG4gICAgICAgICAgfVxuICAgICAgICB9KVxuICAgICAgfSk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgLy8gaWYgdGhlIHJvdXRlcyBkYXRhIGlzIG5vdCBwcm92aWRlZCwgd2UgY3JlYXRlIHRoZSBjaGlsZHJlbiByb3V0ZXMgYmFzZWQgb24gdGhlIGZpcnN0IHF1ZXJ5J3MgdGFic1xuICAgICAgLy8gY3JlYXRlIHRoZSBjaGlsZHJlbiByb3V0ZXMgZm9yIHRoZSBzZWFyY2ggcm91dGVcbiAgICAgIGNoaWxkcmVuID0gZmlyc3RRdWVyeUNvbmZpZy50YWJzLm1hcCh0YWIgPT4gKHtcbiAgICAgICAgcGF0aDogdGFiLm5hbWUsXG4gICAgICAgIGNvbXBvbmVudDogdGhpcy5jb21wb25lbnRzLmZpbmQoYyA9PiBjLnBhdGggPT09IHRhYi5uYW1lKT8uY29tcG9uZW50IHx8IHRoaXMuZGVmYXVsdENvbXBvbmVudCgpLFxuICAgICAgICBkYXRhOiB7IHF1ZXJ5TmFtZTogZmlyc3RRdWVyeS5uYW1lLCBkaXNwbGF5OiB0YWIuZGlzcGxheSB8fCB0YWIubmFtZSB9XG4gICAgICB9KSk7XG4gICAgfVxuXG4gICAgY29uc3Qgc2VhcmNoUGF0aCA9IHRoaXMucm91dGVyLmNvbmZpZy5maW5kKHJvdXRlID0+IHJvdXRlLnBhdGggPT09ICdzZWFyY2gnKVxuICAgICAgfHwge1xuICAgICAgcGF0aDogJ3NlYXJjaCcsXG4gICAgICBjb21wb25lbnQ6IHRoaXMuY29tcG9uZW50cy5maW5kKGMgPT4gYy5wYXRoID09PSAnc2VhcmNoJyk/LmNvbXBvbmVudCB8fCB0aGlzLmRlZmF1bHRMYXlvdXRDb21wb25lbnQoKSxcbiAgICAgIGNhbkFjdGl2YXRlOiBbQXV0aEd1YXJkKCksIEluaXRpYWxpemF0aW9uR3VhcmQoKV0sXG4gICAgICBjaGlsZHJlbjogW11cbiAgICB9O1xuXG4gICAgc2VhcmNoUGF0aC5jb21wb25lbnQgPSB0aGlzLmNvbXBvbmVudHMuZmluZChjID0+IGMucGF0aCA9PT0gJ3NlYXJjaCcpPy5jb21wb25lbnQgfHwgdGhpcy5kZWZhdWx0TGF5b3V0Q29tcG9uZW50KCk7XG4gICAgc2VhcmNoUGF0aC5jaGlsZHJlbiA9IFsuLi5jaGlsZHJlbiwgeyBwYXRoOiAnKionLCByZWRpcmVjdFRvOiAnYWxsJywgcGF0aE1hdGNoOiAnZnVsbCcgfV07XG5cbiAgICBjb25zdCBuZXdDb25maWcgPSBbc2VhcmNoUGF0aCwgLi4uY3VycmVudENvbmZpZ107XG4gICAgLy8gZmluYWxseSB3ZSByZXNldCB0aGUgcm91dGVyIGNvbmZpZyB3aXRoIHRoZSBuZXcgcm91dGVzXG4gICAgdGhpcy5yb3V0ZXIucmVzZXRDb25maWcobmV3Q29uZmlnKTtcbiAgfVxufSJdfQ==
@@ -0,0 +1,85 @@
1
+ import { Injectable, Injector, inject, signal } from '@angular/core';
2
+ import { forkJoin, from, of } from 'rxjs';
3
+ import { getState } from '@ngrx/signals';
4
+ import { fetchSuggest } from '@sinequa/atomic';
5
+ import { UserSettingsStore } from '../stores/user-settings.store';
6
+ import { AppStore } from '../stores/app.store';
7
+ import * as i0 from "@angular/core";
8
+ export class AutocompleteService {
9
+ constructor() {
10
+ this.opened = signal(false);
11
+ this.injector = inject(Injector);
12
+ this.userSettingsStore = inject(UserSettingsStore);
13
+ this.appStore = inject(AppStore);
14
+ }
15
+ /**
16
+ * Retrieves autocomplete items for the given text, max count for each
17
+ * category handled by the service can be specified in the admin
18
+ *
19
+ * @param text Text to retrieve autocomplete items for
20
+ * @returns An observable of an array of {@link Suggestion} arrays grouped by
21
+ * suggestion queries configured in the admin
22
+ */
23
+ getFromSuggestQueriesForText(text) {
24
+ // Do not ask for autocomplete items if the text is empty
25
+ if (!text)
26
+ return of([]);
27
+ const queries = this.appStore.getWebServiceByType('autocomplete')?.suggestQueries?.split(',') ?? [];
28
+ const obss = queries.reduce((acc, curr) => {
29
+ acc.push(from(fetchSuggest(curr, text)));
30
+ return acc;
31
+ }, []);
32
+ return forkJoin(obss);
33
+ }
34
+ /**
35
+ * Retrieves autocomplete items for the given text from the user settings
36
+ *
37
+ * @param text Text to retrieve autocomplete items for
38
+ * @param maxCount Maximum number of items to retrieve
39
+ * @returns An observable of an array of {@link Suggestion} arrays grouped by
40
+ * `recent-searches`, `saved-searches`, `bookmarks` from the user settings
41
+ */
42
+ getFromUserSettingsForText(text, maxCount) {
43
+ const { bookmarks, recentSearches, savedSearches } = getState(this.userSettingsStore);
44
+ const items = [];
45
+ if (typeof maxCount === 'number')
46
+ maxCount = { recentSearches: maxCount, savedSearches: maxCount, bookmarks: maxCount };
47
+ if (recentSearches) {
48
+ // don't filter if the text is empty
49
+ const matchingRecentSearches = text
50
+ ? recentSearches.filter(recentSearch => recentSearch.display?.toLocaleLowerCase().includes(text.toLocaleLowerCase()))
51
+ : recentSearches;
52
+ const searches = matchingRecentSearches.slice(0, maxCount?.recentSearches);
53
+ if (searches.length > 0)
54
+ items.push(...searches.map(search => ({ category: 'recent-search', ...search })));
55
+ }
56
+ if (savedSearches) {
57
+ // don't filter if the text is empty
58
+ const matchingSavedSearches = text
59
+ ? savedSearches.filter(savedSearch => savedSearch.display?.toLocaleLowerCase().includes(text.toLocaleLowerCase()))
60
+ : savedSearches;
61
+ const searches = matchingSavedSearches.slice(0, maxCount?.savedSearches);
62
+ if (searches.length > 0)
63
+ items.push(...searches.map(search => ({ category: 'saved-search', ...search })));
64
+ }
65
+ if (bookmarks) {
66
+ // don't filter if the text is empty
67
+ const matchingBookmarks = text
68
+ ? bookmarks.filter(bookmark => bookmark.label?.toLowerCase().includes(text.toLowerCase()))
69
+ : bookmarks;
70
+ const searches = matchingBookmarks.slice(0, maxCount?.bookmarks);
71
+ if (searches.length > 0)
72
+ items.push(...searches.map(search => ({ category: 'bookmark', display: search.label ?? '', ...search })));
73
+ }
74
+ return items;
75
+ }
76
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: AutocompleteService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
77
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: AutocompleteService, providedIn: 'root' }); }
78
+ }
79
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: AutocompleteService, decorators: [{
80
+ type: Injectable,
81
+ args: [{
82
+ providedIn: 'root'
83
+ }]
84
+ }] });
85
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXV0b2NvbXBsZXRlLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9hdG9taWMtYW5ndWxhci9zcmMvbGliL3NlcnZpY2VzL2F1dG9jb21wbGV0ZS5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsUUFBUSxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDckUsT0FBTyxFQUFjLFFBQVEsRUFBRSxJQUFJLEVBQUUsRUFBRSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQ3RELE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFFekMsT0FBTyxFQUE0QixZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUV6RSxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQztBQUNsRSxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0scUJBQXFCLENBQUM7O0FBYy9DLE1BQU0sT0FBTyxtQkFBbUI7SUFIaEM7UUFJVyxXQUFNLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBRXZCLGFBQVEsR0FBRyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUE7UUFFcEMsc0JBQWlCLEdBQUcsTUFBTSxDQUFDLGlCQUFpQixDQUFDLENBQUM7UUFDOUMsYUFBUSxHQUFHLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQztLQStFN0I7SUE3RUM7Ozs7Ozs7T0FPRztJQUNILDRCQUE0QixDQUFDLElBQVk7UUFDdkMseURBQXlEO1FBQ3pELElBQUksQ0FBQyxJQUFJO1lBQUUsT0FBTyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7UUFFekIsTUFBTSxPQUFPLEdBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxtQkFBbUIsQ0FBQyxjQUFjLENBQTRCLEVBQUUsY0FBYyxFQUFFLEtBQUssQ0FBQyxHQUFHLENBQUMsSUFBSSxF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QyxFQUFFLFFBQVEsRUFBRSxTQUFTLENBQUMsQ0FBQztZQUVqRSxJQUFJLFFBQVEsQ0FBQyxNQUFNLEdBQUcsQ0FBQztnQkFDckIsS0FBSyxDQUFDLElBQUksQ0FBQyxHQUFHLFFBQVEsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsUUFBUSxFQUFFLFVBQVUsRUFBRSxPQUFPLEVBQUUsTUFBTSxDQUFDLEtBQUssSUFBSSxFQUFFLEVBQUUsR0FBRyxNQUFNLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUM5RyxDQUFDO1FBRUQsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDOzhHQXBGVSxtQkFBbUI7a0hBQW5CLG1CQUFtQixjQUZsQixNQUFNOzsyRkFFUCxtQkFBbUI7a0JBSC9CLFVBQVU7bUJBQUM7b0JBQ1YsVUFBVSxFQUFFLE1BQU07aUJBQ25CIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSwgSW5qZWN0b3IsIGluamVjdCwgc2lnbmFsIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBPYnNlcnZhYmxlLCBmb3JrSm9pbiwgZnJvbSwgb2YgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IGdldFN0YXRlIH0gZnJvbSAnQG5ncngvc2lnbmFscyc7XG5cbmltcG9ydCB7IENDV2ViU2VydmljZSwgU3VnZ2VzdGlvbiwgZmV0Y2hTdWdnZXN0IH0gZnJvbSAnQHNpbmVxdWEvYXRvbWljJztcblxuaW1wb3J0IHsgVXNlclNldHRpbmdzU3RvcmUgfSBmcm9tICcuLi9zdG9yZXMvdXNlci1zZXR0aW5ncy5zdG9yZSc7XG5pbXBvcnQgeyBBcHBTdG9yZSB9IGZyb20gJy4uL3N0b3Jlcy9hcHAuc3RvcmUnO1xuaW1wb3J0IHsgQXV0b2NvbXBsZXRlIH0gZnJvbSAnLi4vbW9kZWxzL2F1dG9jb21wbGV0ZSc7XG5cblxudHlwZSBBdXRvY29tcGxldGVXZWJTZXJ2aWNlID0gQ0NXZWJTZXJ2aWNlICYge1xuICBhbGxvd2VkV2l0aEFueVNCQT86IGJvb2xlYW4sXG4gIHJldmlzaW9uPzogbnVtYmVyLFxuICBzdWdnZXN0UXVlcmllcz86IHN0cmluZyxcbiAgdXNlRGlzdHJpYnV0aW9uUmVnZXg/OiBib29sZWFuLFxufVxuXG5ASW5qZWN0YWJsZSh7XG4gIHByb3ZpZGVkSW46ICdyb290J1xufSlcbmV4cG9ydCBjbGFzcyBBdXRvY29tcGxldGVTZXJ2aWNlIHtcbiAgcmVhZG9ubHkgb3BlbmVkID0gc2lnbmFsKGZhbHNlKTtcblxuICByZWFkb25seSBpbmplY3RvciA9IGluamVjdChJbmplY3RvcilcblxuICB1c2VyU2V0dGluZ3NTdG9yZSA9IGluamVjdChVc2VyU2V0dGluZ3NTdG9yZSk7XG4gIGFwcFN0b3JlID0gaW5qZWN0KEFwcFN0b3JlKTtcblxuICAvKipcbiAgICogUmV0cmlldmVzIGF1dG9jb21wbGV0ZSBpdGVtcyBmb3IgdGhlIGdpdmVuIHRleHQsIG1heCBjb3VudCBmb3IgZWFjaFxuICAgKiBjYXRlZ29yeSBoYW5kbGVkIGJ5IHRoZSBzZXJ2aWNlIGNhbiBiZSBzcGVjaWZpZWQgaW4gdGhlIGFkbWluXG4gICAqXG4gICAqIEBwYXJhbSB0ZXh0IFRleHQgdG8gcmV0cmlldmUgYXV0b2NvbXBsZXRlIGl0ZW1zIGZvclxuICAgKiBAcmV0dXJucyBBbiBvYnNlcnZhYmxlIG9mIGFuIGFycmF5IG9mIHtAbGluayBTdWdnZXN0aW9ufSBhcnJheXMgZ3JvdXBlZCBieVxuICAgKiBzdWdnZXN0aW9uIHF1ZXJpZXMgY29uZmlndXJlZCBpbiB0aGUgYWRtaW5cbiAgICovXG4gIGdldEZyb21TdWdnZXN0UXVlcmllc0ZvclRleHQodGV4dDogc3RyaW5nKTogT2JzZXJ2YWJsZTxTdWdnZXN0aW9uW11bXT4ge1xuICAgIC8vIERvIG5vdCBhc2sgZm9yIGF1dG9jb21wbGV0ZSBpdGVtcyBpZiB0aGUgdGV4dCBpcyBlbXB0eVxuICAgIGlmICghdGV4dCkgcmV0dXJuIG9mKFtdKTtcblxuICAgIGNvbnN0IHF1ZXJpZXMgPSAodGhpcy5hcHBTdG9yZS5nZXRXZWJTZXJ2aWNlQnlUeXBlKCdhdXRvY29tcGxldGUnKSBhcyBBdXRvY29tcGxldGVXZWJTZXJ2aWNlKT8uc3VnZ2VzdFF1ZXJpZXM/LnNwbGl0KCcsJykgPz8gW107XG4gICAgY29uc3Qgb2JzcyA9IHF1ZXJpZXMucmVkdWNlKChhY2M6IE9ic2VydmFibGU8U3VnZ2VzdGlvbltdPltdLCBjdXJyOiBzdHJpbmcpID0+IHtcbiAgICAgIGFjYy5wdXNoKGZyb20oZmV0Y2hTdWdnZXN0KGN1cnIsIHRleHQpKSk7XG4gICAgICByZXR1cm4gYWNjO1xuICAgIH0sIFtdIGFzIE9ic2VydmFibGU8U3VnZ2VzdGlvbltdPltdKTtcblxuICAgIHJldHVybiBmb3JrSm9pbjxTdWdnZXN0aW9uW11bXT4ob2Jzcyk7XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldmVzIGF1dG9jb21wbGV0ZSBpdGVtcyBmb3IgdGhlIGdpdmVuIHRleHQgZnJvbSB0aGUgdXNlciBzZXR0aW5nc1xuICAgKlxuICAgKiBAcGFyYW0gdGV4dCBUZXh0IHRvIHJldHJpZXZlIGF1dG9jb21wbGV0ZSBpdGVtcyBmb3JcbiAgICogQHBhcmFtIG1heENvdW50IE1heGltdW0gbnVtYmVyIG9mIGl0ZW1zIHRvIHJldHJpZXZlXG4gICAqIEByZXR1cm5zIEFuIG9ic2VydmFibGUgb2YgYW4gYXJyYXkgb2Yge0BsaW5rIFN1Z2dlc3Rpb259IGFycmF5cyBncm91cGVkIGJ5XG4gICAqIGByZWNlbnQtc2VhcmNoZXNgLCBgc2F2ZWQtc2VhcmNoZXNgLCBgYm9va21hcmtzYCBmcm9tIHRoZSB1c2VyIHNldHRpbmdzXG4gICAqL1xuICBnZXRGcm9tVXNlclNldHRpbmdzRm9yVGV4dCh0ZXh0OiBzdHJpbmcsIG1heENvdW50PzogbnVtYmVyIHwgQXV0b2NvbXBsZXRlKTogU3VnZ2VzdGlvbltdIHtcbiAgICBjb25zdCB7IGJvb2ttYXJrcywgcmVjZW50U2VhcmNoZXMsIHNhdmVkU2VhcmNoZXMgfSA9IGdldFN0YXRlKHRoaXMudXNlclNldHRpbmdzU3RvcmUpO1xuICAgIGNvbnN0IGl0ZW1zOiBTdWdnZXN0aW9uW10gPSBbXTtcblxuICAgIGlmICh0eXBlb2YgbWF4Q291bnQgPT09ICdudW1iZXInKVxuICAgICAgbWF4Q291bnQgPSB7IHJlY2VudFNlYXJjaGVzOiBtYXhDb3VudCwgc2F2ZWRTZWFyY2hlczogbWF4Q291bnQsIGJvb2ttYXJrczogbWF4Q291bnQgfTtcblxuICAgIGlmIChyZWNlbnRTZWFyY2hlcykge1xuXG4gICAgICAvLyBkb24ndCBmaWx0ZXIgaWYgdGhlIHRleHQgaXMgZW1wdHlcbiAgICAgIGNvbnN0IG1hdGNoaW5nUmVjZW50U2VhcmNoZXMgPSB0ZXh0XG4gICAgICAgID8gcmVjZW50U2VhcmNoZXMuZmlsdGVyKHJlY2VudFNlYXJjaCA9PiByZWNlbnRTZWFyY2guZGlzcGxheT8udG9Mb2NhbGVMb3dlckNhc2UoKS5pbmNsdWRlcyh0ZXh0LnRvTG9jYWxlTG93ZXJDYXNlKCkpKVxuICAgICAgICA6IHJlY2VudFNlYXJjaGVzO1xuXG4gICAgICBjb25zdCBzZWFyY2hlcyA9IG1hdGNoaW5nUmVjZW50U2VhcmNoZXMuc2xpY2UoMCwgbWF4Q291bnQ/LnJlY2VudFNlYXJjaGVzKTtcblxuICAgICAgaWYgKHNlYXJjaGVzLmxlbmd0aCA+IDApXG4gICAgICAgIGl0ZW1zLnB1c2goLi4uc2VhcmNoZXMubWFwKHNlYXJjaCA9PiAoeyBjYXRlZ29yeTogJ3JlY2VudC1zZWFyY2gnLCAuLi5zZWFyY2ggfSkpKTtcbiAgICB9XG5cbiAgICBpZiAoc2F2ZWRTZWFyY2hlcykge1xuXG4gICAgICAvLyBkb24ndCBmaWx0ZXIgaWYgdGhlIHRleHQgaXMgZW1wdHlcbiAgICAgIGNvbnN0IG1hdGNoaW5nU2F2ZWRTZWFyY2hlcyA9IHRleHRcbiAgICAgICAgPyBzYXZlZFNlYXJjaGVzLmZpbHRlcihzYXZlZFNlYXJjaCA9PiBzYXZlZFNlYXJjaC5kaXNwbGF5Py50b0xvY2FsZUxvd2VyQ2FzZSgpLmluY2x1ZGVzKHRleHQudG9Mb2NhbGVMb3dlckNhc2UoKSkpXG4gICAgICAgIDogc2F2ZWRTZWFyY2hlcztcblxuICAgICAgY29uc3Qgc2VhcmNoZXMgPSBtYXRjaGluZ1NhdmVkU2VhcmNoZXMuc2xpY2UoMCwgbWF4Q291bnQ/LnNhdmVkU2VhcmNoZXMpO1xuXG4gICAgICBpZiAoc2VhcmNoZXMubGVuZ3RoID4gMClcbiAgICAgICAgaXRlbXMucHVzaCguLi5zZWFyY2hlcy5tYXAoc2VhcmNoID0+ICh7IGNhdGVnb3J5OiAnc2F2ZWQtc2VhcmNoJywgLi4uc2VhcmNoIH0pKSk7XG4gICAgfVxuXG4gICAgaWYgKGJvb2ttYXJrcykge1xuXG4gICAgICAvLyBkb24ndCBmaWx0ZXIgaWYgdGhlIHRleHQgaXMgZW1wdHlcbiAgICAgIGNvbnN0IG1hdGNoaW5nQm9va21hcmtzID0gdGV4dFxuICAgICAgICA/IGJvb2ttYXJrcy5maWx0ZXIoYm9va21hcmsgPT4gYm9va21hcmsubGFiZWw/LnRvTG93ZXJDYXNlKCkuaW5jbHVkZXModGV4dC50b0xvd2VyQ2FzZSgpKSlcbiAgICAgICAgOiBib29rbWFya3M7XG5cbiAgICAgIGNvbnN0IHNlYXJjaGVzID0gbWF0Y2hpbmdCb29rbWFya3Muc2xpY2UoMCwgbWF4Q291bnQ/LmJvb2ttYXJrcyk7XG5cbiAgICAgIGlmIChzZWFyY2hlcy5sZW5ndGggPiAwKVxuICAgICAgICBpdGVtcy5wdXNoKC4uLnNlYXJjaGVzLm1hcChzZWFyY2ggPT4gKHsgY2F0ZWdvcnk6ICdib29rbWFyaycsIGRpc3BsYXk6IHNlYXJjaC5sYWJlbCA/PyAnJywgLi4uc2VhcmNoIH0pKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGl0ZW1zO1xuICB9XG59XG4iXX0=
@@ -0,0 +1,23 @@
1
+ import { Injectable } from '@angular/core';
2
+ import { BehaviorSubject } from 'rxjs';
3
+ import * as i0 from "@angular/core";
4
+ export class BackdropService {
5
+ constructor() {
6
+ this.isVisible = new BehaviorSubject(false);
7
+ }
8
+ show() {
9
+ this.isVisible.next(true);
10
+ }
11
+ hide() {
12
+ this.isVisible.next(false);
13
+ }
14
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: BackdropService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
15
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: BackdropService, providedIn: 'root' }); }
16
+ }
17
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: BackdropService, decorators: [{
18
+ type: Injectable,
19
+ args: [{
20
+ providedIn: 'root'
21
+ }]
22
+ }] });
23
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFja2Ryb3Auc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2F0b21pYy1hbmd1bGFyL3NyYy9saWIvc2VydmljZXMvZHJhd2VyL2JhY2tkcm9wLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUMzQyxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sTUFBTSxDQUFDOztBQUt2QyxNQUFNLE9BQU8sZUFBZTtJQUg1QjtRQUlTLGNBQVMsR0FBRyxJQUFJLGVBQWUsQ0FBVSxLQUFLLENBQUMsQ0FBQztLQVN4RDtJQVBRLElBQUk7UUFDVCxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUM1QixDQUFDO0lBRU0sSUFBSTtRQUNULElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQzdCLENBQUM7OEdBVFUsZUFBZTtrSEFBZixlQUFlLGNBRmQsTUFBTTs7MkZBRVAsZUFBZTtrQkFIM0IsVUFBVTttQkFBQztvQkFDVixVQUFVLEVBQUUsTUFBTTtpQkFDbkIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3RhYmxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBCZWhhdmlvclN1YmplY3QgfSBmcm9tICdyeGpzJztcblxuQEluamVjdGFibGUoe1xuICBwcm92aWRlZEluOiAncm9vdCdcbn0pXG5leHBvcnQgY2xhc3MgQmFja2Ryb3BTZXJ2aWNlIHtcbiAgcHVibGljIGlzVmlzaWJsZSA9IG5ldyBCZWhhdmlvclN1YmplY3Q8Ym9vbGVhbj4oZmFsc2UpO1xuXG4gIHB1YmxpYyBzaG93KCk6IHZvaWQge1xuICAgIHRoaXMuaXNWaXNpYmxlLm5leHQodHJ1ZSk7XG4gIH1cblxuICBwdWJsaWMgaGlkZSgpOiB2b2lkIHtcbiAgICB0aGlzLmlzVmlzaWJsZS5uZXh0KGZhbHNlKTtcbiAgfVxufVxuIl19
@@ -0,0 +1,152 @@
1
+ import { EventEmitter, Injectable, inject } from '@angular/core';
2
+ import { BehaviorSubject, Subscription } from 'rxjs';
3
+ import { getState } from '@ngrx/signals';
4
+ import { SelectionHistoryService } from '../selection-history.service';
5
+ import { SelectionService } from '../selection.service';
6
+ import { NavigationService } from '../navigation.service';
7
+ import { SelectionStore } from '../../stores/selection.store';
8
+ import { BackdropService } from './backdrop.service';
9
+ import * as i0 from "@angular/core";
10
+ export class DrawerStackService {
11
+ constructor() {
12
+ this.isOpened = new BehaviorSubject(false);
13
+ this.toggleTopDrawerExtension$ = new EventEmitter();
14
+ this.forceTopDrawerCollapse$ = new EventEmitter();
15
+ this.closeTopDrawer$ = new EventEmitter();
16
+ this.closeAllDrawers$ = new EventEmitter();
17
+ this.isChatOpened = new BehaviorSubject(false);
18
+ this.openChatDrawer$ = new EventEmitter();
19
+ this.closeChatDrawer$ = new EventEmitter();
20
+ this.askAI$ = new EventEmitter();
21
+ this.selection = inject(SelectionService);
22
+ this.selectionHistory = inject(SelectionHistoryService);
23
+ this.selectionStore = inject(SelectionStore);
24
+ this.navigationService = inject(NavigationService);
25
+ this.backdropService = inject(BackdropService);
26
+ this.subscriptions = new Subscription();
27
+ // on new search, close all drawers including chat drawer
28
+ this.subscriptions.add(this.navigationService.navigationEnd$.subscribe(() => {
29
+ this.closeAssistant();
30
+ this.closeAll();
31
+ }));
32
+ }
33
+ ngOnDestroy() {
34
+ this.subscriptions.unsubscribe();
35
+ }
36
+ /**
37
+ * Sets current drawer stack status to open
38
+ */
39
+ open(componentType) {
40
+ this.componentType = componentType;
41
+ this.isOpened.next(true);
42
+ }
43
+ /**
44
+ * Emits event to extend the top drawer
45
+ */
46
+ extend() {
47
+ this.toggleTopDrawerExtension$.next();
48
+ }
49
+ /**
50
+ * Emits event to close the top drawer, checks if history is empty, if so,
51
+ * sets current drawer stack status to closed and clears history and current
52
+ * selection
53
+ */
54
+ close() {
55
+ this.closeTopDrawer$.next();
56
+ if (this.selectionHistory.getCurrentSelectionIndex() === -1) {
57
+ this.isOpened.next(false);
58
+ this.selectionHistory.clearHistory();
59
+ }
60
+ }
61
+ /**
62
+ * Emits event to close the top drawer
63
+ */
64
+ closeTop() {
65
+ this.closeTopDrawer$.next();
66
+ }
67
+ /**
68
+ * Sets current drawer stack status to closed, clears history and emits event
69
+ * to close all drawers
70
+ *
71
+ * @param keepDrawerOpen if true, do not trigger layout animation
72
+ */
73
+ closeAll(keepDrawerOpen = false) {
74
+ if (!keepDrawerOpen)
75
+ this.isOpened.next(false);
76
+ this.selectionHistory.clearHistory();
77
+ this.closeAllDrawers$.next();
78
+ }
79
+ /**
80
+ * Replace the current selection with the given article by closing all
81
+ * drawers and opening the drawer with the new selection without triggering
82
+ * layout animation
83
+ *
84
+ * @param article the article to replace the current selection with
85
+ */
86
+ replace(article) {
87
+ const { id } = getState(this.selectionStore);
88
+ if (id && (!article || article.id === id))
89
+ return;
90
+ // close everything without trigger layout animation
91
+ this.closeAll(true);
92
+ // set selection
93
+ this.selection.setCurrentArticle(article);
94
+ // open drawer
95
+ this.open();
96
+ }
97
+ /**
98
+ * Stack the given article by setting the current selection and opening the
99
+ * drawer
100
+ *
101
+ * @param article the article to stack
102
+ */
103
+ stack(article, withQueryText) {
104
+ const { id } = getState(this.selectionStore);
105
+ if (id && (!article || article.id === id))
106
+ return;
107
+ // force top drawer to collapse
108
+ this.forceTopDrawerCollapse$.next();
109
+ // set selection
110
+ this.selection.setCurrentArticle(article, withQueryText);
111
+ // open drawer
112
+ this.open();
113
+ }
114
+ toggleAssistant() {
115
+ if (this.isChatOpened.getValue()) {
116
+ this.backdropService.hide();
117
+ this.closeAssistant();
118
+ }
119
+ else {
120
+ this.backdropService.show();
121
+ this.openAssistant();
122
+ }
123
+ }
124
+ openAssistant() {
125
+ this.isChatOpened.next(true);
126
+ this.isOpened.next(true);
127
+ this.openChatDrawer$.next();
128
+ this.backdropService.show();
129
+ }
130
+ closeAssistant(keepDrawerOpen = false) {
131
+ this.isChatOpened.next(false);
132
+ if (!keepDrawerOpen && this.selectionHistory.getCurrentSelectionIndex() === -1) {
133
+ this.isOpened.next(false);
134
+ this.closeAllDrawers$.next();
135
+ }
136
+ this.closeChatDrawer$.next();
137
+ this.backdropService.hide();
138
+ }
139
+ askAI(text) {
140
+ this.openAssistant();
141
+ this.askAI$.next(text);
142
+ }
143
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: DrawerStackService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
144
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: DrawerStackService, providedIn: 'root' }); }
145
+ }
146
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.5", ngImport: i0, type: DrawerStackService, decorators: [{
147
+ type: Injectable,
148
+ args: [{
149
+ providedIn: 'root'
150
+ }]
151
+ }], ctorParameters: () => [] });
152
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZHJhd2VyLXN0YWNrLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9hdG9taWMtYW5ndWxhci9zcmMvbGliL3NlcnZpY2VzL2RyYXdlci9kcmF3ZXItc3RhY2suc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsWUFBWSxFQUFFLFVBQVUsRUFBbUIsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ2xGLE9BQU8sRUFBRSxlQUFlLEVBQUUsWUFBWSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQ3JELE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFJekMsT0FBTyxFQUFFLHVCQUF1QixFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFDdkUsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDeEQsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDMUQsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLDhCQUE4QixDQUFDO0FBQzlELE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQzs7QUFNckQsTUFBTSxPQUFPLGtCQUFrQjtJQXNCN0I7UUFyQmdCLGFBQVEsR0FBRyxJQUFJLGVBQWUsQ0FBVSxLQUFLLENBQUMsQ0FBQztRQUMvQyw4QkFBeUIsR0FBRyxJQUFJLFlBQVksRUFBUSxDQUFDO1FBQ3JELDRCQUF1QixHQUFHLElBQUksWUFBWSxFQUFRLENBQUM7UUFDbkQsb0JBQWUsR0FBRyxJQUFJLFlBQVksRUFBUSxDQUFDO1FBQzNDLHFCQUFnQixHQUFHLElBQUksWUFBWSxFQUFRLENBQUM7UUFFNUMsaUJBQVksR0FBRyxJQUFJLGVBQWUsQ0FBVSxLQUFLLENBQUMsQ0FBQztRQUNuRCxvQkFBZSxHQUFHLElBQUksWUFBWSxFQUFRLENBQUM7UUFDM0MscUJBQWdCLEdBQUcsSUFBSSxZ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QUFJLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDL0IsQ0FBQztRQUVELElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUM3QixJQUFJLENBQUMsZUFBZSxDQUFDLElBQUksRUFBRSxDQUFDO0lBQzlCLENBQUM7SUFFTSxLQUFLLENBQUMsSUFBWTtRQUN2QixJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7UUFDckIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDekIsQ0FBQzs4R0EvSlUsa0JBQWtCO2tIQUFsQixrQkFBa0IsY0FGakIsTUFBTTs7MkZBRVAsa0JBQWtCO2tCQUg5QixVQUFVO21CQUFDO29CQUNWLFVBQVUsRUFBRSxNQUFNO2lCQUNuQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEV2ZW50RW1pdHRlciwgSW5qZWN0YWJsZSwgT25EZXN0cm95LCBUeXBlLCBpbmplY3QgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEJlaGF2aW9yU3ViamVjdCwgU3Vic2NyaXB0aW9uIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBnZXRTdGF0ZSB9IGZyb20gJ0BuZ3J4L3NpZ25hbHMnO1xuXG5pbXBvcnQgeyBBcnRpY2xlIH0gZnJvbSAnQHNpbmVxdWEvYXRvbWljJztcblxuaW1wb3J0IHsgU2VsZWN0aW9uSGlzdG9yeVNlcnZpY2UgfSBmcm9tICcuLi9zZWxlY3Rpb24taGlzdG9yeS5zZXJ2aWNlJztcbmltcG9ydCB7IFNlbGVjdGlvblNlcnZpY2UgfSBmcm9tICcuLi9zZWxlY3Rpb24uc2VydmljZSc7XG5pbXBvcnQgeyBOYXZpZ2F0aW9uU2VydmljZSB9IGZyb20gJy4uL25hdmlnYXRpb24uc2VydmljZSc7XG5pbXBvcnQgeyBTZWxlY3Rpb25TdG9yZSB9IGZyb20gJy4uLy4uL3N0b3Jlcy9zZWxlY3Rpb24uc3RvcmUnO1xuaW1wb3J0IHsgQmFja2Ryb3BTZXJ2aWNlIH0gZnJvbSAnLi9iYWNrZHJvcC5zZXJ2aWNlJztcblxuXG5ASW5qZWN0YWJsZSh7XG4gIHByb3ZpZGVkSW46ICdyb290J1xufSlcbmV4cG9ydCBjbGFzcyBEcmF3ZXJTdGFja1NlcnZpY2UgaW1wbGVtZW50cyBPbkRlc3Ryb3kge1xuICBwdWJsaWMgcmVhZG9ubHkgaXNPcGVuZWQgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PGJvb2xlYW4+KGZhbHNlKTtcbiAgcHVibGljIHJlYWRvbmx5IHRvZ2dsZVRvcERyYXdlckV4dGVuc2lvbiQgPSBuZXcgRXZlbnRFbWl0dGVyPHZvaWQ+KCk7XG4gIHB1YmxpYyByZWFkb25seSBmb3JjZVRvcERyYXdlckNvbGxhcHNlJCA9IG5ldyBFdmVudEVtaXR0ZXI8dm9pZD4oKTtcbiAgcHVibGljIHJlYWRvbmx5IGNsb3NlVG9wRHJhd2VyJCA9IG5ldyBFdmVudEVtaXR0ZXI8dm9pZD4oKTtcbiAgcHVibGljIHJlYWRvbmx5IGNsb3NlQWxsRHJhd2VycyQgPSBuZXcgRXZlbnRFbWl0dGVyPHZvaWQ+KCk7XG5cbiAgcHVibGljIHJlYWRvbmx5IGlzQ2hhdE9wZW5lZCA9IG5ldyBCZWhhdmlvclN1YmplY3Q8Ym9vbGVhbj4oZmFsc2UpO1xuICBwdWJsaWMgcmVhZG9ubHkgb3BlbkNoYXREcmF3ZXIkID0gbmV3IEV2ZW50RW1pdHRlcjx2b2lkPigpO1xuICBwdWJsaWMgcmVhZG9ubHkgY2xvc2VDaGF0RHJhd2VyJCA9IG5ldyBFdmVudEVtaXR0ZXI8dm9pZD4oKTtcbiAgcHVibGljIHJlYWRvbmx5IGFza0FJJCA9IG5ldyBFdmVudEVtaXR0ZXI8c3RyaW5nPigpO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgc2VsZWN0aW9uID0gaW5qZWN0KFNlbGVjdGlvblNlcnZpY2UpO1xuICBwcml2YXRlIHJlYWRvbmx5IHNlbGVjdGlvbkhpc3RvcnkgPSBpbmplY3QoU2VsZWN0aW9uSGlzdG9yeVNlcnZpY2UpO1xuICBwcml2YXRlIHJlYWRvbmx5IHNlbGVjdGlvblN0b3JlID0gaW5qZWN0KFNlbGVjdGlvblN0b3JlKTtcbiAgcHJpdmF0ZSByZWFkb25seSBuYXZpZ2F0aW9uU2VydmljZSA9IGluamVjdChOYXZpZ2F0aW9uU2VydmljZSk7XG4gIHByaXZhdGUgcmVhZG9ubHkgYmFja2Ryb3BTZXJ2aWNlID0gaW5qZWN0KEJhY2tkcm9wU2VydmljZSk7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBzdWJzY3JpcHRpb25zID0gbmV3IFN1YnNjcmlwdGlvbigpO1xuXG4gIHB1YmxpYyBjb21wb25lbnRUeXBlPzogVHlwZTxhbnk+O1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIC8vIG9uIG5ldyBzZWFyY2gsIGNsb3NlIGFsbCBkcmF3ZXJzIGluY2x1ZGluZyBjaGF0IGRyYXdlclxuICAgIHRoaXMuc3Vic2NyaXB0aW9ucy5hZGQoXG4gICAgICB0aGlzLm5hdmlnYXRpb25TZXJ2aWNlLm5hdmlnYXRpb25FbmQkLnN1YnNjcmliZSgoKSA9PiB7XG4gICAgICAgIHRoaXMuY2xvc2VBc3Npc3RhbnQoKTtcbiAgICAgICAgdGhpcy5jbG9zZUFsbCgpO1xuICAgICAgfSlcbiAgICApO1xuICB9XG5cbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgdGhpcy5zdWJzY3JpcHRpb25zLnVuc3Vic2NyaWJlKCk7XG4gIH1cblxuICAvKipcbiAgICogU2V0cyBjdXJyZW50IGRyYXdlciBzdGFjayBzdGF0dXMgdG8gb3BlblxuICAgKi9cbiAgcHVibGljIG9wZW4oY29tcG9uZW50VHlwZT86IFR5cGU8YW55Pik6IHZvaWQge1xuICAgIHRoaXMuY29tcG9uZW50VHlwZSA9IGNvbXBvbmVudFR5cGU7XG4gICAgdGhpcy5pc09wZW5lZC5uZXh0KHRydWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIEVtaXRzIGV2ZW50IHRvIGV4dGVuZCB0aGUgdG9wIGRyYXdlclxuICAgKi9cbiAgcHVibGljIGV4dGVuZCgpOiB2b2lkIHtcbiAgICB0aGlzLnRvZ2dsZVRvcERyYXdlckV4dGVuc2lvbiQubmV4dCgpO1xuICB9XG5cbiAgLyoqXG4gICAqIEVtaXRzIGV2ZW50IHRvIGNsb3NlIHRoZSB0b3AgZHJhd2VyLCBjaGVja3MgaWYgaGlzdG9yeSBpcyBlbXB0eSwgaWYgc28sXG4gICAqIHNldHMgY3VycmVudCBkcmF3ZXIgc3RhY2sgc3RhdHVzIHRvIGNsb3NlZCBhbmQgY2xlYXJzIGhpc3RvcnkgYW5kIGN1cnJlbnRcbiAgICogc2VsZWN0aW9uXG4gICAqL1xuICBwdWJsaWMgY2xvc2UoKTogdm9pZCB7XG4gICAgdGhpcy5jbG9zZVRvcERyYXdlciQubmV4dCgpO1xuXG4gICAgaWYgKHRoaXMuc2VsZWN0aW9uSGlzdG9yeS5nZXRDdXJyZW50U2VsZWN0aW9uSW5kZXgoKSA9PT0gLTEpIHtcbiAgICAgIHRoaXMuaXNPcGVuZWQubmV4dChmYWxzZSk7XG4gICAgICB0aGlzLnNlbGVjdGlvbkhpc3RvcnkuY2xlYXJIaXN0b3J5KCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEVtaXRzIGV2ZW50IHRvIGNsb3NlIHRoZSB0b3AgZHJhd2VyXG4gICAqL1xuICBwdWJsaWMgY2xvc2VUb3AoKTogdm9pZCB7XG4gICAgdGhpcy5jbG9zZVRvcERyYXdlciQubmV4dCgpO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgY3VycmVudCBkcmF3ZXIgc3RhY2sgc3RhdHVzIHRvIGNsb3NlZCwgY2xlYXJzIGhpc3RvcnkgYW5kIGVtaXRzIGV2ZW50XG4gICAqIHRvIGNsb3NlIGFsbCBkcmF3ZXJzXG4gICAqXG4gICAqIEBwYXJhbSBrZWVwRHJhd2VyT3BlbiBpZiB0cnVlLCBkbyBub3QgdHJpZ2dlciBsYXlvdXQgYW5pbWF0aW9uXG4gICAqL1xuICBwdWJsaWMgY2xvc2VBbGwoa2VlcERyYXdlck9wZW46IGJvb2xlYW4gPSBmYWxzZSk6IHZvaWQge1xuICAgIGlmICgha2VlcERyYXdlck9wZW4pIHRoaXMuaXNPcGVuZWQubmV4dChmYWxzZSk7XG5cbiAgICB0aGlzLnNlbGVjdGlvbkhpc3RvcnkuY2xlYXJIaXN0b3J5KCk7XG5cbiAgICB0aGlzLmNsb3NlQWxsRHJhd2VycyQubmV4dCgpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlcGxhY2UgdGhlIGN1cnJlbnQgc2VsZWN0aW9uIHdpdGggdGhlIGdpdmVuIGFydGljbGUgYnkgY2xvc2luZyBhbGxcbiAgICogZHJhd2VycyBhbmQgb3BlbmluZyB0aGUgZHJhd2VyIHdpdGggdGhlIG5ldyBzZWxlY3Rpb24gd2l0aG91dCB0cmlnZ2VyaW5nXG4gICAqIGxheW91dCBhbmltYXRpb25cbiAgICpcbiAgICogQHBhcmFtIGFydGljbGUgdGhlIGFydGljbGUgdG8gcmVwbGFjZSB0aGUgY3VycmVudCBzZWxlY3Rpb24gd2l0aFxuICAgKi9cbiAgcHVibGljIHJlcGxhY2UoYXJ0aWNsZTogQXJ0aWNsZSB8IHVuZGVmaW5lZCk6IHZvaWQge1xuICAgIGNvbnN0IHsgaWQgfSA9IGdldFN0YXRlKHRoaXMuc2VsZWN0aW9uU3RvcmUpO1xuXG4gICAgaWYgKGlkICYmICghYXJ0aWNsZSB8fCBhcnRpY2xlLmlkID09PSBpZCkpIHJldHVybjtcblxuICAgIC8vIGNsb3NlIGV2ZXJ5dGhpbmcgd2l0aG91dCB0cmlnZ2VyIGxheW91dCBhbmltYXRpb25cbiAgICB0aGlzLmNsb3NlQWxsKHRydWUpO1xuXG4gICAgLy8gc2V0IHNlbGVjdGlvblxuICAgIHRoaXMuc2VsZWN0aW9uLnNldEN1cnJlbnRBcnRpY2xlKGFydGljbGUpO1xuICAgIC8vIG9wZW4gZHJhd2VyXG4gICAgdGhpcy5vcGVuKCk7XG4gIH1cblxuICAvKipcbiAgICogU3RhY2sgdGhlIGdpdmVuIGFydGljbGUgYnkgc2V0dGluZyB0aGUgY3VycmVudCBzZWxlY3Rpb24gYW5kIG9wZW5pbmcgdGhlXG4gICAqIGRyYXdlclxuICAgKlxuICAgKiBAcGFyYW0gYXJ0aWNsZSB0aGUgYXJ0aWNsZSB0byBzdGFja1xuICAgKi9cbiAgcHVibGljIHN0YWNrKGFydGljbGU6IEFydGljbGUgfCB1bmRlZmluZWQsIHdpdGhRdWVyeVRleHQ/OiBib29sZWFuKTogdm9pZCB7XG4gICAgY29uc3QgeyBpZCB9ID0gZ2V0U3RhdGUodGhpcy5zZWxlY3Rpb25TdG9yZSk7XG5cbiAgICBpZiAoaWQgJiYgKCFhcnRpY2xlIHx8IGFydGljbGUuaWQgPT09IGlkKSkgcmV0dXJuO1xuXG4gICAgLy8gZm9yY2UgdG9wIGRyYXdlciB0byBjb2xsYXBzZVxuICAgIHRoaXMuZm9yY2VUb3BEcmF3ZXJDb2xsYXBzZSQubmV4dCgpO1xuICAgIC8vIHNldCBzZWxlY3Rpb25cbiAgICB0aGlzLnNlbGVjdGlvbi5zZXRDdXJyZW50QXJ0aWNsZShhcnRpY2xlLCB3aXRoUXVlcnlUZXh0KTtcbiAgICAvLyBvcGVuIGRyYXdlclxuICAgIHRoaXMub3BlbigpO1xuICB9XG5cbiAgcHVibGljIHRvZ2dsZUFzc2lzdGFudCgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5pc0NoYXRPcGVuZWQuZ2V0VmFsdWUoKSkge1xuICAgICAgdGhpcy5iYWNrZHJvcFNlcnZpY2UuaGlkZSgpO1xuICAgICAgdGhpcy5jbG9zZUFzc2lzdGFudCgpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmJhY2tkcm9wU2VydmljZS5zaG93KCk7XG4gICAgICB0aGlzLm9wZW5Bc3Npc3RhbnQoKTtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgb3BlbkFzc2lzdGFudCgpOiB2b2lkIHtcbiAgICB0aGlzLmlzQ2hhdE9wZW5lZC5uZXh0KHRydWUpO1xuICAgIHRoaXMuaXNPcGVuZWQubmV4dCh0cnVlKTtcbiAgICB0aGlzLm9wZW5DaGF0RHJhd2VyJC5uZXh0KCk7XG5cbiAgICB0aGlzLmJhY2tkcm9wU2VydmljZS5zaG93KCk7XG4gIH1cblxuICBwdWJsaWMgY2xvc2VBc3Npc3RhbnQoa2VlcERyYXdlck9wZW46IGJvb2xlYW4gPSBmYWxzZSk6IHZvaWQge1xuICAgIHRoaXMuaXNDaGF0T3BlbmVkLm5leHQoZmFsc2UpO1xuXG4gICAgaWYgKCFrZWVwRHJhd2VyT3BlbiAmJiB0aGlzLnNlbGVjdGlvbkhpc3RvcnkuZ2V0Q3VycmVudFNlbGVjdGlvbkluZGV4KCkgPT09IC0xKSB7XG4gICAgICB0aGlzLmlzT3BlbmVkLm5leHQoZmFsc2UpO1xuICAgICAgdGhpcy5jbG9zZUFsbERyYXdlcnMkLm5leHQoKTtcbiAgICB9XG5cbiAgICB0aGlzLmNsb3NlQ2hhdERyYXdlciQubmV4dCgpO1xuICAgIHRoaXMuYmFja2Ryb3BTZXJ2aWNlLmhpZGUoKTtcbiAgfVxuXG4gIHB1YmxpYyBhc2tBSSh0ZXh0OiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0aGlzLm9wZW5Bc3Npc3RhbnQoKTtcbiAgICB0aGlzLmFza0FJJC5uZXh0KHRleHQpO1xuICB9XG59XG4iXX0=