@cleavelandprice/ngx-lib 3.1.9 → 3.1.11

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 (42) hide show
  1. package/active-directory/gui/components/user-chooser/user-chooser.component.d.ts +54 -0
  2. package/active-directory/gui/components/user-form-field/user-form-field.component.d.ts +27 -0
  3. package/active-directory/gui/gui.module.d.ts +20 -0
  4. package/active-directory/gui/index.d.ts +5 -0
  5. package/active-directory/gui/model/default-user-chooser-config.d.ts +2 -0
  6. package/active-directory/gui/model/default-user-chooser-filter-options-config.d.ts +2 -0
  7. package/active-directory/gui/model/default-user-chooser-pre-processing-group-config.d.ts +2 -0
  8. package/active-directory/gui/model/selectable-user.d.ts +5 -0
  9. package/active-directory/gui/model/user-chooser-data.d.ts +21 -0
  10. package/active-directory/gui/model/user-chooser-filter-options.d.ts +7 -0
  11. package/active-directory/gui/model/user-chooser-mode.d.ts +4 -0
  12. package/active-directory/gui/model/user-chooser-pre-processing-group.d.ts +6 -0
  13. package/active-directory/gui/public_api.d.ts +10 -0
  14. package/authentication/token/gui/token-gui.module.d.ts +6 -6
  15. package/esm2020/active-directory/active-directory.module.mjs +3 -2
  16. package/esm2020/active-directory/gui/cleavelandprice-ngx-lib-active-directory-gui.mjs +5 -0
  17. package/esm2020/active-directory/gui/components/user-chooser/user-chooser.component.mjs +352 -0
  18. package/esm2020/active-directory/gui/components/user-form-field/user-form-field.component.mjs +118 -0
  19. package/esm2020/active-directory/gui/gui.module.mjs +73 -0
  20. package/esm2020/active-directory/gui/model/default-user-chooser-config.mjs +18 -0
  21. package/esm2020/active-directory/gui/model/default-user-chooser-filter-options-config.mjs +8 -0
  22. package/esm2020/active-directory/gui/model/default-user-chooser-pre-processing-group-config.mjs +7 -0
  23. package/esm2020/active-directory/gui/model/selectable-user.mjs +2 -0
  24. package/esm2020/active-directory/gui/model/user-chooser-data.mjs +2 -0
  25. package/esm2020/active-directory/gui/model/user-chooser-filter-options.mjs +2 -0
  26. package/esm2020/active-directory/gui/model/user-chooser-mode.mjs +6 -0
  27. package/esm2020/active-directory/gui/model/user-chooser-pre-processing-group.mjs +2 -0
  28. package/esm2020/active-directory/gui/public_api.mjs +11 -0
  29. package/esm2020/authentication/token/gui/token-gui.module.mjs +9 -9
  30. package/fesm2015/cleavelandprice-ngx-lib-active-directory-gui.mjs +574 -0
  31. package/fesm2015/cleavelandprice-ngx-lib-active-directory-gui.mjs.map +1 -0
  32. package/fesm2015/cleavelandprice-ngx-lib-active-directory.mjs +2 -1
  33. package/fesm2015/cleavelandprice-ngx-lib-active-directory.mjs.map +1 -1
  34. package/fesm2015/cleavelandprice-ngx-lib-authentication-token-gui.mjs +9 -9
  35. package/fesm2015/cleavelandprice-ngx-lib-authentication-token-gui.mjs.map +1 -1
  36. package/fesm2020/cleavelandprice-ngx-lib-active-directory-gui.mjs +564 -0
  37. package/fesm2020/cleavelandprice-ngx-lib-active-directory-gui.mjs.map +1 -0
  38. package/fesm2020/cleavelandprice-ngx-lib-active-directory.mjs +2 -1
  39. package/fesm2020/cleavelandprice-ngx-lib-active-directory.mjs.map +1 -1
  40. package/fesm2020/cleavelandprice-ngx-lib-authentication-token-gui.mjs +9 -9
  41. package/fesm2020/cleavelandprice-ngx-lib-authentication-token-gui.mjs.map +1 -1
  42. package/package.json +9 -1
