@myrmidon/auth-jwt-admin 0.1.2 → 1.0.1
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/esm2020/lib/auth-jwt-admin.module.mjs +11 -11
- package/esm2020/lib/components/auth-jwt-registration/auth-jwt-registration.component.mjs +6 -6
- package/esm2020/lib/components/confirm-dialog/confirm-dialog.component.mjs +3 -3
- package/esm2020/lib/components/password-strength-bar/password-strength-bar.component.mjs +3 -3
- package/esm2020/lib/components/state/user-list.repository.mjs +144 -0
- package/esm2020/lib/components/user-editor/user-editor.component.mjs +7 -7
- package/esm2020/lib/components/user-filter/user-filter.component.mjs +16 -19
- package/esm2020/lib/components/user-list/user-list.component.mjs +37 -103
- package/esm2020/lib/services/auth-jwt-account.service.mjs +7 -7
- package/esm2020/lib/services/dialog.service.mjs +3 -3
- package/fesm2015/myrmidon-auth-jwt-admin.mjs +190 -224
- package/fesm2015/myrmidon-auth-jwt-admin.mjs.map +1 -1
- package/fesm2020/myrmidon-auth-jwt-admin.mjs +189 -222
- package/fesm2020/myrmidon-auth-jwt-admin.mjs.map +1 -1
- package/lib/components/auth-jwt-registration/auth-jwt-registration.component.d.ts +1 -1
- package/lib/components/confirm-dialog/confirm-dialog.component.d.ts +1 -1
- package/lib/components/password-strength-bar/password-strength-bar.component.d.ts +1 -1
- package/lib/components/state/user-list.repository.d.ts +36 -0
- package/lib/components/user-editor/user-editor.component.d.ts +1 -1
- package/lib/components/user-filter/user-filter.component.d.ts +7 -8
- package/lib/components/user-list/user-list.component.d.ts +11 -20
- package/lib/services/auth-jwt-account.service.d.ts +1 -3
- package/package.json +6 -6
- package/esm2020/lib/components/state/users.paginator.mjs +0 -12
- package/esm2020/lib/components/state/users.query.mjs +0 -20
- package/esm2020/lib/components/state/users.service.mjs +0 -65
- package/esm2020/lib/components/state/users.store.mjs +0 -27
- package/lib/components/state/users.paginator.d.ts +0 -3
- package/lib/components/state/users.query.d.ts +0 -12
- package/lib/components/state/users.service.d.ts +0 -19
- package/lib/components/state/users.store.d.ts +0 -13
|
@@ -1,43 +1,45 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { Injectable, EventEmitter, Component, Input, Output,
|
|
2
|
+
import { Injectable, EventEmitter, Component, Input, Output, Optional, Inject, NgModule } from '@angular/core';
|
|
3
3
|
import * as i1$1 from '@angular/forms';
|
|
4
4
|
import { Validators, FormsModule, ReactiveFormsModule } from '@angular/forms';
|
|
5
|
-
import { retry, catchError, take
|
|
5
|
+
import { retry, catchError, take } from 'rxjs/operators';
|
|
6
6
|
import * as i2$1 from '@angular/material/snack-bar';
|
|
7
7
|
import { MatSnackBarModule } from '@angular/material/snack-bar';
|
|
8
8
|
import * as i1 from '@angular/common/http';
|
|
9
9
|
import { HttpParams, HttpClientModule } from '@angular/common/http';
|
|
10
10
|
import * as i2 from '@myrmidon/ng-tools';
|
|
11
11
|
import { NgToolsModule } from '@myrmidon/ng-tools';
|
|
12
|
-
import * as
|
|
12
|
+
import * as i4 from '@angular/common';
|
|
13
13
|
import { CommonModule } from '@angular/common';
|
|
14
|
-
import * as
|
|
14
|
+
import * as i5 from '@angular/material/button';
|
|
15
15
|
import { MatButtonModule } from '@angular/material/button';
|
|
16
16
|
import * as i6 from '@angular/material/icon';
|
|
17
17
|
import { MatIconModule } from '@angular/material/icon';
|
|
18
|
-
import * as i7
|
|
19
|
-
import * as i8 from '@angular/material/input';
|
|
18
|
+
import * as i7 from '@angular/material/input';
|
|
20
19
|
import { MatInputModule } from '@angular/material/input';
|
|
20
|
+
import * as i8 from '@angular/material/form-field';
|
|
21
21
|
import * as i9 from '@angular/material/progress-spinner';
|
|
22
22
|
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
|
23
|
-
import
|
|
24
|
-
import {
|
|
25
|
-
import {
|
|
26
|
-
import
|
|
23
|
+
import { __rest } from 'tslib';
|
|
24
|
+
import { BehaviorSubject, combineLatest, map, debounceTime, take as take$1 } from 'rxjs';
|
|
25
|
+
import { select, createStore, withProps } from '@ngneat/elf';
|
|
26
|
+
import { selectActiveEntity, withEntities, withActiveId, upsertEntities, deleteAllEntities, setActiveId } from '@ngneat/elf-entities';
|
|
27
|
+
import { selectPaginationData, selectCurrentPageEntities, deleteAllPages, withPagination, updatePaginationData, setPage, hasPage, setCurrentPage } from '@ngneat/elf-pagination';
|
|
28
|
+
import { selectRequestStatus, withRequestsCache, withRequestsStatus, updateRequestStatus } from '@ngneat/elf-requests';
|
|
29
|
+
import * as i9$1 from '@angular/material/tooltip';
|
|
27
30
|
import { MatTooltipModule } from '@angular/material/tooltip';
|
|
28
|
-
import { BehaviorSubject, combineLatest } from 'rxjs';
|
|
29
31
|
import * as i1$2 from '@angular/material/dialog';
|
|
30
32
|
import { MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog';
|
|
31
33
|
import * as i2$2 from '@myrmidon/auth-jwt-login';
|
|
32
34
|
import { AuthJwtLoginModule } from '@myrmidon/auth-jwt-login';
|
|
33
|
-
import * as
|
|
35
|
+
import * as i7$1 from '@angular/material/paginator';
|
|
34
36
|
import { MatPaginatorModule } from '@angular/material/paginator';
|
|
35
|
-
import * as
|
|
37
|
+
import * as i8$1 from '@angular/material/progress-bar';
|
|
36
38
|
import { MatProgressBarModule } from '@angular/material/progress-bar';
|
|
37
|
-
import * as i5 from '@angular/material/checkbox';
|
|
39
|
+
import * as i5$1 from '@angular/material/checkbox';
|
|
38
40
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
|
39
|
-
import { MatCardModule } from '@angular/material/card';
|
|
40
41
|
import { RouterModule } from '@angular/router';
|
|
42
|
+
import { MatCardModule } from '@angular/material/card';
|
|
41
43
|
|
|
42
44
|
class PasswordValidators {
|
|
43
45
|
/** "Standard" password validator for my API services. */
|
|
@@ -148,10 +150,10 @@ class AuthJwtAccountService {
|
|
|
148
150
|
})
|
|
149
151
|
.pipe(retry(3), catchError(this._error.handleError));
|
|
150
152
|
}
|
|
151
|
-
getUsers(filter) {
|
|
153
|
+
getUsers(filter, pageNumber = 1, pageSize = 20) {
|
|
152
154
|
let httpParams = new HttpParams();
|
|
153
|
-
httpParams = httpParams.set('pageNumber',
|
|
154
|
-
httpParams = httpParams.set('pageSize',
|
|
155
|
+
httpParams = httpParams.set('pageNumber', pageNumber.toString());
|
|
156
|
+
httpParams = httpParams.set('pageSize', pageSize.toString());
|
|
155
157
|
if (filter.name) {
|
|
156
158
|
httpParams = httpParams.set('name', filter.name);
|
|
157
159
|
}
|
|
@@ -248,9 +250,9 @@ class AuthJwtAccountService {
|
|
|
248
250
|
.pipe(catchError(this._error.handleError));
|
|
249
251
|
}
|
|
250
252
|
}
|
|
251
|
-
AuthJwtAccountService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
252
|
-
AuthJwtAccountService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
253
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
253
|
+
AuthJwtAccountService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: AuthJwtAccountService, deps: [{ token: i1.HttpClient }, { token: i2.ErrorService }, { token: i2.EnvService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
254
|
+
AuthJwtAccountService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: AuthJwtAccountService, providedIn: 'root' });
|
|
255
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: AuthJwtAccountService, decorators: [{
|
|
254
256
|
type: Injectable,
|
|
255
257
|
args: [{
|
|
256
258
|
providedIn: 'root',
|
|
@@ -324,9 +326,9 @@ class PasswordStrengthBarComponent {
|
|
|
324
326
|
}
|
|
325
327
|
}
|
|
326
328
|
}
|
|
327
|
-
PasswordStrengthBarComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
328
|
-
PasswordStrengthBarComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "
|
|
329
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
329
|
+
PasswordStrengthBarComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: PasswordStrengthBarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
330
|
+
PasswordStrengthBarComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.0", type: PasswordStrengthBarComponent, selector: "auth-jwt-password-strength-bar", inputs: { passwordToCheck: "passwordToCheck" }, outputs: { strengthChange: "strengthChange" }, usesOnChanges: true, ngImport: i0, template: "<div id=\"strength\">\n <small>strength:</small>\n <ul id=\"strengthBar\">\n <li class=\"point\" [style.background-color]=\"bars[0]\"></li>\n <li class=\"point\" [style.background-color]=\"bars[1]\"></li>\n <li class=\"point\" [style.background-color]=\"bars[2]\"></li>\n <li class=\"point\" [style.background-color]=\"bars[3]\"></li>\n <li class=\"point\" [style.background-color]=\"bars[4]\"></li>\n </ul>\n</div>\n", styles: ["ul#strengthBar{display:inline;list-style:none;margin:0 0 0 15px;padding:0;vertical-align:2px}li.point:last{margin:0!important}li.point{background:#ddd;border-radius:2px;display:inline-block;height:5px;margin-right:1px;width:20px}\n"] });
|
|
331
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: PasswordStrengthBarComponent, decorators: [{
|
|
330
332
|
type: Component,
|
|
331
333
|
args: [{ selector: 'auth-jwt-password-strength-bar', template: "<div id=\"strength\">\n <small>strength:</small>\n <ul id=\"strengthBar\">\n <li class=\"point\" [style.background-color]=\"bars[0]\"></li>\n <li class=\"point\" [style.background-color]=\"bars[1]\"></li>\n <li class=\"point\" [style.background-color]=\"bars[2]\"></li>\n <li class=\"point\" [style.background-color]=\"bars[3]\"></li>\n <li class=\"point\" [style.background-color]=\"bars[4]\"></li>\n </ul>\n</div>\n", styles: ["ul#strengthBar{display:inline;list-style:none;margin:0 0 0 15px;padding:0;vertical-align:2px}li.point:last{margin:0!important}li.point{background:#ddd;border-radius:2px;display:inline-block;height:5px;margin-right:1px;width:20px}\n"] }]
|
|
332
334
|
}], ctorParameters: function () { return []; }, propDecorators: { passwordToCheck: [{
|
|
@@ -514,118 +516,155 @@ class AuthJwtRegistrationComponent {
|
|
|
514
516
|
});
|
|
515
517
|
}
|
|
516
518
|
}
|
|
517
|
-
AuthJwtRegistrationComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
518
|
-
AuthJwtRegistrationComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "
|
|
519
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
519
|
+
AuthJwtRegistrationComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: AuthJwtRegistrationComponent, deps: [{ token: i1$1.UntypedFormBuilder }, { token: i2$1.MatSnackBar }, { token: AuthJwtAccountService }], target: i0.ɵɵFactoryTarget.Component });
|
|
520
|
+
AuthJwtRegistrationComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.0", type: AuthJwtRegistrationComponent, selector: "auth-jwt-registration", outputs: { registered: "registered" }, ngImport: i0, template: "<div>\n <div>\n <p>\n To register a new user, you must provide his email address, choose a\n password, and choose a username, which must be unique (you will be\n notified if another user has already taken that name). The username must\n include only letters/digits, start with a letter, and be no shorter than 3\n characters, nor longer than 50.\n </p>\n <p>\n To promote a decent security level, the password must include at least 8\n characters, uppercase and lowercase letters, digits, and punctuation (like\n dashes, stops, parentheses, etc.).\n </p>\n <p>\n Once registered, the user will receive an email message to the email\n address you specified; he will have to click on the provided link to\n complete the registration process.\n </p>\n </div>\n\n <form role=\"form\" [formGroup]=\"registration\" (submit)=\"onSubmit()\">\n <fieldset>\n <label>register user</label>\n <!-- email -->\n <div>\n <mat-form-field>\n <input\n matInput\n type=\"email\"\n id=\"email\"\n maxlength=\"256\"\n required\n autofocus\n spellcheck=\"false\"\n placeholder=\"email\"\n formControlName=\"email\"\n />\n <mat-error>{{ getEmailErrorLabel() }}</mat-error>\n <mat-icon *ngIf=\"email.pending\">hourglass</mat-icon>\n </mat-form-field>\n </div>\n\n <!-- name -->\n <div>\n <mat-form-field>\n <input\n matInput\n type=\"text\"\n id=\"name\"\n maxlength=\"50\"\n required\n pattern=\"^[a-zA-Z][a-zA-Z0-9]{2,49}$\"\n spellcheck=\"false\"\n placeholder=\"username\"\n formControlName=\"name\"\n />\n <mat-error>{{ getNameErrorLabel() }}</mat-error>\n <mat-icon *ngIf=\"name.pending\">hourglass</mat-icon>\n </mat-form-field>\n </div>\n\n <!-- first name -->\n <div>\n <mat-form-field>\n <input\n matInput\n type=\"text\"\n id=\"firstName\"\n maxlength=\"50\"\n required\n spellcheck=\"false\"\n placeholder=\"first name\"\n formControlName=\"firstName\"\n />\n <mat-error\n *ngIf=\"\n firstName.hasError('required') &&\n (firstName.dirty || firstName.touched)\n \"\n class=\"text-danger small\"\n >\n first name required\n </mat-error>\n </mat-form-field>\n </div>\n\n <!-- last name -->\n <div>\n <mat-form-field>\n <input\n matInput\n type=\"text\"\n id=\"lastName\"\n maxlength=\"50\"\n required\n spellcheck=\"false\"\n placeholder=\"last name\"\n formControlName=\"lastName\"\n />\n <mat-error\n *ngIf=\"\n lastName.hasError('required') &&\n (lastName.dirty || lastName.touched)\n \"\n class=\"text-danger small\"\n >\n last name required\n </mat-error>\n </mat-form-field>\n </div>\n\n <div [formGroup]=\"passwords\">\n <!-- password -->\n <div>\n <mat-form-field>\n <input\n matInput\n type=\"password\"\n name=\"password\"\n autocomplete=\"new-password\"\n maxlength=\"50\"\n required\n spellcheck=\"false\"\n placeholder=\"password\"\n formControlName=\"password\"\n />\n <auth-jwt-password-strength-bar [passwordToCheck]=\"password.value\">\n </auth-jwt-password-strength-bar>\n <mat-error>{{ getPasswordErrorLabel() }}</mat-error>\n </mat-form-field>\n </div>\n\n <!-- confirm password -->\n <div>\n <mat-form-field>\n <input\n matInput\n type=\"password\"\n name=\"confirmPassword\"\n maxlength=\"50\"\n required\n spellcheck=\"false\"\n placeholder=\"confirm password\"\n formControlName=\"confirmPassword\"\n />\n <mat-error\n *ngIf=\"\n passwords.hasError('areEqual') &&\n (confirmPassword.dirty || confirmPassword.touched)\n \"\n >\n password differs from confirmation password\n </mat-error>\n </mat-form-field>\n </div>\n </div>\n\n <button\n mat-raised-button\n type=\"submit\"\n color=\"primary\"\n [disabled]=\"\n !registration.valid || busy || name.pending || email.pending\n \"\n >\n register\n </button>\n <mat-progress-spinner\n diameter=\"20\"\n *ngIf=\"busy\"\n aria-label=\"Busy\"\n ></mat-progress-spinner>\n </fieldset>\n </form>\n</div>\n", styles: ["mat-form-field{width:400px}fieldset{border:1px solid silver;border-radius:8px;padding:16px}\n"], dependencies: [{ kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.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$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$1.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i1$1.PatternValidator, selector: "[pattern][formControlName],[pattern][formControl],[pattern][ngModel]", inputs: ["pattern"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i5.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.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i7.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: i8.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i8.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "component", type: i9.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "component", type: PasswordStrengthBarComponent, selector: "auth-jwt-password-strength-bar", inputs: ["passwordToCheck"], outputs: ["strengthChange"] }] });
|
|
521
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: AuthJwtRegistrationComponent, decorators: [{
|
|
520
522
|
type: Component,
|
|
521
523
|
args: [{ selector: 'auth-jwt-registration', template: "<div>\n <div>\n <p>\n To register a new user, you must provide his email address, choose a\n password, and choose a username, which must be unique (you will be\n notified if another user has already taken that name). The username must\n include only letters/digits, start with a letter, and be no shorter than 3\n characters, nor longer than 50.\n </p>\n <p>\n To promote a decent security level, the password must include at least 8\n characters, uppercase and lowercase letters, digits, and punctuation (like\n dashes, stops, parentheses, etc.).\n </p>\n <p>\n Once registered, the user will receive an email message to the email\n address you specified; he will have to click on the provided link to\n complete the registration process.\n </p>\n </div>\n\n <form role=\"form\" [formGroup]=\"registration\" (submit)=\"onSubmit()\">\n <fieldset>\n <label>register user</label>\n <!-- email -->\n <div>\n <mat-form-field>\n <input\n matInput\n type=\"email\"\n id=\"email\"\n maxlength=\"256\"\n required\n autofocus\n spellcheck=\"false\"\n placeholder=\"email\"\n formControlName=\"email\"\n />\n <mat-error>{{ getEmailErrorLabel() }}</mat-error>\n <mat-icon *ngIf=\"email.pending\">hourglass</mat-icon>\n </mat-form-field>\n </div>\n\n <!-- name -->\n <div>\n <mat-form-field>\n <input\n matInput\n type=\"text\"\n id=\"name\"\n maxlength=\"50\"\n required\n pattern=\"^[a-zA-Z][a-zA-Z0-9]{2,49}$\"\n spellcheck=\"false\"\n placeholder=\"username\"\n formControlName=\"name\"\n />\n <mat-error>{{ getNameErrorLabel() }}</mat-error>\n <mat-icon *ngIf=\"name.pending\">hourglass</mat-icon>\n </mat-form-field>\n </div>\n\n <!-- first name -->\n <div>\n <mat-form-field>\n <input\n matInput\n type=\"text\"\n id=\"firstName\"\n maxlength=\"50\"\n required\n spellcheck=\"false\"\n placeholder=\"first name\"\n formControlName=\"firstName\"\n />\n <mat-error\n *ngIf=\"\n firstName.hasError('required') &&\n (firstName.dirty || firstName.touched)\n \"\n class=\"text-danger small\"\n >\n first name required\n </mat-error>\n </mat-form-field>\n </div>\n\n <!-- last name -->\n <div>\n <mat-form-field>\n <input\n matInput\n type=\"text\"\n id=\"lastName\"\n maxlength=\"50\"\n required\n spellcheck=\"false\"\n placeholder=\"last name\"\n formControlName=\"lastName\"\n />\n <mat-error\n *ngIf=\"\n lastName.hasError('required') &&\n (lastName.dirty || lastName.touched)\n \"\n class=\"text-danger small\"\n >\n last name required\n </mat-error>\n </mat-form-field>\n </div>\n\n <div [formGroup]=\"passwords\">\n <!-- password -->\n <div>\n <mat-form-field>\n <input\n matInput\n type=\"password\"\n name=\"password\"\n autocomplete=\"new-password\"\n maxlength=\"50\"\n required\n spellcheck=\"false\"\n placeholder=\"password\"\n formControlName=\"password\"\n />\n <auth-jwt-password-strength-bar [passwordToCheck]=\"password.value\">\n </auth-jwt-password-strength-bar>\n <mat-error>{{ getPasswordErrorLabel() }}</mat-error>\n </mat-form-field>\n </div>\n\n <!-- confirm password -->\n <div>\n <mat-form-field>\n <input\n matInput\n type=\"password\"\n name=\"confirmPassword\"\n maxlength=\"50\"\n required\n spellcheck=\"false\"\n placeholder=\"confirm password\"\n formControlName=\"confirmPassword\"\n />\n <mat-error\n *ngIf=\"\n passwords.hasError('areEqual') &&\n (confirmPassword.dirty || confirmPassword.touched)\n \"\n >\n password differs from confirmation password\n </mat-error>\n </mat-form-field>\n </div>\n </div>\n\n <button\n mat-raised-button\n type=\"submit\"\n color=\"primary\"\n [disabled]=\"\n !registration.valid || busy || name.pending || email.pending\n \"\n >\n register\n </button>\n <mat-progress-spinner\n diameter=\"20\"\n *ngIf=\"busy\"\n aria-label=\"Busy\"\n ></mat-progress-spinner>\n </fieldset>\n </form>\n</div>\n", styles: ["mat-form-field{width:400px}fieldset{border:1px solid silver;border-radius:8px;padding:16px}\n"] }]
|
|
522
524
|
}], ctorParameters: function () { return [{ type: i1$1.UntypedFormBuilder }, { type: i2$1.MatSnackBar }, { type: AuthJwtAccountService }]; }, propDecorators: { registered: [{
|
|
523
525
|
type: Output
|
|
524
526
|
}] } });
|
|
525
527
|
|
|
526
|
-
const
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
528
|
+
const PAGE_SIZE = 20;
|
|
529
|
+
class UserListRepository {
|
|
530
|
+
constructor(_accService) {
|
|
531
|
+
this._accService = _accService;
|
|
532
|
+
// create store
|
|
533
|
+
this._store = this.createStore();
|
|
534
|
+
this._lastPageSize = PAGE_SIZE;
|
|
535
|
+
this._loading$ = new BehaviorSubject(false);
|
|
536
|
+
this._saving$ = new BehaviorSubject(false);
|
|
537
|
+
this.loading$ = this._loading$.asObservable();
|
|
538
|
+
this.saving$ = this._saving$.asObservable();
|
|
539
|
+
// combine pagination parameters with page data for our consumers
|
|
540
|
+
this.pagination$ = combineLatest([
|
|
541
|
+
this._store.pipe(selectPaginationData()),
|
|
542
|
+
this._store.pipe(selectCurrentPageEntities()),
|
|
543
|
+
]).pipe(map(([pagination, data]) => (Object.assign(Object.assign({}, pagination), { data }))), debounceTime(0));
|
|
544
|
+
// the active user, if required
|
|
545
|
+
this.activeUser$ = this._store.pipe(selectActiveEntity());
|
|
546
|
+
// the filter, if required
|
|
547
|
+
this.filter$ = this._store.pipe(select((state) => state.filter));
|
|
548
|
+
this.filter$.subscribe((filter) => {
|
|
549
|
+
// when filter changed, reset any existing page and move to page 1
|
|
550
|
+
const paginationData = this._store.getValue().pagination;
|
|
551
|
+
this._store.update(deleteAllPages());
|
|
552
|
+
// load page 1
|
|
553
|
+
this.loadPage(1, paginationData.perPage);
|
|
554
|
+
});
|
|
555
|
+
// the request status
|
|
556
|
+
this.status$ = this._store.pipe(selectRequestStatus('user-list'));
|
|
557
|
+
// load page 1 and subscribe to pagination
|
|
558
|
+
this.loadPage(1, PAGE_SIZE);
|
|
559
|
+
this.pagination$.subscribe(console.log);
|
|
560
|
+
}
|
|
561
|
+
createStore() {
|
|
562
|
+
const store = createStore({ name: 'user-list' }, withProps({
|
|
563
|
+
filter: {},
|
|
564
|
+
}), withEntities({ idKey: 'userName' }), withActiveId(), withRequestsCache(), withRequestsStatus(), withPagination());
|
|
565
|
+
return store;
|
|
566
|
+
}
|
|
567
|
+
adaptPage(page) {
|
|
568
|
+
// adapt the server page DataPage<T> to Elf pagination
|
|
569
|
+
return {
|
|
570
|
+
currentPage: page.pageNumber,
|
|
571
|
+
perPage: page.pageSize,
|
|
572
|
+
lastPage: page.pageCount,
|
|
573
|
+
total: page.total,
|
|
574
|
+
data: page.items,
|
|
575
|
+
};
|
|
555
576
|
}
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.6", ngImport: i0, type: UsersQuery, decorators: [{
|
|
560
|
-
type: Injectable,
|
|
561
|
-
args: [{ providedIn: 'root' }]
|
|
562
|
-
}], ctorParameters: function () { return [{ type: UsersStore }]; } });
|
|
563
|
-
|
|
564
|
-
class UsersService {
|
|
565
|
-
constructor(_store, _accountService) {
|
|
566
|
-
this._store = _store;
|
|
567
|
-
this._accountService = _accountService;
|
|
577
|
+
addPage(response) {
|
|
578
|
+
const { data } = response, paginationData = __rest(response, ["data"]);
|
|
579
|
+
this._store.update(upsertEntities(data), updatePaginationData(paginationData), setPage(paginationData.currentPage, data.map((c) => c.userName)));
|
|
568
580
|
}
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
this._store.
|
|
575
|
-
|
|
581
|
+
loadPage(pageNumber, pageSize) {
|
|
582
|
+
if (!pageSize) {
|
|
583
|
+
pageSize = PAGE_SIZE;
|
|
584
|
+
}
|
|
585
|
+
// if the page exists and page size is the same, just move to it
|
|
586
|
+
if (this._store.query(hasPage(pageNumber)) &&
|
|
587
|
+
pageSize === this._lastPageSize) {
|
|
588
|
+
console.log('Page exists: ' + pageNumber);
|
|
589
|
+
this._store.update(setCurrentPage(pageNumber));
|
|
590
|
+
return;
|
|
591
|
+
}
|
|
592
|
+
// reset cached pages if page size changed
|
|
593
|
+
if (this._lastPageSize !== pageSize) {
|
|
594
|
+
this._store.update(deleteAllPages());
|
|
595
|
+
this._lastPageSize = pageSize;
|
|
596
|
+
}
|
|
597
|
+
// load page from server
|
|
598
|
+
this._store.update(updateRequestStatus('user-list', 'pending'));
|
|
599
|
+
this._loading$.next(true);
|
|
600
|
+
this._accService
|
|
601
|
+
.getUsers(this._store.getValue().filter, pageNumber, pageSize)
|
|
602
|
+
.pipe(take$1(1))
|
|
603
|
+
.subscribe((page) => {
|
|
604
|
+
this._loading$.next(false);
|
|
605
|
+
this.addPage(Object.assign(Object.assign({}, this.adaptPage(page)), { data: page.items }));
|
|
606
|
+
this._store.update(updateRequestStatus('user-list', 'success'));
|
|
576
607
|
});
|
|
577
608
|
}
|
|
609
|
+
setFilter(filter) {
|
|
610
|
+
this._store.update((state) => (Object.assign(Object.assign({}, state), { filter: filter })));
|
|
611
|
+
}
|
|
612
|
+
clearCache() {
|
|
613
|
+
this._store.update(deleteAllEntities(), deleteAllPages());
|
|
614
|
+
}
|
|
578
615
|
setActive(name) {
|
|
579
|
-
this._store.
|
|
616
|
+
this._store.update(setActiveId(name));
|
|
580
617
|
}
|
|
581
618
|
updateActive(user) {
|
|
582
619
|
const promise = new Promise((resolve, reject) => {
|
|
583
|
-
this.
|
|
584
|
-
this.
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
}
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
620
|
+
this._saving$.next(true);
|
|
621
|
+
this._accService.updateUser(user).subscribe({
|
|
622
|
+
next: (_) => {
|
|
623
|
+
this._saving$.next(false);
|
|
624
|
+
this._store.update(upsertEntities(user));
|
|
625
|
+
resolve(true);
|
|
626
|
+
},
|
|
627
|
+
error: (error) => {
|
|
628
|
+
this._saving$.next(false);
|
|
629
|
+
console.error(`Error updating user ${user.userName}: ` +
|
|
630
|
+
JSON.stringify(error || {}));
|
|
631
|
+
resolve(false);
|
|
632
|
+
},
|
|
596
633
|
});
|
|
597
634
|
});
|
|
598
635
|
return promise;
|
|
599
636
|
}
|
|
600
637
|
deleteUser(name) {
|
|
601
638
|
const promise = new Promise((resolve, reject) => {
|
|
602
|
-
this.
|
|
603
|
-
this.
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
639
|
+
this._saving$.next(true);
|
|
640
|
+
this._accService.deleteUser(name).subscribe({
|
|
641
|
+
next: (_) => {
|
|
642
|
+
this._saving$.next(false);
|
|
643
|
+
this.clearCache();
|
|
644
|
+
this.loadPage(1);
|
|
645
|
+
resolve(true);
|
|
646
|
+
},
|
|
647
|
+
error: (error) => {
|
|
648
|
+
this._saving$.next(false);
|
|
649
|
+
console.error(`Error deleting user ${name}: ` + JSON.stringify(error || {}));
|
|
650
|
+
reject(error);
|
|
651
|
+
},
|
|
613
652
|
});
|
|
614
653
|
});
|
|
615
654
|
return promise;
|
|
616
655
|
}
|
|
617
656
|
}
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
657
|
+
UserListRepository.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: UserListRepository, deps: [{ token: AuthJwtAccountService }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
658
|
+
UserListRepository.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: UserListRepository, providedIn: 'root' });
|
|
659
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: UserListRepository, decorators: [{
|
|
621
660
|
type: Injectable,
|
|
622
661
|
args: [{ providedIn: 'root' }]
|
|
623
|
-
}], ctorParameters: function () { return [{ type:
|
|
662
|
+
}], ctorParameters: function () { return [{ type: AuthJwtAccountService }]; } });
|
|
624
663
|
|
|
625
664
|
class UserFilterComponent {
|
|
626
|
-
constructor(formBuilder,
|
|
627
|
-
this.
|
|
628
|
-
this.filter$ =
|
|
665
|
+
constructor(formBuilder, _repository) {
|
|
666
|
+
this._repository = _repository;
|
|
667
|
+
this.filter$ = _repository.filter$;
|
|
629
668
|
// form
|
|
630
669
|
this.name = formBuilder.control(null);
|
|
631
670
|
this.form = formBuilder.group({
|
|
@@ -638,7 +677,7 @@ class UserFilterComponent {
|
|
|
638
677
|
});
|
|
639
678
|
}
|
|
640
679
|
updateForm(filter) {
|
|
641
|
-
this.name.setValue(filter.name);
|
|
680
|
+
this.name.setValue(filter.name || null);
|
|
642
681
|
this.form.markAsPristine();
|
|
643
682
|
}
|
|
644
683
|
reset() {
|
|
@@ -648,8 +687,6 @@ class UserFilterComponent {
|
|
|
648
687
|
getFilter() {
|
|
649
688
|
var _a;
|
|
650
689
|
return {
|
|
651
|
-
pageNumber: 1,
|
|
652
|
-
pageSize: 20,
|
|
653
690
|
name: (_a = this.name.value) === null || _a === void 0 ? void 0 : _a.trim(),
|
|
654
691
|
};
|
|
655
692
|
}
|
|
@@ -659,27 +696,18 @@ class UserFilterComponent {
|
|
|
659
696
|
}
|
|
660
697
|
const filter = this.getFilter();
|
|
661
698
|
// update filter in state
|
|
662
|
-
this.
|
|
699
|
+
this._repository.setFilter(filter);
|
|
663
700
|
}
|
|
664
701
|
}
|
|
665
|
-
UserFilterComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
666
|
-
UserFilterComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "
|
|
667
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
702
|
+
UserFilterComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: UserFilterComponent, deps: [{ token: i1$1.FormBuilder }, { token: UserListRepository }], target: i0.ɵɵFactoryTarget.Component });
|
|
703
|
+
UserFilterComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.0", type: UserFilterComponent, selector: "auth-jwt-user-filter", inputs: { disabled: "disabled" }, ngImport: i0, template: "<form [formGroup]=\"form\" (submit)=\"apply()\" ng-disabled=\"disabled\">\n <div class=\"form-row\">\n <mat-form-field>\n <input matInput [formControl]=\"name\" placeholder=\"name or ID\" />\n <button\n mat-icon-button\n matSuffix\n type=\"button\"\n (click)=\"reset()\"\n color=\"warn\"\n matTooltip=\"Reset filters\"\n [disabled]=\"disabled\"\n >\n <mat-icon>clear</mat-icon>\n </button>\n </mat-form-field>\n\n <button\n style=\"margin-top: -20px\"\n type=\"submit\"\n mat-icon-button\n color=\"primary\"\n [disabled]=\"disabled\"\n matTooltip=\"Apply filters\"\n >\n <mat-icon>check_circle</mat-icon>\n </button>\n </div>\n</form>\n", styles: [".form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}\n"], dependencies: [{ kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.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$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: i5.MatIconButton, selector: "button[mat-icon-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "component", type: i6.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i7.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: i8.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i8.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]" }, { kind: "directive", type: i9$1.MatTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }] });
|
|
704
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: UserFilterComponent, decorators: [{
|
|
668
705
|
type: Component,
|
|
669
|
-
args: [{ selector: 'auth-jwt-user-filter', template: "<form [formGroup]=\"form\" (submit)=\"apply()\" ng-disabled=\"disabled\">\n <mat-form-field>\n
|
|
670
|
-
}], ctorParameters: function () { return [{ type: i1$1.
|
|
706
|
+
args: [{ selector: 'auth-jwt-user-filter', template: "<form [formGroup]=\"form\" (submit)=\"apply()\" ng-disabled=\"disabled\">\n <div class=\"form-row\">\n <mat-form-field>\n <input matInput [formControl]=\"name\" placeholder=\"name or ID\" />\n <button\n mat-icon-button\n matSuffix\n type=\"button\"\n (click)=\"reset()\"\n color=\"warn\"\n matTooltip=\"Reset filters\"\n [disabled]=\"disabled\"\n >\n <mat-icon>clear</mat-icon>\n </button>\n </mat-form-field>\n\n <button\n style=\"margin-top: -20px\"\n type=\"submit\"\n mat-icon-button\n color=\"primary\"\n [disabled]=\"disabled\"\n matTooltip=\"Apply filters\"\n >\n <mat-icon>check_circle</mat-icon>\n </button>\n </div>\n</form>\n", styles: [".form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}\n"] }]
|
|
707
|
+
}], ctorParameters: function () { return [{ type: i1$1.FormBuilder }, { type: UserListRepository }]; }, propDecorators: { disabled: [{
|
|
671
708
|
type: Input
|
|
672
709
|
}] } });
|
|
673
710
|
|
|
674
|
-
// create a factory provider for the paginator
|
|
675
|
-
const USERS_PAGINATOR = new InjectionToken('USERS_PAGINATOR', {
|
|
676
|
-
providedIn: 'root',
|
|
677
|
-
factory: () => {
|
|
678
|
-
const query = inject(UsersQuery);
|
|
679
|
-
return new PaginatorPlugin(query).withControls().withRange();
|
|
680
|
-
},
|
|
681
|
-
});
|
|
682
|
-
|
|
683
711
|
// https://medium.com/@tarik.nzl/making-use-of-dialogs-in-material-2-mddialog-7533d27df41
|
|
684
712
|
class ConfirmDialogComponent {
|
|
685
713
|
constructor(dialogRef, data) {
|
|
@@ -692,9 +720,9 @@ class ConfirmDialogComponent {
|
|
|
692
720
|
}
|
|
693
721
|
ngOnInit() { }
|
|
694
722
|
}
|
|
695
|
-
ConfirmDialogComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
696
|
-
ConfirmDialogComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "
|
|
697
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
723
|
+
ConfirmDialogComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: ConfirmDialogComponent, deps: [{ token: i1$2.MatDialogRef }, { token: MAT_DIALOG_DATA, optional: true }], target: i0.ɵɵFactoryTarget.Component });
|
|
724
|
+
ConfirmDialogComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.0", type: ConfirmDialogComponent, selector: "ng-component", ngImport: i0, template: "<h1 mat-dialog-title>{{ title }}</h1>\r\n<mat-dialog-content>\r\n {{ prompt }}\r\n</mat-dialog-content>\r\n<mat-dialog-actions>\r\n <button\r\n type=\"button\"\r\n mat-raised-button\r\n color=\"warn\"\r\n (click)=\"dialogRef.close(true)\"\r\n >\r\n {{ ok }}\r\n </button>\r\n <button type=\"button\" mat-button (click)=\"dialogRef.close()\">\r\n {{ cancel }}\r\n </button>\r\n</mat-dialog-actions>\r\n", styles: [""], dependencies: [{ kind: "component", type: i5.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "directive", type: i1$2.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1$2.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "directive", type: i1$2.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }] });
|
|
725
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: ConfirmDialogComponent, decorators: [{
|
|
698
726
|
type: Component,
|
|
699
727
|
args: [{ template: "<h1 mat-dialog-title>{{ title }}</h1>\r\n<mat-dialog-content>\r\n {{ prompt }}\r\n</mat-dialog-content>\r\n<mat-dialog-actions>\r\n <button\r\n type=\"button\"\r\n mat-raised-button\r\n color=\"warn\"\r\n (click)=\"dialogRef.close(true)\"\r\n >\r\n {{ ok }}\r\n </button>\r\n <button type=\"button\" mat-button (click)=\"dialogRef.close()\">\r\n {{ cancel }}\r\n </button>\r\n</mat-dialog-actions>\r\n" }]
|
|
700
728
|
}], ctorParameters: function () {
|
|
@@ -730,9 +758,9 @@ class DialogService {
|
|
|
730
758
|
return dialogRef.afterClosed();
|
|
731
759
|
}
|
|
732
760
|
}
|
|
733
|
-
DialogService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
734
|
-
DialogService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
735
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
761
|
+
DialogService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: DialogService, deps: [{ token: i1$2.MatDialog }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
762
|
+
DialogService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: DialogService, providedIn: 'root' });
|
|
763
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: DialogService, decorators: [{
|
|
736
764
|
type: Injectable,
|
|
737
765
|
args: [{
|
|
738
766
|
providedIn: 'root'
|
|
@@ -828,11 +856,11 @@ class UserEditorComponent {
|
|
|
828
856
|
this.userChange.emit(this.getUserFromForm());
|
|
829
857
|
}
|
|
830
858
|
}
|
|
831
|
-
UserEditorComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
832
|
-
UserEditorComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "
|
|
833
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
859
|
+
UserEditorComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: UserEditorComponent, deps: [{ token: i1$1.UntypedFormBuilder }, { token: i2$2.AuthJwtService }], target: i0.ɵɵFactoryTarget.Component });
|
|
860
|
+
UserEditorComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.0", type: UserEditorComponent, selector: "auth-jwt-user-editor", inputs: { user: "user" }, outputs: { userChange: "userChange", editorClose: "editorClose" }, ngImport: i0, template: "<form [formGroup]=\"form\" (submit)=\"save()\">\n <div class=\"form-row\">\n <!-- email -->\n <mat-form-field>\n <mat-label>email</mat-label>\n <input type=\"text\" matInput [formControl]=\"email\" />\n <mat-error\n *ngIf=\"email.hasError('required') && (email.dirty || email.touched)\"\n >\n email address required\n </mat-error>\n <mat-error\n *ngIf=\"email.hasError('pattern') && (email.dirty || email.touched)\"\n >\n invalid email address\n </mat-error>\n </mat-form-field>\n\n <!-- emailConfirmed -->\n <mat-checkbox [formControl]=\"emailConfirmed\"\n >email address confirmed</mat-checkbox\n >\n </div>\n\n <!-- lockoutEnabled -->\n <div class=\"form-row\">\n <mat-checkbox [formControl]=\"lockoutEnabled\">lockout enabled</mat-checkbox>\n <button\n mat-icon-button\n color=\"primary\"\n (click)=\"endLockout()\"\n [disabled]=\"unlocked\"\n matTooltip=\"Unlock this user if locked\"\n >\n <mat-icon>lock_open</mat-icon>\n </button>\n </div>\n\n <div class=\"form-row\">\n <!-- firstName -->\n <mat-form-field>\n <mat-label>first name</mat-label>\n <input type=\"text\" matInput [formControl]=\"firstName\" />\n <mat-error\n *ngIf=\"\n firstName.hasError('required') &&\n (firstName.dirty || firstName.touched)\n \"\n >\n first name required\n </mat-error>\n <mat-error\n *ngIf=\"\n firstName.hasError('maxlength') &&\n (firstName.dirty || firstName.touched)\n \"\n >\n first name too long\n </mat-error>\n </mat-form-field>\n\n <!-- lastName -->\n <mat-form-field>\n <mat-label>last name</mat-label>\n <input type=\"text\" matInput [formControl]=\"lastName\" />\n <mat-error\n *ngIf=\"\n lastName.hasError('required') && (lastName.dirty || lastName.touched)\n \"\n >\n last name required\n </mat-error>\n <mat-error\n *ngIf=\"\n lastName.hasError('maxlength') && (lastName.dirty || lastName.touched)\n \"\n >\n last name too long\n </mat-error>\n </mat-form-field>\n </div>\n\n <!-- roles -->\n <div>\n <mat-form-field style=\"width: 16em\">\n <mat-label>roles</mat-label>\n <input type=\"text\" matInput [formControl]=\"roles\" />\n <mat-error\n *ngIf=\"roles.hasError('maxlength') && (roles.dirty || roles.touched)\"\n >\n too long\n </mat-error>\n <mat-hint>roles (separated by space)</mat-hint>\n </mat-form-field>\n </div>\n\n <!-- buttons -->\n <br />\n <div>\n <button mat-icon-button color=\"warn\" matTooltip=\"Close\" (click)=\"close()\">\n <mat-icon>cancel</mat-icon>\n </button>\n <button\n type=\"submit\"\n mat-icon-button\n color=\"primary\"\n [disabled]=\"form.invalid\"\n matTooltip=\"Save user\"\n >\n <mat-icon>check_circle</mat-icon>\n </button>\n </div>\n</form>\n", styles: [".form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}\n"], dependencies: [{ kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$1.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$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: i5.MatIconButton, selector: "button[mat-icon-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "component", type: i5$1.MatCheckbox, selector: "mat-checkbox", inputs: ["disableRipple", "color", "tabIndex"], exportAs: ["matCheckbox"] }, { kind: "component", type: i6.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i7.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: i8.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i8.MatLabel, selector: "mat-label" }, { kind: "directive", type: i8.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i8.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i9$1.MatTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }] });
|
|
861
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: UserEditorComponent, decorators: [{
|
|
834
862
|
type: Component,
|
|
835
|
-
args: [{ selector: 'auth-jwt-user-editor', template: "<form [formGroup]=\"form\" (submit)=\"save()\">\n <!-- email -->\n
|
|
863
|
+
args: [{ selector: 'auth-jwt-user-editor', template: "<form [formGroup]=\"form\" (submit)=\"save()\">\n <div class=\"form-row\">\n <!-- email -->\n <mat-form-field>\n <mat-label>email</mat-label>\n <input type=\"text\" matInput [formControl]=\"email\" />\n <mat-error\n *ngIf=\"email.hasError('required') && (email.dirty || email.touched)\"\n >\n email address required\n </mat-error>\n <mat-error\n *ngIf=\"email.hasError('pattern') && (email.dirty || email.touched)\"\n >\n invalid email address\n </mat-error>\n </mat-form-field>\n\n <!-- emailConfirmed -->\n <mat-checkbox [formControl]=\"emailConfirmed\"\n >email address confirmed</mat-checkbox\n >\n </div>\n\n <!-- lockoutEnabled -->\n <div class=\"form-row\">\n <mat-checkbox [formControl]=\"lockoutEnabled\">lockout enabled</mat-checkbox>\n <button\n mat-icon-button\n color=\"primary\"\n (click)=\"endLockout()\"\n [disabled]=\"unlocked\"\n matTooltip=\"Unlock this user if locked\"\n >\n <mat-icon>lock_open</mat-icon>\n </button>\n </div>\n\n <div class=\"form-row\">\n <!-- firstName -->\n <mat-form-field>\n <mat-label>first name</mat-label>\n <input type=\"text\" matInput [formControl]=\"firstName\" />\n <mat-error\n *ngIf=\"\n firstName.hasError('required') &&\n (firstName.dirty || firstName.touched)\n \"\n >\n first name required\n </mat-error>\n <mat-error\n *ngIf=\"\n firstName.hasError('maxlength') &&\n (firstName.dirty || firstName.touched)\n \"\n >\n first name too long\n </mat-error>\n </mat-form-field>\n\n <!-- lastName -->\n <mat-form-field>\n <mat-label>last name</mat-label>\n <input type=\"text\" matInput [formControl]=\"lastName\" />\n <mat-error\n *ngIf=\"\n lastName.hasError('required') && (lastName.dirty || lastName.touched)\n \"\n >\n last name required\n </mat-error>\n <mat-error\n *ngIf=\"\n lastName.hasError('maxlength') && (lastName.dirty || lastName.touched)\n \"\n >\n last name too long\n </mat-error>\n </mat-form-field>\n </div>\n\n <!-- roles -->\n <div>\n <mat-form-field style=\"width: 16em\">\n <mat-label>roles</mat-label>\n <input type=\"text\" matInput [formControl]=\"roles\" />\n <mat-error\n *ngIf=\"roles.hasError('maxlength') && (roles.dirty || roles.touched)\"\n >\n too long\n </mat-error>\n <mat-hint>roles (separated by space)</mat-hint>\n </mat-form-field>\n </div>\n\n <!-- buttons -->\n <br />\n <div>\n <button mat-icon-button color=\"warn\" matTooltip=\"Close\" (click)=\"close()\">\n <mat-icon>cancel</mat-icon>\n </button>\n <button\n type=\"submit\"\n mat-icon-button\n color=\"primary\"\n [disabled]=\"form.invalid\"\n matTooltip=\"Save user\"\n >\n <mat-icon>check_circle</mat-icon>\n </button>\n </div>\n</form>\n", styles: [".form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}\n"] }]
|
|
836
864
|
}], ctorParameters: function () { return [{ type: i1$1.UntypedFormBuilder }, { type: i2$2.AuthJwtService }]; }, propDecorators: { user: [{
|
|
837
865
|
type: Input
|
|
838
866
|
}], userChange: [{
|
|
@@ -842,77 +870,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.6", ngImpor
|
|
|
842
870
|
}] } });
|
|
843
871
|
|
|
844
872
|
class UserListComponent {
|
|
845
|
-
constructor(
|
|
846
|
-
this.
|
|
847
|
-
this._accountService = _accountService;
|
|
848
|
-
this._usersService = _usersService;
|
|
873
|
+
constructor(_repository, _dialogService, _gravatarService) {
|
|
874
|
+
this._repository = _repository;
|
|
849
875
|
this._dialogService = _dialogService;
|
|
850
876
|
this._gravatarService = _gravatarService;
|
|
851
|
-
this.
|
|
852
|
-
this.
|
|
853
|
-
this.
|
|
854
|
-
// https://netbasal.com/manage-your-entities-with-akita-like-a-boss-768732f8d4d1
|
|
855
|
-
this.active$ = userQuery.selectActive();
|
|
856
|
-
this.pagination$ = combineLatest([
|
|
857
|
-
this.paginator.pageChanges,
|
|
858
|
-
this.pageSize.valueChanges.pipe(
|
|
859
|
-
// we are required to emit at least the initial value
|
|
860
|
-
// as combineLatest emits only if ALL observables have emitted
|
|
861
|
-
startWith(20),
|
|
862
|
-
// clear the cache when page size changes
|
|
863
|
-
tap((_) => {
|
|
864
|
-
this.paginator.clearCache();
|
|
865
|
-
})),
|
|
866
|
-
this._filter$.pipe(
|
|
867
|
-
// clear the cache when filters changed
|
|
868
|
-
tap((_) => {
|
|
869
|
-
this.paginator.clearCache();
|
|
870
|
-
})),
|
|
871
|
-
this._refresh$.pipe(
|
|
872
|
-
// clear the cache when forcing refresh
|
|
873
|
-
tap((_) => {
|
|
874
|
-
this.paginator.clearCache();
|
|
875
|
-
})),
|
|
876
|
-
]).pipe(
|
|
877
|
-
// for each emitted value, combine into a filter and use it
|
|
878
|
-
// to request the page from server
|
|
879
|
-
switchMap(([pageNumber, pageSize, filter, refresh]) => {
|
|
880
|
-
// const filter = { ...this._docsQuery.getValue().filter };
|
|
881
|
-
const f = Object.assign({}, filter);
|
|
882
|
-
f.pageNumber = pageNumber;
|
|
883
|
-
f.pageSize = pageSize;
|
|
884
|
-
const request = this.getRequest(f);
|
|
885
|
-
// update saved filters
|
|
886
|
-
this.paginator.metadata.set('filter', f);
|
|
887
|
-
return this.paginator.getPage(request);
|
|
888
|
-
}));
|
|
889
|
-
}
|
|
890
|
-
ngOnDestroy() {
|
|
891
|
-
this.paginator.destroy();
|
|
892
|
-
}
|
|
893
|
-
getRequest(filter) {
|
|
894
|
-
return () => this._accountService.getUsers(filter).pipe(
|
|
895
|
-
// adapt server results to the paginator plugin
|
|
896
|
-
map((p) => {
|
|
897
|
-
return {
|
|
898
|
-
currentPage: p.pageNumber,
|
|
899
|
-
perPage: p.pageSize,
|
|
900
|
-
lastPage: p.pageCount,
|
|
901
|
-
data: p.items,
|
|
902
|
-
total: p.total,
|
|
903
|
-
};
|
|
904
|
-
}));
|
|
877
|
+
this.pagination$ = _repository.pagination$;
|
|
878
|
+
this.active$ = _repository.activeUser$;
|
|
879
|
+
this.loading$ = _repository.loading$;
|
|
905
880
|
}
|
|
906
881
|
pageChange(event) {
|
|
907
|
-
|
|
908
|
-
this.paginator.setPage(event.pageIndex + 1);
|
|
909
|
-
if (event.pageSize !== this.pageSize.value) {
|
|
910
|
-
this.pageSize.setValue(event.pageSize);
|
|
911
|
-
}
|
|
912
|
-
}
|
|
913
|
-
refresh() {
|
|
914
|
-
this.paginator.clearCache();
|
|
915
|
-
this._refresh$.next(this._refresh$.value + 1);
|
|
882
|
+
this._repository.loadPage(event.pageIndex + 1, event.pageSize);
|
|
916
883
|
}
|
|
917
884
|
deleteUser(user) {
|
|
918
885
|
this._dialogService
|
|
@@ -922,45 +889,44 @@ class UserListComponent {
|
|
|
922
889
|
if (!yes) {
|
|
923
890
|
return;
|
|
924
891
|
}
|
|
925
|
-
this.
|
|
926
|
-
this.
|
|
892
|
+
this._repository.deleteUser(user.userName).finally(() => {
|
|
893
|
+
this._repository.clearCache();
|
|
894
|
+
this._repository.loadPage(1);
|
|
927
895
|
});
|
|
928
896
|
});
|
|
929
897
|
}
|
|
930
898
|
setActiveUser(user) {
|
|
931
|
-
this.
|
|
899
|
+
this._repository.setActive((user === null || user === void 0 ? void 0 : user.userName) || null);
|
|
932
900
|
}
|
|
933
901
|
resetActiveUser() {
|
|
934
|
-
this.
|
|
902
|
+
this._repository.setActive(null);
|
|
935
903
|
}
|
|
936
904
|
saveActiveUser(user) {
|
|
937
|
-
this.
|
|
938
|
-
|
|
939
|
-
});
|
|
905
|
+
this._repository.updateActive(user);
|
|
906
|
+
this._repository.setActive(null);
|
|
940
907
|
}
|
|
941
908
|
onUserEditorClose() {
|
|
942
|
-
this.
|
|
909
|
+
this._repository.setActive(null);
|
|
943
910
|
}
|
|
944
911
|
getGravatarUrl(email, size = 80) {
|
|
945
912
|
return this._gravatarService.buildGravatarUrl(email, size);
|
|
946
913
|
}
|
|
914
|
+
clearCache() {
|
|
915
|
+
this._repository.clearCache();
|
|
916
|
+
this._repository.loadPage(1);
|
|
917
|
+
}
|
|
947
918
|
}
|
|
948
|
-
UserListComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
949
|
-
UserListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "
|
|
950
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
919
|
+
UserListComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: UserListComponent, deps: [{ token: UserListRepository }, { token: DialogService }, { token: i2$2.GravatarService }], target: i0.ɵɵFactoryTarget.Component });
|
|
920
|
+
UserListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.0.0", type: UserListComponent, selector: "auth-jwt-user-list", ngImport: i0, template: "<div id=\"container\">\n <div>\n <!-- filters -->\n <div style=\"grid-area: filters\">\n <auth-jwt-user-filter></auth-jwt-user-filter>\n </div>\n\n <!-- list -->\n <div style=\"grid-area: list\" *ngIf=\"pagination$ | async as pagination\">\n <div *ngIf=\"loading$ | async\" gdArea=\"progress\">\n <mat-progress-bar mode=\"indeterminate\"></mat-progress-bar>\n </div>\n <table>\n <thead>\n <td></td>\n <td></td>\n <th>name</th>\n <th class=\"noif-lt-md\">first</th>\n <th class=\"noif-lt-md\">last</th>\n <th class=\"noif-lt-md\">email</th>\n <th>roles</th>\n <th class=\"noif-lt-md\">lock end</th>\n </thead>\n <tbody>\n <tr *ngFor=\"let user of pagination.data\">\n <td>\n <button\n mat-icon-button\n type=\"button\"\n matTooltip=\"Edit {{ user.userName }}\"\n color=\"primary\"\n (click)=\"setActiveUser(user)\"\n >\n <mat-icon>mode_edit</mat-icon>\n </button>\n <button\n mat-icon-button\n type=\"button\"\n matTooltip=\"Delete {{ user.userName }}\"\n color=\"warn\"\n (click)=\"deleteUser(user)\"\n >\n <mat-icon>remove_circle</mat-icon>\n </button>\n </td>\n <td>\n <img\n [src]=\"getGravatarUrl(user.email, 32)\"\n [alt]=\"user.userName\"\n />\n </td>\n <td>{{ user.userName }}</td>\n <td class=\"noif-lt-md\">{{ user.firstName }}</td>\n <td class=\"noif-lt-md\">{{ user.lastName }}</td>\n <td class=\"noif-lt-md\">\n <a [href]=\"'mailto:' + user.email\">{{ user.email }}</a>\n </td>\n <td>{{ user.roles.join(\" \") }}</td>\n <td class=\"noif-lt-md\">{{ user.lockoutEnd }}</td>\n </tr>\n </tbody>\n </table>\n\n <!-- paginator -->\n <div style=\"grid-area: paginator; justify-content: end\" class=\"form-row\">\n <button\n type=\"button\"\n mat-icon-button\n color=\"warn\"\n matTooltip=\"Clear items cache\"\n (click)=\"clearCache()\"\n >\n <mat-icon>autorenew</mat-icon>\n </button>\n\n <mat-paginator\n gdArea=\"pager\"\n gdAlignColumns=\"center\"\n gdAlignRows=\"start\"\n [length]=\"pagination.total\"\n [pageSize]=\"pagination.perPage\"\n [pageSizeOptions]=\"[20, 50, 75, 100]\"\n [pageIndex]=\"pagination.currentPage - 1\"\n [showFirstLastButtons]=\"true\"\n (page)=\"pageChange($event)\"\n ></mat-paginator>\n </div>\n </div>\n </div>\n\n <!-- editor -->\n <div style=\"grid-area: editor\" *ngIf=\"active$ | async as active\">\n <fieldset>\n <legend>{{ active.userName }}</legend>\n <auth-jwt-user-editor\n [user]=\"active\"\n (userChange)=\"saveActiveUser($event)\"\n (editorClose)=\"resetActiveUser()\"\n ></auth-jwt-user-editor>\n </fieldset>\n </div>\n</div>\n", styles: ["tr:nth-child(odd){background-color:#f8f8f8}th{padding:0 8px;text-align:left;color:silver;font-weight:400}td{padding:0 8px}td.command{width:24px}table{width:100%;border-collapse:collapse}fieldset{border:1px solid silver;border-radius:8px;padding:16px}.form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}div#container{display:grid;grid-template-rows:auto 1fr auto auto;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));grid-template-areas:\"filters\" \"list\" \"paginator\" \"editor\";gap:8px}@media only screen and (max-width: 959px){.noif-lt-md{display:none}}\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: i5.MatIconButton, selector: "button[mat-icon-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "component", type: i6.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i7$1.MatPaginator, selector: "mat-paginator", inputs: ["disabled"], exportAs: ["matPaginator"] }, { kind: "component", type: i8$1.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "directive", type: i9$1.MatTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }, { kind: "component", type: UserFilterComponent, selector: "auth-jwt-user-filter", inputs: ["disabled"] }, { kind: "component", type: UserEditorComponent, selector: "auth-jwt-user-editor", inputs: ["user"], outputs: ["userChange", "editorClose"] }, { kind: "pipe", type: i4.AsyncPipe, name: "async" }] });
|
|
921
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: UserListComponent, decorators: [{
|
|
951
922
|
type: Component,
|
|
952
|
-
args: [{ selector: 'auth-jwt-user-list', template: "<div
|
|
953
|
-
}], ctorParameters: function () {
|
|
954
|
-
return [{ type: i15.PaginatorPlugin, decorators: [{
|
|
955
|
-
type: Inject,
|
|
956
|
-
args: [USERS_PAGINATOR]
|
|
957
|
-
}] }, { type: UsersQuery }, { type: AuthJwtAccountService }, { type: UsersService }, { type: DialogService }, { type: i2$2.GravatarService }, { type: i1$1.UntypedFormBuilder }];
|
|
958
|
-
} });
|
|
923
|
+
args: [{ selector: 'auth-jwt-user-list', template: "<div id=\"container\">\n <div>\n <!-- filters -->\n <div style=\"grid-area: filters\">\n <auth-jwt-user-filter></auth-jwt-user-filter>\n </div>\n\n <!-- list -->\n <div style=\"grid-area: list\" *ngIf=\"pagination$ | async as pagination\">\n <div *ngIf=\"loading$ | async\" gdArea=\"progress\">\n <mat-progress-bar mode=\"indeterminate\"></mat-progress-bar>\n </div>\n <table>\n <thead>\n <td></td>\n <td></td>\n <th>name</th>\n <th class=\"noif-lt-md\">first</th>\n <th class=\"noif-lt-md\">last</th>\n <th class=\"noif-lt-md\">email</th>\n <th>roles</th>\n <th class=\"noif-lt-md\">lock end</th>\n </thead>\n <tbody>\n <tr *ngFor=\"let user of pagination.data\">\n <td>\n <button\n mat-icon-button\n type=\"button\"\n matTooltip=\"Edit {{ user.userName }}\"\n color=\"primary\"\n (click)=\"setActiveUser(user)\"\n >\n <mat-icon>mode_edit</mat-icon>\n </button>\n <button\n mat-icon-button\n type=\"button\"\n matTooltip=\"Delete {{ user.userName }}\"\n color=\"warn\"\n (click)=\"deleteUser(user)\"\n >\n <mat-icon>remove_circle</mat-icon>\n </button>\n </td>\n <td>\n <img\n [src]=\"getGravatarUrl(user.email, 32)\"\n [alt]=\"user.userName\"\n />\n </td>\n <td>{{ user.userName }}</td>\n <td class=\"noif-lt-md\">{{ user.firstName }}</td>\n <td class=\"noif-lt-md\">{{ user.lastName }}</td>\n <td class=\"noif-lt-md\">\n <a [href]=\"'mailto:' + user.email\">{{ user.email }}</a>\n </td>\n <td>{{ user.roles.join(\" \") }}</td>\n <td class=\"noif-lt-md\">{{ user.lockoutEnd }}</td>\n </tr>\n </tbody>\n </table>\n\n <!-- paginator -->\n <div style=\"grid-area: paginator; justify-content: end\" class=\"form-row\">\n <button\n type=\"button\"\n mat-icon-button\n color=\"warn\"\n matTooltip=\"Clear items cache\"\n (click)=\"clearCache()\"\n >\n <mat-icon>autorenew</mat-icon>\n </button>\n\n <mat-paginator\n gdArea=\"pager\"\n gdAlignColumns=\"center\"\n gdAlignRows=\"start\"\n [length]=\"pagination.total\"\n [pageSize]=\"pagination.perPage\"\n [pageSizeOptions]=\"[20, 50, 75, 100]\"\n [pageIndex]=\"pagination.currentPage - 1\"\n [showFirstLastButtons]=\"true\"\n (page)=\"pageChange($event)\"\n ></mat-paginator>\n </div>\n </div>\n </div>\n\n <!-- editor -->\n <div style=\"grid-area: editor\" *ngIf=\"active$ | async as active\">\n <fieldset>\n <legend>{{ active.userName }}</legend>\n <auth-jwt-user-editor\n [user]=\"active\"\n (userChange)=\"saveActiveUser($event)\"\n (editorClose)=\"resetActiveUser()\"\n ></auth-jwt-user-editor>\n </fieldset>\n </div>\n</div>\n", styles: ["tr:nth-child(odd){background-color:#f8f8f8}th{padding:0 8px;text-align:left;color:silver;font-weight:400}td{padding:0 8px}td.command{width:24px}table{width:100%;border-collapse:collapse}fieldset{border:1px solid silver;border-radius:8px;padding:16px}.form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}div#container{display:grid;grid-template-rows:auto 1fr auto auto;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));grid-template-areas:\"filters\" \"list\" \"paginator\" \"editor\";gap:8px}@media only screen and (max-width: 959px){.noif-lt-md{display:none}}\n"] }]
|
|
924
|
+
}], ctorParameters: function () { return [{ type: UserListRepository }, { type: DialogService }, { type: i2$2.GravatarService }]; } });
|
|
959
925
|
|
|
960
926
|
class AuthJwtAdminModule {
|
|
961
927
|
}
|
|
962
|
-
AuthJwtAdminModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
963
|
-
AuthJwtAdminModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "
|
|
928
|
+
AuthJwtAdminModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: AuthJwtAdminModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
929
|
+
AuthJwtAdminModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.0.0", ngImport: i0, type: AuthJwtAdminModule, declarations: [AuthJwtRegistrationComponent,
|
|
964
930
|
PasswordStrengthBarComponent,
|
|
965
931
|
UserFilterComponent,
|
|
966
932
|
UserListComponent,
|
|
@@ -987,7 +953,7 @@ AuthJwtAdminModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", vers
|
|
|
987
953
|
PasswordStrengthBarComponent,
|
|
988
954
|
UserFilterComponent,
|
|
989
955
|
UserListComponent] });
|
|
990
|
-
AuthJwtAdminModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "
|
|
956
|
+
AuthJwtAdminModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: AuthJwtAdminModule, imports: [CommonModule,
|
|
991
957
|
HttpClientModule,
|
|
992
958
|
FormsModule,
|
|
993
959
|
RouterModule,
|
|
@@ -1006,7 +972,7 @@ AuthJwtAdminModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", vers
|
|
|
1006
972
|
MatTooltipModule,
|
|
1007
973
|
AuthJwtLoginModule,
|
|
1008
974
|
NgToolsModule] });
|
|
1009
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
975
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.0", ngImport: i0, type: AuthJwtAdminModule, decorators: [{
|
|
1010
976
|
type: NgModule,
|
|
1011
977
|
args: [{
|
|
1012
978
|
declarations: [
|