@cleavelandprice/ngx-lib 3.1.10 → 3.1.12

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 (36) 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 +22 -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/esm2020/active-directory/active-directory.module.mjs +3 -2
  15. package/esm2020/active-directory/gui/cleavelandprice-ngx-lib-active-directory-gui.mjs +5 -0
  16. package/esm2020/active-directory/gui/components/user-chooser/user-chooser.component.mjs +356 -0
  17. package/esm2020/active-directory/gui/components/user-form-field/user-form-field.component.mjs +118 -0
  18. package/esm2020/active-directory/gui/gui.module.mjs +73 -0
  19. package/esm2020/active-directory/gui/model/default-user-chooser-config.mjs +18 -0
  20. package/esm2020/active-directory/gui/model/default-user-chooser-filter-options-config.mjs +8 -0
  21. package/esm2020/active-directory/gui/model/default-user-chooser-pre-processing-group-config.mjs +7 -0
  22. package/esm2020/active-directory/gui/model/selectable-user.mjs +2 -0
  23. package/esm2020/active-directory/gui/model/user-chooser-data.mjs +2 -0
  24. package/esm2020/active-directory/gui/model/user-chooser-filter-options.mjs +2 -0
  25. package/esm2020/active-directory/gui/model/user-chooser-mode.mjs +6 -0
  26. package/esm2020/active-directory/gui/model/user-chooser-pre-processing-group.mjs +2 -0
  27. package/esm2020/active-directory/gui/public_api.mjs +11 -0
  28. package/fesm2015/cleavelandprice-ngx-lib-active-directory-gui.mjs +578 -0
  29. package/fesm2015/cleavelandprice-ngx-lib-active-directory-gui.mjs.map +1 -0
  30. package/fesm2015/cleavelandprice-ngx-lib-active-directory.mjs +2 -1
  31. package/fesm2015/cleavelandprice-ngx-lib-active-directory.mjs.map +1 -1
  32. package/fesm2020/cleavelandprice-ngx-lib-active-directory-gui.mjs +568 -0
  33. package/fesm2020/cleavelandprice-ngx-lib-active-directory-gui.mjs.map +1 -0
  34. package/fesm2020/cleavelandprice-ngx-lib-active-directory.mjs +2 -1
  35. package/fesm2020/cleavelandprice-ngx-lib-active-directory.mjs.map +1 -1
  36. package/package.json +9 -1