@@ -0,0 +1,574 @@
1
+ import * as i0 from '@angular/core';
2
+ import { Component, Inject, ViewChild, EventEmitter, Output, Input, NgModule } from '@angular/core';
3
+ import * as i5 from '@angular/forms';
4
+ import { FormGroup, FormControl, ReactiveFormsModule } from '@angular/forms';
5
+ import * as i1 from '@angular/material/dialog';
6
+ import { MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog';
7
+ import * as i10 from '@angular/material/list';
8
+ import { MatSelectionList, MatListModule } from '@angular/material/list';
9
+ import { MatTableDataSource, MatTableModule } from '@angular/material/table';
10
+ import { of, forkJoin, debounceTime } from 'rxjs';
11
+ import * as i2 from '@cleavelandprice/ngx-lib/active-directory';
12
+ import * as i3 from '@cleavelandprice/ngx-lib/sharepoint';
13
+ import * as i4 from '@angular/common';
14
+ import { CommonModule } from '@angular/common';
15
+ import * as i6 from '@angular/material/button';
16
+ import { MatButtonModule } from '@angular/material/button';
17
+ import * as i7 from '@angular/material/form-field';
18
+ import { MatFormFieldModule } from '@angular/material/form-field';
19
+ import * as i8 from '@angular/material/icon';
20
+ import { MatIconModule } from '@angular/material/icon';
21
+ import * as i9 from '@angular/material/input';
22
+ import { MatInputModule } from '@angular/material/input';
23
+ import * as i11 from '@angular/material/progress-spinner';
24
+ import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
25
+ import * as i12 from '@angular/material/slide-toggle';
26
+ import { MatSlideToggleModule } from '@angular/material/slide-toggle';
27
+ import * as i13 from '@angular/material/tooltip';
28
+ import { MatTooltipModule } from '@angular/material/tooltip';
29
+
30
+ const defaultUserChooserFilterOptionsConfig = {
31
+ accountName: true,
32
+ department: true,
33
+ groupMembership: false,
34
+ phoneNumber: true,
35
+ title: true
36
+ };
37
+
38
+ const defaultUserChooserPreProcessingGroupConfig = {
39
+ accountNames: [],
40
+ departments: [],
41
+ groups: [],
42
+ titles: []
43
+ };
44
+
45
+ var UserChooserMode;
46
+ (function (UserChooserMode) {
47
+ UserChooserMode[UserChooserMode["Single"] = 0] = "Single";
48
+ UserChooserMode[UserChooserMode["Multiple"] = 1] = "Multiple";
49
+ })(UserChooserMode || (UserChooserMode = {}));
50
+
51
+ const defaultUserChooserConfig = {
52
+ closeWhenSelectionMade: false,
53
+ includeDisabledUsers: false,
54
+ parentOu: undefined,
55
+ showGroupMembershipTooltips: false,
56
+ showPhone: true,
57
+ title: 'Select User(s)',
58
+ mode: UserChooserMode.Single,
59
+ returnUserObjects: false,
60
+ filterOptions: defaultUserChooserFilterOptionsConfig,
61
+ exclusions: defaultUserChooserPreProcessingGroupConfig,
62
+ inclusions: defaultUserChooserPreProcessingGroupConfig,
63
+ preSelections: defaultUserChooserPreProcessingGroupConfig
64
+ };
65
+
66
+ class UserChooserComponent {
67
+ //#endregion
68
+ //#region Lifecycle
69
+ constructor(data, dialogRef, activeDirectoryService, sharePointService) {
70
+ this.data = data;
71
+ this.dialogRef = dialogRef;
72
+ this.activeDirectoryService = activeDirectoryService;
73
+ this.sharePointService = sharePointService;
74
+ //#region Fields
75
+ this.selectionList = null;
76
+ this.filterForm = new FormGroup({
77
+ filter: new FormControl()
78
+ });
79
+ this.dataSource = null;
80
+ this.photos = null;
81
+ this.groups = null; // May or may not get populated, depending on config data sent in
82
+ this.data = Object.assign(Object.assign({}, defaultUserChooserConfig), data);
83
+ }
84
+ //#endregion
85
+ //#region Properties
86
+ get isMultiMode() {
87
+ return this.data.mode === UserChooserMode.Multiple;
88
+ }
89
+ get selectedOptions() {
90
+ var _a, _b;
91
+ return (_b = (_a = this.selectionList) === null || _a === void 0 ? void 0 : _a.options.filter(o => o.selected)) !== null && _b !== void 0 ? _b : [];
92
+ }
93
+ get filterValue() {
94
+ return this.filterForm.value.filter;
95
+ }
96
+ get adGroupsNeeded() {
97
+ // If any are these are true, then we need to pull AD groups for use later
98
+ return this.data.showGroupMembershipTooltips ||
99
+ this.data.exclusions.groups.length > 0 ||
100
+ this.data.inclusions.groups.length > 0 ||
101
+ this.data.preSelections.groups.length > 0 ||
102
+ this.data.filterOptions.groupMembership;
103
+ }
104
+ ngOnInit() {
105
+ this.getData();
106
+ this.listenForFilterChanges();
107
+ }
108
+ //#endregion
109
+ //#region Events
110
+ listSelectionChanged(options) {
111
+ if (this.data.mode === UserChooserMode.Single &&
112
+ this.selectedOptions.length &&
113
+ this.data.closeWhenSelectionMade) {
114
+ this.close();
115
+ }
116
+ }
117
+ optionSelectionChanged(option) {
118
+ var _a;
119
+ const user = (_a = this.dataSource) === null || _a === void 0 ? void 0 : _a.data.find(u => u.sAMAccountName.toLocaleLowerCase() === option.value.sAMAccountName.toLowerCase());
120
+ if (user) {
121
+ user.selected = option.selected;
122
+ }
123
+ }
124
+ hideUnselectedChanged(selected) {
125
+ var _a;
126
+ (_a = this.filterForm.get('filter')) === null || _a === void 0 ? void 0 : _a.setValue(selected ? '{selected:true}' : null);
127
+ }
128
+ selectAll() {
129
+ var _a, _b, _c;
130
+ (_a = this.selectionList) === null || _a === void 0 ? void 0 : _a.selectAll();
131
+ if ((_b = this.selectionList) === null || _b === void 0 ? void 0 : _b.options) {
132
+ this.listSelectionChanged((_c = this.selectionList) === null || _c === void 0 ? void 0 : _c.options.toArray());
133
+ }
134
+ }
135
+ deselectAll() {
136
+ var _a;
137
+ (_a = this.selectionList) === null || _a === void 0 ? void 0 : _a.deselectAll();
138
+ }
139
+ //#endregion
140
+ //#region Utilities
141
+ getData() {
142
+ const dataObservables = [
143
+ this.data.users ?
144
+ // Users were passed in
145
+ of(this.data.users) :
146
+ // Users need to be retrieved
147
+ this.activeDirectoryService.getUsers(false, this.data.includeDisabledUsers, this.data.parentOu),
148
+ this.data.photos ?
149
+ // Photos were passed in
150
+ of(this.data.photos) :
151
+ // Photos need to be retrieved
152
+ this.sharePointService.getPhotos()
153
+ ];
154
+ // Do we need AD groups?
155
+ if (this.adGroupsNeeded) {
156
+ dataObservables.push(this.activeDirectoryService.getGroups());
157
+ }
158
+ forkJoin(dataObservables)
159
+ //.subscribe(([users, photos]) => {
160
+ .subscribe(data => {
161
+ // Need groups in place before we handle exclusions/inclusions/pre-selections
162
+ this.groups = this.adGroupsNeeded ? data[2] : null;
163
+ let users = data[0];
164
+ users = this.includeUsersByAccountName(users);
165
+ users = this.includeUsersByGroupName(users);
166
+ users = this.includeUsersByDepartment(users);
167
+ users = this.includeUsersByTitle(users);
168
+ users = this.excludeUsersByAccountName(users);
169
+ users = this.excludeUsersByGroupName(users);
170
+ users = this.excludeUsersByDepartment(users);
171
+ users = this.excludeUsersByTitle(users);
172
+ users = this.preSelectUsersByAccountName(users);
173
+ users = this.preSelectUsersByGroupName(users);
174
+ users = this.preSelectUsersByDepartment(users);
175
+ users = this.preSelectUsersByTitle(users);
176
+ this.dataSource = new MatTableDataSource(users);
177
+ this.photos = data[1];
178
+ this.setFilterPredicate();
179
+ });
180
+ }
181
+ close() {
182
+ this.dialogRef.close(this.selectedOptions
183
+ .map(o => o.value)
184
+ .map(u => this.data.returnUserObjects ? u : u.sAMAccountName));
185
+ }
186
+ getPhoto(user) {
187
+ var _a, _b;
188
+ return (_b = (_a = this.photos) === null || _a === void 0 ? void 0 : _a.find(p => {
189
+ var _a, _b, _c;
190
+ return (p.employeeNumber && p.employeeNumber.toString() === user.employeeNumber) ||
191
+ ((_a = p.accountName) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === user.sAMAccountName.toLowerCase() ||
192
+ ((_b = p.displayName) === null || _b === void 0 ? void 0 : _b.toLowerCase()) === user.displayName.toLowerCase() ||
193
+ ((_c = p.title) === null || _c === void 0 ? void 0 : _c.toLowerCase()) === user.displayName.toLowerCase();
194
+ })) === null || _b === void 0 ? void 0 : _b.encodedAbsUrl;
195
+ }
196
+ //#region Exclusions - won't be included in the dataSource at all
197
+ excludeUsersByAccountName(users) {
198
+ this.data.exclusions.accountNames
199
+ .forEach(accountName => {
200
+ const index = users.findIndex(u => u.sAMAccountName.toLowerCase() === accountName.toLowerCase());
201
+ if (index === -1) {
202
+ return;
203
+ }
204
+ users.splice(index, 1);
205
+ });
206
+ return users;
207
+ }
208
+ excludeUsersByGroupName(users) {
209
+ this.data.exclusions.groups
210
+ .forEach(groupName => {
211
+ var _a;
212
+ const group = (_a = this.groups) === null || _a === void 0 ? void 0 : _a.find(g => g.name.toLowerCase() === groupName.toLowerCase());
213
+ if (!group) {
214
+ return;
215
+ }
216
+ group.member.forEach(groupMemberDn => {
217
+ const index = users.findIndex(u => u.distinguishedName === groupMemberDn);
218
+ if (index === -1) {
219
+ return;
220
+ }
221
+ users.splice(index, 1);
222
+ });
223
+ });
224
+ return users;
225
+ }
226
+ excludeUsersByDepartment(users) {
227
+ this.data.exclusions.departments
228
+ .forEach(department => {
229
+ const excludedUsers = users.filter(u => { var _a; return ((_a = u.department) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === department.toLowerCase(); });
230
+ excludedUsers.forEach(user => {
231
+ const index = users.indexOf(user);
232
+ users.splice(index, 1);
233
+ });
234
+ });
235
+ return users;
236
+ }
237
+ excludeUsersByTitle(users) {
238
+ this.data.exclusions.titles
239
+ .forEach(title => {
240
+ const excludedUsers = users.filter(u => { var _a; return ((_a = u.title) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === title.toLowerCase(); });
241
+ excludedUsers.forEach(user => {
242
+ const index = users.indexOf(user);
243
+ users.splice(index, 1);
244
+ });
245
+ });
246
+ return users;
247
+ }
248
+ //#endregion
249
+ //#region Inclusions - only these will be included in the dataSource
250
+ includeUsersByAccountName(users) {
251
+ return users.filter(user => this.data.inclusions.accountNames.length === 0 || // No account inclusions specified
252
+ this.data.inclusions.accountNames.find(accountName => accountName.toLowerCase() === user.sAMAccountName.toLowerCase()));
253
+ }
254
+ includeUsersByDepartment(users) {
255
+ return users.filter(user => this.data.inclusions.departments.length === 0 || // No department inclusions specified
256
+ this.data.inclusions.departments.find(department => { var _a; return department.toLowerCase() === ((_a = user.department) === null || _a === void 0 ? void 0 : _a.toLowerCase()); }));
257
+ }
258
+ includeUsersByTitle(users) {
259
+ return users.filter(user => this.data.inclusions.titles.length === 0 || // No title inclusions specified
260
+ this.data.inclusions.titles.find(title => { var _a; return title.toLowerCase() === ((_a = user.title) === null || _a === void 0 ? void 0 : _a.toLowerCase()); }));
261
+ }
262
+ includeUsersByGroupName(users) {
263
+ if (!this.data.inclusions.groups.length) {
264
+ return users; // No group inclusions specified
265
+ }
266
+ // Cheating a bit and leveraging the 'selected' property to keep track of who should be included
267
+ // Since inclusions happen befor pre-selections, we can do that, as long as we set 'selected' back to false when we're done
268
+ this.data.inclusions.groups
269
+ .forEach(groupName => {
270
+ var _a;
271
+ const group = (_a = this.groups) === null || _a === void 0 ? void 0 : _a.find(g => g.name.toLowerCase() === groupName.toLowerCase());
272
+ if (!group) {
273
+ return;
274
+ }
275
+ users
276
+ .filter(user => group.member.find(groupMemberDn => groupMemberDn === user.distinguishedName))
277
+ .forEach(user => user.selected = true);
278
+ });
279
+ // At this point, all of the appropriate users should have 'selected' set to true
280
+ const selectedUsers = users.filter(user => user.selected); // Subset of the original list
281
+ // Reset 'selected' to false, and return
282
+ selectedUsers.forEach(user => user.selected = false);
283
+ return selectedUsers;
284
+ }
285
+ //#endregion
286
+ //#region Pre-Selections
287
+ preSelectUsersByAccountName(users) {
288
+ this.data.preSelections.accountNames
289
+ .forEach(accountName => {
290
+ const user = users.find(u => u.sAMAccountName.toLowerCase() === accountName.toLowerCase());
291
+ if (!user) {
292
+ return;
293
+ }
294
+ user.selected = true;
295
+ });
296
+ return users;
297
+ }
298
+ preSelectUsersByDepartment(users) {
299
+ this.data.preSelections.departments
300
+ .forEach(department => users
301
+ .filter(u => { var _a; return ((_a = u.department) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === department.toLowerCase(); })
302
+ .forEach(user => user.selected = true));
303
+ return users;
304
+ }
305
+ preSelectUsersByTitle(users) {
306
+ this.data.preSelections.titles
307
+ .forEach(title => users
308
+ .filter(u => { var _a; return ((_a = u.title) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === title.toLowerCase(); })
309
+ .forEach(user => user.selected = true));
310
+ return users;
311
+ }
312
+ preSelectUsersByGroupName(users) {
313
+ this.data.preSelections.groups
314
+ .forEach(groupName => {
315
+ var _a;
316
+ const group = (_a = this.groups) === null || _a === void 0 ? void 0 : _a.find(g => g.name.toLowerCase() === groupName.toLowerCase());
317
+ if (!group) {
318
+ return;
319
+ }
320
+ group.member.forEach(groupMemberDn => {
321
+ const user = users.find(u => u.distinguishedName === groupMemberDn);
322
+ if (!user) {
323
+ return;
324
+ }
325
+ user.selected = true;
326
+ });
327
+ });
328
+ return users;
329
+ }
330
+ //#endregion
331
+ setFilterPredicate() {
332
+ if (!this.dataSource) {
333
+ return;
334
+ }
335
+ this.dataSource.filterPredicate = (user, filter) => {
336
+ if (filter === '{selected:true}') {
337
+ return user.selected;
338
+ }
339
+ else {
340
+ const regex = new RegExp(filter, 'i'); // Case-insensitive
341
+ let match = false; // The end result - whether or not a employee matches the filter
342
+ const filterProperties = ['displayName'];
343
+ if (this.data.filterOptions.accountName) {
344
+ filterProperties.push('sAMAccountName');
345
+ }
346
+ if (this.data.filterOptions.title) {
347
+ filterProperties.push('title');
348
+ }
349
+ if (this.data.filterOptions.department) {
350
+ filterProperties.push('department');
351
+ }
352
+ if (this.data.filterOptions.phoneNumber) {
353
+ filterProperties.push('telephoneNumber');
354
+ }
355
+ // Match on the properties configured above
356
+ filterProperties
357
+ .forEach(field => {
358
+ // @ts-ignore
359
+ if (user[field] && user[field].match(regex)) {
360
+ match = true;
361
+ }
362
+ });
363
+ // Match on group membership (group name)
364
+ if (this.data.filterOptions.groupMembership) {
365
+ user.memberOf.forEach(groupDn => {
366
+ var _a;
367
+ const group = (_a = this.groups) === null || _a === void 0 ? void 0 : _a.find(group => group.distinguishedName === groupDn && group.name.match(regex));
368
+ if (group) {
369
+ match = true;
370
+ }
371
+ });
372
+ }
373
+ return match;
374
+ }
375
+ };
376
+ }
377
+ listenForFilterChanges() {
378
+ var _a;
379
+ (_a = this.filterForm.get('filter')) === null || _a === void 0 ? void 0 : _a.valueChanges.pipe(debounceTime(500)).subscribe(() => { var _a; return this.dataSource.filter = (_a = this.filterForm.value.filter) === null || _a === void 0 ? void 0 : _a.trim().toLowerCase(); });
380
+ }
381
+ tooltip(user) {
382
+ return this.data.showGroupMembershipTooltips ?
383
+ user.memberOf
384
+ .map(groupDn => {
385
+ var _a, _b;
386
+ return (_b = (_a = this.groups) === null || _a === void 0 ? void 0 : _a.find(group => group.distinguishedName === groupDn)) === null || _b === void 0 ? void 0 : _b.name;
387
+ })
388
+ .sort((a, b) => a > b ? 1 : -1)
389
+ .join('\n') :
390
+ '';
391
+ }
392
+ }
393
+ UserChooserComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.1", ngImport: i0, type: UserChooserComponent, deps: [{ token: MAT_DIALOG_DATA }, { token: i1.MatDialogRef }, { token: i2.ActiveDirectoryService }, { token: i3.SharePointService }], target: i0.ɵɵFactoryTarget.Component });
394
+ UserChooserComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.2.1", type: UserChooserComponent, selector: "user-chooser", viewQueries: [{ propertyName: "selectionList", first: true, predicate: MatSelectionList, descendants: true }], ngImport: i0, template: "<div id=\"dialog-title\">\n <h2 mat-dialog-title>{{ data.title }}</h2>\n\n <div>\n {{ selectedOptions.length }} selected\n </div>\n</div>\n\n<mat-dialog-content>\n <div *ngIf=\"!(dataSource && photos)\">\n <mat-spinner [diameter]=\"50\"></mat-spinner>\n <h2 id=\"spinner-message\">Getting users and photos...</h2>\n </div>\n\n <ng-container *ngIf=\"dataSource && photos\">\n <form [formGroup]=\"filterForm\">\n <mat-form-field *ngIf=\"dataSource\">\n <input matInput placeholder=\"Search\" formControlName=\"filter\">\n\n <button *ngIf=\"filterForm.value.filter\" matSuffix mat-icon-button aria-label=\"Clear\" (click)=\"filterForm.get('filter')?.setValue('')\">\n <mat-icon fontIcon=\"close\"></mat-icon>\n </button>\n </mat-form-field>\n </form>\n\n <mat-selection-list [multiple]=\"isMultiMode\"\n (selectionChange)=\"listSelectionChanged($event.options)\">\n\n <mat-list-option *ngFor=\"let user of dataSource?.filteredData\" [value]=\"user\" [selected]=\"user.selected\"\n (selectedChange)=\"optionSelectionChanged(option)\" #option>\n\n <img *ngIf=\"getPhoto(user)\" matListAvatar alt=\"\" [src]=\"getPhoto(user)\">\n\n <mat-icon *ngIf=\"!getPhoto(user)\" matListAvatar class=\"no-photo\"\n fontIcon=\"account_circle\">\n </mat-icon>\n \n <div class=\"user\">\n <div [matTooltip]=\"tooltip(user)\" class=\"user-name\">\n {{ user.displayName }}\n <div *ngIf=\"data.showPhone && user.telephoneNumber\">{{ user.telephoneNumber }}</div>\n </div>\n \n <div>{{ user.department }}</div>\n \n <div class=\"title\">{{ user.title }}</div>\n </div>\n </mat-list-option>\n </mat-selection-list>\n </ng-container>\n</mat-dialog-content>\n\n<mat-dialog-actions>\n <ng-container *ngIf=\"dataSource && photos\">\n <mat-slide-toggle *ngIf=\"selectedOptions.length\" (change)=\"hideUnselectedChanged($event.checked)\">\n Hide Unselected\n </mat-slide-toggle>\n\n <button mat-raised-button color=\"primary\" (click)=\"selectAll()\"\n *ngIf=\"isMultiMode\">\n <mat-icon fontIcon=\"select_all\"></mat-icon>\n <span class=\"hide-mobile\">Select All</span>\n </button>\n \n <button mat-raised-button color=\"primary\" (click)=\"deselectAll()\"\n *ngIf=\"isMultiMode && selectedOptions.length\">\n <mat-icon fontIcon=\"clear_all\"></mat-icon>\n <span class=\"hide-mobile\">Clear All</span>\n </button>\n\n <button mat-raised-button color=\"primary\" (click)=\"close()\" matTooltip=\"Accept your selection\"\n [disabled]=\"!selectedOptions.length\">\n <mat-icon fontIcon=\"check\"></mat-icon>\n <span class=\"hide-mobile\">Ok</span>\n </button>\n </ng-container>\n\n <button mat-raised-button color=\"warn\" mat-dialog-close matTooltip=\"Close this window\">\n <mat-icon fontIcon=\"close\"></mat-icon>\n <span class=\"hide-mobile\">Cancel</span>\n </button>\n</mat-dialog-actions>", styles: ["::ng-deep .mat-tooltip{font-size:1em!important;white-space:pre-line}mat-dialog-content{min-width:50vw}#dialog-title{display:flex;justify-content:space-between}.mat-spinner{margin:0 auto}#spinner-message{text-align:center;padding:.5em}mat-form-field{width:100%}.title{font-style:italic;color:#757575}img,.no-photo{width:2rem;height:2rem;font-size:2.3rem!important;border-radius:100%}.hide-mobile{display:none}mat-dialog-actions{display:grid;grid-auto-flow:column;grid-gap:1em;justify-content:center}.user-name{display:flex;justify-content:space-between}.user-name>div:last-child{margin-right:10rem;font-weight:400;font-style:italic;color:#757575}@media (min-width:801px){.user{display:grid;grid-template-columns:1fr 1fr 1fr}.user>div:first-child{font-weight:700}.hide-mobile{display:initial}}\n", ".material-icons{font-family:Material Icons;font-weight:400;font-style:normal;font-size:24px;display:inline-block;line-height:1;text-transform:none;letter-spacing:normal;word-wrap:normal;white-space:nowrap;direction:ltr;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;-moz-osx-font-smoothing:grayscale;font-feature-settings:\"liga\"}\n"], dependencies: [{ kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i5.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i5.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i5.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i5.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i6.MatButton, selector: "button[mat-button], button[mat-raised-button], button[mat-icon-button], button[mat-fab], button[mat-mini-fab], button[mat-stroked-button], button[mat-flat-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "directive", type: i1.MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "directive", type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "directive", type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "component", type: i7.MatFormField, selector: "mat-form-field", inputs: ["color", "appearance", "hideRequiredMarker", "hintLabel", "floatLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i7.MatSuffix, selector: "[matSuffix]" }, { kind: "component", type: i8.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i9.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "directive", type: i10.MatListAvatarCssMatStyler, selector: "[mat-list-avatar], [matListAvatar]" }, { kind: "component", type: i10.MatSelectionList, selector: "mat-selection-list", inputs: ["disableRipple", "color", "compareWith", "disabled", "multiple"], outputs: ["selectionChange"], exportAs: ["matSelectionList"] }, { kind: "component", type: i10.MatListOption, selector: "mat-list-option", inputs: ["disableRipple", "checkboxPosition", "color", "value", "disabled", "selected"], outputs: ["selectedChange"], exportAs: ["matListOption"] }, { kind: "component", type: i11.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "diameter", "strokeWidth", "mode", "value"], exportAs: ["matProgressSpinner"] }, { kind: "component", type: i12.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["disabled", "disableRipple", "color", "tabIndex"], exportAs: ["matSlideToggle"] }, { kind: "directive", type: i13.MatTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }] });
395
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.1", ngImport: i0, type: UserChooserComponent, decorators: [{
396
+ type: Component,
397
+ args: [{ selector: 'user-chooser', template: "<div id=\"dialog-title\">\n <h2 mat-dialog-title>{{ data.title }}</h2>\n\n <div>\n {{ selectedOptions.length }} selected\n </div>\n</div>\n\n<mat-dialog-content>\n <div *ngIf=\"!(dataSource && photos)\">\n <mat-spinner [diameter]=\"50\"></mat-spinner>\n <h2 id=\"spinner-message\">Getting users and photos...</h2>\n </div>\n\n <ng-container *ngIf=\"dataSource && photos\">\n <form [formGroup]=\"filterForm\">\n <mat-form-field *ngIf=\"dataSource\">\n <input matInput placeholder=\"Search\" formControlName=\"filter\">\n\n <button *ngIf=\"filterForm.value.filter\" matSuffix mat-icon-button aria-label=\"Clear\" (click)=\"filterForm.get('filter')?.setValue('')\">\n <mat-icon fontIcon=\"close\"></mat-icon>\n </button>\n </mat-form-field>\n </form>\n\n <mat-selection-list [multiple]=\"isMultiMode\"\n (selectionChange)=\"listSelectionChanged($event.options)\">\n\n <mat-list-option *ngFor=\"let user of dataSource?.filteredData\" [value]=\"user\" [selected]=\"user.selected\"\n (selectedChange)=\"optionSelectionChanged(option)\" #option>\n\n <img *ngIf=\"getPhoto(user)\" matListAvatar alt=\"\" [src]=\"getPhoto(user)\">\n\n <mat-icon *ngIf=\"!getPhoto(user)\" matListAvatar class=\"no-photo\"\n fontIcon=\"account_circle\">\n </mat-icon>\n \n <div class=\"user\">\n <div [matTooltip]=\"tooltip(user)\" class=\"user-name\">\n {{ user.displayName }}\n <div *ngIf=\"data.showPhone && user.telephoneNumber\">{{ user.telephoneNumber }}</div>\n </div>\n \n <div>{{ user.department }}</div>\n \n <div class=\"title\">{{ user.title }}</div>\n </div>\n </mat-list-option>\n </mat-selection-list>\n </ng-container>\n</mat-dialog-content>\n\n<mat-dialog-actions>\n <ng-container *ngIf=\"dataSource && photos\">\n <mat-slide-toggle *ngIf=\"selectedOptions.length\" (change)=\"hideUnselectedChanged($event.checked)\">\n Hide Unselected\n </mat-slide-toggle>\n\n <button mat-raised-button color=\"primary\" (click)=\"selectAll()\"\n *ngIf=\"isMultiMode\">\n <mat-icon fontIcon=\"select_all\"></mat-icon>\n <span class=\"hide-mobile\">Select All</span>\n </button>\n \n <button mat-raised-button color=\"primary\" (click)=\"deselectAll()\"\n *ngIf=\"isMultiMode && selectedOptions.length\">\n <mat-icon fontIcon=\"clear_all\"></mat-icon>\n <span class=\"hide-mobile\">Clear All</span>\n </button>\n\n <button mat-raised-button color=\"primary\" (click)=\"close()\" matTooltip=\"Accept your selection\"\n [disabled]=\"!selectedOptions.length\">\n <mat-icon fontIcon=\"check\"></mat-icon>\n <span class=\"hide-mobile\">Ok</span>\n </button>\n </ng-container>\n\n <button mat-raised-button color=\"warn\" mat-dialog-close matTooltip=\"Close this window\">\n <mat-icon fontIcon=\"close\"></mat-icon>\n <span class=\"hide-mobile\">Cancel</span>\n </button>\n</mat-dialog-actions>", styles: ["::ng-deep .mat-tooltip{font-size:1em!important;white-space:pre-line}mat-dialog-content{min-width:50vw}#dialog-title{display:flex;justify-content:space-between}.mat-spinner{margin:0 auto}#spinner-message{text-align:center;padding:.5em}mat-form-field{width:100%}.title{font-style:italic;color:#757575}img,.no-photo{width:2rem;height:2rem;font-size:2.3rem!important;border-radius:100%}.hide-mobile{display:none}mat-dialog-actions{display:grid;grid-auto-flow:column;grid-gap:1em;justify-content:center}.user-name{display:flex;justify-content:space-between}.user-name>div:last-child{margin-right:10rem;font-weight:400;font-style:italic;color:#757575}@media (min-width:801px){.user{display:grid;grid-template-columns:1fr 1fr 1fr}.user>div:first-child{font-weight:700}.hide-mobile{display:initial}}\n", ".material-icons{font-family:Material Icons;font-weight:400;font-style:normal;font-size:24px;display:inline-block;line-height:1;text-transform:none;letter-spacing:normal;word-wrap:normal;white-space:nowrap;direction:ltr;-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;-moz-osx-font-smoothing:grayscale;font-feature-settings:\"liga\"}\n"] }]
398
+ }], ctorParameters: function () {
399
+ return [{ type: undefined, decorators: [{
400
+ type: Inject,
401
+ args: [MAT_DIALOG_DATA]
402
+ }] }, { type: i1.MatDialogRef }, { type: i2.ActiveDirectoryService }, { type: i3.SharePointService }];
403
+ }, propDecorators: { selectionList: [{
404
+ type: ViewChild,
405
+ args: [MatSelectionList]
406
+ }] } });
407
+
408
+ class UserFormFieldComponent {
409
+ //#endregion
410
+ //#region Lifecycle
411
+ constructor(dialog, activeDirectoryService, sharePointService) {
412
+ this.dialog = dialog;
413
+ this.activeDirectoryService = activeDirectoryService;
414
+ this.sharePointService = sharePointService;
415
+ //#region Fields
416
+ this.usersSelected = new EventEmitter();
417
+ this.placeholder = 'Select User(s)';
418
+ this.clickable = true;
419
+ /*
420
+ @Input() mode = UserChooserMode.Multiple;
421
+ @Input() preSelectAccountNames = true;
422
+ @Input() includeDisabledUsers = false;
423
+ @Input() parentOu = undefined;*/
424
+ this.accountNames = [];
425
+ this.users = undefined;
426
+ this.photos = undefined;
427
+ }
428
+ //#endregion
429
+ //#region Properties
430
+ get isEdge() {
431
+ return window.navigator.userAgent.indexOf('Edge') > -1;
432
+ }
433
+ ngOnInit() {
434
+ this.userChooserData = Object.assign(Object.assign({}, defaultUserChooserConfig), this.userChooserData);
435
+ // If users have been pre-selected in the config, store those in accountNames, which drives the UI of this component
436
+ this.accountNames = this.userChooserData.preSelections.accountNames;
437
+ this.getData();
438
+ }
439
+ //#endregion
440
+ //#region Events
441
+ selectUser() {
442
+ if (!this.clickable) {
443
+ return;
444
+ }
445
+ const data = Object.assign(Object.assign({}, this.userChooserData), { users: this.users, photos: this.photos });
446
+ this.dialog.open(UserChooserComponent, {
447
+ data: data
448
+ })
449
+ .afterClosed()
450
+ .subscribe(accountNames => {
451
+ if (!accountNames) {
452
+ return;
453
+ }
454
+ this.accountNames = accountNames;
455
+ this.usersSelected.emit(accountNames);
456
+ });
457
+ }
458
+ //#endregion
459
+ //#region Utilities
460
+ getData() {
461
+ forkJoin([
462
+ this.userChooserData.users ?
463
+ // Users were passed in
464
+ of(this.userChooserData.users) :
465
+ // Users need to be retrieved
466
+ this.activeDirectoryService.getUsers(false, this.userChooserData.includeDisabledUsers, this.userChooserData.parentOu),
467
+ this.userChooserData.photos ?
468
+ // Photos were passed in
469
+ of(this.userChooserData.photos) :
470
+ // Photos need to be retrieved
471
+ this.sharePointService.getPhotos()
472
+ ])
473
+ .subscribe(([users, photos]) => {
474
+ this.users = users;
475
+ this.photos = photos;
476
+ });
477
+ }
478
+ getUser(accountName) {
479
+ var _a;
480
+ return (_a = this.users) === null || _a === void 0 ? void 0 : _a.find(u => u.sAMAccountName.toLowerCase() === accountName.toLowerCase());
481
+ }
482
+ getPhoto(accountName) {
483
+ var _a, _b;
484
+ const user = this.getUser(accountName);
485
+ if (!user) {
486
+ return undefined;
487
+ }
488
+ return (_b = (_a = this.photos) === null || _a === void 0 ? void 0 : _a.find(p => {
489
+ var _a, _b, _c;
490
+ return (p.employeeNumber && p.employeeNumber.toString() === user.employeeNumber) ||
491
+ ((_a = p.accountName) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === user.sAMAccountName.toLowerCase() ||
492
+ ((_b = p.displayName) === null || _b === void 0 ? void 0 : _b.toLowerCase()) === user.displayName.toLowerCase() ||
493
+ ((_c = p.title) === null || _c === void 0 ? void 0 : _c.toLowerCase()) === user.displayName.toLowerCase();
494
+ })) === null || _b === void 0 ? void 0 : _b.encodedAbsUrl;
495
+ }
496
+ }
497
+ UserFormFieldComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.1", ngImport: i0, type: UserFormFieldComponent, deps: [{ token: i1.MatDialog }, { token: i2.ActiveDirectoryService }, { token: i3.SharePointService }], target: i0.ɵɵFactoryTarget.Component });
498
+ UserFormFieldComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.2.1", type: UserFormFieldComponent, selector: "user-form-field", inputs: { placeholder: "placeholder", clickable: "clickable", userChooserData: "userChooserData" }, outputs: { usersSelected: "usersSelected" }, ngImport: i0, template: "<!-- In Microsoft Edge, selectEmployee() never gets called if the input fields are disabled\n So... I'm dynamically setting the disabled property based on whether or not the browser is Edge.\n It's definitely a better experience if the field IS disabled.\n Otherwise, it's confusing - especially because Edge is SO SLOW to display the resulting dialog window.\n-->\n\n<div (click)=\"selectUser()\" [class.clickable]=\"clickable\">\n <mat-form-field *ngIf=\"!accountNames?.length\">\n <input matInput [disabled]=\"!isEdge\" [placeholder]=\"placeholder\">\n </mat-form-field>\n \n <div *ngIf=\"accountNames?.length\"\n [class.grid]=\"accountNames.length > 1\"\n [class.three]=\"accountNames.length > 2\"\n [class.four]=\"accountNames.length > 3\"\n [class.five]=\"accountNames.length > 4\">\n\n <div *ngFor=\"let accountName of accountNames; let i=index\" class=\"user\">\n <!--<img *ngIf=\"accountName && empUtils.getEmployee(accountName)\" alt=\"\" [src]=\"empUtils.getEmployee(accountName) | employeePhotoUrl:cacheService.photos\">-->\n <img *ngIf=\"getPhoto(accountName)\" matListAvatar alt=\"\" [src]=\"getPhoto(accountName)\">\n \n <mat-form-field>\n <input matInput [disabled]=\"!isEdge\" [placeholder]=\"i === 0 ? placeholder : ''\"\n [value]=\"accountName ? getUser(accountName)?.displayName : accountName\">\n </mat-form-field>\n </div>\n </div>\n </div>", styles: [".user{display:grid;grid-template-columns:auto 1fr;grid-gap:.5em;align-items:center}.clickable,.clickable input{cursor:pointer!important}img{width:2em;height:2em;border-radius:100%}@media (min-width:801px){.grid{display:grid;grid-template-columns:repeat(2,1fr);grid-gap:1em}.three{grid-template-columns:repeat(3,1fr)}.four{grid-template-columns:repeat(4,1fr)}.five{grid-template-columns:repeat(5,1fr)}::ng-deep .grid mat-form-field{width:15vw}}\n"], dependencies: [{ kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i7.MatFormField, selector: "mat-form-field", inputs: ["color", "appearance", "hideRequiredMarker", "hintLabel", "floatLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i9.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "directive", type: i10.MatListAvatarCssMatStyler, selector: "[mat-list-avatar], [matListAvatar]" }] });
499
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.1", ngImport: i0, type: UserFormFieldComponent, decorators: [{
500
+ type: Component,
501
+ args: [{ selector: 'user-form-field', template: "<!-- In Microsoft Edge, selectEmployee() never gets called if the input fields are disabled\n So... I'm dynamically setting the disabled property based on whether or not the browser is Edge.\n It's definitely a better experience if the field IS disabled.\n Otherwise, it's confusing - especially because Edge is SO SLOW to display the resulting dialog window.\n-->\n\n<div (click)=\"selectUser()\" [class.clickable]=\"clickable\">\n <mat-form-field *ngIf=\"!accountNames?.length\">\n <input matInput [disabled]=\"!isEdge\" [placeholder]=\"placeholder\">\n </mat-form-field>\n \n <div *ngIf=\"accountNames?.length\"\n [class.grid]=\"accountNames.length > 1\"\n [class.three]=\"accountNames.length > 2\"\n [class.four]=\"accountNames.length > 3\"\n [class.five]=\"accountNames.length > 4\">\n\n <div *ngFor=\"let accountName of accountNames; let i=index\" class=\"user\">\n <!--<img *ngIf=\"accountName && empUtils.getEmployee(accountName)\" alt=\"\" [src]=\"empUtils.getEmployee(accountName) | employeePhotoUrl:cacheService.photos\">-->\n <img *ngIf=\"getPhoto(accountName)\" matListAvatar alt=\"\" [src]=\"getPhoto(accountName)\">\n \n <mat-form-field>\n <input matInput [disabled]=\"!isEdge\" [placeholder]=\"i === 0 ? placeholder : ''\"\n [value]=\"accountName ? getUser(accountName)?.displayName : accountName\">\n </mat-form-field>\n </div>\n </div>\n </div>", styles: [".user{display:grid;grid-template-columns:auto 1fr;grid-gap:.5em;align-items:center}.clickable,.clickable input{cursor:pointer!important}img{width:2em;height:2em;border-radius:100%}@media (min-width:801px){.grid{display:grid;grid-template-columns:repeat(2,1fr);grid-gap:1em}.three{grid-template-columns:repeat(3,1fr)}.four{grid-template-columns:repeat(4,1fr)}.five{grid-template-columns:repeat(5,1fr)}::ng-deep .grid mat-form-field{width:15vw}}\n"] }]
502
+ }], ctorParameters: function () { return [{ type: i1.MatDialog }, { type: i2.ActiveDirectoryService }, { type: i3.SharePointService }]; }, propDecorators: { usersSelected: [{
503
+ type: Output
504
+ }], placeholder: [{
505
+ type: Input
506
+ }], clickable: [{
507
+ type: Input
508
+ }], userChooserData: [{
509
+ type: Input
510
+ }] } });
511
+
512
+ class GuiModule {
513
+ }
514
+ GuiModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.1", ngImport: i0, type: GuiModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
515
+ GuiModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.2.1", ngImport: i0, type: GuiModule, declarations: [UserChooserComponent,
516
+ UserFormFieldComponent], imports: [CommonModule,
517
+ ReactiveFormsModule,
518
+ MatButtonModule,
519
+ MatDialogModule,
520
+ MatFormFieldModule,
521
+ MatIconModule,
522
+ MatInputModule,
523
+ MatListModule,
524
+ MatProgressSpinnerModule,
525
+ MatSlideToggleModule,
526
+ MatTableModule,
527
+ MatTooltipModule], exports: [UserChooserComponent,
528
+ UserFormFieldComponent] });
529
+ GuiModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.2.1", ngImport: i0, type: GuiModule, imports: [CommonModule,
530
+ ReactiveFormsModule,
531
+ MatButtonModule,
532
+ MatDialogModule,
533
+ MatFormFieldModule,
534
+ MatIconModule,
535
+ MatInputModule,
536
+ MatListModule,
537
+ MatProgressSpinnerModule,
538
+ MatSlideToggleModule,
539
+ MatTableModule,
540
+ MatTooltipModule] });
541
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.1", ngImport: i0, type: GuiModule, decorators: [{
542
+ type: NgModule,
543
+ args: [{
544
+ declarations: [
545
+ UserChooserComponent,
546
+ UserFormFieldComponent
547
+ ],
548
+ imports: [
549
+ CommonModule,
550
+ ReactiveFormsModule,
551
+ MatButtonModule,
552
+ MatDialogModule,
553
+ MatFormFieldModule,
554
+ MatIconModule,
555
+ MatInputModule,
556
+ MatListModule,
557
+ MatProgressSpinnerModule,
558
+ MatSlideToggleModule,
559
+ MatTableModule,
560
+ MatTooltipModule
561
+ ],
562
+ exports: [
563
+ UserChooserComponent,
564
+ UserFormFieldComponent
565
+ ]
566
+ }]
567
+ }] });
568
+
569
+ /**
570
+ * Generated bundle index. Do not edit.
571
+ */
572
+
573
+ export { GuiModule, UserChooserComponent, UserChooserMode, UserFormFieldComponent, defaultUserChooserConfig, defaultUserChooserFilterOptionsConfig, defaultUserChooserPreProcessingGroupConfig };
574
+ //# sourceMappingURL=cleavelandprice-ngx-lib-active-directory-gui.mjs.map