@cleavelandprice/ngx-lib 3.11.3 → 3.12.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/gui/components/user-chooser/user-chooser.component.d.ts +20 -2
- package/active-directory/gui/components/user-form-field/user-form-field.component.d.ts +5 -4
- package/authentication/token/gui/components/login/login.component.d.ts +3 -3
- package/authentication/token/gui/components/login-form/login-form.component.d.ts +1 -2
- package/authentication/token/gui/services/authentication.service.d.ts +2 -4
- package/authentication/token/services/authentication.service.d.ts +3 -4
- package/dialog/components/base/base.component.d.ts +6 -5
- package/esm2022/active-directory/gui/components/user-chooser/user-chooser.component.mjs +60 -68
- package/esm2022/active-directory/gui/components/user-form-field/user-form-field.component.mjs +22 -27
- package/esm2022/authentication/token/gui/components/login/login.component.mjs +9 -10
- package/esm2022/authentication/token/gui/components/login-form/login-form.component.mjs +11 -12
- package/esm2022/authentication/token/gui/services/authentication.service.mjs +5 -7
- package/esm2022/authentication/token/services/authentication.service.mjs +9 -8
- package/esm2022/dialog/components/base/base.component.mjs +26 -26
- package/esm2022/lib/services/app-path-config.service.mjs +13 -10
- package/esm2022/quill/components/editor/editor.component.mjs +41 -48
- package/esm2022/quill/mention/components/editor/editor.component.mjs +30 -40
- package/esm2022/sharepoint/components/user-photo/user-photo.component.mjs +36 -0
- package/esm2022/sharepoint/pipes/user-photo-url.pipe.mjs +38 -0
- package/esm2022/sharepoint/public_api.mjs +3 -3
- package/esm2022/sharepoint/sharepoint.module.mjs +11 -11
- package/esm2022/upload/components/upload-dialog/upload-dialog.component.mjs +3 -3
- package/fesm2022/cleavelandprice-ngx-lib-active-directory-gui.mjs +79 -91
- package/fesm2022/cleavelandprice-ngx-lib-active-directory-gui.mjs.map +1 -1
- package/fesm2022/cleavelandprice-ngx-lib-authentication-token-gui.mjs +23 -27
- package/fesm2022/cleavelandprice-ngx-lib-authentication-token-gui.mjs.map +1 -1
- package/fesm2022/cleavelandprice-ngx-lib-authentication-token.mjs +8 -7
- package/fesm2022/cleavelandprice-ngx-lib-authentication-token.mjs.map +1 -1
- package/fesm2022/cleavelandprice-ngx-lib-dialog.mjs +25 -25
- package/fesm2022/cleavelandprice-ngx-lib-dialog.mjs.map +1 -1
- package/fesm2022/cleavelandprice-ngx-lib-quill-mention.mjs +30 -40
- package/fesm2022/cleavelandprice-ngx-lib-quill-mention.mjs.map +1 -1
- package/fesm2022/cleavelandprice-ngx-lib-quill.mjs +43 -49
- package/fesm2022/cleavelandprice-ngx-lib-quill.mjs.map +1 -1
- package/fesm2022/cleavelandprice-ngx-lib-sharepoint.mjs +34 -35
- package/fesm2022/cleavelandprice-ngx-lib-sharepoint.mjs.map +1 -1
- package/fesm2022/cleavelandprice-ngx-lib-upload.mjs +2 -2
- package/fesm2022/cleavelandprice-ngx-lib-upload.mjs.map +1 -1
- package/fesm2022/cleavelandprice-ngx-lib.mjs +12 -9
- package/fesm2022/cleavelandprice-ngx-lib.mjs.map +1 -1
- package/lib/services/app-path-config.service.d.ts +1 -2
- package/package.json +1 -1
- package/quill/components/editor/editor.component.d.ts +2 -7
- package/quill/mention/components/editor/editor.component.d.ts +13 -10
- package/sharepoint/components/user-photo/user-photo.component.d.ts +15 -0
- package/sharepoint/pipes/{employee-photo-url.pipe.d.ts → user-photo-url.pipe.d.ts} +3 -3
- package/sharepoint/public_api.d.ts +2 -2
- package/sharepoint/sharepoint.module.d.ts +3 -3
- package/esm2022/sharepoint/components/employee-photo/employee-photo.component.mjs +0 -37
- package/esm2022/sharepoint/pipes/employee-photo-url.pipe.mjs +0 -38
- package/sharepoint/components/employee-photo/employee-photo.component.d.ts +0 -15
|
@@ -76,13 +76,13 @@ export class UploadDialogComponent {
|
|
|
76
76
|
});
|
|
77
77
|
}
|
|
78
78
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.2", ngImport: i0, type: UploadDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
79
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.1.2", type: UploadDialogComponent, selector: "ng-component", viewQueries: [{ propertyName: "file", first: true, predicate: ["file"], descendants: true, static: true }], ngImport: i0, template: "<input type=\"file\" #file style=\"display: none\" (change)=\"onFilesAdded()\" multiple />\n\n<div mat-dialog-title id=\"title\">\n <div>{{ uploadService.config.uploadDialogTitle }}</div>\n <button [disabled]=\"uploading || uploadSuccessful\" mat-raised-button color=\"primary\" class=\"add-files-btn\" (click)=\"addFiles()\">\n {{ uploadService.config.uploadDialogAddFilesButtonText }}\n </button>\n</div>\n\n@if (existingFileConflict) {\n <div id=\"conflict\">\n {{ existingFileConflict }} already exists on the server and cannot be overwritten\n </div>\n}\n\n<mat-dialog-content>\n <mat-list>\n @for (file of files; track file) {\n <mat-list-item>\n <h4 mat-line>{{file.name}}</h4>\n @if (progress) {\n <mat-progress-bar mode=\"determinate\" [value]=\"progress[file.name].progress | async\"
|
|
79
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.1.2", type: UploadDialogComponent, selector: "ng-component", viewQueries: [{ propertyName: "file", first: true, predicate: ["file"], descendants: true, static: true }], ngImport: i0, template: "<input type=\"file\" #file style=\"display: none\" (change)=\"onFilesAdded()\" multiple />\n\n<div mat-dialog-title id=\"title\">\n <div>{{ uploadService.config.uploadDialogTitle }}</div>\n <button [disabled]=\"uploading || uploadSuccessful\" mat-raised-button color=\"primary\" class=\"add-files-btn\" (click)=\"addFiles()\">\n {{ uploadService.config.uploadDialogAddFilesButtonText }}\n </button>\n</div>\n\n@if (existingFileConflict) {\n <div id=\"conflict\">\n {{ existingFileConflict }} already exists on the server and cannot be overwritten\n </div>\n}\n\n<mat-dialog-content>\n <mat-list>\n @for (file of files; track file) {\n <mat-list-item>\n <h4 mat-line>{{file.name}}</h4>\n @if (progress) {\n <mat-progress-bar mode=\"determinate\" [value]=\"progress[file.name].progress | async\"/>\n }\n </mat-list-item>\n }\n </mat-list>\n</mat-dialog-content>\n\n<mat-dialog-actions id=\"actions\">\n @if (showCancelButton) {\n <button mat-button mat-dialog-close>{{ uploadService.config.uploadDialogCancelButtonText }}</button>\n }\n @if (files.size > 0) {\n <button mat-raised-button color=\"primary\" [disabled]=\"!canBeClosed\" (click)=\"closeDialog()\">{{ primaryButtonText }}</button>\n }\n</mat-dialog-actions>\n", styles: ["#title{display:flex;justify-content:space-between}#actions{display:flex;justify-content:flex-end}#conflict{font-size:.8em;color:red;margin-top:.5em}\n"], dependencies: [{ kind: "component", type: i1.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "directive", type: i2.MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "directive", type: i2.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i2.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i2.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "component", type: i3.MatList, selector: "mat-list", exportAs: ["matList"] }, { kind: "component", type: i3.MatListItem, selector: "mat-list-item, a[mat-list-item], button[mat-list-item]", inputs: ["activated"], exportAs: ["matListItem"] }, { kind: "component", type: i4.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }] }); }
|
|
80
80
|
}
|
|
81
81
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.2", ngImport: i0, type: UploadDialogComponent, decorators: [{
|
|
82
82
|
type: Component,
|
|
83
|
-
args: [{ template: "<input type=\"file\" #file style=\"display: none\" (change)=\"onFilesAdded()\" multiple />\n\n<div mat-dialog-title id=\"title\">\n <div>{{ uploadService.config.uploadDialogTitle }}</div>\n <button [disabled]=\"uploading || uploadSuccessful\" mat-raised-button color=\"primary\" class=\"add-files-btn\" (click)=\"addFiles()\">\n {{ uploadService.config.uploadDialogAddFilesButtonText }}\n </button>\n</div>\n\n@if (existingFileConflict) {\n <div id=\"conflict\">\n {{ existingFileConflict }} already exists on the server and cannot be overwritten\n </div>\n}\n\n<mat-dialog-content>\n <mat-list>\n @for (file of files; track file) {\n <mat-list-item>\n <h4 mat-line>{{file.name}}</h4>\n @if (progress) {\n <mat-progress-bar mode=\"determinate\" [value]=\"progress[file.name].progress | async\"
|
|
83
|
+
args: [{ template: "<input type=\"file\" #file style=\"display: none\" (change)=\"onFilesAdded()\" multiple />\n\n<div mat-dialog-title id=\"title\">\n <div>{{ uploadService.config.uploadDialogTitle }}</div>\n <button [disabled]=\"uploading || uploadSuccessful\" mat-raised-button color=\"primary\" class=\"add-files-btn\" (click)=\"addFiles()\">\n {{ uploadService.config.uploadDialogAddFilesButtonText }}\n </button>\n</div>\n\n@if (existingFileConflict) {\n <div id=\"conflict\">\n {{ existingFileConflict }} already exists on the server and cannot be overwritten\n </div>\n}\n\n<mat-dialog-content>\n <mat-list>\n @for (file of files; track file) {\n <mat-list-item>\n <h4 mat-line>{{file.name}}</h4>\n @if (progress) {\n <mat-progress-bar mode=\"determinate\" [value]=\"progress[file.name].progress | async\"/>\n }\n </mat-list-item>\n }\n </mat-list>\n</mat-dialog-content>\n\n<mat-dialog-actions id=\"actions\">\n @if (showCancelButton) {\n <button mat-button mat-dialog-close>{{ uploadService.config.uploadDialogCancelButtonText }}</button>\n }\n @if (files.size > 0) {\n <button mat-raised-button color=\"primary\" [disabled]=\"!canBeClosed\" (click)=\"closeDialog()\">{{ primaryButtonText }}</button>\n }\n</mat-dialog-actions>\n", styles: ["#title{display:flex;justify-content:space-between}#actions{display:flex;justify-content:flex-end}#conflict{font-size:.8em;color:red;margin-top:.5em}\n"] }]
|
|
84
84
|
}], propDecorators: { file: [{
|
|
85
85
|
type: ViewChild,
|
|
86
86
|
args: ['file', { static: true }]
|
|
87
87
|
}] } });
|
|
88
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
88
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXBsb2FkLWRpYWxvZy5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9jbGVhdmVsYW5kcHJpY2Uvbmd4LWxpYi91cGxvYWQvc3JjL2NvbXBvbmVudHMvdXBsb2FkLWRpYWxvZy91cGxvYWQtZGlhbG9nLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2NsZWF2ZWxhbmRwcmljZS9uZ3gtbGliL3VwbG9hZC9zcmMvY29tcG9uZW50cy91cGxvYWQtZGlhbG9nL3VwbG9hZC1kaWFsb2cuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBYyxNQUFNLEVBQVUsU0FBUyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ2pGLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUN4RCxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBRWhDLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQzs7Ozs7OztBQU1oRSxNQUFNLE9BQU8scUJBQXFCO0lBSmxDO1FBS0Usa0JBQWtCO1FBQ1gsY0FBUyxHQUFHLE1BQU0sQ0FBQyxDQUFBLFlBQW1DLENBQUEsQ0FBQyxDQUFDO1FBQ3hELGtCQUFhLEdBQUcsTUFBTSxDQUFDLGFBQWEsQ0FBQyxDQUFDO1FBSXRDLFVBQUssR0FBYyxJQUFJLEdBQUcsRUFBRSxDQUFDO1FBS3BDLGdCQUFXLEdBQUcsSUFBSSxDQUFDO1FBRW5CLHFCQUFnQixHQUFHLElBQUksQ0FBQztRQUN4QixjQUFTLEdBQUcsS0FBSyxDQUFDO1FBQ2xCLHFCQUFnQixHQUFHLEtBQUssQ0FBQztLQXlFMUI7SUF2RUMsUUFBUTtRQUNOLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLE1BQU0sQ0FBQyw0QkFBNEIsQ0FBQztJQUNsRixDQUFDO0lBRUQsUUFBUTtRQUNOLElBQUksQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLEtBQUssRUFBRSxDQUFDO0lBQ2xDLENBQUM7SUFFRCxZQUFZO1FBQ1YsTUFBTSxLQUFLLEdBQTRCLElBQUksQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLEtBQUssQ0FBQztRQUNyRSxLQUFLLE1BQU0sR0FBRyxJQUFJLEtBQUssRUFBRSxDQUFDO1lBQ3hCLElBQUksQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsQ0FBQztnQkFDMUIsaUNBQWlDO2dCQUNqQyxJQUFJLENBQUMsYUFBYSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDO3FCQUN2QyxTQUFTLENBQUMsTUFBTSxDQUFDLEVBQUU7b0JBQ2xCLElBQUksTUFBTSxFQUFFLENBQUM7d0JBQ1gsSUFBSSxDQUFDLG9CQUFvQixHQUFHLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUM7b0JBQzlDLENBQUM7b0JBRUQsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO3dCQUNaLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO29CQUM3QixDQUFDO2dCQUNILENBQUMsQ0FBQyxDQUFDO1lBQ1AsQ0FBQztRQUNILENBQUM7SUFDSCxDQUFDO0lBRUQsV0FBVztRQUNULDREQUE0RDtRQUM1RCxJQUFJLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO1lBQzFCLE9BQU8sSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUNoQyxDQUFDO1FBRUQseUNBQXlDO1FBQ3pDLElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDO1FBRXRCLDZDQUE2QztRQUM3QyxJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUV0RCx5Q0FBeUM7UUFDekMsTUFBTSxzQkFBc0IsR0FBVSxFQUFFLENBQUM7UUFFekMsS0FBSyxJQUFJLEdBQUcsSUFBSSxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7WUFDOUIsc0JBQXNCLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDM0QsQ0FBQztRQUVELDZCQUE2QjtRQUU3QixrREFBa0Q7UUFDbEQsSUFBSSxDQUFDLGlCQUFpQixHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsTUFBTSxDQUFDLDRCQUE0QixDQUFDO1FBRWhGLGtEQUFrRDtRQUNsRCxJQUFJLENBQUMsV0FBVyxHQUFHLEtBQUssQ0FBQztRQUN6QixJQUFJLENBQUMsU0FBUyxDQUFDLFlBQVksR0FBRyxJQUFJLENBQUM7UUFFbkMseUJBQXlCO1FBQ3pCLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxLQUFLLENBQUM7UUFFOUIsaURBQWlEO1FBQ2pELFFBQVEsQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsRUFBRTtZQUMvQyx3Q0FBd0M7WUFDeEMsSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLENBQUM7WUFDeEIsSUFBSSxDQUFDLFNBQVMsQ0FBQyxZQUFZLEdBQUcsS0FBSyxDQUFDO1lBRXBDLG1DQUFtQztZQUNuQyxJQUFJLENBQUMsZ0JBQWdCLEdBQUcsSUFBSSxDQUFDO1lBRTdCLCtDQUErQztZQUMvQyxJQUFJLENBQUMsU0FBUyxHQUFHLEtBQUssQ0FBQztRQUN6QixDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7OEdBeEZVLHFCQUFxQjtrR0FBckIscUJBQXFCLGdLQ1ZsQywwd0NBb0NBOzsyRkQxQmEscUJBQXFCO2tCQUpqQyxTQUFTOzs4QkFVNkIsSUFBSTtzQkFBeEMsU0FBUzt1QkFBQyxNQUFNLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBFbGVtZW50UmVmLCBpbmplY3QsIE9uSW5pdCwgVmlld0NoaWxkIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7IE1hdERpYWxvZ1JlZiB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2RpYWxvZyc7XHJcbmltcG9ydCB7IGZvcmtKb2luIH0gZnJvbSAncnhqcyc7XHJcblxyXG5pbXBvcnQgeyBVcGxvYWRTZXJ2aWNlIH0gZnJvbSAnLi8uLi8uLi9zZXJ2aWNlcy91cGxvYWQuc2VydmljZSc7XHJcblxyXG5AQ29tcG9uZW50KHtcclxuICB0ZW1wbGF0ZVVybDogJy4vdXBsb2FkLWRpYWxvZy5jb21wb25lbnQuaHRtbCcsXHJcbiAgc3R5bGVVcmxzOiBbJy4vdXBsb2FkLWRpYWxvZy5jb21wb25lbnQuY3NzJ11cclxufSlcclxuZXhwb3J0IGNsYXNzIFVwbG9hZERpYWxvZ0NvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCB7XHJcbiAgLy8jcmVnaW9uIFNlcnZpY2VzXHJcbiAgcHVibGljIGRpYWxvZ1JlZiA9IGluamVjdChNYXREaWFsb2dSZWY8VXBsb2FkRGlhbG9nQ29tcG9uZW50Pik7XHJcbiAgcHVibGljIHVwbG9hZFNlcnZpY2UgPSBpbmplY3QoVXBsb2FkU2VydmljZSk7XHJcbiAgLy8jZW5kcmVnaW9uXHJcblxyXG4gIEBWaWV3Q2hpbGQoJ2ZpbGUnLCB7IHN0YXRpYzogdHJ1ZSB9KSBmaWxlITogRWxlbWVudFJlZjtcclxuICBwdWJsaWMgZmlsZXM6IFNldDxGaWxlPiA9IG5ldyBTZXQoKTtcclxuICBleGlzdGluZ0ZpbGVDb25mbGljdD86IHN0cmluZztcclxuXHJcbiAgLy8gU3RhdGVcclxuICBwcm9ncmVzczogYW55O1xyXG4gIGNhbkJlQ2xvc2VkID0gdHJ1ZTtcclxuICBwcmltYXJ5QnV0dG9uVGV4dD86IHN0cmluZztcclxuICBzaG93Q2FuY2VsQnV0dG9uID0gdHJ1ZTtcclxuICB1cGxvYWRpbmcgPSBmYWxzZTtcclxuICB1cGxvYWRTdWNjZXNzZnVsID0gZmFsc2U7XHJcblxyXG4gIG5nT25Jbml0KCkge1xyXG4gICAgdGhpcy5wcmltYXJ5QnV0dG9uVGV4dCA9IHRoaXMudXBsb2FkU2VydmljZS5jb25maWcudXBsb2FkRGlhbG9nVXBsb2FkQnV0dG9uVGV4dDtcclxuICB9XHJcblxyXG4gIGFkZEZpbGVzKCkge1xyXG4gICAgdGhpcy5maWxlLm5hdGl2ZUVsZW1lbnQuY2xpY2soKTtcclxuICB9XHJcblxyXG4gIG9uRmlsZXNBZGRlZCgpIHtcclxuICAgIGNvbnN0IGZpbGVzOiB7IFtrZXk6IHN0cmluZ106IEZpbGUgfSA9IHRoaXMuZmlsZS5uYXRpdmVFbGVtZW50LmZpbGVzO1xyXG4gICAgZm9yIChjb25zdCBrZXkgaW4gZmlsZXMpIHtcclxuICAgICAgaWYgKCFpc05hTihwYXJzZUludChrZXkpKSkge1xyXG4gICAgICAgIC8vIFNlZSBpZiB0aGUgZmlsZSBhbHJlYWR5IGV4aXN0c1xyXG4gICAgICAgIHRoaXMudXBsb2FkU2VydmljZS5leGlzdHMoZmlsZXNba2V5XS5uYW1lKVxyXG4gICAgICAgICAgLnN1YnNjcmliZShleGlzdHMgPT4ge1xyXG4gICAgICAgICAgICBpZiAoZXhpc3RzKSB7XHJcbiAgICAgICAgICAgICAgdGhpcy5leGlzdGluZ0ZpbGVDb25mbGljdCA9IGZpbGVzW2tleV0ubmFtZTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgaWYgKCFleGlzdHMpIHtcclxuICAgICAgICAgICAgICB0aGlzLmZpbGVzLmFkZChmaWxlc1trZXldKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfSk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIGNsb3NlRGlhbG9nKCkge1xyXG4gICAgLy8gaWYgZXZlcnl0aGluZyB3YXMgdXBsb2FkZWQgYWxyZWFkeSwganVzdCBjbG9zZSB0aGUgZGlhbG9nXHJcbiAgICBpZiAodGhpcy51cGxvYWRTdWNjZXNzZnVsKSB7XHJcbiAgICAgIHJldHVybiB0aGlzLmRpYWxvZ1JlZi5jbG9zZSgpO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIHNldCB0aGUgY29tcG9uZW50IHN0YXRlIHRvIFwidXBsb2FkaW5nXCJcclxuICAgIHRoaXMudXBsb2FkaW5nID0gdHJ1ZTtcclxuXHJcbiAgICAvLyBzdGFydCB0aGUgdXBsb2FkIGFuZCBzYXZlIHRoZSBwcm9ncmVzcyBtYXBcclxuICAgIHRoaXMucHJvZ3Jlc3MgPSB0aGlzLnVwbG9hZFNlcnZpY2UudXBsb2FkKHRoaXMuZmlsZXMpO1xyXG5cclxuICAgIC8vIGNvbnZlcnQgdGhlIHByb2dyZXNzIG1hcCBpbnRvIGFuIGFycmF5XHJcbiAgICBjb25zdCBhbGxQcm9ncmVzc09ic2VydmFibGVzOiBhbnlbXSA9IFtdO1xyXG5cclxuICAgIGZvciAobGV0IGtleSBpbiB0aGlzLnByb2dyZXNzKSB7XHJcbiAgICAgIGFsbFByb2dyZXNzT2JzZXJ2YWJsZXMucHVzaCh0aGlzLnByb2dyZXNzW2tleV0ucHJvZ3Jlc3MpO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIEFkanVzdCB0aGUgc3RhdGUgdmFyaWFibGVzXHJcblxyXG4gICAgLy8gVGhlIE9LLWJ1dHRvbiBzaG91bGQgaGF2ZSB0aGUgdGV4dCBcIkZpbmlzaFwiIG5vd1xyXG4gICAgdGhpcy5wcmltYXJ5QnV0dG9uVGV4dCA9IHRoaXMudXBsb2FkU2VydmljZS5jb25maWcudXBsb2FkRGlhbG9nRmluaXNoQnV0dG9uVGV4dDtcclxuXHJcbiAgICAvLyBUaGUgZGlhbG9nIHNob3VsZCBub3QgYmUgY2xvc2VkIHdoaWxlIHVwbG9hZGluZ1xyXG4gICAgdGhpcy5jYW5CZUNsb3NlZCA9IGZhbHNlO1xyXG4gICAgdGhpcy5kaWFsb2dSZWYuZGlzYWJsZUNsb3NlID0gdHJ1ZTtcclxuXHJcbiAgICAvLyBIaWRlIHRoZSBjYW5jZWwtYnV0dG9uXHJcbiAgICB0aGlzLnNob3dDYW5jZWxCdXR0b24gPSBmYWxzZTtcclxuXHJcbiAgICAvLyBXaGVuIGFsbCBwcm9ncmVzcy1vYnNlcnZhYmxlcyBhcmUgY29tcGxldGVkLi4uXHJcbiAgICBmb3JrSm9pbihhbGxQcm9ncmVzc09ic2VydmFibGVzKS5zdWJzY3JpYmUoZW5kID0+IHtcclxuICAgICAgLy8gLi4uIHRoZSBkaWFsb2cgY2FuIGJlIGNsb3NlZCBhZ2Fpbi4uLlxyXG4gICAgICB0aGlzLmNhbkJlQ2xvc2VkID0gdHJ1ZTtcclxuICAgICAgdGhpcy5kaWFsb2dSZWYuZGlzYWJsZUNsb3NlID0gZmFsc2U7XHJcblxyXG4gICAgICAvLyAuLi4gdGhlIHVwbG9hZCB3YXMgc3VjY2Vzc2Z1bC4uLlxyXG4gICAgICB0aGlzLnVwbG9hZFN1Y2Nlc3NmdWwgPSB0cnVlO1xyXG5cclxuICAgICAgLy8gLi4uIGFuZCB0aGUgY29tcG9uZW50IGlzIG5vIGxvbmdlciB1cGxvYWRpbmdcclxuICAgICAgdGhpcy51cGxvYWRpbmcgPSBmYWxzZTtcclxuICAgIH0pO1xyXG4gIH1cclxufVxyXG4iLCI8aW5wdXQgdHlwZT1cImZpbGVcIiAjZmlsZSBzdHlsZT1cImRpc3BsYXk6IG5vbmVcIiAoY2hhbmdlKT1cIm9uRmlsZXNBZGRlZCgpXCIgbXVsdGlwbGUgLz5cblxuPGRpdiBtYXQtZGlhbG9nLXRpdGxlIGlkPVwidGl0bGVcIj5cbiAgPGRpdj57eyB1cGxvYWRTZXJ2aWNlLmNvbmZpZy51cGxvYWREaWFsb2dUaXRsZSB9fTwvZGl2PlxuICA8YnV0dG9uIFtkaXNhYmxlZF09XCJ1cGxvYWRpbmcgfHwgdXBsb2FkU3VjY2Vzc2Z1bFwiIG1hdC1yYWlzZWQtYnV0dG9uIGNvbG9yPVwicHJpbWFyeVwiIGNsYXNzPVwiYWRkLWZpbGVzLWJ0blwiIChjbGljayk9XCJhZGRGaWxlcygpXCI+XG4gICAge3sgdXBsb2FkU2VydmljZS5jb25maWcudXBsb2FkRGlhbG9nQWRkRmlsZXNCdXR0b25UZXh0IH19XG4gIDwvYnV0dG9uPlxuPC9kaXY+XG5cbkBpZiAoZXhpc3RpbmdGaWxlQ29uZmxpY3QpIHtcbiAgPGRpdiBpZD1cImNvbmZsaWN0XCI+XG4gICAge3sgZXhpc3RpbmdGaWxlQ29uZmxpY3QgfX0gYWxyZWFkeSBleGlzdHMgb24gdGhlIHNlcnZlciBhbmQgY2Fubm90IGJlIG92ZXJ3cml0dGVuXG4gIDwvZGl2PlxufVxuXG48bWF0LWRpYWxvZy1jb250ZW50PlxuICA8bWF0LWxpc3Q+XG4gICAgQGZvciAoZmlsZSBvZiBmaWxlczsgdHJhY2sgZmlsZSkge1xuICAgICAgPG1hdC1saXN0LWl0ZW0+XG4gICAgICAgIDxoNCBtYXQtbGluZT57e2ZpbGUubmFtZX19PC9oND5cbiAgICAgICAgQGlmIChwcm9ncmVzcykge1xuICAgICAgICAgIDxtYXQtcHJvZ3Jlc3MtYmFyIG1vZGU9XCJkZXRlcm1pbmF0ZVwiIFt2YWx1ZV09XCJwcm9ncmVzc1tmaWxlLm5hbWVdLnByb2dyZXNzIHwgYXN5bmNcIi8+XG4gICAgICAgIH1cbiAgICAgIDwvbWF0LWxpc3QtaXRlbT5cbiAgICB9XG4gIDwvbWF0LWxpc3Q+XG48L21hdC1kaWFsb2ctY29udGVudD5cblxuPG1hdC1kaWFsb2ctYWN0aW9ucyBpZD1cImFjdGlvbnNcIj5cbiAgQGlmIChzaG93Q2FuY2VsQnV0dG9uKSB7XG4gICAgPGJ1dHRvbiBtYXQtYnV0dG9uIG1hdC1kaWFsb2ctY2xvc2U+e3sgdXBsb2FkU2VydmljZS5jb25maWcudXBsb2FkRGlhbG9nQ2FuY2VsQnV0dG9uVGV4dCB9fTwvYnV0dG9uPlxuICB9XG4gIEBpZiAoZmlsZXMuc2l6ZSA+IDApIHtcbiAgICA8YnV0dG9uIG1hdC1yYWlzZWQtYnV0dG9uIGNvbG9yPVwicHJpbWFyeVwiIFtkaXNhYmxlZF09XCIhY2FuQmVDbG9zZWRcIiAoY2xpY2spPVwiY2xvc2VEaWFsb2coKVwiPnt7IHByaW1hcnlCdXR0b25UZXh0IH19PC9idXR0b24+XG4gIH1cbjwvbWF0LWRpYWxvZy1hY3Rpb25zPlxuIl19
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ActiveDirectoryService, ServiceConfig } from '@cleavelandprice/ngx-lib/active-directory';
|
|
2
2
|
export * from '@cleavelandprice/ngx-lib/active-directory';
|
|
3
3
|
import * as i0 from '@angular/core';
|
|
4
|
-
import { inject, Component,
|
|
4
|
+
import { inject, Component, ViewChild, EventEmitter, input, Output, NgModule, Optional, SkipSelf } from '@angular/core';
|
|
5
5
|
import * as i1 from '@angular/forms';
|
|
6
6
|
import { FormGroup, FormControl, ReactiveFormsModule } from '@angular/forms';
|
|
7
7
|
import * as i3 from '@angular/material/dialog';
|
|
@@ -85,10 +85,22 @@ class UserChooserData {
|
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
class UserChooserComponent {
|
|
88
|
+
constructor() {
|
|
89
|
+
//#region Services
|
|
90
|
+
this.dialogRef = inject((MatDialogRef));
|
|
91
|
+
this.activeDirectoryService = inject(ActiveDirectoryService);
|
|
92
|
+
this.sharePointService = inject(SharePointService);
|
|
93
|
+
this.data = inject(MAT_DIALOG_DATA);
|
|
94
|
+
this._data = { ...new UserChooserData(), ...this.data };
|
|
95
|
+
////filterInputFocused = false;
|
|
96
|
+
this.filterForm = new FormGroup({
|
|
97
|
+
filter: new FormControl()
|
|
98
|
+
});
|
|
99
|
+
}
|
|
88
100
|
//#endregion
|
|
89
101
|
//#region Properties
|
|
90
102
|
get isMultiMode() {
|
|
91
|
-
return this.
|
|
103
|
+
return this._data.mode === UserChooserMode.Multiple;
|
|
92
104
|
}
|
|
93
105
|
get selectedOptions() {
|
|
94
106
|
return this.selectionList?.options.filter(o => o.selected) ?? [];
|
|
@@ -101,31 +113,15 @@ class UserChooserComponent {
|
|
|
101
113
|
}
|
|
102
114
|
get adGroupsNeeded() {
|
|
103
115
|
// If any are these are true, then we need to pull AD groups for use later
|
|
104
|
-
return this.
|
|
105
|
-
this.
|
|
106
|
-
this.
|
|
107
|
-
this.
|
|
108
|
-
this.
|
|
109
|
-
(this.
|
|
116
|
+
return this._data.showGroupMembershipTooltips ||
|
|
117
|
+
this._data.exclusions.groups.length > 0 ||
|
|
118
|
+
this._data.inclusions.groups.length > 0 ||
|
|
119
|
+
this._data.preSelections.groups.length > 0 ||
|
|
120
|
+
this._data.filterOptions.groupMembership ||
|
|
121
|
+
(this._data.selectableGroupNames?.length ?? 0) > 0; // debug
|
|
110
122
|
}
|
|
111
123
|
//#endregion
|
|
112
124
|
//#region Lifecycle
|
|
113
|
-
constructor(data) {
|
|
114
|
-
this.data = data;
|
|
115
|
-
//#region Fields
|
|
116
|
-
//#region Services
|
|
117
|
-
this.dialogRef = inject((MatDialogRef));
|
|
118
|
-
this.activeDirectoryService = inject(ActiveDirectoryService);
|
|
119
|
-
this.sharePointService = inject(SharePointService);
|
|
120
|
-
////filterInputFocused = false;
|
|
121
|
-
this.filterForm = new FormGroup({
|
|
122
|
-
filter: new FormControl()
|
|
123
|
-
});
|
|
124
|
-
this.data = {
|
|
125
|
-
...new UserChooserData(),
|
|
126
|
-
...data
|
|
127
|
-
};
|
|
128
|
-
}
|
|
129
125
|
ngOnInit() {
|
|
130
126
|
this.getData();
|
|
131
127
|
this.listenForFilterChanges();
|
|
@@ -141,9 +137,9 @@ class UserChooserComponent {
|
|
|
141
137
|
//#endregion
|
|
142
138
|
//#region Events
|
|
143
139
|
listSelectionChanged(options) {
|
|
144
|
-
if (this.
|
|
140
|
+
if (this._data.mode === UserChooserMode.Single &&
|
|
145
141
|
this.selectedOptions.length &&
|
|
146
|
-
this.
|
|
142
|
+
this._data.closeWhenSelectionMade) {
|
|
147
143
|
this.close();
|
|
148
144
|
}
|
|
149
145
|
}
|
|
@@ -176,22 +172,22 @@ class UserChooserComponent {
|
|
|
176
172
|
}
|
|
177
173
|
getData() {
|
|
178
174
|
const dataObservables = [
|
|
179
|
-
this.
|
|
175
|
+
this._data.users ?
|
|
180
176
|
// Users were passed in
|
|
181
|
-
of(this.
|
|
177
|
+
of(this._data.users) :
|
|
182
178
|
// Users need to be retrieved
|
|
183
|
-
this.activeDirectoryService.getUsers(false, this.
|
|
184
|
-
this.
|
|
179
|
+
this.activeDirectoryService.getUsers(false, this._data.includeDisabledUsers, this._data.parentOu),
|
|
180
|
+
this._data.photos ?
|
|
185
181
|
// Photos were passed in
|
|
186
|
-
of(this.
|
|
182
|
+
of(this._data.photos) :
|
|
187
183
|
// Photos need to be retrieved
|
|
188
184
|
this.sharePointService.getPhotos()
|
|
189
185
|
];
|
|
190
186
|
// Do we need AD groups?
|
|
191
187
|
if (this.adGroupsNeeded) {
|
|
192
|
-
this.
|
|
188
|
+
this._data.groups ?
|
|
193
189
|
// Groups were passed in
|
|
194
|
-
of(this.
|
|
190
|
+
of(this._data.groups) :
|
|
195
191
|
// Groups need to be retrieved
|
|
196
192
|
dataObservables.push(this.activeDirectoryService.getGroups());
|
|
197
193
|
}
|
|
@@ -218,8 +214,8 @@ class UserChooserComponent {
|
|
|
218
214
|
const usersAndGroups = [
|
|
219
215
|
...users
|
|
220
216
|
];
|
|
221
|
-
if (this.
|
|
222
|
-
this.
|
|
217
|
+
if (this._data.selectableGroupNames?.length) {
|
|
218
|
+
this._data.selectableGroupNames
|
|
223
219
|
.forEach(groupName => {
|
|
224
220
|
const group = this.groups.find(g => g.displayName === groupName);
|
|
225
221
|
if (group) {
|
|
@@ -241,8 +237,8 @@ class UserChooserComponent {
|
|
|
241
237
|
return;
|
|
242
238
|
}
|
|
243
239
|
const value = this.selectedUsers
|
|
244
|
-
.map(u => this.
|
|
245
|
-
this.dialogRef.close(this.
|
|
240
|
+
.map(u => this._data.returnUserObjects ? u : u.sAMAccountName);
|
|
241
|
+
this.dialogRef.close(this._data.mode === UserChooserMode.Multiple ?
|
|
246
242
|
value :
|
|
247
243
|
value[0]);
|
|
248
244
|
}
|
|
@@ -257,7 +253,7 @@ class UserChooserComponent {
|
|
|
257
253
|
}
|
|
258
254
|
//#region Exclusions - won't be included in the dataSource at all
|
|
259
255
|
excludeUsersByAccountName(users) {
|
|
260
|
-
this.
|
|
256
|
+
this._data.exclusions.accountNames
|
|
261
257
|
.forEach(accountName => {
|
|
262
258
|
const index = users.findIndex(u => u.sAMAccountName.toLowerCase() === accountName.toLowerCase());
|
|
263
259
|
if (index === -1) {
|
|
@@ -268,7 +264,7 @@ class UserChooserComponent {
|
|
|
268
264
|
return users;
|
|
269
265
|
}
|
|
270
266
|
excludeUsersByGroupName(users) {
|
|
271
|
-
this.
|
|
267
|
+
this._data.exclusions.groups
|
|
272
268
|
.forEach(groupName => {
|
|
273
269
|
const group = this.groups?.find(g => g.name.toLowerCase() === groupName.toLowerCase());
|
|
274
270
|
if (!group) {
|
|
@@ -285,7 +281,7 @@ class UserChooserComponent {
|
|
|
285
281
|
return users;
|
|
286
282
|
}
|
|
287
283
|
excludeUsersByDepartment(users) {
|
|
288
|
-
this.
|
|
284
|
+
this._data.exclusions.departments
|
|
289
285
|
.forEach(department => {
|
|
290
286
|
const excludedUsers = users.filter(u => u.department?.toLowerCase() === department.toLowerCase());
|
|
291
287
|
excludedUsers.forEach(user => {
|
|
@@ -296,7 +292,7 @@ class UserChooserComponent {
|
|
|
296
292
|
return users;
|
|
297
293
|
}
|
|
298
294
|
excludeUsersByTitle(users) {
|
|
299
|
-
this.
|
|
295
|
+
this._data.exclusions.titles
|
|
300
296
|
.forEach(title => {
|
|
301
297
|
const excludedUsers = users.filter(u => u.title?.toLowerCase() === title.toLowerCase());
|
|
302
298
|
excludedUsers.forEach(user => {
|
|
@@ -309,24 +305,24 @@ class UserChooserComponent {
|
|
|
309
305
|
//#endregion
|
|
310
306
|
//#region Inclusions - only these will be included in the dataSource
|
|
311
307
|
includeUsersByAccountName(users) {
|
|
312
|
-
return users.filter(user => this.
|
|
313
|
-
this.
|
|
308
|
+
return users.filter(user => this._data.inclusions.accountNames.length === 0 || // No account inclusions specified
|
|
309
|
+
this._data.inclusions.accountNames.find(accountName => accountName.toLowerCase() === user.sAMAccountName.toLowerCase()));
|
|
314
310
|
}
|
|
315
311
|
includeUsersByDepartment(users) {
|
|
316
|
-
return users.filter(user => this.
|
|
317
|
-
this.
|
|
312
|
+
return users.filter(user => this._data.inclusions.departments.length === 0 || // No department inclusions specified
|
|
313
|
+
this._data.inclusions.departments.find(department => department.toLowerCase() === user.department?.toLowerCase()));
|
|
318
314
|
}
|
|
319
315
|
includeUsersByTitle(users) {
|
|
320
|
-
return users.filter(user => this.
|
|
321
|
-
this.
|
|
316
|
+
return users.filter(user => this._data.inclusions.titles.length === 0 || // No title inclusions specified
|
|
317
|
+
this._data.inclusions.titles.find(title => title.toLowerCase() === user.title?.toLowerCase()));
|
|
322
318
|
}
|
|
323
319
|
includeUsersByGroupName(users) {
|
|
324
|
-
if (!this.
|
|
320
|
+
if (!this._data.inclusions.groups.length) {
|
|
325
321
|
return users; // No group inclusions specified
|
|
326
322
|
}
|
|
327
323
|
// Cheating a bit and leveraging the 'selected' property to keep track of who should be included
|
|
328
324
|
// Since inclusions happen befor pre-selections, we can do that, as long as we set 'selected' back to false when we're done
|
|
329
|
-
this.
|
|
325
|
+
this._data.inclusions.groups
|
|
330
326
|
.forEach(groupName => {
|
|
331
327
|
const group = this.groups?.find(g => g.name.toLowerCase() === groupName.toLowerCase());
|
|
332
328
|
if (!group) {
|
|
@@ -345,7 +341,7 @@ class UserChooserComponent {
|
|
|
345
341
|
//#endregion
|
|
346
342
|
//#region Pre-Selections
|
|
347
343
|
preSelectUsersByAccountName(users) {
|
|
348
|
-
this.
|
|
344
|
+
this._data.preSelections.accountNames
|
|
349
345
|
.forEach(accountName => {
|
|
350
346
|
const user = users.find(u => u.sAMAccountName.toLowerCase() === accountName.toLowerCase());
|
|
351
347
|
if (!user) {
|
|
@@ -356,21 +352,21 @@ class UserChooserComponent {
|
|
|
356
352
|
return users;
|
|
357
353
|
}
|
|
358
354
|
preSelectUsersByDepartment(users) {
|
|
359
|
-
this.
|
|
355
|
+
this._data.preSelections.departments
|
|
360
356
|
.forEach(department => users
|
|
361
357
|
.filter(u => u.department?.toLowerCase() === department.toLowerCase())
|
|
362
358
|
.forEach(user => user.selected = true));
|
|
363
359
|
return users;
|
|
364
360
|
}
|
|
365
361
|
preSelectUsersByTitle(users) {
|
|
366
|
-
this.
|
|
362
|
+
this._data.preSelections.titles
|
|
367
363
|
.forEach(title => users
|
|
368
364
|
.filter(u => u.title?.toLowerCase() === title.toLowerCase())
|
|
369
365
|
.forEach(user => user.selected = true));
|
|
370
366
|
return users;
|
|
371
367
|
}
|
|
372
368
|
preSelectUsersByGroupName(users) {
|
|
373
|
-
this.
|
|
369
|
+
this._data.preSelections.groups
|
|
374
370
|
.forEach(groupName => {
|
|
375
371
|
const group = this.groups?.find(g => g.name.toLowerCase() === groupName.toLowerCase());
|
|
376
372
|
if (!group) {
|
|
@@ -399,16 +395,16 @@ class UserChooserComponent {
|
|
|
399
395
|
const regex = new RegExp(filter, 'i'); // Case-insensitive
|
|
400
396
|
let match = false; // The end result - whether or not a employee matches the filter
|
|
401
397
|
const filterProperties = ['displayName'];
|
|
402
|
-
if (this.
|
|
398
|
+
if (this._data.filterOptions.accountName) {
|
|
403
399
|
filterProperties.push('sAMAccountName');
|
|
404
400
|
}
|
|
405
|
-
if (this.
|
|
401
|
+
if (this._data.filterOptions.title) {
|
|
406
402
|
filterProperties.push('title');
|
|
407
403
|
}
|
|
408
|
-
if (this.
|
|
404
|
+
if (this._data.filterOptions.department) {
|
|
409
405
|
filterProperties.push('department');
|
|
410
406
|
}
|
|
411
|
-
if (this.
|
|
407
|
+
if (this._data.filterOptions.phoneNumber) {
|
|
412
408
|
filterProperties.push('telephoneNumber');
|
|
413
409
|
}
|
|
414
410
|
// Match on the properties configured above
|
|
@@ -420,7 +416,7 @@ class UserChooserComponent {
|
|
|
420
416
|
}
|
|
421
417
|
});
|
|
422
418
|
// Match on group membership (group name)
|
|
423
|
-
if (this.
|
|
419
|
+
if (this._data.filterOptions.groupMembership) {
|
|
424
420
|
user.memberOf.forEach(groupDn => {
|
|
425
421
|
const group = this.groups?.find(group => group.distinguishedName === groupDn && group.name.match(regex));
|
|
426
422
|
if (group) {
|
|
@@ -438,7 +434,7 @@ class UserChooserComponent {
|
|
|
438
434
|
.subscribe(() => this.dataSource.filter = this.filterForm.value.filter?.trim().toLowerCase());
|
|
439
435
|
}
|
|
440
436
|
tooltip(user) {
|
|
441
|
-
return this.
|
|
437
|
+
return this._data.showGroupMembershipTooltips ?
|
|
442
438
|
user.memberOf
|
|
443
439
|
.map(groupDn => this.groups
|
|
444
440
|
?.find(group => group.distinguishedName === groupDn)?.name)
|
|
@@ -446,16 +442,13 @@ class UserChooserComponent {
|
|
|
446
442
|
.join('\n') :
|
|
447
443
|
'';
|
|
448
444
|
}
|
|
449
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.2", ngImport: i0, type: UserChooserComponent, deps: [
|
|
450
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.1.2", 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>{{
|
|
445
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.2", ngImport: i0, type: UserChooserComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
446
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.1.2", 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 @if (dataSource && photos) {\n <form [formGroup]=\"filterForm\">\n @if (dataSource) {\n <mat-form-field>\n <input matInput placeholder=\"Search\" formControlName=\"filter\" #filterInput>\n @if (filterForm.value.filter) {\n <button matSuffix mat-icon-button aria-label=\"Clear\" (click)=\"filterForm.get('filter')?.setValue('')\">\n <mat-icon fontIcon=\"close\"/>\n </button>\n }\n </mat-form-field>\n }\n </form>\n <mat-selection-list [multiple]=\"isMultiMode\"\n (selectionChange)=\"listSelectionChanged($event.options)\">\n @for (user of dataSource?.filteredData; track user) {\n <mat-list-option [value]=\"user\" [selected]=\"user.selected\"\n (selectedChange)=\"optionSelectionChanged(option)\" #option>\n @if (getPhoto(user)) {\n <img matListItemAvatar alt=\"\" [src]=\"getPhoto(user)\">\n } @else {\n <mat-icon matListItemAvatar class=\"no-photo\"\n [fontIcon]=\"isUser(user) ? 'account_circle' : 'group'\"/>\n }\n <div class=\"user\">\n <div [matTooltip]=\"tooltip(user)\" class=\"user-name\">\n {{ user.displayName }}\n @if (isUser(user) && _data.showPhone && castUser(user).telephoneNumber) {\n <div>{{ castUser(user).telephoneNumber }}</div>\n }\n </div>\n @if (isUser(user)) {\n <div>{{ castUser(user).department }}</div>\n <div class=\"title\">{{ castUser(user).title }}</div>\n }\n </div>\n </mat-list-option>\n }\n </mat-selection-list>\n } @else {\n <div>\n <mat-spinner [diameter]=\"50\"/>\n <h2 id=\"spinner-message\">Getting users and photos...</h2>\n </div>\n }\n</mat-dialog-content>\n\n<mat-dialog-actions>\n @if (dataSource && photos) {\n @if (selectedOptions.length) {\n <mat-slide-toggle (change)=\"hideUnselectedChanged($event.checked)\">\n Hide Unselected\n </mat-slide-toggle>\n }\n @if (isMultiMode) {\n <button mat-raised-button color=\"primary\" (click)=\"selectAll()\"\n >\n <mat-icon fontIcon=\"select_all\"/>\n <span class=\"hide-mobile\">Select All</span>\n </button>\n }\n @if (isMultiMode && selectedOptions.length) {\n <button mat-raised-button color=\"primary\" (click)=\"deselectAll()\"\n >\n <mat-icon fontIcon=\"clear_all\"/>\n <span class=\"hide-mobile\">Clear All</span>\n </button>\n }\n @if (isMultiMode || !_data.closeWhenSelectionMade) {\n <button mat-raised-button color=\"primary\" (click)=\"close()\" matTooltip=\"Accept your selection\"\n [disabled]=\"!selectedOptions.length\">\n <mat-icon fontIcon=\"check\"/>\n <span class=\"hide-mobile\">Ok</span>\n </button>\n }\n }\n\n <button mat-raised-button color=\"warn\" mat-dialog-close matTooltip=\"Close this window\">\n <mat-icon fontIcon=\"close\"/>\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: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.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: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i2.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i2.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "directive", type: i3.MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "directive", type: i3.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i3.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i3.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i6.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: i7.MatSelectionList, selector: "mat-selection-list", inputs: ["color", "compareWith", "multiple", "hideSingleSelectionIndicator", "disabled"], outputs: ["selectionChange"], exportAs: ["matSelectionList"] }, { kind: "component", type: i7.MatListOption, selector: "mat-list-option", inputs: ["togglePosition", "checkboxPosition", "color", "value", "selected"], outputs: ["selectedChange"], exportAs: ["matListOption"] }, { kind: "directive", type: i7.MatListItemAvatar, selector: "[matListItemAvatar]" }, { kind: "component", type: i8.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "component", type: i9.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "directive", type: i10.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }] }); }
|
|
451
447
|
}
|
|
452
448
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.2", ngImport: i0, type: UserChooserComponent, decorators: [{
|
|
453
449
|
type: Component,
|
|
454
|
-
args: [{ template: "<div id=\"dialog-title\">\n <h2 mat-dialog-title>{{
|
|
455
|
-
}],
|
|
456
|
-
type: Inject,
|
|
457
|
-
args: [MAT_DIALOG_DATA]
|
|
458
|
-
}] }], propDecorators: { selectionList: [{
|
|
450
|
+
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 @if (dataSource && photos) {\n <form [formGroup]=\"filterForm\">\n @if (dataSource) {\n <mat-form-field>\n <input matInput placeholder=\"Search\" formControlName=\"filter\" #filterInput>\n @if (filterForm.value.filter) {\n <button matSuffix mat-icon-button aria-label=\"Clear\" (click)=\"filterForm.get('filter')?.setValue('')\">\n <mat-icon fontIcon=\"close\"/>\n </button>\n }\n </mat-form-field>\n }\n </form>\n <mat-selection-list [multiple]=\"isMultiMode\"\n (selectionChange)=\"listSelectionChanged($event.options)\">\n @for (user of dataSource?.filteredData; track user) {\n <mat-list-option [value]=\"user\" [selected]=\"user.selected\"\n (selectedChange)=\"optionSelectionChanged(option)\" #option>\n @if (getPhoto(user)) {\n <img matListItemAvatar alt=\"\" [src]=\"getPhoto(user)\">\n } @else {\n <mat-icon matListItemAvatar class=\"no-photo\"\n [fontIcon]=\"isUser(user) ? 'account_circle' : 'group'\"/>\n }\n <div class=\"user\">\n <div [matTooltip]=\"tooltip(user)\" class=\"user-name\">\n {{ user.displayName }}\n @if (isUser(user) && _data.showPhone && castUser(user).telephoneNumber) {\n <div>{{ castUser(user).telephoneNumber }}</div>\n }\n </div>\n @if (isUser(user)) {\n <div>{{ castUser(user).department }}</div>\n <div class=\"title\">{{ castUser(user).title }}</div>\n }\n </div>\n </mat-list-option>\n }\n </mat-selection-list>\n } @else {\n <div>\n <mat-spinner [diameter]=\"50\"/>\n <h2 id=\"spinner-message\">Getting users and photos...</h2>\n </div>\n }\n</mat-dialog-content>\n\n<mat-dialog-actions>\n @if (dataSource && photos) {\n @if (selectedOptions.length) {\n <mat-slide-toggle (change)=\"hideUnselectedChanged($event.checked)\">\n Hide Unselected\n </mat-slide-toggle>\n }\n @if (isMultiMode) {\n <button mat-raised-button color=\"primary\" (click)=\"selectAll()\"\n >\n <mat-icon fontIcon=\"select_all\"/>\n <span class=\"hide-mobile\">Select All</span>\n </button>\n }\n @if (isMultiMode && selectedOptions.length) {\n <button mat-raised-button color=\"primary\" (click)=\"deselectAll()\"\n >\n <mat-icon fontIcon=\"clear_all\"/>\n <span class=\"hide-mobile\">Clear All</span>\n </button>\n }\n @if (isMultiMode || !_data.closeWhenSelectionMade) {\n <button mat-raised-button color=\"primary\" (click)=\"close()\" matTooltip=\"Accept your selection\"\n [disabled]=\"!selectedOptions.length\">\n <mat-icon fontIcon=\"check\"/>\n <span class=\"hide-mobile\">Ok</span>\n </button>\n }\n }\n\n <button mat-raised-button color=\"warn\" mat-dialog-close matTooltip=\"Close this window\">\n <mat-icon fontIcon=\"close\"/>\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"] }]
|
|
451
|
+
}], propDecorators: { selectionList: [{
|
|
459
452
|
type: ViewChild,
|
|
460
453
|
args: [MatSelectionList]
|
|
461
454
|
}], filterInput: [{
|
|
@@ -473,8 +466,9 @@ class UserFormFieldComponent {
|
|
|
473
466
|
//#endregion
|
|
474
467
|
this.usersSelected = new EventEmitter(); // string for Single mode, string[] for multi
|
|
475
468
|
this.userUnSelected = new EventEmitter();
|
|
476
|
-
this.placeholder = 'Select User(s)';
|
|
477
|
-
this.clickable = true;
|
|
469
|
+
this.placeholder = input('Select User(s)');
|
|
470
|
+
this.clickable = input(true);
|
|
471
|
+
this.userChooserData = input.required();
|
|
478
472
|
this.accountNames = [];
|
|
479
473
|
}
|
|
480
474
|
//#endregion
|
|
@@ -485,22 +479,22 @@ class UserFormFieldComponent {
|
|
|
485
479
|
//#endregion
|
|
486
480
|
//#region Lifecycle
|
|
487
481
|
ngOnInit() {
|
|
488
|
-
this.
|
|
482
|
+
this._userChooserData = {
|
|
489
483
|
...new UserChooserData(),
|
|
490
|
-
...this.userChooserData
|
|
484
|
+
...this.userChooserData()
|
|
491
485
|
};
|
|
492
486
|
// If users have been pre-selected in the config, store those in accountNames, which drives the UI of this component
|
|
493
|
-
this.accountNames = this.
|
|
487
|
+
this.accountNames = this._userChooserData.preSelections.accountNames;
|
|
494
488
|
this.getData();
|
|
495
489
|
}
|
|
496
490
|
//#endregion
|
|
497
491
|
//#region Events
|
|
498
492
|
selectUser() {
|
|
499
|
-
if (!this.clickable) {
|
|
493
|
+
if (!this.clickable()) {
|
|
500
494
|
return;
|
|
501
495
|
}
|
|
502
496
|
const data = {
|
|
503
|
-
...this.
|
|
497
|
+
...this._userChooserData,
|
|
504
498
|
users: this.users,
|
|
505
499
|
photos: this.photos,
|
|
506
500
|
};
|
|
@@ -516,33 +510,33 @@ class UserFormFieldComponent {
|
|
|
516
510
|
selected :
|
|
517
511
|
[selected];
|
|
518
512
|
// Overwrite what may have been passed in, for subsequent launches of UserChooserComponent - otherwise it just keeps getting fed stale data
|
|
519
|
-
this.
|
|
513
|
+
this._userChooserData.preSelections.accountNames = this.accountNames;
|
|
520
514
|
this.usersSelected.emit(selected);
|
|
521
515
|
});
|
|
522
516
|
}
|
|
523
517
|
unSelectUser(accountName) {
|
|
524
518
|
const index = this.accountNames.findIndex(a => a === accountName);
|
|
525
519
|
this.accountNames.splice(index, 1);
|
|
526
|
-
this.
|
|
520
|
+
this._userChooserData.preSelections.accountNames = this.accountNames;
|
|
527
521
|
this.userUnSelected.emit(accountName);
|
|
528
522
|
}
|
|
529
523
|
//#endregion
|
|
530
524
|
//#region Utilities
|
|
531
525
|
getData() {
|
|
532
526
|
forkJoin([
|
|
533
|
-
this.
|
|
527
|
+
this._userChooserData.users ?
|
|
534
528
|
// Users were passed in
|
|
535
|
-
of(this.
|
|
529
|
+
of(this._userChooserData.users) :
|
|
536
530
|
// Users need to be retrieved
|
|
537
|
-
this.activeDirectoryService.getUsers(false, this.
|
|
538
|
-
this.
|
|
531
|
+
this.activeDirectoryService.getUsers(false, this._userChooserData.includeDisabledUsers, this._userChooserData.parentOu),
|
|
532
|
+
this._userChooserData.groups ?
|
|
539
533
|
// Groups were passed in
|
|
540
|
-
of(this.
|
|
534
|
+
of(this._userChooserData.groups) :
|
|
541
535
|
// Groups need to be retrieved
|
|
542
|
-
this.activeDirectoryService.getGroups(this.
|
|
543
|
-
this.
|
|
536
|
+
this.activeDirectoryService.getGroups(this._userChooserData.parentOu),
|
|
537
|
+
this._userChooserData.photos ?
|
|
544
538
|
// Photos were passed in
|
|
545
|
-
of(this.
|
|
539
|
+
of(this._userChooserData.photos) :
|
|
546
540
|
// Photos need to be retrieved
|
|
547
541
|
this.sharePointService.getPhotos()
|
|
548
542
|
])
|
|
@@ -569,21 +563,15 @@ class UserFormFieldComponent {
|
|
|
569
563
|
p.title?.toLowerCase() === user.displayName.toLowerCase())?.encodedAbsUrl;
|
|
570
564
|
}
|
|
571
565
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.2", ngImport: i0, type: UserFormFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
572
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.1.2", type: UserFormFieldComponent, selector: "cp-user-field", inputs: { placeholder: "placeholder", clickable: "clickable", userChooserData: "userChooserData" }, outputs: { usersSelected: "usersSelected", userUnSelected: "userUnSelected" }, ngImport: i0, template: "\n<!-- In Microsoft Edge, selectUser() never gets called if the input fields are disabled\nSo... I'm dynamically setting the disabled property based on whether or not the browser is Edge.\nIt's definitely a better experience if the field IS disabled.\nOtherwise, it's confusing - especially because Edge is SO SLOW to display the resulting dialog window.\n-->\n<!-- Update 8/24/2023:\nThe above problem also exists in Chrome now.\nSo instead of dynamically setting [disabled] based on browser type,\nI'm applying CSS to suppress mouse events on the input - thus making it bubble up to the parent control, which responds the way we want/\n-->\n\n@if (users && photos) {\n <div (click)=\"selectUser()\" [class.clickable]=\"clickable\">\n @if (accountNames
|
|
566
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.1.2", type: UserFormFieldComponent, selector: "cp-user-field", inputs: { placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, clickable: { classPropertyName: "clickable", publicName: "clickable", isSignal: true, isRequired: false, transformFunction: null }, userChooserData: { classPropertyName: "userChooserData", publicName: "userChooserData", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { usersSelected: "usersSelected", userUnSelected: "userUnSelected" }, ngImport: i0, template: "\n<!-- In Microsoft Edge, selectUser() never gets called if the input fields are disabled\nSo... I'm dynamically setting the disabled property based on whether or not the browser is Edge.\nIt's definitely a better experience if the field IS disabled.\nOtherwise, it's confusing - especially because Edge is SO SLOW to display the resulting dialog window.\n-->\n<!-- Update 8/24/2023:\nThe above problem also exists in Chrome now.\nSo instead of dynamically setting [disabled] based on browser type,\nI'm applying CSS to suppress mouse events on the input - thus making it bubble up to the parent control, which responds the way we want/\n-->\n\n@if (users && photos) {\n <div (click)=\"selectUser()\" [class.clickable]=\"clickable()\">\n @if (accountNames.length) {\n <div\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 @for (accountName of accountNames; track accountName; let i = $index) {\n <div class=\"user\">\n <!--<img *ngIf=\"accountName && empUtils.getEmployee(accountName)\" alt=\"\" [src]=\"empUtils.getEmployee(accountName) | employeePhotoUrl:cacheService.photos\">-->\n @if (getPhoto(accountName)) {\n <img matListItemAvatar alt=\"\" [src]=\"getPhoto(accountName)\">\n }\n @if (getGroup(accountName)) {\n <mat-icon>group</mat-icon>\n }\n <mat-form-field>\n <!-- [disabled]=\"!isEdge\" -->\n <input matInput disabled [placeholder]=\"i === 0 ? placeholder() : ''\"\n [value]=\"getUser(accountName) ? getUser(accountName)?.displayName : getGroup(accountName) ? getGroup(accountName)?.displayName : accountName\">\n <button matSuffix mat-icon-button aria-label=\"Clear\" (click)=\"$event.stopPropagation(); unSelectUser(accountName)\">\n <mat-icon fontIcon=\"close\"/>\n </button>\n </mat-form-field>\n </div>\n }\n </div>\n } @else {\n <mat-form-field>\n <input matInput disabled [placeholder]=\"placeholder()\"> <!-- [disabled]=\"!isEdge\" -->\n </mat-form-field>\n }\n </div>\n} @else {\n <mat-progress-bar mode=\"indeterminate\"/>\n}", 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}}input[disabled]{pointer-events:none}\n"], dependencies: [{ kind: "component", type: i2.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i6.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: i7.MatListItemAvatar, selector: "[matListItemAvatar]" }, { kind: "component", type: i6$1.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }] }); }
|
|
573
567
|
}
|
|
574
568
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.2", ngImport: i0, type: UserFormFieldComponent, decorators: [{
|
|
575
569
|
type: Component,
|
|
576
|
-
args: [{ selector: 'cp-user-field', template: "\n<!-- In Microsoft Edge, selectUser() never gets called if the input fields are disabled\nSo... I'm dynamically setting the disabled property based on whether or not the browser is Edge.\nIt's definitely a better experience if the field IS disabled.\nOtherwise, it's confusing - especially because Edge is SO SLOW to display the resulting dialog window.\n-->\n<!-- Update 8/24/2023:\nThe above problem also exists in Chrome now.\nSo instead of dynamically setting [disabled] based on browser type,\nI'm applying CSS to suppress mouse events on the input - thus making it bubble up to the parent control, which responds the way we want/\n-->\n\n@if (users && photos) {\n <div (click)=\"selectUser()\" [class.clickable]=\"clickable\">\n @if (accountNames
|
|
570
|
+
args: [{ selector: 'cp-user-field', template: "\n<!-- In Microsoft Edge, selectUser() never gets called if the input fields are disabled\nSo... I'm dynamically setting the disabled property based on whether or not the browser is Edge.\nIt's definitely a better experience if the field IS disabled.\nOtherwise, it's confusing - especially because Edge is SO SLOW to display the resulting dialog window.\n-->\n<!-- Update 8/24/2023:\nThe above problem also exists in Chrome now.\nSo instead of dynamically setting [disabled] based on browser type,\nI'm applying CSS to suppress mouse events on the input - thus making it bubble up to the parent control, which responds the way we want/\n-->\n\n@if (users && photos) {\n <div (click)=\"selectUser()\" [class.clickable]=\"clickable()\">\n @if (accountNames.length) {\n <div\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 @for (accountName of accountNames; track accountName; let i = $index) {\n <div class=\"user\">\n <!--<img *ngIf=\"accountName && empUtils.getEmployee(accountName)\" alt=\"\" [src]=\"empUtils.getEmployee(accountName) | employeePhotoUrl:cacheService.photos\">-->\n @if (getPhoto(accountName)) {\n <img matListItemAvatar alt=\"\" [src]=\"getPhoto(accountName)\">\n }\n @if (getGroup(accountName)) {\n <mat-icon>group</mat-icon>\n }\n <mat-form-field>\n <!-- [disabled]=\"!isEdge\" -->\n <input matInput disabled [placeholder]=\"i === 0 ? placeholder() : ''\"\n [value]=\"getUser(accountName) ? getUser(accountName)?.displayName : getGroup(accountName) ? getGroup(accountName)?.displayName : accountName\">\n <button matSuffix mat-icon-button aria-label=\"Clear\" (click)=\"$event.stopPropagation(); unSelectUser(accountName)\">\n <mat-icon fontIcon=\"close\"/>\n </button>\n </mat-form-field>\n </div>\n }\n </div>\n } @else {\n <mat-form-field>\n <input matInput disabled [placeholder]=\"placeholder()\"> <!-- [disabled]=\"!isEdge\" -->\n </mat-form-field>\n }\n </div>\n} @else {\n <mat-progress-bar mode=\"indeterminate\"/>\n}", 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}}input[disabled]{pointer-events:none}\n"] }]
|
|
577
571
|
}], propDecorators: { usersSelected: [{
|
|
578
572
|
type: Output
|
|
579
573
|
}], userUnSelected: [{
|
|
580
574
|
type: Output
|
|
581
|
-
}], placeholder: [{
|
|
582
|
-
type: Input
|
|
583
|
-
}], clickable: [{
|
|
584
|
-
type: Input
|
|
585
|
-
}], userChooserData: [{
|
|
586
|
-
type: Input
|
|
587
575
|
}] } });
|
|
588
576
|
|
|
589
577
|
class GuiModule {
|