@cleavelandprice/ngx-lib 3.7.3 → 3.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/active-directory/active-directory.module.d.ts +11 -11
- package/active-directory/gui/components/user-chooser/user-chooser.component.d.ts +58 -58
- package/active-directory/gui/components/user-form-field/user-form-field.component.d.ts +29 -29
- package/active-directory/gui/gui.module.d.ts +25 -25
- package/active-directory/gui/index.d.ts +5 -5
- package/active-directory/gui/model/selectable-user.d.ts +5 -5
- package/active-directory/gui/model/user-chooser-data.d.ts +22 -22
- package/active-directory/gui/model/user-chooser-filter-options.d.ts +7 -7
- package/active-directory/gui/model/user-chooser-mode.d.ts +4 -4
- package/active-directory/gui/model/user-chooser-pre-processing-group.d.ts +6 -6
- package/active-directory/gui/public_api.d.ts +8 -8
- package/active-directory/index.d.ts +5 -5
- package/active-directory/model/ad-object-with-children.d.ts +4 -4
- package/active-directory/model/ad-object.d.ts +13 -13
- package/active-directory/model/cache-object.d.ts +4 -4
- package/active-directory/model/caching-config.d.ts +4 -4
- package/active-directory/model/cleaveland-price-user.d.ts +17 -17
- package/active-directory/model/group.d.ts +7 -7
- package/active-directory/model/logging-config.d.ts +6 -6
- package/active-directory/model/service-config.d.ts +8 -8
- package/active-directory/model/user-or-group.d.ts +7 -7
- package/active-directory/model/user.d.ts +23 -23
- package/active-directory/public_api.d.ts +11 -11
- package/active-directory/services/active-directory.service.d.ts +32 -32
- package/authentication/authentication.base.module.d.ts +7 -7
- package/authentication/index.d.ts +5 -5
- package/authentication/model/abstract-authentication-service.d.ts +16 -16
- package/authentication/model/authenticated-user.d.ts +9 -9
- package/authentication/model/authentication-request.d.ts +8 -8
- package/authentication/model/service-config.d.ts +8 -8
- package/authentication/object/index.d.ts +5 -5
- package/authentication/object/model/service-config.d.ts +4 -4
- package/authentication/object/object.module.d.ts +11 -11
- package/authentication/object/public_api.d.ts +3 -3
- package/authentication/object/services/authentication.service.d.ts +25 -25
- package/authentication/public_api.d.ts +5 -5
- package/authentication/token/gui/components/login/login.component.d.ts +14 -14
- package/authentication/token/gui/components/login-form/login-form.component.d.ts +29 -29
- package/authentication/token/gui/index.d.ts +5 -5
- package/authentication/token/gui/model/login-form-data.d.ts +4 -4
- package/authentication/token/gui/model/service-config.d.ts +5 -5
- package/authentication/token/gui/public_api.d.ts +6 -6
- package/authentication/token/gui/services/authentication.service.d.ts +15 -15
- package/authentication/token/gui/token-gui.module.d.ts +21 -21
- package/authentication/token/index.d.ts +5 -5
- package/authentication/token/model/authentication-token.d.ts +17 -17
- package/authentication/token/model/service-config.d.ts +5 -5
- package/authentication/token/public_api.d.ts +4 -4
- package/authentication/token/services/authentication.service.d.ts +24 -24
- package/authentication/token/token.module.d.ts +11 -11
- package/dialog/components/base/base.component.d.ts +22 -22
- package/dialog/components/choice/choice.component.d.ts +12 -12
- package/dialog/components/confirmation/confirmation.component.d.ts +12 -12
- package/dialog/components/input/input.component.d.ts +12 -12
- package/dialog/components/message/message.component.d.ts +12 -12
- package/dialog/dialog.module.d.ts +18 -18
- package/dialog/index.d.ts +5 -5
- package/dialog/model/confirmation-dialog-mode.d.ts +6 -6
- package/dialog/model/dialog-base-data.d.ts +10 -10
- package/dialog/model/dialog-choice-data.d.ts +4 -4
- package/dialog/model/dialog-type.d.ts +6 -6
- package/dialog/public_api.d.ts +9 -9
- package/esm2022/active-directory/active-directory.module.mjs +40 -0
- package/{esm2020 → esm2022}/active-directory/cleavelandprice-ngx-lib-active-directory.mjs +4 -4
- package/{esm2020 → esm2022}/active-directory/gui/cleavelandprice-ngx-lib-active-directory-gui.mjs +4 -4
- package/esm2022/active-directory/gui/components/user-chooser/user-chooser.component.mjs +375 -0
- package/esm2022/active-directory/gui/components/user-form-field/user-form-field.component.mjs +130 -0
- package/esm2022/active-directory/gui/gui.module.mjs +97 -0
- package/{esm2020 → esm2022}/active-directory/gui/model/selectable-user.mjs +1 -1
- package/{esm2020 → esm2022}/active-directory/gui/model/user-chooser-data.mjs +32 -32
- package/{esm2020 → esm2022}/active-directory/gui/model/user-chooser-filter-options.mjs +9 -9
- package/{esm2020 → esm2022}/active-directory/gui/model/user-chooser-mode.mjs +5 -5
- package/{esm2020 → esm2022}/active-directory/gui/model/user-chooser-pre-processing-group.mjs +8 -8
- package/{esm2020 → esm2022}/active-directory/gui/public_api.mjs +8 -8
- package/{esm2020 → esm2022}/active-directory/model/ad-object-with-children.mjs +1 -1
- package/{esm2020 → esm2022}/active-directory/model/ad-object.mjs +1 -1
- package/{esm2020 → esm2022}/active-directory/model/cache-object.mjs +2 -2
- package/{esm2020 → esm2022}/active-directory/model/caching-config.mjs +6 -6
- package/{esm2020 → esm2022}/active-directory/model/cleaveland-price-user.mjs +1 -1
- package/{esm2020 → esm2022}/active-directory/model/group.mjs +1 -1
- package/{esm2020 → esm2022}/active-directory/model/logging-config.mjs +8 -8
- package/{esm2020 → esm2022}/active-directory/model/service-config.mjs +11 -11
- package/{esm2020 → esm2022}/active-directory/model/user-or-group.mjs +1 -1
- package/{esm2020 → esm2022}/active-directory/model/user.mjs +1 -1
- package/{esm2020 → esm2022}/active-directory/public_api.mjs +11 -11
- package/esm2022/active-directory/services/active-directory.service.mjs +112 -0
- package/esm2022/authentication/authentication.base.module.mjs +20 -0
- package/{esm2020 → esm2022}/authentication/cleavelandprice-ngx-lib-authentication.mjs +4 -4
- package/{esm2020 → esm2022}/authentication/model/abstract-authentication-service.mjs +1 -1
- package/{esm2020 → esm2022}/authentication/model/authenticated-user.mjs +1 -1
- package/{esm2020 → esm2022}/authentication/model/authentication-request.mjs +1 -1
- package/{esm2020 → esm2022}/authentication/model/service-config.mjs +11 -11
- package/{esm2020 → esm2022}/authentication/object/cleavelandprice-ngx-lib-authentication-object.mjs +4 -4
- package/{esm2020 → esm2022}/authentication/object/model/service-config.mjs +8 -8
- package/esm2022/authentication/object/object.module.mjs +40 -0
- package/{esm2020 → esm2022}/authentication/object/public_api.mjs +3 -3
- package/esm2022/authentication/object/services/authentication.service.mjs +109 -0
- package/{esm2020 → esm2022}/authentication/public_api.mjs +5 -5
- package/{esm2020 → esm2022}/authentication/token/cleavelandprice-ngx-lib-authentication-token.mjs +4 -4
- package/{esm2020 → esm2022}/authentication/token/gui/cleavelandprice-ngx-lib-authentication-token-gui.mjs +4 -4
- package/esm2022/authentication/token/gui/components/login/login.component.mjs +45 -0
- package/esm2022/authentication/token/gui/components/login-form/login-form.component.mjs +74 -0
- package/{esm2020 → esm2022}/authentication/token/gui/model/login-form-data.mjs +1 -1
- package/{esm2020 → esm2022}/authentication/token/gui/model/service-config.mjs +9 -9
- package/{esm2020 → esm2022}/authentication/token/gui/public_api.mjs +6 -6
- package/esm2022/authentication/token/gui/services/authentication.service.mjs +79 -0
- package/esm2022/authentication/token/gui/token-gui.module.mjs +82 -0
- package/{esm2020 → esm2022}/authentication/token/model/authentication-token.mjs +1 -1
- package/{esm2020 → esm2022}/authentication/token/model/service-config.mjs +9 -9
- package/{esm2020 → esm2022}/authentication/token/public_api.mjs +4 -4
- package/esm2022/authentication/token/services/authentication.service.mjs +120 -0
- package/esm2022/authentication/token/token.module.mjs +40 -0
- package/{esm2020 → esm2022}/cleavelandprice-ngx-lib.mjs +4 -4
- package/{esm2020 → esm2022}/dialog/cleavelandprice-ngx-lib-dialog.mjs +4 -4
- package/esm2022/dialog/components/base/base.component.mjs +93 -0
- package/esm2022/dialog/components/choice/choice.component.mjs +24 -0
- package/esm2022/dialog/components/confirmation/confirmation.component.mjs +24 -0
- package/esm2022/dialog/components/input/input.component.mjs +24 -0
- package/esm2022/dialog/components/message/message.component.mjs +24 -0
- package/esm2022/dialog/dialog.module.mjs +69 -0
- package/{esm2020 → esm2022}/dialog/model/confirmation-dialog-mode.mjs +7 -7
- package/{esm2020 → esm2022}/dialog/model/dialog-base-data.mjs +1 -1
- package/{esm2020 → esm2022}/dialog/model/dialog-choice-data.mjs +1 -1
- package/{esm2020 → esm2022}/dialog/model/dialog-type.mjs +7 -7
- package/{esm2020 → esm2022}/dialog/public_api.mjs +9 -9
- package/{esm2020 → esm2022}/lib/model/app-path-config.mjs +1 -1
- package/{esm2020 → esm2022}/lib/model/app-type.mjs +1 -1
- package/{esm2020 → esm2022}/lib/model/app.mjs +1 -1
- package/esm2022/lib/model/service-config.mjs +21 -0
- package/esm2022/lib/ngx-lib.module.mjs +37 -0
- package/esm2022/lib/services/app-path-config.service.mjs +46 -0
- package/{esm2020 → esm2022}/msgraph/cleavelandprice-ngx-lib-msgraph.mjs +4 -4
- package/{esm2020 → esm2022}/msgraph/model/address.mjs +1 -1
- package/{esm2020 → esm2022}/msgraph/model/attendee.mjs +1 -1
- package/{esm2020 → esm2022}/msgraph/model/bulk-calendar-events.mjs +1 -1
- package/{esm2020 → esm2022}/msgraph/model/bulk-calendar-request.mjs +1 -1
- package/{esm2020 → esm2022}/msgraph/model/calendar-event.mjs +1 -1
- package/{esm2020 → esm2022}/msgraph/model/coordinates.mjs +1 -1
- package/{esm2020 → esm2022}/msgraph/model/email-address.mjs +1 -1
- package/{esm2020 → esm2022}/msgraph/model/location.mjs +1 -1
- package/{esm2020 → esm2022}/msgraph/model/online-meeting-info.mjs +1 -1
- package/{esm2020 → esm2022}/msgraph/model/patterned-recurrence.mjs +1 -1
- package/{esm2020 → esm2022}/msgraph/model/phone.mjs +1 -1
- package/{esm2020 → esm2022}/msgraph/model/recipient.mjs +1 -1
- package/{esm2020 → esm2022}/msgraph/model/recurrence-pattern.mjs +1 -1
- package/{esm2020 → esm2022}/msgraph/model/recurrence-range.mjs +1 -1
- package/{esm2020 → esm2022}/msgraph/model/response-status.mjs +1 -1
- package/{esm2020 → esm2022}/msgraph/model/room.mjs +5 -5
- package/{esm2020 → esm2022}/msgraph/model/user.mjs +131 -131
- package/esm2022/msgraph/msgraph.module.mjs +33 -0
- package/{esm2020 → esm2022}/msgraph/public_api.mjs +18 -18
- package/{esm2020 → esm2022}/public_api.mjs +9 -9
- package/{esm2020 → esm2022}/quill/cleavelandprice-ngx-lib-quill.mjs +4 -4
- package/esm2022/quill/components/editor/editor.component.mjs +297 -0
- package/esm2022/quill/components/raw/raw.component.mjs +25 -0
- package/{esm2020 → esm2022}/quill/mention/cleavelandprice-ngx-lib-quill-mention.mjs +4 -4
- package/esm2022/quill/mention/components/editor/editor.component.mjs +156 -0
- package/{esm2020 → esm2022}/quill/mention/model/buttons.mjs +3 -3
- package/{esm2020 → esm2022}/quill/mention/model/config.mjs +3 -3
- package/{esm2020 → esm2022}/quill/mention/model/dialog-data.mjs +1 -1
- package/{esm2020 → esm2022}/quill/mention/model/icons.mjs +3 -3
- package/{esm2020 → esm2022}/quill/mention/model/tooltips.mjs +3 -3
- package/{esm2020 → esm2022}/quill/mention/public_api.mjs +7 -7
- package/esm2022/quill/mention/quill-mention.module.mjs +66 -0
- package/{esm2020 → esm2022}/quill/model/buttons.mjs +51 -51
- package/{esm2020 → esm2022}/quill/model/config.mjs +39 -39
- package/{esm2020 → esm2022}/quill/model/dialog-data.mjs +1 -1
- package/{esm2020 → esm2022}/quill/model/icons.mjs +8 -8
- package/{esm2020 → esm2022}/quill/model/tooltips.mjs +54 -54
- package/{esm2020 → esm2022}/quill/public_api.mjs +8 -8
- package/esm2022/quill/quill.module.mjs +79 -0
- package/{esm2020 → esm2022}/sharepoint/cleavelandprice-ngx-lib-sharepoint.mjs +4 -4
- package/esm2022/sharepoint/components/employee-photo/employee-photo.component.mjs +38 -0
- package/{esm2020 → esm2022}/sharepoint/model/base-item.mjs +1 -1
- package/{esm2020 → esm2022}/sharepoint/model/base-request-credential.mjs +1 -1
- package/{esm2020 → esm2022}/sharepoint/model/base-request.mjs +1 -1
- package/{esm2020 → esm2022}/sharepoint/model/cache-object.mjs +2 -2
- package/{esm2020 → esm2022}/sharepoint/model/file-request.mjs +1 -1
- package/{esm2020 → esm2022}/sharepoint/model/folder-request.mjs +1 -1
- package/{esm2020 → esm2022}/sharepoint/model/list-item.mjs +1 -1
- package/{esm2020 → esm2022}/sharepoint/model/list-items-request.mjs +1 -1
- package/{esm2020 → esm2022}/sharepoint/model/photo-item.mjs +1 -1
- package/{esm2020 → esm2022}/sharepoint/model/service-config.mjs +28 -28
- package/{esm2020 → esm2022}/sharepoint/model/uri-request.mjs +1 -1
- package/{esm2020 → esm2022}/sharepoint/model/user-request.mjs +1 -1
- package/{esm2020 → esm2022}/sharepoint/model/user.mjs +1 -1
- package/esm2022/sharepoint/pipes/employee-photo-url.pipe.mjs +39 -0
- package/{esm2020 → esm2022}/sharepoint/public_api.mjs +16 -16
- package/esm2022/sharepoint/services/sharepoint.service.mjs +149 -0
- package/esm2022/sharepoint/sharepoint.module.mjs +50 -0
- package/{esm2020 → esm2022}/upload/cleavelandprice-ngx-lib-upload.mjs +4 -4
- package/esm2022/upload/components/upload/upload.component.mjs +35 -0
- package/esm2022/upload/components/upload-dialog/upload-dialog.component.mjs +87 -0
- package/{esm2020 → esm2022}/upload/model/database-file-info.mjs +1 -1
- package/{esm2020 → esm2022}/upload/model/file-upload-request.mjs +1 -1
- package/{esm2020 → esm2022}/upload/model/filesystem-file-info.mjs +1 -1
- package/{esm2020 → esm2022}/upload/model/service-config.mjs +15 -15
- package/{esm2020 → esm2022}/upload/public_api.mjs +8 -8
- package/esm2022/upload/services/upload.service.mjs +92 -0
- package/esm2022/upload/upload.module.mjs +66 -0
- package/{esm2020 → esm2022}/url-utilities/cleavelandprice-ngx-lib-url-utilities.mjs +4 -4
- package/esm2022/url-utilities/pipes/safe-resource-url.pipe.mjs +21 -0
- package/esm2022/url-utilities/pipes/safe-url.pipe.mjs +21 -0
- package/esm2022/url-utilities/pipes/uri-scheme.pipe.mjs +106 -0
- package/{esm2020 → esm2022}/url-utilities/public_api.mjs +4 -4
- package/esm2022/url-utilities/url-utilities.module.mjs +35 -0
- package/{fesm2020 → fesm2022}/cleavelandprice-ngx-lib-active-directory-gui.mjs +586 -587
- package/{fesm2020 → fesm2022}/cleavelandprice-ngx-lib-active-directory-gui.mjs.map +1 -1
- package/{fesm2020 → fesm2022}/cleavelandprice-ngx-lib-active-directory.mjs +155 -156
- package/{fesm2020 → fesm2022}/cleavelandprice-ngx-lib-active-directory.mjs.map +1 -1
- package/{fesm2020 → fesm2022}/cleavelandprice-ngx-lib-authentication-object.mjs +141 -142
- package/{fesm2020 → fesm2022}/cleavelandprice-ngx-lib-authentication-object.mjs.map +1 -1
- package/{fesm2020 → fesm2022}/cleavelandprice-ngx-lib-authentication-token-gui.mjs +232 -233
- package/{fesm2020 → fesm2022}/cleavelandprice-ngx-lib-authentication-token-gui.mjs.map +1 -1
- package/{fesm2020 → fesm2022}/cleavelandprice-ngx-lib-authentication-token.mjs +152 -153
- package/{fesm2020 → fesm2022}/cleavelandprice-ngx-lib-authentication-token.mjs.map +1 -1
- package/{fesm2015 → fesm2022}/cleavelandprice-ngx-lib-authentication.mjs +25 -26
- package/{fesm2020 → fesm2022}/cleavelandprice-ngx-lib-authentication.mjs.map +1 -1
- package/{fesm2020 → fesm2022}/cleavelandprice-ngx-lib-dialog.mjs +205 -206
- package/{fesm2020 → fesm2022}/cleavelandprice-ngx-lib-dialog.mjs.map +1 -1
- package/{fesm2020 → fesm2022}/cleavelandprice-ngx-lib-msgraph.mjs +161 -162
- package/{fesm2020 → fesm2022}/cleavelandprice-ngx-lib-msgraph.mjs.map +1 -1
- package/{fesm2020 → fesm2022}/cleavelandprice-ngx-lib-quill-mention.mjs +188 -189
- package/{fesm2020 → fesm2022}/cleavelandprice-ngx-lib-quill-mention.mjs.map +1 -1
- package/{fesm2020 → fesm2022}/cleavelandprice-ngx-lib-quill.mjs +492 -493
- package/{fesm2020 → fesm2022}/cleavelandprice-ngx-lib-quill.mjs.map +1 -1
- package/{fesm2020 → fesm2022}/cleavelandprice-ngx-lib-sharepoint.mjs +269 -270
- package/{fesm2020 → fesm2022}/cleavelandprice-ngx-lib-sharepoint.mjs.map +1 -1
- package/{fesm2020 → fesm2022}/cleavelandprice-ngx-lib-upload.mjs +250 -251
- package/{fesm2020 → fesm2022}/cleavelandprice-ngx-lib-upload.mjs.map +1 -1
- package/{fesm2015 → fesm2022}/cleavelandprice-ngx-lib-url-utilities.mjs +159 -160
- package/fesm2022/cleavelandprice-ngx-lib-url-utilities.mjs.map +1 -0
- package/{fesm2020 → fesm2022}/cleavelandprice-ngx-lib.mjs +91 -92
- package/{fesm2020 → fesm2022}/cleavelandprice-ngx-lib.mjs.map +1 -1
- package/index.d.ts +5 -5
- package/lib/model/app-path-config.d.ts +10 -10
- package/lib/model/app-type.d.ts +5 -5
- package/lib/model/app.d.ts +16 -16
- package/lib/model/service-config.d.ts +6 -6
- package/lib/ngx-lib.module.d.ts +10 -10
- package/lib/services/app-path-config.service.d.ts +20 -20
- package/msgraph/index.d.ts +5 -5
- package/msgraph/model/address.d.ts +7 -7
- package/msgraph/model/attendee.d.ts +13 -13
- package/msgraph/model/bulk-calendar-events.d.ts +5 -5
- package/msgraph/model/bulk-calendar-request.d.ts +3 -3
- package/msgraph/model/calendar-event.d.ts +53 -53
- package/msgraph/model/coordinates.d.ts +7 -7
- package/msgraph/model/email-address.d.ts +4 -4
- package/msgraph/model/location.d.ts +12 -12
- package/msgraph/model/online-meeting-info.d.ts +9 -9
- package/msgraph/model/patterned-recurrence.d.ts +6 -6
- package/msgraph/model/phone.d.ts +4 -4
- package/msgraph/model/recipient.d.ts +4 -4
- package/msgraph/model/recurrence-pattern.d.ts +9 -9
- package/msgraph/model/recurrence-range.d.ts +7 -7
- package/msgraph/model/response-status.d.ts +4 -4
- package/msgraph/model/room.d.ts +22 -22
- package/msgraph/model/user.d.ts +29 -29
- package/msgraph/msgraph.module.d.ts +10 -10
- package/msgraph/public_api.d.ts +18 -18
- package/package.json +61 -93
- package/public_api.d.ts +6 -6
- package/quill/components/editor/editor.component.d.ts +53 -53
- package/quill/components/raw/raw.component.d.ts +7 -7
- package/quill/index.d.ts +5 -5
- package/quill/mention/components/editor/editor.component.d.ts +20 -20
- package/quill/mention/index.d.ts +5 -5
- package/quill/mention/model/buttons.d.ts +3 -3
- package/quill/mention/model/config.d.ts +3 -3
- package/quill/mention/model/dialog-data.d.ts +5 -5
- package/quill/mention/model/icons.d.ts +3 -3
- package/quill/mention/model/tooltips.d.ts +3 -3
- package/quill/mention/public_api.d.ts +7 -7
- package/quill/mention/quill-mention.module.d.ts +17 -17
- package/quill/model/buttons.d.ts +29 -29
- package/quill/model/config.d.ts +30 -30
- package/quill/model/dialog-data.d.ts +21 -21
- package/quill/model/icons.d.ts +6 -6
- package/quill/model/tooltips.d.ts +32 -32
- package/quill/public_api.d.ts +8 -8
- package/quill/quill.module.d.ts +20 -20
- package/sharepoint/components/employee-photo/employee-photo.component.d.ts +16 -16
- package/sharepoint/index.d.ts +5 -5
- package/sharepoint/model/base-item.d.ts +4 -4
- package/sharepoint/model/base-request-credential.d.ts +4 -4
- package/sharepoint/model/base-request.d.ts +8 -8
- package/sharepoint/model/cache-object.d.ts +4 -4
- package/sharepoint/model/file-request.d.ts +4 -4
- package/sharepoint/model/folder-request.d.ts +4 -4
- package/sharepoint/model/list-item.d.ts +10 -10
- package/sharepoint/model/list-items-request.d.ts +5 -5
- package/sharepoint/model/photo-item.d.ts +11 -11
- package/sharepoint/model/service-config.d.ts +23 -23
- package/sharepoint/model/uri-request.d.ts +4 -4
- package/sharepoint/model/user-request.d.ts +4 -4
- package/sharepoint/model/user.d.ts +12 -12
- package/sharepoint/pipes/employee-photo-url.pipe.d.ts +12 -12
- package/sharepoint/public_api.d.ts +16 -16
- package/sharepoint/services/sharepoint.service.d.ts +25 -25
- package/sharepoint/sharepoint.module.d.ts +13 -13
- package/upload/components/upload/upload.component.d.ts +15 -15
- package/upload/components/upload-dialog/upload-dialog.component.d.ts +24 -24
- package/upload/index.d.ts +5 -5
- package/upload/model/database-file-info.d.ts +7 -7
- package/upload/model/file-upload-request.d.ts +6 -6
- package/upload/model/filesystem-file-info.d.ts +12 -12
- package/upload/model/service-config.d.ts +15 -15
- package/upload/public_api.d.ts +8 -8
- package/upload/services/upload.service.d.ts +18 -18
- package/upload/upload.module.d.ts +17 -17
- package/url-utilities/index.d.ts +5 -5
- package/url-utilities/pipes/safe-resource-url.pipe.d.ts +10 -10
- package/url-utilities/pipes/safe-url.pipe.d.ts +10 -10
- package/url-utilities/pipes/uri-scheme.pipe.d.ts +9 -9
- package/url-utilities/public_api.d.ts +4 -4
- package/url-utilities/url-utilities.module.d.ts +10 -10
- package/esm2020/active-directory/active-directory.module.mjs +0 -39
- package/esm2020/active-directory/gui/components/user-chooser/user-chooser.component.mjs +0 -374
- package/esm2020/active-directory/gui/components/user-form-field/user-form-field.component.mjs +0 -129
- package/esm2020/active-directory/gui/gui.module.mjs +0 -96
- package/esm2020/active-directory/services/active-directory.service.mjs +0 -111
- package/esm2020/authentication/authentication.base.module.mjs +0 -19
- package/esm2020/authentication/object/object.module.mjs +0 -39
- package/esm2020/authentication/object/services/authentication.service.mjs +0 -108
- package/esm2020/authentication/token/gui/components/login/login.component.mjs +0 -44
- package/esm2020/authentication/token/gui/components/login-form/login-form.component.mjs +0 -73
- package/esm2020/authentication/token/gui/services/authentication.service.mjs +0 -78
- package/esm2020/authentication/token/gui/token-gui.module.mjs +0 -81
- package/esm2020/authentication/token/services/authentication.service.mjs +0 -119
- package/esm2020/authentication/token/token.module.mjs +0 -39
- package/esm2020/dialog/components/base/base.component.mjs +0 -92
- package/esm2020/dialog/components/choice/choice.component.mjs +0 -23
- package/esm2020/dialog/components/confirmation/confirmation.component.mjs +0 -23
- package/esm2020/dialog/components/input/input.component.mjs +0 -23
- package/esm2020/dialog/components/message/message.component.mjs +0 -23
- package/esm2020/dialog/dialog.module.mjs +0 -68
- package/esm2020/lib/model/service-config.mjs +0 -21
- package/esm2020/lib/ngx-lib.module.mjs +0 -36
- package/esm2020/lib/services/app-path-config.service.mjs +0 -45
- package/esm2020/msgraph/msgraph.module.mjs +0 -32
- package/esm2020/quill/components/editor/editor.component.mjs +0 -296
- package/esm2020/quill/components/raw/raw.component.mjs +0 -24
- package/esm2020/quill/mention/components/editor/editor.component.mjs +0 -155
- package/esm2020/quill/mention/quill-mention.module.mjs +0 -65
- package/esm2020/quill/quill.module.mjs +0 -78
- package/esm2020/sharepoint/components/employee-photo/employee-photo.component.mjs +0 -37
- package/esm2020/sharepoint/pipes/employee-photo-url.pipe.mjs +0 -38
- package/esm2020/sharepoint/services/sharepoint.service.mjs +0 -148
- package/esm2020/sharepoint/sharepoint.module.mjs +0 -49
- package/esm2020/upload/components/upload/upload.component.mjs +0 -34
- package/esm2020/upload/components/upload-dialog/upload-dialog.component.mjs +0 -86
- package/esm2020/upload/services/upload.service.mjs +0 -91
- package/esm2020/upload/upload.module.mjs +0 -65
- package/esm2020/url-utilities/pipes/safe-resource-url.pipe.mjs +0 -20
- package/esm2020/url-utilities/pipes/safe-url.pipe.mjs +0 -20
- package/esm2020/url-utilities/pipes/uri-scheme.pipe.mjs +0 -105
- package/esm2020/url-utilities/url-utilities.module.mjs +0 -34
- package/fesm2015/cleavelandprice-ngx-lib-active-directory-gui.mjs +0 -652
- package/fesm2015/cleavelandprice-ngx-lib-active-directory-gui.mjs.map +0 -1
- package/fesm2015/cleavelandprice-ngx-lib-active-directory.mjs +0 -187
- package/fesm2015/cleavelandprice-ngx-lib-active-directory.mjs.map +0 -1
- package/fesm2015/cleavelandprice-ngx-lib-authentication-object.mjs +0 -163
- package/fesm2015/cleavelandprice-ngx-lib-authentication-object.mjs.map +0 -1
- package/fesm2015/cleavelandprice-ngx-lib-authentication-token-gui.mjs +0 -281
- package/fesm2015/cleavelandprice-ngx-lib-authentication-token-gui.mjs.map +0 -1
- package/fesm2015/cleavelandprice-ngx-lib-authentication-token.mjs +0 -175
- package/fesm2015/cleavelandprice-ngx-lib-authentication-token.mjs.map +0 -1
- package/fesm2015/cleavelandprice-ngx-lib-authentication.mjs.map +0 -1
- package/fesm2015/cleavelandprice-ngx-lib-dialog.mjs +0 -251
- package/fesm2015/cleavelandprice-ngx-lib-dialog.mjs.map +0 -1
- package/fesm2015/cleavelandprice-ngx-lib-msgraph.mjs +0 -178
- package/fesm2015/cleavelandprice-ngx-lib-msgraph.mjs.map +0 -1
- package/fesm2015/cleavelandprice-ngx-lib-quill-mention.mjs +0 -230
- package/fesm2015/cleavelandprice-ngx-lib-quill-mention.mjs.map +0 -1
- package/fesm2015/cleavelandprice-ngx-lib-quill.mjs +0 -539
- package/fesm2015/cleavelandprice-ngx-lib-quill.mjs.map +0 -1
- package/fesm2015/cleavelandprice-ngx-lib-sharepoint.mjs +0 -310
- package/fesm2015/cleavelandprice-ngx-lib-sharepoint.mjs.map +0 -1
- package/fesm2015/cleavelandprice-ngx-lib-upload.mjs +0 -288
- package/fesm2015/cleavelandprice-ngx-lib-upload.mjs.map +0 -1
- package/fesm2015/cleavelandprice-ngx-lib-url-utilities.mjs.map +0 -1
- package/fesm2015/cleavelandprice-ngx-lib.mjs +0 -113
- package/fesm2015/cleavelandprice-ngx-lib.mjs.map +0 -1
- package/fesm2020/cleavelandprice-ngx-lib-authentication.mjs +0 -39
- package/fesm2020/cleavelandprice-ngx-lib-url-utilities.mjs +0 -177
- package/fesm2020/cleavelandprice-ngx-lib-url-utilities.mjs.map +0 -1
|
@@ -31,608 +31,607 @@ import { MatTooltipModule } from '@angular/material/tooltip';
|
|
|
31
31
|
import * as i10$1 from '@angular/material/progress-bar';
|
|
32
32
|
import { MatProgressBarModule } from '@angular/material/progress-bar';
|
|
33
33
|
|
|
34
|
-
class UserChooserFilterOptions {
|
|
35
|
-
constructor() {
|
|
36
|
-
this.accountName = true;
|
|
37
|
-
this.department = true;
|
|
38
|
-
this.groupMembership = false;
|
|
39
|
-
this.phoneNumber = true;
|
|
40
|
-
this.title = true;
|
|
41
|
-
}
|
|
34
|
+
class UserChooserFilterOptions {
|
|
35
|
+
constructor() {
|
|
36
|
+
this.accountName = true;
|
|
37
|
+
this.department = true;
|
|
38
|
+
this.groupMembership = false;
|
|
39
|
+
this.phoneNumber = true;
|
|
40
|
+
this.title = true;
|
|
41
|
+
}
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
var UserChooserMode;
|
|
45
|
-
(function (UserChooserMode) {
|
|
46
|
-
UserChooserMode[UserChooserMode["Single"] = 0] = "Single";
|
|
47
|
-
UserChooserMode[UserChooserMode["Multiple"] = 1] = "Multiple";
|
|
44
|
+
var UserChooserMode;
|
|
45
|
+
(function (UserChooserMode) {
|
|
46
|
+
UserChooserMode[UserChooserMode["Single"] = 0] = "Single";
|
|
47
|
+
UserChooserMode[UserChooserMode["Multiple"] = 1] = "Multiple";
|
|
48
48
|
})(UserChooserMode || (UserChooserMode = {}));
|
|
49
49
|
|
|
50
|
-
class UserChooserPreProcessingGroup {
|
|
51
|
-
constructor() {
|
|
52
|
-
this.accountNames = [];
|
|
53
|
-
this.departments = [];
|
|
54
|
-
this.groups = [];
|
|
55
|
-
this.titles = [];
|
|
56
|
-
}
|
|
50
|
+
class UserChooserPreProcessingGroup {
|
|
51
|
+
constructor() {
|
|
52
|
+
this.accountNames = [];
|
|
53
|
+
this.departments = [];
|
|
54
|
+
this.groups = [];
|
|
55
|
+
this.titles = [];
|
|
56
|
+
}
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
class UserChooserData {
|
|
60
|
-
constructor() {
|
|
61
|
-
// Should the dialog close automatically when the user chooses an item?
|
|
62
|
-
// Applies to single-user mode only
|
|
63
|
-
this.closeWhenSelectionMade = false;
|
|
64
|
-
// If the component is tasked with pulling Active Directory users (default setting),
|
|
65
|
-
// should that include disabled users?
|
|
66
|
-
this.includeDisabledUsers = false;
|
|
67
|
-
// If true, the component will return an array of Active Directory User objects.
|
|
68
|
-
// If false (default), the component will return an array of user account names.
|
|
69
|
-
this.returnUserObjects = false;
|
|
70
|
-
// Should the dialog include hover tooptips for each user that displays their group membership
|
|
71
|
-
// You probably don't want this, which is why the default is false
|
|
72
|
-
this.showGroupMembershipTooltips = false;
|
|
73
|
-
// Should the user phone number be displayed next to their name in the dialog
|
|
74
|
-
this.showPhone = true;
|
|
75
|
-
// Title displayed in the dialog
|
|
76
|
-
this.title = 'Select User(s)';
|
|
77
|
-
// Single or Multi mode
|
|
78
|
-
this.mode = UserChooserMode.Single;
|
|
79
|
-
// As the user types into the filter field, the list of users is filtered.
|
|
80
|
-
// The filterOptions determine which user properties are taken into consideration for that filter.
|
|
81
|
-
// Note, displayName is always included (hard-coded), and is therefore not a filter option.
|
|
82
|
-
this.filterOptions = new UserChooserFilterOptions();
|
|
83
|
-
this.exclusions = new UserChooserPreProcessingGroup();
|
|
84
|
-
this.inclusions = new UserChooserPreProcessingGroup();
|
|
85
|
-
this.preSelections = new UserChooserPreProcessingGroup();
|
|
86
|
-
}
|
|
59
|
+
class UserChooserData {
|
|
60
|
+
constructor() {
|
|
61
|
+
// Should the dialog close automatically when the user chooses an item?
|
|
62
|
+
// Applies to single-user mode only
|
|
63
|
+
this.closeWhenSelectionMade = false;
|
|
64
|
+
// If the component is tasked with pulling Active Directory users (default setting),
|
|
65
|
+
// should that include disabled users?
|
|
66
|
+
this.includeDisabledUsers = false;
|
|
67
|
+
// If true, the component will return an array of Active Directory User objects.
|
|
68
|
+
// If false (default), the component will return an array of user account names.
|
|
69
|
+
this.returnUserObjects = false;
|
|
70
|
+
// Should the dialog include hover tooptips for each user that displays their group membership
|
|
71
|
+
// You probably don't want this, which is why the default is false
|
|
72
|
+
this.showGroupMembershipTooltips = false;
|
|
73
|
+
// Should the user phone number be displayed next to their name in the dialog
|
|
74
|
+
this.showPhone = true;
|
|
75
|
+
// Title displayed in the dialog
|
|
76
|
+
this.title = 'Select User(s)';
|
|
77
|
+
// Single or Multi mode
|
|
78
|
+
this.mode = UserChooserMode.Single;
|
|
79
|
+
// As the user types into the filter field, the list of users is filtered.
|
|
80
|
+
// The filterOptions determine which user properties are taken into consideration for that filter.
|
|
81
|
+
// Note, displayName is always included (hard-coded), and is therefore not a filter option.
|
|
82
|
+
this.filterOptions = new UserChooserFilterOptions();
|
|
83
|
+
this.exclusions = new UserChooserPreProcessingGroup();
|
|
84
|
+
this.inclusions = new UserChooserPreProcessingGroup();
|
|
85
|
+
this.preSelections = new UserChooserPreProcessingGroup();
|
|
86
|
+
}
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
-
class UserChooserComponent {
|
|
90
|
-
//#endregion
|
|
91
|
-
//#region
|
|
92
|
-
|
|
93
|
-
this.data
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
this.
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
}
|
|
128
|
-
ngOnInit() {
|
|
129
|
-
this.getData();
|
|
130
|
-
this.listenForFilterChanges();
|
|
131
|
-
}
|
|
132
|
-
ngAfterViewChecked() {
|
|
133
|
-
if (this.filterInputFocused || !this.filterInput) {
|
|
134
|
-
// Control not ready yet, or it has already been given focus
|
|
135
|
-
return;
|
|
136
|
-
}
|
|
137
|
-
this.filterInputFocused = true;
|
|
138
|
-
this.filterInput?.nativeElement.focus();
|
|
139
|
-
}
|
|
140
|
-
//#endregion
|
|
141
|
-
//#region Events
|
|
142
|
-
listSelectionChanged(options) {
|
|
143
|
-
if (this.data.mode === UserChooserMode.Single &&
|
|
144
|
-
this.selectedOptions.length &&
|
|
145
|
-
this.data.closeWhenSelectionMade) {
|
|
146
|
-
this.close();
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
optionSelectionChanged(option) {
|
|
150
|
-
const user = this.dataSource?.data
|
|
151
|
-
.find(u => u.sAMAccountName.toLocaleLowerCase() === option.value.sAMAccountName.toLowerCase());
|
|
152
|
-
if (user) {
|
|
153
|
-
user.selected = option.selected;
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
hideUnselectedChanged(selected) {
|
|
157
|
-
this.filterForm.get('filter')?.setValue(selected ? '{selected:true}' : null);
|
|
158
|
-
}
|
|
159
|
-
selectAll() {
|
|
160
|
-
this.selectionList?.selectAll();
|
|
161
|
-
if (this.selectionList?.options) {
|
|
162
|
-
this.listSelectionChanged(this.selectionList?.options.toArray());
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
deselectAll() {
|
|
166
|
-
this.selectionList?.deselectAll();
|
|
167
|
-
}
|
|
168
|
-
//#endregion
|
|
169
|
-
//#region Utilities
|
|
170
|
-
getData() {
|
|
171
|
-
const dataObservables = [
|
|
172
|
-
this.data.users ?
|
|
173
|
-
// Users were passed in
|
|
174
|
-
of(this.data.users) :
|
|
175
|
-
// Users need to be retrieved
|
|
176
|
-
this.activeDirectoryService.getUsers(false, this.data.includeDisabledUsers, this.data.parentOu),
|
|
177
|
-
this.data.photos ?
|
|
178
|
-
// Photos were passed in
|
|
179
|
-
of(this.data.photos) :
|
|
180
|
-
// Photos need to be retrieved
|
|
181
|
-
this.sharePointService.getPhotos()
|
|
182
|
-
];
|
|
183
|
-
// Do we need AD groups?
|
|
184
|
-
if (this.adGroupsNeeded) {
|
|
185
|
-
this.data.groups ?
|
|
186
|
-
// Groups were passed in
|
|
187
|
-
of(this.data.groups) :
|
|
188
|
-
// Groups need to be retrieved
|
|
189
|
-
dataObservables.push(this.activeDirectoryService.getGroups());
|
|
190
|
-
}
|
|
191
|
-
forkJoin(dataObservables)
|
|
192
|
-
//.subscribe(([users, photos]) => {
|
|
193
|
-
.subscribe(data => {
|
|
194
|
-
// Need groups in place before we handle exclusions/inclusions/pre-selections
|
|
195
|
-
this.groups = this.adGroupsNeeded ? data[2] : null;
|
|
196
|
-
let users = data[0];
|
|
197
|
-
users.forEach(u => u.selected = false); // In case existing data was re-used
|
|
198
|
-
users = this.includeUsersByAccountName(users);
|
|
199
|
-
users = this.includeUsersByGroupName(users);
|
|
200
|
-
users = this.includeUsersByDepartment(users);
|
|
201
|
-
users = this.includeUsersByTitle(users);
|
|
202
|
-
users = this.excludeUsersByAccountName(users);
|
|
203
|
-
users = this.excludeUsersByGroupName(users);
|
|
204
|
-
users = this.excludeUsersByDepartment(users);
|
|
205
|
-
users = this.excludeUsersByTitle(users);
|
|
206
|
-
users = this.preSelectUsersByAccountName(users);
|
|
207
|
-
users = this.preSelectUsersByGroupName(users);
|
|
208
|
-
users = this.preSelectUsersByDepartment(users);
|
|
209
|
-
users = this.preSelectUsersByTitle(users);
|
|
210
|
-
this.dataSource = new MatTableDataSource(users);
|
|
211
|
-
this.photos = data[1];
|
|
212
|
-
this.setFilterPredicate();
|
|
213
|
-
});
|
|
214
|
-
}
|
|
215
|
-
close() {
|
|
216
|
-
if (!this.selectedUsers) {
|
|
217
|
-
this.dialogRef.close();
|
|
218
|
-
return;
|
|
219
|
-
}
|
|
220
|
-
const value = this.selectedUsers
|
|
221
|
-
.map(u => this.data.returnUserObjects ? u : u.sAMAccountName);
|
|
222
|
-
this.dialogRef.close(this.data.mode === UserChooserMode.Multiple ?
|
|
223
|
-
value :
|
|
224
|
-
value[0]);
|
|
225
|
-
}
|
|
226
|
-
getPhoto(user) {
|
|
227
|
-
return this.photos?.find(p => (p.employeeNumber && p.employeeNumber.toString() === user.employeeNumber) ||
|
|
228
|
-
p.accountName?.toLowerCase() === user.sAMAccountName.toLowerCase() ||
|
|
229
|
-
p.displayName?.toLowerCase() === user.displayName.toLowerCase() ||
|
|
230
|
-
p.title?.toLowerCase() === user.displayName.toLowerCase())?.encodedAbsUrl;
|
|
231
|
-
}
|
|
232
|
-
//#region Exclusions - won't be included in the dataSource at all
|
|
233
|
-
excludeUsersByAccountName(users) {
|
|
234
|
-
this.data.exclusions.accountNames
|
|
235
|
-
.forEach(accountName => {
|
|
236
|
-
const index = users.findIndex(u => u.sAMAccountName.toLowerCase() === accountName.toLowerCase());
|
|
237
|
-
if (index === -1) {
|
|
238
|
-
return;
|
|
239
|
-
}
|
|
240
|
-
users.splice(index, 1);
|
|
241
|
-
});
|
|
242
|
-
return users;
|
|
243
|
-
}
|
|
244
|
-
excludeUsersByGroupName(users) {
|
|
245
|
-
this.data.exclusions.groups
|
|
246
|
-
.forEach(groupName => {
|
|
247
|
-
const group = this.groups?.find(g => g.name.toLowerCase() === groupName.toLowerCase());
|
|
248
|
-
if (!group) {
|
|
249
|
-
return;
|
|
250
|
-
}
|
|
251
|
-
group.member.forEach(groupMemberDn => {
|
|
252
|
-
const index = users.findIndex(u => u.distinguishedName === groupMemberDn);
|
|
253
|
-
if (index === -1) {
|
|
254
|
-
return;
|
|
255
|
-
}
|
|
256
|
-
users.splice(index, 1);
|
|
257
|
-
});
|
|
258
|
-
});
|
|
259
|
-
return users;
|
|
260
|
-
}
|
|
261
|
-
excludeUsersByDepartment(users) {
|
|
262
|
-
this.data.exclusions.departments
|
|
263
|
-
.forEach(department => {
|
|
264
|
-
const excludedUsers = users.filter(u => u.department?.toLowerCase() === department.toLowerCase());
|
|
265
|
-
excludedUsers.forEach(user => {
|
|
266
|
-
const index = users.indexOf(user);
|
|
267
|
-
users.splice(index, 1);
|
|
268
|
-
});
|
|
269
|
-
});
|
|
270
|
-
return users;
|
|
271
|
-
}
|
|
272
|
-
excludeUsersByTitle(users) {
|
|
273
|
-
this.data.exclusions.titles
|
|
274
|
-
.forEach(title => {
|
|
275
|
-
const excludedUsers = users.filter(u => u.title?.toLowerCase() === title.toLowerCase());
|
|
276
|
-
excludedUsers.forEach(user => {
|
|
277
|
-
const index = users.indexOf(user);
|
|
278
|
-
users.splice(index, 1);
|
|
279
|
-
});
|
|
280
|
-
});
|
|
281
|
-
return users;
|
|
282
|
-
}
|
|
283
|
-
//#endregion
|
|
284
|
-
//#region Inclusions - only these will be included in the dataSource
|
|
285
|
-
includeUsersByAccountName(users) {
|
|
286
|
-
return users.filter(user => this.data.inclusions.accountNames.length === 0 || // No account inclusions specified
|
|
287
|
-
this.data.inclusions.accountNames.find(accountName => accountName.toLowerCase() === user.sAMAccountName.toLowerCase()));
|
|
288
|
-
}
|
|
289
|
-
includeUsersByDepartment(users) {
|
|
290
|
-
return users.filter(user => this.data.inclusions.departments.length === 0 || // No department inclusions specified
|
|
291
|
-
this.data.inclusions.departments.find(department => department.toLowerCase() === user.department?.toLowerCase()));
|
|
292
|
-
}
|
|
293
|
-
includeUsersByTitle(users) {
|
|
294
|
-
return users.filter(user => this.data.inclusions.titles.length === 0 || // No title inclusions specified
|
|
295
|
-
this.data.inclusions.titles.find(title => title.toLowerCase() === user.title?.toLowerCase()));
|
|
296
|
-
}
|
|
297
|
-
includeUsersByGroupName(users) {
|
|
298
|
-
if (!this.data.inclusions.groups.length) {
|
|
299
|
-
return users; // No group inclusions specified
|
|
300
|
-
}
|
|
301
|
-
// Cheating a bit and leveraging the 'selected' property to keep track of who should be included
|
|
302
|
-
// Since inclusions happen befor pre-selections, we can do that, as long as we set 'selected' back to false when we're done
|
|
303
|
-
this.data.inclusions.groups
|
|
304
|
-
.forEach(groupName => {
|
|
305
|
-
const group = this.groups?.find(g => g.name.toLowerCase() === groupName.toLowerCase());
|
|
306
|
-
if (!group) {
|
|
307
|
-
return;
|
|
308
|
-
}
|
|
309
|
-
users
|
|
310
|
-
.filter(user => group.member.find(groupMemberDn => groupMemberDn === user.distinguishedName))
|
|
311
|
-
.forEach(user => user.selected = true);
|
|
312
|
-
});
|
|
313
|
-
// At this point, all of the appropriate users should have 'selected' set to true
|
|
314
|
-
const selectedUsers = users.filter(user => user.selected); // Subset of the original list
|
|
315
|
-
// Reset 'selected' to false, and return
|
|
316
|
-
selectedUsers.forEach(user => user.selected = false);
|
|
317
|
-
return selectedUsers;
|
|
318
|
-
}
|
|
319
|
-
//#endregion
|
|
320
|
-
//#region Pre-Selections
|
|
321
|
-
preSelectUsersByAccountName(users) {
|
|
322
|
-
this.data.preSelections.accountNames
|
|
323
|
-
.forEach(accountName => {
|
|
324
|
-
const user = users.find(u => u.sAMAccountName.toLowerCase() === accountName.toLowerCase());
|
|
325
|
-
if (!user) {
|
|
326
|
-
return;
|
|
327
|
-
}
|
|
328
|
-
user.selected = true;
|
|
329
|
-
});
|
|
330
|
-
return users;
|
|
331
|
-
}
|
|
332
|
-
preSelectUsersByDepartment(users) {
|
|
333
|
-
this.data.preSelections.departments
|
|
334
|
-
.forEach(department => users
|
|
335
|
-
.filter(u => u.department?.toLowerCase() === department.toLowerCase())
|
|
336
|
-
.forEach(user => user.selected = true));
|
|
337
|
-
return users;
|
|
338
|
-
}
|
|
339
|
-
preSelectUsersByTitle(users) {
|
|
340
|
-
this.data.preSelections.titles
|
|
341
|
-
.forEach(title => users
|
|
342
|
-
.filter(u => u.title?.toLowerCase() === title.toLowerCase())
|
|
343
|
-
.forEach(user => user.selected = true));
|
|
344
|
-
return users;
|
|
345
|
-
}
|
|
346
|
-
preSelectUsersByGroupName(users) {
|
|
347
|
-
this.data.preSelections.groups
|
|
348
|
-
.forEach(groupName => {
|
|
349
|
-
const group = this.groups?.find(g => g.name.toLowerCase() === groupName.toLowerCase());
|
|
350
|
-
if (!group) {
|
|
351
|
-
return;
|
|
352
|
-
}
|
|
353
|
-
group.member.forEach(groupMemberDn => {
|
|
354
|
-
const user = users.find(u => u.distinguishedName === groupMemberDn);
|
|
355
|
-
if (!user) {
|
|
356
|
-
return;
|
|
357
|
-
}
|
|
358
|
-
user.selected = true;
|
|
359
|
-
});
|
|
360
|
-
});
|
|
361
|
-
return users;
|
|
362
|
-
}
|
|
363
|
-
//#endregion
|
|
364
|
-
setFilterPredicate() {
|
|
365
|
-
if (!this.dataSource) {
|
|
366
|
-
return;
|
|
367
|
-
}
|
|
368
|
-
this.dataSource.filterPredicate = (user, filter) => {
|
|
369
|
-
if (filter === '{selected:true}') {
|
|
370
|
-
return user.selected;
|
|
371
|
-
}
|
|
372
|
-
else {
|
|
373
|
-
const regex = new RegExp(filter, 'i'); // Case-insensitive
|
|
374
|
-
let match = false; // The end result - whether or not a employee matches the filter
|
|
375
|
-
const filterProperties = ['displayName'];
|
|
376
|
-
if (this.data.filterOptions.accountName) {
|
|
377
|
-
filterProperties.push('sAMAccountName');
|
|
378
|
-
}
|
|
379
|
-
if (this.data.filterOptions.title) {
|
|
380
|
-
filterProperties.push('title');
|
|
381
|
-
}
|
|
382
|
-
if (this.data.filterOptions.department) {
|
|
383
|
-
filterProperties.push('department');
|
|
384
|
-
}
|
|
385
|
-
if (this.data.filterOptions.phoneNumber) {
|
|
386
|
-
filterProperties.push('telephoneNumber');
|
|
387
|
-
}
|
|
388
|
-
// Match on the properties configured above
|
|
389
|
-
filterProperties
|
|
390
|
-
.forEach(field => {
|
|
391
|
-
// @ts-ignore
|
|
392
|
-
if (user[field] && user[field].match(regex)) {
|
|
393
|
-
match = true;
|
|
394
|
-
}
|
|
395
|
-
});
|
|
396
|
-
// Match on group membership (group name)
|
|
397
|
-
if (this.data.filterOptions.groupMembership) {
|
|
398
|
-
user.memberOf.forEach(groupDn => {
|
|
399
|
-
const group = this.groups?.find(group => group.distinguishedName === groupDn && group.name.match(regex));
|
|
400
|
-
if (group) {
|
|
401
|
-
match = true;
|
|
402
|
-
}
|
|
403
|
-
});
|
|
404
|
-
}
|
|
405
|
-
return match;
|
|
406
|
-
}
|
|
407
|
-
};
|
|
408
|
-
}
|
|
409
|
-
listenForFilterChanges() {
|
|
410
|
-
this.filterForm.get('filter')?.valueChanges
|
|
411
|
-
.pipe(debounceTime(250))
|
|
412
|
-
.subscribe(() => this.dataSource.filter = this.filterForm.value.filter?.trim().toLowerCase());
|
|
413
|
-
}
|
|
414
|
-
tooltip(user) {
|
|
415
|
-
return this.data.showGroupMembershipTooltips ?
|
|
416
|
-
user.memberOf
|
|
417
|
-
.map(groupDn => this.groups
|
|
418
|
-
?.find(group => group.distinguishedName === groupDn)?.name)
|
|
419
|
-
.sort((a, b) => a > b ? 1 : -1)
|
|
420
|
-
.join('\n') :
|
|
421
|
-
'';
|
|
422
|
-
}
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
427
|
-
type: Component,
|
|
428
|
-
args: [{ template: "<div id=\"dialog-title\">\n <h2 mat-dialog-title>{{ data.title }}</h2>\n\n <div id=\"num-selected\">\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\" #filterInput>\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)\" matListItemAvatar alt=\"\" [src]=\"getPhoto(user)\">\n\n <mat-icon *ngIf=\"!getPhoto(user)\" matListItemAvatar 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 *ngIf=\"isMultiMode || !data.closeWhenSelectionMade\" 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}#num-selected{margin:1em 1em 0 0}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"] }]
|
|
429
|
-
}], ctorParameters: function () { return [{ type: UserChooserData, decorators: [{
|
|
430
|
-
type: Inject,
|
|
431
|
-
args: [MAT_DIALOG_DATA]
|
|
432
|
-
}] }, { type: i1.MatDialogRef }, { type: i2.ActiveDirectoryService }, { type: i3.SharePointService }]; }, propDecorators: { selectionList: [{
|
|
433
|
-
type: ViewChild,
|
|
434
|
-
args: [MatSelectionList]
|
|
435
|
-
}], filterInput: [{
|
|
436
|
-
type: ViewChild,
|
|
437
|
-
args: ['filterInput']
|
|
89
|
+
class UserChooserComponent {
|
|
90
|
+
//#endregion
|
|
91
|
+
//#region Properties
|
|
92
|
+
get isMultiMode() {
|
|
93
|
+
return this.data.mode === UserChooserMode.Multiple;
|
|
94
|
+
}
|
|
95
|
+
get selectedOptions() {
|
|
96
|
+
return this.selectionList?.options.filter(o => o.selected) ?? [];
|
|
97
|
+
}
|
|
98
|
+
get selectedUsers() {
|
|
99
|
+
return this.dataSource?.data?.filter(d => d.selected) ?? [];
|
|
100
|
+
}
|
|
101
|
+
get filterValue() {
|
|
102
|
+
return this.filterForm.value.filter;
|
|
103
|
+
}
|
|
104
|
+
get adGroupsNeeded() {
|
|
105
|
+
// If any are these are true, then we need to pull AD groups for use later
|
|
106
|
+
return this.data.showGroupMembershipTooltips ||
|
|
107
|
+
this.data.exclusions.groups.length > 0 ||
|
|
108
|
+
this.data.inclusions.groups.length > 0 ||
|
|
109
|
+
this.data.preSelections.groups.length > 0 ||
|
|
110
|
+
this.data.filterOptions.groupMembership;
|
|
111
|
+
}
|
|
112
|
+
//#endregion
|
|
113
|
+
//#region Lifecycle
|
|
114
|
+
constructor(data, dialogRef, activeDirectoryService, sharePointService) {
|
|
115
|
+
this.data = data;
|
|
116
|
+
this.dialogRef = dialogRef;
|
|
117
|
+
this.activeDirectoryService = activeDirectoryService;
|
|
118
|
+
this.sharePointService = sharePointService;
|
|
119
|
+
this.filterInputFocused = false;
|
|
120
|
+
this.filterForm = new FormGroup({
|
|
121
|
+
filter: new FormControl()
|
|
122
|
+
});
|
|
123
|
+
this.data = {
|
|
124
|
+
...new UserChooserData(),
|
|
125
|
+
...data
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
ngOnInit() {
|
|
129
|
+
this.getData();
|
|
130
|
+
this.listenForFilterChanges();
|
|
131
|
+
}
|
|
132
|
+
ngAfterViewChecked() {
|
|
133
|
+
if (this.filterInputFocused || !this.filterInput) {
|
|
134
|
+
// Control not ready yet, or it has already been given focus
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
this.filterInputFocused = true;
|
|
138
|
+
this.filterInput?.nativeElement.focus();
|
|
139
|
+
}
|
|
140
|
+
//#endregion
|
|
141
|
+
//#region Events
|
|
142
|
+
listSelectionChanged(options) {
|
|
143
|
+
if (this.data.mode === UserChooserMode.Single &&
|
|
144
|
+
this.selectedOptions.length &&
|
|
145
|
+
this.data.closeWhenSelectionMade) {
|
|
146
|
+
this.close();
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
optionSelectionChanged(option) {
|
|
150
|
+
const user = this.dataSource?.data
|
|
151
|
+
.find(u => u.sAMAccountName.toLocaleLowerCase() === option.value.sAMAccountName.toLowerCase());
|
|
152
|
+
if (user) {
|
|
153
|
+
user.selected = option.selected;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
hideUnselectedChanged(selected) {
|
|
157
|
+
this.filterForm.get('filter')?.setValue(selected ? '{selected:true}' : null);
|
|
158
|
+
}
|
|
159
|
+
selectAll() {
|
|
160
|
+
this.selectionList?.selectAll();
|
|
161
|
+
if (this.selectionList?.options) {
|
|
162
|
+
this.listSelectionChanged(this.selectionList?.options.toArray());
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
deselectAll() {
|
|
166
|
+
this.selectionList?.deselectAll();
|
|
167
|
+
}
|
|
168
|
+
//#endregion
|
|
169
|
+
//#region Utilities
|
|
170
|
+
getData() {
|
|
171
|
+
const dataObservables = [
|
|
172
|
+
this.data.users ?
|
|
173
|
+
// Users were passed in
|
|
174
|
+
of(this.data.users) :
|
|
175
|
+
// Users need to be retrieved
|
|
176
|
+
this.activeDirectoryService.getUsers(false, this.data.includeDisabledUsers, this.data.parentOu),
|
|
177
|
+
this.data.photos ?
|
|
178
|
+
// Photos were passed in
|
|
179
|
+
of(this.data.photos) :
|
|
180
|
+
// Photos need to be retrieved
|
|
181
|
+
this.sharePointService.getPhotos()
|
|
182
|
+
];
|
|
183
|
+
// Do we need AD groups?
|
|
184
|
+
if (this.adGroupsNeeded) {
|
|
185
|
+
this.data.groups ?
|
|
186
|
+
// Groups were passed in
|
|
187
|
+
of(this.data.groups) :
|
|
188
|
+
// Groups need to be retrieved
|
|
189
|
+
dataObservables.push(this.activeDirectoryService.getGroups());
|
|
190
|
+
}
|
|
191
|
+
forkJoin(dataObservables)
|
|
192
|
+
//.subscribe(([users, photos]) => {
|
|
193
|
+
.subscribe(data => {
|
|
194
|
+
// Need groups in place before we handle exclusions/inclusions/pre-selections
|
|
195
|
+
this.groups = this.adGroupsNeeded ? data[2] : null;
|
|
196
|
+
let users = data[0];
|
|
197
|
+
users.forEach(u => u.selected = false); // In case existing data was re-used
|
|
198
|
+
users = this.includeUsersByAccountName(users);
|
|
199
|
+
users = this.includeUsersByGroupName(users);
|
|
200
|
+
users = this.includeUsersByDepartment(users);
|
|
201
|
+
users = this.includeUsersByTitle(users);
|
|
202
|
+
users = this.excludeUsersByAccountName(users);
|
|
203
|
+
users = this.excludeUsersByGroupName(users);
|
|
204
|
+
users = this.excludeUsersByDepartment(users);
|
|
205
|
+
users = this.excludeUsersByTitle(users);
|
|
206
|
+
users = this.preSelectUsersByAccountName(users);
|
|
207
|
+
users = this.preSelectUsersByGroupName(users);
|
|
208
|
+
users = this.preSelectUsersByDepartment(users);
|
|
209
|
+
users = this.preSelectUsersByTitle(users);
|
|
210
|
+
this.dataSource = new MatTableDataSource(users);
|
|
211
|
+
this.photos = data[1];
|
|
212
|
+
this.setFilterPredicate();
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
close() {
|
|
216
|
+
if (!this.selectedUsers) {
|
|
217
|
+
this.dialogRef.close();
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
const value = this.selectedUsers
|
|
221
|
+
.map(u => this.data.returnUserObjects ? u : u.sAMAccountName);
|
|
222
|
+
this.dialogRef.close(this.data.mode === UserChooserMode.Multiple ?
|
|
223
|
+
value :
|
|
224
|
+
value[0]);
|
|
225
|
+
}
|
|
226
|
+
getPhoto(user) {
|
|
227
|
+
return this.photos?.find(p => (p.employeeNumber && p.employeeNumber.toString() === user.employeeNumber) ||
|
|
228
|
+
p.accountName?.toLowerCase() === user.sAMAccountName.toLowerCase() ||
|
|
229
|
+
p.displayName?.toLowerCase() === user.displayName.toLowerCase() ||
|
|
230
|
+
p.title?.toLowerCase() === user.displayName.toLowerCase())?.encodedAbsUrl;
|
|
231
|
+
}
|
|
232
|
+
//#region Exclusions - won't be included in the dataSource at all
|
|
233
|
+
excludeUsersByAccountName(users) {
|
|
234
|
+
this.data.exclusions.accountNames
|
|
235
|
+
.forEach(accountName => {
|
|
236
|
+
const index = users.findIndex(u => u.sAMAccountName.toLowerCase() === accountName.toLowerCase());
|
|
237
|
+
if (index === -1) {
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
users.splice(index, 1);
|
|
241
|
+
});
|
|
242
|
+
return users;
|
|
243
|
+
}
|
|
244
|
+
excludeUsersByGroupName(users) {
|
|
245
|
+
this.data.exclusions.groups
|
|
246
|
+
.forEach(groupName => {
|
|
247
|
+
const group = this.groups?.find(g => g.name.toLowerCase() === groupName.toLowerCase());
|
|
248
|
+
if (!group) {
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
group.member.forEach(groupMemberDn => {
|
|
252
|
+
const index = users.findIndex(u => u.distinguishedName === groupMemberDn);
|
|
253
|
+
if (index === -1) {
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
users.splice(index, 1);
|
|
257
|
+
});
|
|
258
|
+
});
|
|
259
|
+
return users;
|
|
260
|
+
}
|
|
261
|
+
excludeUsersByDepartment(users) {
|
|
262
|
+
this.data.exclusions.departments
|
|
263
|
+
.forEach(department => {
|
|
264
|
+
const excludedUsers = users.filter(u => u.department?.toLowerCase() === department.toLowerCase());
|
|
265
|
+
excludedUsers.forEach(user => {
|
|
266
|
+
const index = users.indexOf(user);
|
|
267
|
+
users.splice(index, 1);
|
|
268
|
+
});
|
|
269
|
+
});
|
|
270
|
+
return users;
|
|
271
|
+
}
|
|
272
|
+
excludeUsersByTitle(users) {
|
|
273
|
+
this.data.exclusions.titles
|
|
274
|
+
.forEach(title => {
|
|
275
|
+
const excludedUsers = users.filter(u => u.title?.toLowerCase() === title.toLowerCase());
|
|
276
|
+
excludedUsers.forEach(user => {
|
|
277
|
+
const index = users.indexOf(user);
|
|
278
|
+
users.splice(index, 1);
|
|
279
|
+
});
|
|
280
|
+
});
|
|
281
|
+
return users;
|
|
282
|
+
}
|
|
283
|
+
//#endregion
|
|
284
|
+
//#region Inclusions - only these will be included in the dataSource
|
|
285
|
+
includeUsersByAccountName(users) {
|
|
286
|
+
return users.filter(user => this.data.inclusions.accountNames.length === 0 || // No account inclusions specified
|
|
287
|
+
this.data.inclusions.accountNames.find(accountName => accountName.toLowerCase() === user.sAMAccountName.toLowerCase()));
|
|
288
|
+
}
|
|
289
|
+
includeUsersByDepartment(users) {
|
|
290
|
+
return users.filter(user => this.data.inclusions.departments.length === 0 || // No department inclusions specified
|
|
291
|
+
this.data.inclusions.departments.find(department => department.toLowerCase() === user.department?.toLowerCase()));
|
|
292
|
+
}
|
|
293
|
+
includeUsersByTitle(users) {
|
|
294
|
+
return users.filter(user => this.data.inclusions.titles.length === 0 || // No title inclusions specified
|
|
295
|
+
this.data.inclusions.titles.find(title => title.toLowerCase() === user.title?.toLowerCase()));
|
|
296
|
+
}
|
|
297
|
+
includeUsersByGroupName(users) {
|
|
298
|
+
if (!this.data.inclusions.groups.length) {
|
|
299
|
+
return users; // No group inclusions specified
|
|
300
|
+
}
|
|
301
|
+
// Cheating a bit and leveraging the 'selected' property to keep track of who should be included
|
|
302
|
+
// Since inclusions happen befor pre-selections, we can do that, as long as we set 'selected' back to false when we're done
|
|
303
|
+
this.data.inclusions.groups
|
|
304
|
+
.forEach(groupName => {
|
|
305
|
+
const group = this.groups?.find(g => g.name.toLowerCase() === groupName.toLowerCase());
|
|
306
|
+
if (!group) {
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
users
|
|
310
|
+
.filter(user => group.member.find(groupMemberDn => groupMemberDn === user.distinguishedName))
|
|
311
|
+
.forEach(user => user.selected = true);
|
|
312
|
+
});
|
|
313
|
+
// At this point, all of the appropriate users should have 'selected' set to true
|
|
314
|
+
const selectedUsers = users.filter(user => user.selected); // Subset of the original list
|
|
315
|
+
// Reset 'selected' to false, and return
|
|
316
|
+
selectedUsers.forEach(user => user.selected = false);
|
|
317
|
+
return selectedUsers;
|
|
318
|
+
}
|
|
319
|
+
//#endregion
|
|
320
|
+
//#region Pre-Selections
|
|
321
|
+
preSelectUsersByAccountName(users) {
|
|
322
|
+
this.data.preSelections.accountNames
|
|
323
|
+
.forEach(accountName => {
|
|
324
|
+
const user = users.find(u => u.sAMAccountName.toLowerCase() === accountName.toLowerCase());
|
|
325
|
+
if (!user) {
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
328
|
+
user.selected = true;
|
|
329
|
+
});
|
|
330
|
+
return users;
|
|
331
|
+
}
|
|
332
|
+
preSelectUsersByDepartment(users) {
|
|
333
|
+
this.data.preSelections.departments
|
|
334
|
+
.forEach(department => users
|
|
335
|
+
.filter(u => u.department?.toLowerCase() === department.toLowerCase())
|
|
336
|
+
.forEach(user => user.selected = true));
|
|
337
|
+
return users;
|
|
338
|
+
}
|
|
339
|
+
preSelectUsersByTitle(users) {
|
|
340
|
+
this.data.preSelections.titles
|
|
341
|
+
.forEach(title => users
|
|
342
|
+
.filter(u => u.title?.toLowerCase() === title.toLowerCase())
|
|
343
|
+
.forEach(user => user.selected = true));
|
|
344
|
+
return users;
|
|
345
|
+
}
|
|
346
|
+
preSelectUsersByGroupName(users) {
|
|
347
|
+
this.data.preSelections.groups
|
|
348
|
+
.forEach(groupName => {
|
|
349
|
+
const group = this.groups?.find(g => g.name.toLowerCase() === groupName.toLowerCase());
|
|
350
|
+
if (!group) {
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
group.member.forEach(groupMemberDn => {
|
|
354
|
+
const user = users.find(u => u.distinguishedName === groupMemberDn);
|
|
355
|
+
if (!user) {
|
|
356
|
+
return;
|
|
357
|
+
}
|
|
358
|
+
user.selected = true;
|
|
359
|
+
});
|
|
360
|
+
});
|
|
361
|
+
return users;
|
|
362
|
+
}
|
|
363
|
+
//#endregion
|
|
364
|
+
setFilterPredicate() {
|
|
365
|
+
if (!this.dataSource) {
|
|
366
|
+
return;
|
|
367
|
+
}
|
|
368
|
+
this.dataSource.filterPredicate = (user, filter) => {
|
|
369
|
+
if (filter === '{selected:true}') {
|
|
370
|
+
return user.selected;
|
|
371
|
+
}
|
|
372
|
+
else {
|
|
373
|
+
const regex = new RegExp(filter, 'i'); // Case-insensitive
|
|
374
|
+
let match = false; // The end result - whether or not a employee matches the filter
|
|
375
|
+
const filterProperties = ['displayName'];
|
|
376
|
+
if (this.data.filterOptions.accountName) {
|
|
377
|
+
filterProperties.push('sAMAccountName');
|
|
378
|
+
}
|
|
379
|
+
if (this.data.filterOptions.title) {
|
|
380
|
+
filterProperties.push('title');
|
|
381
|
+
}
|
|
382
|
+
if (this.data.filterOptions.department) {
|
|
383
|
+
filterProperties.push('department');
|
|
384
|
+
}
|
|
385
|
+
if (this.data.filterOptions.phoneNumber) {
|
|
386
|
+
filterProperties.push('telephoneNumber');
|
|
387
|
+
}
|
|
388
|
+
// Match on the properties configured above
|
|
389
|
+
filterProperties
|
|
390
|
+
.forEach(field => {
|
|
391
|
+
// @ts-ignore
|
|
392
|
+
if (user[field] && user[field].match(regex)) {
|
|
393
|
+
match = true;
|
|
394
|
+
}
|
|
395
|
+
});
|
|
396
|
+
// Match on group membership (group name)
|
|
397
|
+
if (this.data.filterOptions.groupMembership) {
|
|
398
|
+
user.memberOf.forEach(groupDn => {
|
|
399
|
+
const group = this.groups?.find(group => group.distinguishedName === groupDn && group.name.match(regex));
|
|
400
|
+
if (group) {
|
|
401
|
+
match = true;
|
|
402
|
+
}
|
|
403
|
+
});
|
|
404
|
+
}
|
|
405
|
+
return match;
|
|
406
|
+
}
|
|
407
|
+
};
|
|
408
|
+
}
|
|
409
|
+
listenForFilterChanges() {
|
|
410
|
+
this.filterForm.get('filter')?.valueChanges
|
|
411
|
+
.pipe(debounceTime(250))
|
|
412
|
+
.subscribe(() => this.dataSource.filter = this.filterForm.value.filter?.trim().toLowerCase());
|
|
413
|
+
}
|
|
414
|
+
tooltip(user) {
|
|
415
|
+
return this.data.showGroupMembershipTooltips ?
|
|
416
|
+
user.memberOf
|
|
417
|
+
.map(groupDn => this.groups
|
|
418
|
+
?.find(group => group.distinguishedName === groupDn)?.name)
|
|
419
|
+
.sort((a, b) => a > b ? 1 : -1)
|
|
420
|
+
.join('\n') :
|
|
421
|
+
'';
|
|
422
|
+
}
|
|
423
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.1", ngImport: i0, type: UserChooserComponent, deps: [{ token: MAT_DIALOG_DATA }, { token: i1.MatDialogRef }, { token: i2.ActiveDirectoryService }, { token: i3.SharePointService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
424
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.0.1", type: UserChooserComponent, selector: "ng-component", viewQueries: [{ propertyName: "selectionList", first: true, predicate: MatSelectionList, descendants: true }, { propertyName: "filterInput", first: true, predicate: ["filterInput"], descendants: true }], ngImport: i0, template: "<div id=\"dialog-title\">\n <h2 mat-dialog-title>{{ data.title }}</h2>\n\n <div id=\"num-selected\">\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\" #filterInput>\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)\" matListItemAvatar alt=\"\" [src]=\"getPhoto(user)\">\n\n <mat-icon *ngIf=\"!getPhoto(user)\" matListItemAvatar 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 *ngIf=\"isMultiMode || !data.closeWhenSelectionMade\" 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}#num-selected{margin:1em 1em 0 0}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-flat-button], button[mat-stroked-button] ", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "component", type: i6.MatIconButton, selector: "button[mat-icon-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: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i7.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { 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: "component", type: i10.MatSelectionList, selector: "mat-selection-list", inputs: ["color", "compareWith", "multiple", "hideSingleSelectionIndicator", "disabled"], outputs: ["selectionChange"], exportAs: ["matSelectionList"] }, { kind: "component", type: i10.MatListOption, selector: "mat-list-option", inputs: ["togglePosition", "checkboxPosition", "color", "value", "selected"], outputs: ["selectedChange"], exportAs: ["matListOption"] }, { kind: "directive", type: i10.MatListItemAvatar, selector: "[matListItemAvatar]" }, { kind: "component", type: i11.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], 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"] }] }); }
|
|
425
|
+
}
|
|
426
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.1", ngImport: i0, type: UserChooserComponent, decorators: [{
|
|
427
|
+
type: Component,
|
|
428
|
+
args: [{ template: "<div id=\"dialog-title\">\n <h2 mat-dialog-title>{{ data.title }}</h2>\n\n <div id=\"num-selected\">\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\" #filterInput>\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)\" matListItemAvatar alt=\"\" [src]=\"getPhoto(user)\">\n\n <mat-icon *ngIf=\"!getPhoto(user)\" matListItemAvatar 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 *ngIf=\"isMultiMode || !data.closeWhenSelectionMade\" 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}#num-selected{margin:1em 1em 0 0}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"] }]
|
|
429
|
+
}], ctorParameters: function () { return [{ type: UserChooserData, decorators: [{
|
|
430
|
+
type: Inject,
|
|
431
|
+
args: [MAT_DIALOG_DATA]
|
|
432
|
+
}] }, { type: i1.MatDialogRef }, { type: i2.ActiveDirectoryService }, { type: i3.SharePointService }]; }, propDecorators: { selectionList: [{
|
|
433
|
+
type: ViewChild,
|
|
434
|
+
args: [MatSelectionList]
|
|
435
|
+
}], filterInput: [{
|
|
436
|
+
type: ViewChild,
|
|
437
|
+
args: ['filterInput']
|
|
438
438
|
}] } });
|
|
439
439
|
|
|
440
|
-
class UserFormFieldComponent {
|
|
441
|
-
//#endregion
|
|
442
|
-
//#region
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
this.
|
|
450
|
-
this.
|
|
451
|
-
this.
|
|
452
|
-
|
|
453
|
-
this.
|
|
454
|
-
this.
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
}
|
|
461
|
-
ngOnInit() {
|
|
462
|
-
this.userChooserData = {
|
|
463
|
-
...new UserChooserData(),
|
|
464
|
-
...this.userChooserData
|
|
465
|
-
};
|
|
466
|
-
// If users have been pre-selected in the config, store those in accountNames, which drives the UI of this component
|
|
467
|
-
this.accountNames = this.userChooserData.preSelections.accountNames;
|
|
468
|
-
this.getData();
|
|
469
|
-
}
|
|
470
|
-
//#endregion
|
|
471
|
-
//#region Events
|
|
472
|
-
selectUser() {
|
|
473
|
-
if (!this.clickable) {
|
|
474
|
-
return;
|
|
475
|
-
}
|
|
476
|
-
const data = {
|
|
477
|
-
...this.userChooserData,
|
|
478
|
-
users: this.users,
|
|
479
|
-
photos: this.photos,
|
|
480
|
-
};
|
|
481
|
-
this.dialog.open(UserChooserComponent, {
|
|
482
|
-
data: data
|
|
483
|
-
})
|
|
484
|
-
.afterClosed()
|
|
485
|
-
.subscribe((selected) => {
|
|
486
|
-
if (!selected) {
|
|
487
|
-
return;
|
|
488
|
-
}
|
|
489
|
-
this.accountNames = Array.isArray(selected) ?
|
|
490
|
-
selected :
|
|
491
|
-
[selected];
|
|
492
|
-
// Overwrite what may have been passed in, for subsequent launches of UserChooserComponent - otherwise it just keeps getting fed stale data
|
|
493
|
-
this.userChooserData.preSelections.accountNames = this.accountNames;
|
|
494
|
-
this.usersSelected.emit(selected);
|
|
495
|
-
});
|
|
496
|
-
}
|
|
497
|
-
unSelectUser(accountName) {
|
|
498
|
-
const index = this.accountNames.findIndex(a => a === accountName);
|
|
499
|
-
this.accountNames.splice(index, 1);
|
|
500
|
-
this.userChooserData.preSelections.accountNames = this.accountNames;
|
|
501
|
-
this.userUnSelected.emit(accountName);
|
|
502
|
-
}
|
|
503
|
-
//#endregion
|
|
504
|
-
//#region Utilities
|
|
505
|
-
getData() {
|
|
506
|
-
forkJoin([
|
|
507
|
-
this.userChooserData.users ?
|
|
508
|
-
// Users were passed in
|
|
509
|
-
of(this.userChooserData.users) :
|
|
510
|
-
// Users need to be retrieved
|
|
511
|
-
this.activeDirectoryService.getUsers(false, this.userChooserData.includeDisabledUsers, this.userChooserData.parentOu),
|
|
512
|
-
this.userChooserData.photos ?
|
|
513
|
-
// Photos were passed in
|
|
514
|
-
of(this.userChooserData.photos) :
|
|
515
|
-
// Photos need to be retrieved
|
|
516
|
-
this.sharePointService.getPhotos()
|
|
517
|
-
])
|
|
518
|
-
.subscribe(([users, photos]) => {
|
|
519
|
-
this.users = users;
|
|
520
|
-
this.photos = photos;
|
|
521
|
-
});
|
|
522
|
-
}
|
|
523
|
-
getUser(accountName) {
|
|
524
|
-
return this.users?.find(u => u.sAMAccountName.toLowerCase() === accountName.toLowerCase());
|
|
525
|
-
}
|
|
526
|
-
getPhoto(accountName) {
|
|
527
|
-
const user = this.getUser(accountName);
|
|
528
|
-
if (!user) {
|
|
529
|
-
return undefined;
|
|
530
|
-
}
|
|
531
|
-
return this.photos?.find(p => (p.employeeNumber && p.employeeNumber.toString() === user.employeeNumber) ||
|
|
532
|
-
p.accountName?.toLowerCase() === user.sAMAccountName.toLowerCase() ||
|
|
533
|
-
p.displayName?.toLowerCase() === user.displayName.toLowerCase() ||
|
|
534
|
-
p.title?.toLowerCase() === user.displayName.toLowerCase())?.encodedAbsUrl;
|
|
535
|
-
}
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
540
|
-
type: Component,
|
|
541
|
-
args: [{ selector: 'cp-user-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<mat-progress-bar *ngIf=\"!(users && photos)\" mode=\"indeterminate\"></mat-progress-bar>\n\n<div *ngIf=\"users && photos\" (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)\" matListItemAvatar 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\n <button matSuffix mat-icon-button aria-label=\"Clear\" (click)=\"$event.stopPropagation(); unSelectUser(accountName)\">\n <mat-icon fontIcon=\"close\"></mat-icon>\n </button>\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"] }]
|
|
542
|
-
}], ctorParameters: function () { return [{ type: i1.MatDialog }, { type: i2.ActiveDirectoryService }, { type: i3.SharePointService }]; }, propDecorators: { usersSelected: [{
|
|
543
|
-
type: Output
|
|
544
|
-
}], userUnSelected: [{
|
|
545
|
-
type: Output
|
|
546
|
-
}], placeholder: [{
|
|
547
|
-
type: Input
|
|
548
|
-
}], clickable: [{
|
|
549
|
-
type: Input
|
|
550
|
-
}], userChooserData: [{
|
|
551
|
-
type: Input
|
|
440
|
+
class UserFormFieldComponent {
|
|
441
|
+
//#endregion
|
|
442
|
+
//#region Properties
|
|
443
|
+
get isEdge() {
|
|
444
|
+
return window.navigator.userAgent.indexOf('Edge') > -1;
|
|
445
|
+
}
|
|
446
|
+
//#endregion
|
|
447
|
+
//#region Lifecycle
|
|
448
|
+
constructor(dialog, activeDirectoryService, sharePointService) {
|
|
449
|
+
this.dialog = dialog;
|
|
450
|
+
this.activeDirectoryService = activeDirectoryService;
|
|
451
|
+
this.sharePointService = sharePointService;
|
|
452
|
+
//#region Fields
|
|
453
|
+
this.usersSelected = new EventEmitter(); // string for Single mode, string[] for multi
|
|
454
|
+
this.userUnSelected = new EventEmitter();
|
|
455
|
+
this.placeholder = 'Select User(s)';
|
|
456
|
+
this.clickable = true;
|
|
457
|
+
this.accountNames = [];
|
|
458
|
+
this.users = undefined;
|
|
459
|
+
this.photos = undefined;
|
|
460
|
+
}
|
|
461
|
+
ngOnInit() {
|
|
462
|
+
this.userChooserData = {
|
|
463
|
+
...new UserChooserData(),
|
|
464
|
+
...this.userChooserData
|
|
465
|
+
};
|
|
466
|
+
// If users have been pre-selected in the config, store those in accountNames, which drives the UI of this component
|
|
467
|
+
this.accountNames = this.userChooserData.preSelections.accountNames;
|
|
468
|
+
this.getData();
|
|
469
|
+
}
|
|
470
|
+
//#endregion
|
|
471
|
+
//#region Events
|
|
472
|
+
selectUser() {
|
|
473
|
+
if (!this.clickable) {
|
|
474
|
+
return;
|
|
475
|
+
}
|
|
476
|
+
const data = {
|
|
477
|
+
...this.userChooserData,
|
|
478
|
+
users: this.users,
|
|
479
|
+
photos: this.photos,
|
|
480
|
+
};
|
|
481
|
+
this.dialog.open(UserChooserComponent, {
|
|
482
|
+
data: data
|
|
483
|
+
})
|
|
484
|
+
.afterClosed()
|
|
485
|
+
.subscribe((selected) => {
|
|
486
|
+
if (!selected) {
|
|
487
|
+
return;
|
|
488
|
+
}
|
|
489
|
+
this.accountNames = Array.isArray(selected) ?
|
|
490
|
+
selected :
|
|
491
|
+
[selected];
|
|
492
|
+
// Overwrite what may have been passed in, for subsequent launches of UserChooserComponent - otherwise it just keeps getting fed stale data
|
|
493
|
+
this.userChooserData.preSelections.accountNames = this.accountNames;
|
|
494
|
+
this.usersSelected.emit(selected);
|
|
495
|
+
});
|
|
496
|
+
}
|
|
497
|
+
unSelectUser(accountName) {
|
|
498
|
+
const index = this.accountNames.findIndex(a => a === accountName);
|
|
499
|
+
this.accountNames.splice(index, 1);
|
|
500
|
+
this.userChooserData.preSelections.accountNames = this.accountNames;
|
|
501
|
+
this.userUnSelected.emit(accountName);
|
|
502
|
+
}
|
|
503
|
+
//#endregion
|
|
504
|
+
//#region Utilities
|
|
505
|
+
getData() {
|
|
506
|
+
forkJoin([
|
|
507
|
+
this.userChooserData.users ?
|
|
508
|
+
// Users were passed in
|
|
509
|
+
of(this.userChooserData.users) :
|
|
510
|
+
// Users need to be retrieved
|
|
511
|
+
this.activeDirectoryService.getUsers(false, this.userChooserData.includeDisabledUsers, this.userChooserData.parentOu),
|
|
512
|
+
this.userChooserData.photos ?
|
|
513
|
+
// Photos were passed in
|
|
514
|
+
of(this.userChooserData.photos) :
|
|
515
|
+
// Photos need to be retrieved
|
|
516
|
+
this.sharePointService.getPhotos()
|
|
517
|
+
])
|
|
518
|
+
.subscribe(([users, photos]) => {
|
|
519
|
+
this.users = users;
|
|
520
|
+
this.photos = photos;
|
|
521
|
+
});
|
|
522
|
+
}
|
|
523
|
+
getUser(accountName) {
|
|
524
|
+
return this.users?.find(u => u.sAMAccountName.toLowerCase() === accountName.toLowerCase());
|
|
525
|
+
}
|
|
526
|
+
getPhoto(accountName) {
|
|
527
|
+
const user = this.getUser(accountName);
|
|
528
|
+
if (!user) {
|
|
529
|
+
return undefined;
|
|
530
|
+
}
|
|
531
|
+
return this.photos?.find(p => (p.employeeNumber && p.employeeNumber.toString() === user.employeeNumber) ||
|
|
532
|
+
p.accountName?.toLowerCase() === user.sAMAccountName.toLowerCase() ||
|
|
533
|
+
p.displayName?.toLowerCase() === user.displayName.toLowerCase() ||
|
|
534
|
+
p.title?.toLowerCase() === user.displayName.toLowerCase())?.encodedAbsUrl;
|
|
535
|
+
}
|
|
536
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.1", ngImport: i0, type: UserFormFieldComponent, deps: [{ token: i1.MatDialog }, { token: i2.ActiveDirectoryService }, { token: i3.SharePointService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
537
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.0.1", type: UserFormFieldComponent, selector: "cp-user-field", inputs: { placeholder: "placeholder", clickable: "clickable", userChooserData: "userChooserData" }, outputs: { usersSelected: "usersSelected", userUnSelected: "userUnSelected" }, 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<mat-progress-bar *ngIf=\"!(users && photos)\" mode=\"indeterminate\"></mat-progress-bar>\n\n<div *ngIf=\"users && photos\" (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)\" matListItemAvatar 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\n <button matSuffix mat-icon-button aria-label=\"Clear\" (click)=\"$event.stopPropagation(); unSelectUser(accountName)\">\n <mat-icon fontIcon=\"close\"></mat-icon>\n </button>\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: i6.MatIconButton, selector: "button[mat-icon-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "component", type: i7.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i7.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { 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.MatListItemAvatar, selector: "[matListItemAvatar]" }, { kind: "component", type: i10$1.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }] }); }
|
|
538
|
+
}
|
|
539
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.1", ngImport: i0, type: UserFormFieldComponent, decorators: [{
|
|
540
|
+
type: Component,
|
|
541
|
+
args: [{ selector: 'cp-user-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<mat-progress-bar *ngIf=\"!(users && photos)\" mode=\"indeterminate\"></mat-progress-bar>\n\n<div *ngIf=\"users && photos\" (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)\" matListItemAvatar 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\n <button matSuffix mat-icon-button aria-label=\"Clear\" (click)=\"$event.stopPropagation(); unSelectUser(accountName)\">\n <mat-icon fontIcon=\"close\"></mat-icon>\n </button>\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"] }]
|
|
542
|
+
}], ctorParameters: function () { return [{ type: i1.MatDialog }, { type: i2.ActiveDirectoryService }, { type: i3.SharePointService }]; }, propDecorators: { usersSelected: [{
|
|
543
|
+
type: Output
|
|
544
|
+
}], userUnSelected: [{
|
|
545
|
+
type: Output
|
|
546
|
+
}], placeholder: [{
|
|
547
|
+
type: Input
|
|
548
|
+
}], clickable: [{
|
|
549
|
+
type: Input
|
|
550
|
+
}], userChooserData: [{
|
|
551
|
+
type: Input
|
|
552
552
|
}] } });
|
|
553
553
|
|
|
554
|
-
class GuiModule {
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
}
|
|
568
|
-
}
|
|
569
|
-
}
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
600
|
-
type: NgModule,
|
|
601
|
-
args: [{
|
|
602
|
-
declarations: [
|
|
603
|
-
UserChooserComponent,
|
|
604
|
-
UserFormFieldComponent
|
|
605
|
-
],
|
|
606
|
-
imports: [
|
|
607
|
-
CommonModule,
|
|
608
|
-
ReactiveFormsModule,
|
|
609
|
-
MatButtonModule,
|
|
610
|
-
MatDialogModule,
|
|
611
|
-
MatFormFieldModule,
|
|
612
|
-
MatIconModule,
|
|
613
|
-
MatInputModule,
|
|
614
|
-
MatListModule,
|
|
615
|
-
MatProgressBarModule,
|
|
616
|
-
MatProgressSpinnerModule,
|
|
617
|
-
MatSlideToggleModule,
|
|
618
|
-
MatTableModule,
|
|
619
|
-
MatTooltipModule
|
|
620
|
-
],
|
|
621
|
-
exports: [
|
|
622
|
-
UserChooserComponent,
|
|
623
|
-
UserFormFieldComponent
|
|
624
|
-
]
|
|
625
|
-
}]
|
|
626
|
-
}], ctorParameters: function () { return [{ type: GuiModule, decorators: [{
|
|
627
|
-
type: Optional
|
|
628
|
-
}, {
|
|
629
|
-
type: SkipSelf
|
|
554
|
+
class GuiModule {
|
|
555
|
+
static forRoot(config) {
|
|
556
|
+
return {
|
|
557
|
+
ngModule: GuiModule,
|
|
558
|
+
providers: [
|
|
559
|
+
ActiveDirectoryService,
|
|
560
|
+
{ provide: ServiceConfig, useValue: config }
|
|
561
|
+
]
|
|
562
|
+
};
|
|
563
|
+
}
|
|
564
|
+
constructor(parentModule) {
|
|
565
|
+
if (parentModule) {
|
|
566
|
+
throw new Error('ActiveDirectoryGuiModule is already loaded. Import it in the AppModule only');
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.1", ngImport: i0, type: GuiModule, deps: [{ token: GuiModule, optional: true, skipSelf: true }], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
570
|
+
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.0.1", ngImport: i0, type: GuiModule, declarations: [UserChooserComponent,
|
|
571
|
+
UserFormFieldComponent], imports: [CommonModule,
|
|
572
|
+
ReactiveFormsModule,
|
|
573
|
+
MatButtonModule,
|
|
574
|
+
MatDialogModule,
|
|
575
|
+
MatFormFieldModule,
|
|
576
|
+
MatIconModule,
|
|
577
|
+
MatInputModule,
|
|
578
|
+
MatListModule,
|
|
579
|
+
MatProgressBarModule,
|
|
580
|
+
MatProgressSpinnerModule,
|
|
581
|
+
MatSlideToggleModule,
|
|
582
|
+
MatTableModule,
|
|
583
|
+
MatTooltipModule], exports: [UserChooserComponent,
|
|
584
|
+
UserFormFieldComponent] }); }
|
|
585
|
+
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.0.1", ngImport: i0, type: GuiModule, imports: [CommonModule,
|
|
586
|
+
ReactiveFormsModule,
|
|
587
|
+
MatButtonModule,
|
|
588
|
+
MatDialogModule,
|
|
589
|
+
MatFormFieldModule,
|
|
590
|
+
MatIconModule,
|
|
591
|
+
MatInputModule,
|
|
592
|
+
MatListModule,
|
|
593
|
+
MatProgressBarModule,
|
|
594
|
+
MatProgressSpinnerModule,
|
|
595
|
+
MatSlideToggleModule,
|
|
596
|
+
MatTableModule,
|
|
597
|
+
MatTooltipModule] }); }
|
|
598
|
+
}
|
|
599
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.1", ngImport: i0, type: GuiModule, decorators: [{
|
|
600
|
+
type: NgModule,
|
|
601
|
+
args: [{
|
|
602
|
+
declarations: [
|
|
603
|
+
UserChooserComponent,
|
|
604
|
+
UserFormFieldComponent
|
|
605
|
+
],
|
|
606
|
+
imports: [
|
|
607
|
+
CommonModule,
|
|
608
|
+
ReactiveFormsModule,
|
|
609
|
+
MatButtonModule,
|
|
610
|
+
MatDialogModule,
|
|
611
|
+
MatFormFieldModule,
|
|
612
|
+
MatIconModule,
|
|
613
|
+
MatInputModule,
|
|
614
|
+
MatListModule,
|
|
615
|
+
MatProgressBarModule,
|
|
616
|
+
MatProgressSpinnerModule,
|
|
617
|
+
MatSlideToggleModule,
|
|
618
|
+
MatTableModule,
|
|
619
|
+
MatTooltipModule
|
|
620
|
+
],
|
|
621
|
+
exports: [
|
|
622
|
+
UserChooserComponent,
|
|
623
|
+
UserFormFieldComponent
|
|
624
|
+
]
|
|
625
|
+
}]
|
|
626
|
+
}], ctorParameters: function () { return [{ type: GuiModule, decorators: [{
|
|
627
|
+
type: Optional
|
|
628
|
+
}, {
|
|
629
|
+
type: SkipSelf
|
|
630
630
|
}] }]; } });
|
|
631
631
|
|
|
632
|
-
/**
|
|
633
|
-
* Generated bundle index. Do not edit.
|
|
632
|
+
/**
|
|
633
|
+
* Generated bundle index. Do not edit.
|
|
634
634
|
*/
|
|
635
635
|
|
|
636
636
|
export { GuiModule, UserChooserComponent, UserChooserData, UserChooserFilterOptions, UserChooserMode, UserChooserPreProcessingGroup, UserFormFieldComponent };
|
|
637
637
|
//# sourceMappingURL=cleavelandprice-ngx-lib-active-directory-gui.mjs.map
|
|
638
|
-
//# sourceMappingURL=cleavelandprice-ngx-lib-active-directory-gui.mjs.map
|