@@ -0,0 +1,578 @@
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
+ this.data.groups ?
157
+ // Groups were passed in
158
+ of(this.data.groups) :
159
+ // Groups need to be retrieved
160
+ dataObservables.push(this.activeDirectoryService.getGroups());
161
+ }
162
+ forkJoin(dataObservables)
163
+ //.subscribe(([users, photos]) => {
164
+ .subscribe(data => {
165
+ // Need groups in place before we handle exclusions/inclusions/pre-selections
166
+ this.groups = this.adGroupsNeeded ? data[2] : null;
167
+ let users = data[0];
168
+ users = this.includeUsersByAccountName(users);
169
+ users = this.includeUsersByGroupName(users);
170
+ users = this.includeUsersByDepartment(users);
171
+ users = this.includeUsersByTitle(users);
172
+ users = this.excludeUsersByAccountName(users);
173
+ users = this.excludeUsersByGroupName(users);
174
+ users = this.excludeUsersByDepartment(users);
175
+ users = this.excludeUsersByTitle(users);
176
+ users = this.preSelectUsersByAccountName(users);
177
+ users = this.preSelectUsersByGroupName(users);
178
+ users = this.preSelectUsersByDepartment(users);
179
+ users = this.preSelectUsersByTitle(users);
180
+ this.dataSource = new MatTableDataSource(users);
181
+ this.photos = data[1];
182
+ this.setFilterPredicate();
183
+ });
184
+ }
185
+ close() {
186
+ this.dialogRef.close(this.selectedOptions
187
+ .map(o => o.value)
188
+ .map(u => this.data.returnUserObjects ? u : u.sAMAccountName));
189
+ }
190
+ getPhoto(user) {
191
+ var _a, _b;
192
+ return (_b = (_a = this.photos) === null || _a === void 0 ? void 0 : _a.find(p => {
193
+ var _a, _b, _c;
194
+ return (p.employeeNumber && p.employeeNumber.toString() === user.employeeNumber) ||
195
+ ((_a = p.accountName) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === user.sAMAccountName.toLowerCase() ||
196
+ ((_b = p.displayName) === null || _b === void 0 ? void 0 : _b.toLowerCase()) === user.displayName.toLowerCase() ||
197
+ ((_c = p.title) === null || _c === void 0 ? void 0 : _c.toLowerCase()) === user.displayName.toLowerCase();
198
+ })) === null || _b === void 0 ? void 0 : _b.encodedAbsUrl;
199
+ }
200
+ //#region Exclusions - won't be included in the dataSource at all
201
+ excludeUsersByAccountName(users) {
202
+ this.data.exclusions.accountNames
203
+ .forEach(accountName => {
204
+ const index = users.findIndex(u => u.sAMAccountName.toLowerCase() === accountName.toLowerCase());
205
+ if (index === -1) {
206
+ return;
207
+ }
208
+ users.splice(index, 1);
209
+ });
210
+ return users;
211
+ }
212
+ excludeUsersByGroupName(users) {
213
+ this.data.exclusions.groups
214
+ .forEach(groupName => {
215
+ var _a;
216
+ const group = (_a = this.groups) === null || _a === void 0 ? void 0 : _a.find(g => g.name.toLowerCase() === groupName.toLowerCase());
217
+ if (!group) {
218
+ return;
219
+ }
220
+ group.member.forEach(groupMemberDn => {
221
+ const index = users.findIndex(u => u.distinguishedName === groupMemberDn);
222
+ if (index === -1) {
223
+ return;
224
+ }
225
+ users.splice(index, 1);
226
+ });
227
+ });
228
+ return users;
229
+ }
230
+ excludeUsersByDepartment(users) {
231
+ this.data.exclusions.departments
232
+ .forEach(department => {
233
+ const excludedUsers = users.filter(u => { var _a; return ((_a = u.department) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === department.toLowerCase(); });
234
+ excludedUsers.forEach(user => {
235
+ const index = users.indexOf(user);
236
+ users.splice(index, 1);
237
+ });
238
+ });
239
+ return users;
240
+ }
241
+ excludeUsersByTitle(users) {
242
+ this.data.exclusions.titles
243
+ .forEach(title => {
244
+ const excludedUsers = users.filter(u => { var _a; return ((_a = u.title) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === title.toLowerCase(); });
245
+ excludedUsers.forEach(user => {
246
+ const index = users.indexOf(user);
247
+ users.splice(index, 1);
248
+ });
249
+ });
250
+ return users;
251
+ }
252
+ //#endregion
253
+ //#region Inclusions - only these will be included in the dataSource
254
+ includeUsersByAccountName(users) {
255
+ return users.filter(user => this.data.inclusions.accountNames.length === 0 || // No account inclusions specified
256
+ this.data.inclusions.accountNames.find(accountName => accountName.toLowerCase() === user.sAMAccountName.toLowerCase()));
257
+ }
258
+ includeUsersByDepartment(users) {
259
+ return users.filter(user => this.data.inclusions.departments.length === 0 || // No department inclusions specified
260
+ this.data.inclusions.departments.find(department => { var _a; return department.toLowerCase() === ((_a = user.department) === null || _a === void 0 ? void 0 : _a.toLowerCase()); }));
261
+ }
262
+ includeUsersByTitle(users) {
263
+ return users.filter(user => this.data.inclusions.titles.length === 0 || // No title inclusions specified
264
+ this.data.inclusions.titles.find(title => { var _a; return title.toLowerCase() === ((_a = user.title) === null || _a === void 0 ? void 0 : _a.toLowerCase()); }));
265
+ }
266
+ includeUsersByGroupName(users) {
267
+ if (!this.data.inclusions.groups.length) {
268
+ return users; // No group inclusions specified
269
+ }
270
+ // Cheating a bit and leveraging the 'selected' property to keep track of who should be included
271
+ // Since inclusions happen befor pre-selections, we can do that, as long as we set 'selected' back to false when we're done
272
+ this.data.inclusions.groups
273
+ .forEach(groupName => {
274
+ var _a;
275
+ const group = (_a = this.groups) === null || _a === void 0 ? void 0 : _a.find(g => g.name.toLowerCase() === groupName.toLowerCase());
276
+ if (!group) {
277
+ return;
278
+ }
279
+ users
280
+ .filter(user => group.member.find(groupMemberDn => groupMemberDn === user.distinguishedName))
281
+ .forEach(user => user.selected = true);
282
+ });
283
+ // At this point, all of the appropriate users should have 'selected' set to true
284
+ const selectedUsers = users.filter(user => user.selected); // Subset of the original list
285
+ // Reset 'selected' to false, and return
286
+ selectedUsers.forEach(user => user.selected = false);
287
+ return selectedUsers;
288
+ }
289
+ //#endregion
290
+ //#region Pre-Selections
291
+ preSelectUsersByAccountName(users) {
292
+ this.data.preSelections.accountNames
293
+ .forEach(accountName => {
294
+ const user = users.find(u => u.sAMAccountName.toLowerCase() === accountName.toLowerCase());
295
+ if (!user) {
296
+ return;
297
+ }
298
+ user.selected = true;
299
+ });
300
+ return users;
301
+ }
302
+ preSelectUsersByDepartment(users) {
303
+ this.data.preSelections.departments
304
+ .forEach(department => users
305
+ .filter(u => { var _a; return ((_a = u.department) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === department.toLowerCase(); })
306
+ .forEach(user => user.selected = true));
307
+ return users;
308
+ }
309
+ preSelectUsersByTitle(users) {
310
+ this.data.preSelections.titles
311
+ .forEach(title => users
312
+ .filter(u => { var _a; return ((_a = u.title) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === title.toLowerCase(); })
313
+ .forEach(user => user.selected = true));
314
+ return users;
315
+ }
316
+ preSelectUsersByGroupName(users) {
317
+ this.data.preSelections.groups
318
+ .forEach(groupName => {
319
+ var _a;
320
+ const group = (_a = this.groups) === null || _a === void 0 ? void 0 : _a.find(g => g.name.toLowerCase() === groupName.toLowerCase());
321
+ if (!group) {
322
+ return;
323
+ }
324
+ group.member.forEach(groupMemberDn => {
325
+ const user = users.find(u => u.distinguishedName === groupMemberDn);
326
+ if (!user) {
327
+ return;
328
+ }
329
+ user.selected = true;
330
+ });
331
+ });
332
+ return users;
333
+ }
334
+ //#endregion
335
+ setFilterPredicate() {
336
+ if (!this.dataSource) {
337
+ return;
338
+ }
339
+ this.dataSource.filterPredicate = (user, filter) => {
340
+ if (filter === '{selected:true}') {
341
+ return user.selected;
342
+ }
343
+ else {
344
+ const regex = new RegExp(filter, 'i'); // Case-insensitive
345
+ let match = false; // The end result - whether or not a employee matches the filter
346
+ const filterProperties = ['displayName'];
347
+ if (this.data.filterOptions.accountName) {
348
+ filterProperties.push('sAMAccountName');
349
+ }
350
+ if (this.data.filterOptions.title) {
351
+ filterProperties.push('title');
352
+ }
353
+ if (this.data.filterOptions.department) {
354
+ filterProperties.push('department');
355
+ }
356
+ if (this.data.filterOptions.phoneNumber) {
357
+ filterProperties.push('telephoneNumber');
358
+ }
359
+ // Match on the properties configured above
360
+ filterProperties
361
+ .forEach(field => {
362
+ // @ts-ignore
363
+ if (user[field] && user[field].match(regex)) {
364
+ match = true;
365
+ }
366
+ });
367
+ // Match on group membership (group name)
368
+ if (this.data.filterOptions.groupMembership) {
369
+ user.memberOf.forEach(groupDn => {
370
+ var _a;
371
+ const group = (_a = this.groups) === null || _a === void 0 ? void 0 : _a.find(group => group.distinguishedName === groupDn && group.name.match(regex));
372
+ if (group) {
373
+ match = true;
374
+ }
375
+ });
376
+ }
377
+ return match;
378
+ }
379
+ };
380
+ }
381
+ listenForFilterChanges() {
382
+ var _a;
383
+ (_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(); });
384
+ }
385
+ tooltip(user) {
386
+ return this.data.showGroupMembershipTooltips ?
387
+ user.memberOf
388
+ .map(groupDn => {
389
+ var _a, _b;
390
+ 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;
391
+ })
392
+ .sort((a, b) => a > b ? 1 : -1)
393
+ .join('\n') :
394
+ '';
395
+ }
396
+ }
397
+ 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 });
398
+ 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"] }] });
399
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.1", ngImport: i0, type: UserChooserComponent, decorators: [{
400
+ type: Component,
401
+ 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"] }]
402
+ }], ctorParameters: function () {
403
+ return [{ type: undefined, decorators: [{
404
+ type: Inject,
405
+ args: [MAT_DIALOG_DATA]
406
+ }] }, { type: i1.MatDialogRef }, { type: i2.ActiveDirectoryService }, { type: i3.SharePointService }];
407
+ }, propDecorators: { selectionList: [{
408
+ type: ViewChild,
409
+ args: [MatSelectionList]
410
+ }] } });
411
+
412
+ class UserFormFieldComponent {
413
+ //#endregion
414
+ //#region Lifecycle
415
+ constructor(dialog, activeDirectoryService, sharePointService) {
416
+ this.dialog = dialog;
417
+ this.activeDirectoryService = activeDirectoryService;
418
+ this.sharePointService = sharePointService;
419
+ //#region Fields
420
+ this.usersSelected = new EventEmitter();
421
+ this.placeholder = 'Select User(s)';
422
+ this.clickable = true;
423
+ /*
424
+ @Input() mode = UserChooserMode.Multiple;
425
+ @Input() preSelectAccountNames = true;
426
+ @Input() includeDisabledUsers = false;
427
+ @Input() parentOu = undefined;*/
428
+ this.accountNames = [];
429
+ this.users = undefined;
430
+ this.photos = undefined;
431
+ }
432
+ //#endregion
433
+ //#region Properties
434
+ get isEdge() {
435
+ return window.navigator.userAgent.indexOf('Edge') > -1;
436
+ }
437
+ ngOnInit() {
438
+ this.userChooserData = Object.assign(Object.assign({}, defaultUserChooserConfig), this.userChooserData);
439
+ // If users have been pre-selected in the config, store those in accountNames, which drives the UI of this component
440
+ this.accountNames = this.userChooserData.preSelections.accountNames;
441
+ this.getData();
442
+ }
443
+ //#endregion
444
+ //#region Events
445
+ selectUser() {
446
+ if (!this.clickable) {
447
+ return;
448
+ }
449
+ const data = Object.assign(Object.assign({}, this.userChooserData), { users: this.users, photos: this.photos });
450
+ this.dialog.open(UserChooserComponent, {
451
+ data: data
452
+ })
453
+ .afterClosed()
454
+ .subscribe(accountNames => {
455
+ if (!accountNames) {
456
+ return;
457
+ }
458
+ this.accountNames = accountNames;
459
+ this.usersSelected.emit(accountNames);
460
+ });
461
+ }
462
+ //#endregion
463
+ //#region Utilities
464
+ getData() {
465
+ forkJoin([
466
+ this.userChooserData.users ?
467
+ // Users were passed in
468
+ of(this.userChooserData.users) :
469
+ // Users need to be retrieved
470
+ this.activeDirectoryService.getUsers(false, this.userChooserData.includeDisabledUsers, this.userChooserData.parentOu),
471
+ this.userChooserData.photos ?
472
+ // Photos were passed in
473
+ of(this.userChooserData.photos) :
474
+ // Photos need to be retrieved
475
+ this.sharePointService.getPhotos()
476
+ ])
477
+ .subscribe(([users, photos]) => {
478
+ this.users = users;
479
+ this.photos = photos;
480
+ });
481
+ }
482
+ getUser(accountName) {
483
+ var _a;
484
+ return (_a = this.users) === null || _a === void 0 ? void 0 : _a.find(u => u.sAMAccountName.toLowerCase() === accountName.toLowerCase());
485
+ }
486
+ getPhoto(accountName) {
487
+ var _a, _b;
488
+ const user = this.getUser(accountName);
489
+ if (!user) {
490
+ return undefined;
491
+ }
492
+ return (_b = (_a = this.photos) === null || _a === void 0 ? void 0 : _a.find(p => {
493
+ var _a, _b, _c;
494
+ return (p.employeeNumber && p.employeeNumber.toString() === user.employeeNumber) ||
495
+ ((_a = p.accountName) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === user.sAMAccountName.toLowerCase() ||
496
+ ((_b = p.displayName) === null || _b === void 0 ? void 0 : _b.toLowerCase()) === user.displayName.toLowerCase() ||
497
+ ((_c = p.title) === null || _c === void 0 ? void 0 : _c.toLowerCase()) === user.displayName.toLowerCase();
498
+ })) === null || _b === void 0 ? void 0 : _b.encodedAbsUrl;
499
+ }
500
+ }
501
+ 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 });
502
+ 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]" }] });
503
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.1", ngImport: i0, type: UserFormFieldComponent, decorators: [{
504
+ type: Component,
505
+ 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"] }]
506
+ }], ctorParameters: function () { return [{ type: i1.MatDialog }, { type: i2.ActiveDirectoryService }, { type: i3.SharePointService }]; }, propDecorators: { usersSelected: [{
507
+ type: Output
508
+ }], placeholder: [{
509
+ type: Input
510
+ }], clickable: [{
511
+ type: Input
512
+ }], userChooserData: [{
513
+ type: Input
514
+ }] } });
515
+
516
+ class GuiModule {
517
+ }
518
+ GuiModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.1", ngImport: i0, type: GuiModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
519
+ GuiModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.2.1", ngImport: i0, type: GuiModule, declarations: [UserChooserComponent,
520
+ UserFormFieldComponent], imports: [CommonModule,
521
+ ReactiveFormsModule,
522
+ MatButtonModule,
523
+ MatDialogModule,
524
+ MatFormFieldModule,
525
+ MatIconModule,
526
+ MatInputModule,
527
+ MatListModule,
528
+ MatProgressSpinnerModule,
529
+ MatSlideToggleModule,
530
+ MatTableModule,
531
+ MatTooltipModule], exports: [UserChooserComponent,
532
+ UserFormFieldComponent] });
533
+ GuiModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.2.1", ngImport: i0, type: GuiModule, imports: [CommonModule,
534
+ ReactiveFormsModule,
535
+ MatButtonModule,
536
+ MatDialogModule,
537
+ MatFormFieldModule,
538
+ MatIconModule,
539
+ MatInputModule,
540
+ MatListModule,
541
+ MatProgressSpinnerModule,
542
+ MatSlideToggleModule,
543
+ MatTableModule,
544
+ MatTooltipModule] });
545
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.1", ngImport: i0, type: GuiModule, decorators: [{
546
+ type: NgModule,
547
+ args: [{
548
+ declarations: [
549
+ UserChooserComponent,
550
+ UserFormFieldComponent
551
+ ],
552
+ imports: [
553
+ CommonModule,
554
+ ReactiveFormsModule,
555
+ MatButtonModule,
556
+ MatDialogModule,
557
+ MatFormFieldModule,
558
+ MatIconModule,
559
+ MatInputModule,
560
+ MatListModule,
561
+ MatProgressSpinnerModule,
562
+ MatSlideToggleModule,
563
+ MatTableModule,
564
+ MatTooltipModule
565
+ ],
566
+ exports: [
567
+ UserChooserComponent,
568
+ UserFormFieldComponent
569
+ ]
570
+ }]
571
+ }] });
572
+
573
+ /**
574
+ * Generated bundle index. Do not edit.
575
+ */
576
+
577
+ export { GuiModule, UserChooserComponent, UserChooserMode, UserFormFieldComponent, defaultUserChooserConfig, defaultUserChooserFilterOptionsConfig, defaultUserChooserPreProcessingGroupConfig };
578
+ //# sourceMappingURL=cleavelandprice-ngx-lib-active-directory-gui.mjs.map