@mintplayer/ng-spark 22.30.0 → 22.32.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/README.md +2 -2
- package/auth/README.md +216 -0
- package/fesm2022/mintplayer-ng-spark-auth-account.mjs +2023 -0
- package/fesm2022/mintplayer-ng-spark-auth-account.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-spark-auth-auth-bar.mjs +96 -0
- package/fesm2022/mintplayer-ng-spark-auth-auth-bar.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-spark-auth-confirm-email.mjs +200 -0
- package/fesm2022/mintplayer-ng-spark-auth-confirm-email.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-spark-auth-core.mjs +452 -0
- package/fesm2022/mintplayer-ng-spark-auth-core.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-spark-auth-external-login.mjs +201 -0
- package/fesm2022/mintplayer-ng-spark-auth-external-login.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-spark-auth-forgot-password.mjs +196 -0
- package/fesm2022/mintplayer-ng-spark-auth-forgot-password.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-spark-auth-guards.mjs +16 -0
- package/fesm2022/mintplayer-ng-spark-auth-guards.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-spark-auth-interceptors.mjs +18 -0
- package/fesm2022/mintplayer-ng-spark-auth-interceptors.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-spark-auth-login.mjs +282 -0
- package/fesm2022/mintplayer-ng-spark-auth-login.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-spark-auth-models.mjs +114 -0
- package/fesm2022/mintplayer-ng-spark-auth-models.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-spark-auth-pipes.mjs +43 -0
- package/fesm2022/mintplayer-ng-spark-auth-pipes.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-spark-auth-register.mjs +216 -0
- package/fesm2022/mintplayer-ng-spark-auth-register.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-spark-auth-reset-password.mjs +223 -0
- package/fesm2022/mintplayer-ng-spark-auth-reset-password.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-spark-auth-routes.mjs +194 -0
- package/fesm2022/mintplayer-ng-spark-auth-routes.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-spark-auth-sign-in.mjs +210 -0
- package/fesm2022/mintplayer-ng-spark-auth-sign-in.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-spark-auth-two-factor.mjs +218 -0
- package/fesm2022/mintplayer-ng-spark-auth-two-factor.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-spark-auth.mjs +48 -0
- package/fesm2022/mintplayer-ng-spark-auth.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-spark-client-operations.mjs +294 -2
- package/fesm2022/mintplayer-ng-spark-client-operations.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-identity-provider-connected-applications.mjs +389 -0
- package/fesm2022/mintplayer-ng-spark-identity-provider-connected-applications.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-spark-identity-provider-core.mjs +204 -0
- package/fesm2022/mintplayer-ng-spark-identity-provider-core.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-spark-identity-provider-developers.mjs +486 -0
- package/fesm2022/mintplayer-ng-spark-identity-provider-developers.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-spark-identity-provider-management.mjs +350 -0
- package/fesm2022/mintplayer-ng-spark-identity-provider-management.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-spark-identity-provider.mjs +66 -0
- package/fesm2022/mintplayer-ng-spark-identity-provider.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-spark-po-detail.mjs +9 -4
- package/fesm2022/mintplayer-ng-spark-po-detail.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-pwa.mjs +162 -0
- package/fesm2022/mintplayer-ng-spark-pwa.mjs.map +1 -0
- package/fesm2022/mintplayer-ng-spark-services.mjs +11 -1
- package/fesm2022/mintplayer-ng-spark-services.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark-shell.mjs.map +1 -1
- package/fesm2022/mintplayer-ng-spark.mjs.map +1 -1
- package/package.json +99 -1
- package/types/mintplayer-ng-spark-auth-account.d.ts +255 -0
- package/types/mintplayer-ng-spark-auth-auth-bar.d.ts +22 -0
- package/types/mintplayer-ng-spark-auth-confirm-email.d.ts +21 -0
- package/types/mintplayer-ng-spark-auth-core.d.ts +197 -0
- package/types/mintplayer-ng-spark-auth-external-login.d.ts +132 -0
- package/types/mintplayer-ng-spark-auth-forgot-password.d.ts +18 -0
- package/types/mintplayer-ng-spark-auth-guards.d.ts +15 -0
- package/types/mintplayer-ng-spark-auth-interceptors.d.ts +2 -0
- package/types/mintplayer-ng-spark-auth-login.d.ts +46 -0
- package/types/mintplayer-ng-spark-auth-models.d.ts +489 -0
- package/types/mintplayer-ng-spark-auth-pipes.d.ts +8 -0
- package/types/mintplayer-ng-spark-auth-register.d.ts +21 -0
- package/types/mintplayer-ng-spark-auth-reset-password.d.ts +25 -0
- package/types/mintplayer-ng-spark-auth-routes.d.ts +154 -0
- package/types/mintplayer-ng-spark-auth-sign-in.d.ts +84 -0
- package/types/mintplayer-ng-spark-auth-two-factor.d.ts +23 -0
- package/types/mintplayer-ng-spark-auth.d.ts +24 -0
- package/types/mintplayer-ng-spark-client-operations.d.ts +78 -3
- package/types/mintplayer-ng-spark-identity-provider-connected-applications.d.ts +35 -0
- package/types/mintplayer-ng-spark-identity-provider-core.d.ts +144 -0
- package/types/mintplayer-ng-spark-identity-provider-developers.d.ts +55 -0
- package/types/mintplayer-ng-spark-identity-provider-management.d.ts +33 -0
- package/types/mintplayer-ng-spark-identity-provider.d.ts +64 -0
- package/types/mintplayer-ng-spark-pwa.d.ts +89 -0
- package/types/mintplayer-ng-spark-services.d.ts +10 -0
- package/types/mintplayer-ng-spark-shell.d.ts +2 -2
- package/types/mintplayer-ng-spark.d.ts +4 -4
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import * as i0 from "@angular/core";
|
|
2
|
+
import { ChangeDetectionStrategy, Component, inject, signal } from "@angular/core";
|
|
3
|
+
import * as i1 from "@angular/forms";
|
|
4
|
+
import { FormBuilder, ReactiveFormsModule, Validators } from "@angular/forms";
|
|
5
|
+
import { Router, RouterLink } from "@angular/router";
|
|
6
|
+
import { HttpErrorResponse } from "@angular/common/http";
|
|
7
|
+
import { Color } from "@mintplayer/ng-bootstrap";
|
|
8
|
+
import { BsAlertComponent } from "@mintplayer/ng-bootstrap/alert";
|
|
9
|
+
import { BsCardComponent, BsCardHeaderComponent } from "@mintplayer/ng-bootstrap/card";
|
|
10
|
+
import { BsFormComponent, BsFormControlDirective } from "@mintplayer/ng-bootstrap/form";
|
|
11
|
+
import { BsSpinnerComponent } from "@mintplayer/ng-bootstrap/spinner";
|
|
12
|
+
import { SPARK_AUTH_ROUTE_PATHS } from "@mintplayer/ng-spark/auth/models";
|
|
13
|
+
import { SparkAuthService, SparkAuthTranslationService } from "@mintplayer/ng-spark/auth/core";
|
|
14
|
+
import { TranslateKeyPipe } from "@mintplayer/ng-spark/auth/pipes";
|
|
15
|
+
function passwordMatchValidator(control) {
|
|
16
|
+
const password = control.get("password");
|
|
17
|
+
const confirmPassword = control.get("confirmPassword");
|
|
18
|
+
if (password && confirmPassword && password.value !== confirmPassword.value) return { passwordMismatch: true };
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
var SparkRegisterComponent = class SparkRegisterComponent {
|
|
22
|
+
fb = inject(FormBuilder);
|
|
23
|
+
authService = inject(SparkAuthService);
|
|
24
|
+
router = inject(Router);
|
|
25
|
+
translation = inject(SparkAuthTranslationService);
|
|
26
|
+
routePaths = inject(SPARK_AUTH_ROUTE_PATHS);
|
|
27
|
+
colors = Color;
|
|
28
|
+
loading = signal(false, ...ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []);
|
|
29
|
+
errorMessage = signal("", ...ngDevMode ? [{ debugName: "errorMessage" }] : /* istanbul ignore next */ []);
|
|
30
|
+
form = this.fb.group({
|
|
31
|
+
email: ["", [Validators.required, Validators.email]],
|
|
32
|
+
userName: ["", [Validators.required, Validators.pattern(/^[^@]*$/)]],
|
|
33
|
+
password: ["", Validators.required],
|
|
34
|
+
confirmPassword: ["", Validators.required]
|
|
35
|
+
}, { validators: passwordMatchValidator });
|
|
36
|
+
async onSubmit() {
|
|
37
|
+
if (this.form.invalid) {
|
|
38
|
+
this.form.markAllAsTouched();
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
this.loading.set(true);
|
|
42
|
+
this.errorMessage.set("");
|
|
43
|
+
const { email, userName, password } = this.form.value;
|
|
44
|
+
try {
|
|
45
|
+
await this.authService.register(email, password, userName.trim());
|
|
46
|
+
this.router.navigate([this.routePaths.login ?? "/"], { queryParams: { registered: "true" } });
|
|
47
|
+
} catch (err) {
|
|
48
|
+
if (err instanceof HttpErrorResponse) {
|
|
49
|
+
if (err.status === 400 && err.error?.errors) {
|
|
50
|
+
const messages = [].concat(...Object.values(err.error.errors));
|
|
51
|
+
this.errorMessage.set(messages.join(" "));
|
|
52
|
+
} else if (err.error?.detail) this.errorMessage.set(err.error.detail);
|
|
53
|
+
else this.errorMessage.set(this.translation.t("auth.registrationFailed"));
|
|
54
|
+
} else this.errorMessage.set(this.translation.t("auth.registrationFailed"));
|
|
55
|
+
} finally {
|
|
56
|
+
this.loading.set(false);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
60
|
+
minVersion: "12.0.0",
|
|
61
|
+
version: "22.2.0",
|
|
62
|
+
ngImport: i0,
|
|
63
|
+
type: SparkRegisterComponent,
|
|
64
|
+
deps: [],
|
|
65
|
+
target: i0.ɵɵFactoryTarget.Component
|
|
66
|
+
});
|
|
67
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({
|
|
68
|
+
minVersion: "17.0.0",
|
|
69
|
+
version: "22.2.0",
|
|
70
|
+
type: SparkRegisterComponent,
|
|
71
|
+
isStandalone: true,
|
|
72
|
+
selector: "spark-register",
|
|
73
|
+
ngImport: i0,
|
|
74
|
+
template: "<div class=\"d-flex justify-content-center\">\n <bs-card style=\"width: 100%; max-width: 400px;\">\n <bs-card-header>\n <h3 class=\"mb-0 text-center\">{{ 'auth.register' | t }}</h3>\n </bs-card-header>\n <div class=\"p-4\">\n @if (errorMessage()) {\n <bs-alert [type]=\"colors.danger\" class=\"mb-3\">{{ errorMessage() }}</bs-alert>\n }\n\n <bs-form>\n <form [formGroup]=\"form\" (ngSubmit)=\"onSubmit()\">\n <div class=\"mb-3\">\n <label for=\"email\" class=\"form-label\">{{ 'auth.email' | t }}</label>\n <input\n type=\"email\"\n id=\"email\"\n formControlName=\"email\"\n autocomplete=\"email\"\n />\n @if (form.get('email')?.touched && form.get('email')?.hasError('email')) {\n <div class=\"text-danger mt-1\">{{ 'auth.invalidEmail' | t }}</div>\n }\n </div>\n\n <div class=\"mb-3\">\n <label for=\"userName\" class=\"form-label\">{{ 'auth.userName' | t }}</label>\n <input\n type=\"text\"\n id=\"userName\"\n formControlName=\"userName\"\n autocomplete=\"username\"\n />\n <div class=\"form-text\" [class.text-danger]=\"form.get('userName')?.touched && form.get('userName')?.invalid\">{{ 'auth.userNameHint' | t }}</div>\n </div>\n\n <div class=\"mb-3\">\n <label for=\"password\" class=\"form-label\">{{ 'auth.password' | t }}</label>\n <input\n type=\"password\"\n id=\"password\"\n formControlName=\"password\"\n autocomplete=\"new-password\"\n />\n </div>\n\n <div class=\"mb-3\">\n <label for=\"confirmPassword\" class=\"form-label\">{{ 'auth.confirmPassword' | t }}</label>\n <input\n type=\"password\"\n id=\"confirmPassword\"\n formControlName=\"confirmPassword\"\n autocomplete=\"new-password\"\n />\n @if (form.touched && form.hasError('passwordMismatch')) {\n <div class=\"text-danger mt-1\">{{ 'auth.passwordMismatch' | t }}</div>\n }\n </div>\n\n <button\n type=\"submit\"\n class=\"btn btn-primary w-100\"\n [disabled]=\"loading()\"\n >\n @if (loading()) {\n <bs-spinner class=\"me-1\" />\n }\n {{ 'auth.register' | t }}\n </button>\n </form>\n </bs-form>\n\n <!-- withRegistration() is opt-in independently of withLocalLogin(), so the password form may\n not be mounted. An unguarded [routerLink]=\"undefined\" navigates to the current route. -->\n @if (routePaths.login) {\n <div class=\"mt-3 text-center\">\n <span>{{ 'auth.alreadyHaveAccount' | t }} </span>\n <a [routerLink]=\"routePaths.login\">{{ 'auth.login' | t }}</a>\n </div>\n }\n </div>\n </bs-card>\n</div>\n",
|
|
75
|
+
dependencies: [
|
|
76
|
+
{
|
|
77
|
+
kind: "ngmodule",
|
|
78
|
+
type: ReactiveFormsModule
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
kind: "directive",
|
|
82
|
+
type: i1.ɵNgNoValidate,
|
|
83
|
+
selector: "form:not([ngNoForm]):not([ngNativeValidate])"
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
kind: "directive",
|
|
87
|
+
type: i1.DefaultValueAccessor,
|
|
88
|
+
selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]"
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
kind: "directive",
|
|
92
|
+
type: i1.NgControlStatus,
|
|
93
|
+
selector: "[formControlName],[ngModel],[formControl]"
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
kind: "directive",
|
|
97
|
+
type: i1.NgControlStatusGroup,
|
|
98
|
+
selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]"
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
kind: "directive",
|
|
102
|
+
type: i1.FormGroupDirective,
|
|
103
|
+
selector: "[formGroup]",
|
|
104
|
+
inputs: ["formGroup"],
|
|
105
|
+
outputs: ["ngSubmit"],
|
|
106
|
+
exportAs: ["ngForm"]
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
kind: "directive",
|
|
110
|
+
type: i1.FormControlName,
|
|
111
|
+
selector: "[formControlName]",
|
|
112
|
+
inputs: [
|
|
113
|
+
"formControlName",
|
|
114
|
+
"disabled",
|
|
115
|
+
"ngModel"
|
|
116
|
+
],
|
|
117
|
+
outputs: ["ngModelChange"]
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
kind: "directive",
|
|
121
|
+
type: RouterLink,
|
|
122
|
+
selector: "[routerLink]",
|
|
123
|
+
inputs: [
|
|
124
|
+
"target",
|
|
125
|
+
"queryParams",
|
|
126
|
+
"fragment",
|
|
127
|
+
"queryParamsHandling",
|
|
128
|
+
"state",
|
|
129
|
+
"info",
|
|
130
|
+
"relativeTo",
|
|
131
|
+
"preserveFragment",
|
|
132
|
+
"skipLocationChange",
|
|
133
|
+
"replaceUrl",
|
|
134
|
+
"browserUrl",
|
|
135
|
+
"routerLink"
|
|
136
|
+
]
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
kind: "component",
|
|
140
|
+
type: BsAlertComponent,
|
|
141
|
+
selector: "bs-alert",
|
|
142
|
+
inputs: [
|
|
143
|
+
"type",
|
|
144
|
+
"announce",
|
|
145
|
+
"isVisible"
|
|
146
|
+
],
|
|
147
|
+
outputs: ["isVisibleChange", "afterOpenedOrClosed"]
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
kind: "component",
|
|
151
|
+
type: BsCardComponent,
|
|
152
|
+
selector: "bs-card",
|
|
153
|
+
inputs: ["color", "outline"]
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
kind: "component",
|
|
157
|
+
type: BsCardHeaderComponent,
|
|
158
|
+
selector: "bs-card-header",
|
|
159
|
+
inputs: ["color", "navStyle"]
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
kind: "component",
|
|
163
|
+
type: BsFormComponent,
|
|
164
|
+
selector: "bs-form",
|
|
165
|
+
inputs: ["action", "method"],
|
|
166
|
+
outputs: ["submitted"]
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
kind: "directive",
|
|
170
|
+
type: BsFormControlDirective,
|
|
171
|
+
selector: "bs-form input:not(.no-form-control), bs-form textarea:not(.no-form-control)"
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
kind: "component",
|
|
175
|
+
type: BsSpinnerComponent,
|
|
176
|
+
selector: "bs-spinner",
|
|
177
|
+
inputs: ["type", "color"]
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
kind: "pipe",
|
|
181
|
+
type: TranslateKeyPipe,
|
|
182
|
+
name: "t"
|
|
183
|
+
}
|
|
184
|
+
],
|
|
185
|
+
changeDetection: i0.ChangeDetectionStrategy.OnPush
|
|
186
|
+
});
|
|
187
|
+
};
|
|
188
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
189
|
+
minVersion: "12.0.0",
|
|
190
|
+
version: "22.2.0",
|
|
191
|
+
ngImport: i0,
|
|
192
|
+
type: SparkRegisterComponent,
|
|
193
|
+
decorators: [{
|
|
194
|
+
type: Component,
|
|
195
|
+
args: [{
|
|
196
|
+
selector: "spark-register",
|
|
197
|
+
standalone: true,
|
|
198
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
199
|
+
imports: [
|
|
200
|
+
ReactiveFormsModule,
|
|
201
|
+
RouterLink,
|
|
202
|
+
BsAlertComponent,
|
|
203
|
+
BsCardComponent,
|
|
204
|
+
BsCardHeaderComponent,
|
|
205
|
+
BsFormComponent,
|
|
206
|
+
BsFormControlDirective,
|
|
207
|
+
BsSpinnerComponent,
|
|
208
|
+
TranslateKeyPipe
|
|
209
|
+
],
|
|
210
|
+
template: "<div class=\"d-flex justify-content-center\">\n <bs-card style=\"width: 100%; max-width: 400px;\">\n <bs-card-header>\n <h3 class=\"mb-0 text-center\">{{ 'auth.register' | t }}</h3>\n </bs-card-header>\n <div class=\"p-4\">\n @if (errorMessage()) {\n <bs-alert [type]=\"colors.danger\" class=\"mb-3\">{{ errorMessage() }}</bs-alert>\n }\n\n <bs-form>\n <form [formGroup]=\"form\" (ngSubmit)=\"onSubmit()\">\n <div class=\"mb-3\">\n <label for=\"email\" class=\"form-label\">{{ 'auth.email' | t }}</label>\n <input\n type=\"email\"\n id=\"email\"\n formControlName=\"email\"\n autocomplete=\"email\"\n />\n @if (form.get('email')?.touched && form.get('email')?.hasError('email')) {\n <div class=\"text-danger mt-1\">{{ 'auth.invalidEmail' | t }}</div>\n }\n </div>\n\n <div class=\"mb-3\">\n <label for=\"userName\" class=\"form-label\">{{ 'auth.userName' | t }}</label>\n <input\n type=\"text\"\n id=\"userName\"\n formControlName=\"userName\"\n autocomplete=\"username\"\n />\n <div class=\"form-text\" [class.text-danger]=\"form.get('userName')?.touched && form.get('userName')?.invalid\">{{ 'auth.userNameHint' | t }}</div>\n </div>\n\n <div class=\"mb-3\">\n <label for=\"password\" class=\"form-label\">{{ 'auth.password' | t }}</label>\n <input\n type=\"password\"\n id=\"password\"\n formControlName=\"password\"\n autocomplete=\"new-password\"\n />\n </div>\n\n <div class=\"mb-3\">\n <label for=\"confirmPassword\" class=\"form-label\">{{ 'auth.confirmPassword' | t }}</label>\n <input\n type=\"password\"\n id=\"confirmPassword\"\n formControlName=\"confirmPassword\"\n autocomplete=\"new-password\"\n />\n @if (form.touched && form.hasError('passwordMismatch')) {\n <div class=\"text-danger mt-1\">{{ 'auth.passwordMismatch' | t }}</div>\n }\n </div>\n\n <button\n type=\"submit\"\n class=\"btn btn-primary w-100\"\n [disabled]=\"loading()\"\n >\n @if (loading()) {\n <bs-spinner class=\"me-1\" />\n }\n {{ 'auth.register' | t }}\n </button>\n </form>\n </bs-form>\n\n <!-- withRegistration() is opt-in independently of withLocalLogin(), so the password form may\n not be mounted. An unguarded [routerLink]=\"undefined\" navigates to the current route. -->\n @if (routePaths.login) {\n <div class=\"mt-3 text-center\">\n <span>{{ 'auth.alreadyHaveAccount' | t }} </span>\n <a [routerLink]=\"routePaths.login\">{{ 'auth.login' | t }}</a>\n </div>\n }\n </div>\n </bs-card>\n</div>\n"
|
|
211
|
+
}]
|
|
212
|
+
}]
|
|
213
|
+
});
|
|
214
|
+
export { SparkRegisterComponent };
|
|
215
|
+
|
|
216
|
+
//# sourceMappingURL=mintplayer-ng-spark-auth-register.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mintplayer-ng-spark-auth-register.mjs","names":[],"sources":["../../auth/register/src/spark-register.component.ts","../../auth/register/src/spark-register.component.html"],"sourcesContent":["import { ChangeDetectionStrategy, Component, inject, signal } from '@angular/core';\nimport { ReactiveFormsModule, FormBuilder, Validators, AbstractControl, ValidationErrors } from '@angular/forms';\nimport { RouterLink, Router } from '@angular/router';\nimport { HttpErrorResponse } from '@angular/common/http';\nimport { Color } from '@mintplayer/ng-bootstrap';\nimport { BsAlertComponent } from '@mintplayer/ng-bootstrap/alert';\nimport { BsCardComponent, BsCardHeaderComponent } from '@mintplayer/ng-bootstrap/card';\nimport { BsFormComponent, BsFormControlDirective } from '@mintplayer/ng-bootstrap/form';\nimport { BsSpinnerComponent } from '@mintplayer/ng-bootstrap/spinner';\nimport { SPARK_AUTH_ROUTE_PATHS } from '@mintplayer/ng-spark/auth/models';\nimport { SparkAuthService, SparkAuthTranslationService } from '@mintplayer/ng-spark/auth/core';\nimport { TranslateKeyPipe } from '@mintplayer/ng-spark/auth/pipes';\n\nfunction passwordMatchValidator(control: AbstractControl): ValidationErrors | null {\n const password = control.get('password');\n const confirmPassword = control.get('confirmPassword');\n if (password && confirmPassword && password.value !== confirmPassword.value) {\n return { passwordMismatch: true };\n }\n return null;\n}\n\n@Component({\n selector: 'spark-register',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [ReactiveFormsModule, RouterLink, BsAlertComponent, BsCardComponent, BsCardHeaderComponent, BsFormComponent, BsFormControlDirective, BsSpinnerComponent, TranslateKeyPipe],\n templateUrl: './spark-register.component.html',\n})\nexport class SparkRegisterComponent {\n private readonly fb = inject(FormBuilder);\n private readonly authService = inject(SparkAuthService);\n private readonly router = inject(Router);\n private readonly translation = inject(SparkAuthTranslationService);\n readonly routePaths = inject(SPARK_AUTH_ROUTE_PATHS);\n\n colors = Color;\n readonly loading = signal(false);\n readonly errorMessage = signal('');\n\n readonly form = this.fb.group({\n email: ['', [Validators.required, Validators.email]],\n // The public handle other users see; the server refuses '@' too (never an email address).\n userName: ['', [Validators.required, Validators.pattern(/^[^@]*$/)]],\n password: ['', Validators.required],\n confirmPassword: ['', Validators.required],\n }, { validators: passwordMatchValidator });\n\n async onSubmit(): Promise<void> {\n if (this.form.invalid) {\n this.form.markAllAsTouched();\n return;\n }\n\n this.loading.set(true);\n this.errorMessage.set('');\n\n const { email, userName, password } = this.form.value;\n\n try {\n await this.authService.register(email!, password!, userName!.trim());\n // An app can mount registration without the password form (external-only sign-in with\n // self-service account creation). Landing on the site root beats navigating to `undefined`,\n // which the router resolves to the current route — leaving the user on a form they just\n // submitted successfully.\n this.router.navigate([this.routePaths.login ?? '/'], {\n queryParams: { registered: 'true' },\n });\n } catch (err: any) {\n if (err instanceof HttpErrorResponse) {\n if (err.status === 400 && err.error?.errors) {\n const messages = ([] as string[]).concat(...Object.values(err.error.errors) as string[][]);\n this.errorMessage.set(messages.join(' '));\n } else if (err.error?.detail) {\n this.errorMessage.set(err.error.detail);\n } else {\n this.errorMessage.set(this.translation.t('auth.registrationFailed'));\n }\n } else {\n this.errorMessage.set(this.translation.t('auth.registrationFailed'));\n }\n } finally {\n this.loading.set(false);\n }\n }\n}\n\nexport default SparkRegisterComponent;\n","<div class=\"d-flex justify-content-center\">\n <bs-card style=\"width: 100%; max-width: 400px;\">\n <bs-card-header>\n <h3 class=\"mb-0 text-center\">{{ 'auth.register' | t }}</h3>\n </bs-card-header>\n <div class=\"p-4\">\n @if (errorMessage()) {\n <bs-alert [type]=\"colors.danger\" class=\"mb-3\">{{ errorMessage() }}</bs-alert>\n }\n\n <bs-form>\n <form [formGroup]=\"form\" (ngSubmit)=\"onSubmit()\">\n <div class=\"mb-3\">\n <label for=\"email\" class=\"form-label\">{{ 'auth.email' | t }}</label>\n <input\n type=\"email\"\n id=\"email\"\n formControlName=\"email\"\n autocomplete=\"email\"\n />\n @if (form.get('email')?.touched && form.get('email')?.hasError('email')) {\n <div class=\"text-danger mt-1\">{{ 'auth.invalidEmail' | t }}</div>\n }\n </div>\n\n <div class=\"mb-3\">\n <label for=\"userName\" class=\"form-label\">{{ 'auth.userName' | t }}</label>\n <input\n type=\"text\"\n id=\"userName\"\n formControlName=\"userName\"\n autocomplete=\"username\"\n />\n <div class=\"form-text\" [class.text-danger]=\"form.get('userName')?.touched && form.get('userName')?.invalid\">{{ 'auth.userNameHint' | t }}</div>\n </div>\n\n <div class=\"mb-3\">\n <label for=\"password\" class=\"form-label\">{{ 'auth.password' | t }}</label>\n <input\n type=\"password\"\n id=\"password\"\n formControlName=\"password\"\n autocomplete=\"new-password\"\n />\n </div>\n\n <div class=\"mb-3\">\n <label for=\"confirmPassword\" class=\"form-label\">{{ 'auth.confirmPassword' | t }}</label>\n <input\n type=\"password\"\n id=\"confirmPassword\"\n formControlName=\"confirmPassword\"\n autocomplete=\"new-password\"\n />\n @if (form.touched && form.hasError('passwordMismatch')) {\n <div class=\"text-danger mt-1\">{{ 'auth.passwordMismatch' | t }}</div>\n }\n </div>\n\n <button\n type=\"submit\"\n class=\"btn btn-primary w-100\"\n [disabled]=\"loading()\"\n >\n @if (loading()) {\n <bs-spinner class=\"me-1\" />\n }\n {{ 'auth.register' | t }}\n </button>\n </form>\n </bs-form>\n\n <!-- withRegistration() is opt-in independently of withLocalLogin(), so the password form may\n not be mounted. An unguarded [routerLink]=\"undefined\" navigates to the current route. -->\n @if (routePaths.login) {\n <div class=\"mt-3 text-center\">\n <span>{{ 'auth.alreadyHaveAccount' | t }} </span>\n <a [routerLink]=\"routePaths.login\">{{ 'auth.login' | t }}</a>\n </div>\n }\n </div>\n </bs-card>\n</div>\n"],"mappings":"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"}
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
import * as i0 from "@angular/core";
|
|
2
|
+
import { ChangeDetectionStrategy, Component, inject, signal } from "@angular/core";
|
|
3
|
+
import * as i1 from "@angular/forms";
|
|
4
|
+
import { FormBuilder, ReactiveFormsModule, Validators } from "@angular/forms";
|
|
5
|
+
import { ActivatedRoute, Router, RouterLink } from "@angular/router";
|
|
6
|
+
import { HttpErrorResponse } from "@angular/common/http";
|
|
7
|
+
import { Color } from "@mintplayer/ng-bootstrap";
|
|
8
|
+
import { BsAlertComponent } from "@mintplayer/ng-bootstrap/alert";
|
|
9
|
+
import { BsCardComponent, BsCardHeaderComponent } from "@mintplayer/ng-bootstrap/card";
|
|
10
|
+
import { BsFormComponent, BsFormControlDirective } from "@mintplayer/ng-bootstrap/form";
|
|
11
|
+
import { BsSpinnerComponent } from "@mintplayer/ng-bootstrap/spinner";
|
|
12
|
+
import { SPARK_AUTH_ROUTE_PATHS } from "@mintplayer/ng-spark/auth/models";
|
|
13
|
+
import { SparkAuthService, SparkAuthTranslationService } from "@mintplayer/ng-spark/auth/core";
|
|
14
|
+
import { TranslateKeyPipe } from "@mintplayer/ng-spark/auth/pipes";
|
|
15
|
+
function passwordMatchValidator(control) {
|
|
16
|
+
const password = control.get("newPassword");
|
|
17
|
+
const confirmPassword = control.get("confirmPassword");
|
|
18
|
+
if (password && confirmPassword && password.value !== confirmPassword.value) return { passwordMismatch: true };
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
var SparkResetPasswordComponent = class SparkResetPasswordComponent {
|
|
22
|
+
fb = inject(FormBuilder);
|
|
23
|
+
authService = inject(SparkAuthService);
|
|
24
|
+
router = inject(Router);
|
|
25
|
+
route = inject(ActivatedRoute);
|
|
26
|
+
translation = inject(SparkAuthTranslationService);
|
|
27
|
+
routePaths = inject(SPARK_AUTH_ROUTE_PATHS);
|
|
28
|
+
colors = Color;
|
|
29
|
+
loading = signal(false, ...ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []);
|
|
30
|
+
errorMessage = signal("", ...ngDevMode ? [{ debugName: "errorMessage" }] : /* istanbul ignore next */ []);
|
|
31
|
+
successMessage = signal("", ...ngDevMode ? [{ debugName: "successMessage" }] : /* istanbul ignore next */ []);
|
|
32
|
+
email = "";
|
|
33
|
+
code = "";
|
|
34
|
+
form = this.fb.group({
|
|
35
|
+
newPassword: ["", Validators.required],
|
|
36
|
+
confirmPassword: ["", Validators.required]
|
|
37
|
+
}, { validators: passwordMatchValidator });
|
|
38
|
+
ngOnInit() {
|
|
39
|
+
this.email = this.route.snapshot.queryParamMap.get("email") ?? "";
|
|
40
|
+
this.code = this.route.snapshot.queryParamMap.get("code") ?? "";
|
|
41
|
+
if (!this.email || !this.code) this.errorMessage.set(this.translation.t("auth.invalidResetLink"));
|
|
42
|
+
}
|
|
43
|
+
async onSubmit() {
|
|
44
|
+
if (this.form.invalid) {
|
|
45
|
+
this.form.markAllAsTouched();
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
if (!this.email || !this.code) {
|
|
49
|
+
this.errorMessage.set(this.translation.t("auth.invalidResetLink"));
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
this.loading.set(true);
|
|
53
|
+
this.errorMessage.set("");
|
|
54
|
+
this.successMessage.set("");
|
|
55
|
+
const { newPassword } = this.form.value;
|
|
56
|
+
try {
|
|
57
|
+
await this.authService.resetPassword(this.email, this.code, newPassword);
|
|
58
|
+
this.successMessage.set(this.translation.t("auth.resetSuccess"));
|
|
59
|
+
} catch (err) {
|
|
60
|
+
if (err instanceof HttpErrorResponse && err.error?.detail) this.errorMessage.set(err.error.detail);
|
|
61
|
+
else this.errorMessage.set(this.translation.t("auth.resetFailed"));
|
|
62
|
+
} finally {
|
|
63
|
+
this.loading.set(false);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
static ɵfac = i0.ɵɵngDeclareFactory({
|
|
67
|
+
minVersion: "12.0.0",
|
|
68
|
+
version: "22.2.0",
|
|
69
|
+
ngImport: i0,
|
|
70
|
+
type: SparkResetPasswordComponent,
|
|
71
|
+
deps: [],
|
|
72
|
+
target: i0.ɵɵFactoryTarget.Component
|
|
73
|
+
});
|
|
74
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({
|
|
75
|
+
minVersion: "17.0.0",
|
|
76
|
+
version: "22.2.0",
|
|
77
|
+
type: SparkResetPasswordComponent,
|
|
78
|
+
isStandalone: true,
|
|
79
|
+
selector: "spark-reset-password",
|
|
80
|
+
ngImport: i0,
|
|
81
|
+
template: "<div class=\"d-flex justify-content-center\">\n <bs-card style=\"width: 100%; max-width: 400px;\">\n <bs-card-header>\n <h3 class=\"mb-0 text-center\">{{ 'auth.resetPassword' | t }}</h3>\n </bs-card-header>\n <div class=\"p-4\">\n @if (successMessage()) {\n <bs-alert [type]=\"colors.success\" class=\"mb-3\">\n {{ successMessage() }}\n <div class=\"mt-2\">\n <a [routerLink]=\"routePaths.login\">{{ 'auth.goToLogin' | t }}</a>\n </div>\n </bs-alert>\n }\n\n @if (errorMessage()) {\n <bs-alert [type]=\"colors.danger\" class=\"mb-3\">{{ errorMessage() }}</bs-alert>\n }\n\n @if (!successMessage()) {\n <bs-form>\n <form [formGroup]=\"form\" (ngSubmit)=\"onSubmit()\">\n <div class=\"mb-3\">\n <label for=\"newPassword\" class=\"form-label\">{{ 'auth.newPassword' | t }}</label>\n <input\n type=\"password\"\n id=\"newPassword\"\n formControlName=\"newPassword\"\n autocomplete=\"new-password\"\n />\n </div>\n\n <div class=\"mb-3\">\n <label for=\"confirmPassword\" class=\"form-label\">{{ 'auth.confirmPassword' | t }}</label>\n <input\n type=\"password\"\n id=\"confirmPassword\"\n formControlName=\"confirmPassword\"\n autocomplete=\"new-password\"\n />\n @if (form.touched && form.hasError('passwordMismatch')) {\n <div class=\"text-danger mt-1\">{{ 'auth.passwordMismatch' | t }}</div>\n }\n </div>\n\n <button\n type=\"submit\"\n class=\"btn btn-primary w-100\"\n [disabled]=\"loading()\"\n >\n @if (loading()) {\n <bs-spinner class=\"me-1\" />\n }\n {{ 'auth.resetPassword' | t }}\n </button>\n </form>\n </bs-form>\n\n <div class=\"mt-3 text-center\">\n <a [routerLink]=\"routePaths.login\">{{ 'auth.backToLogin' | t }}</a>\n </div>\n }\n </div>\n </bs-card>\n</div>\n",
|
|
82
|
+
dependencies: [
|
|
83
|
+
{
|
|
84
|
+
kind: "ngmodule",
|
|
85
|
+
type: ReactiveFormsModule
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
kind: "directive",
|
|
89
|
+
type: i1.ɵNgNoValidate,
|
|
90
|
+
selector: "form:not([ngNoForm]):not([ngNativeValidate])"
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
kind: "directive",
|
|
94
|
+
type: i1.DefaultValueAccessor,
|
|
95
|
+
selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]"
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
kind: "directive",
|
|
99
|
+
type: i1.NgControlStatus,
|
|
100
|
+
selector: "[formControlName],[ngModel],[formControl]"
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
kind: "directive",
|
|
104
|
+
type: i1.NgControlStatusGroup,
|
|
105
|
+
selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]"
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
kind: "directive",
|
|
109
|
+
type: i1.FormGroupDirective,
|
|
110
|
+
selector: "[formGroup]",
|
|
111
|
+
inputs: ["formGroup"],
|
|
112
|
+
outputs: ["ngSubmit"],
|
|
113
|
+
exportAs: ["ngForm"]
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
kind: "directive",
|
|
117
|
+
type: i1.FormControlName,
|
|
118
|
+
selector: "[formControlName]",
|
|
119
|
+
inputs: [
|
|
120
|
+
"formControlName",
|
|
121
|
+
"disabled",
|
|
122
|
+
"ngModel"
|
|
123
|
+
],
|
|
124
|
+
outputs: ["ngModelChange"]
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
kind: "directive",
|
|
128
|
+
type: RouterLink,
|
|
129
|
+
selector: "[routerLink]",
|
|
130
|
+
inputs: [
|
|
131
|
+
"target",
|
|
132
|
+
"queryParams",
|
|
133
|
+
"fragment",
|
|
134
|
+
"queryParamsHandling",
|
|
135
|
+
"state",
|
|
136
|
+
"info",
|
|
137
|
+
"relativeTo",
|
|
138
|
+
"preserveFragment",
|
|
139
|
+
"skipLocationChange",
|
|
140
|
+
"replaceUrl",
|
|
141
|
+
"browserUrl",
|
|
142
|
+
"routerLink"
|
|
143
|
+
]
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
kind: "component",
|
|
147
|
+
type: BsAlertComponent,
|
|
148
|
+
selector: "bs-alert",
|
|
149
|
+
inputs: [
|
|
150
|
+
"type",
|
|
151
|
+
"announce",
|
|
152
|
+
"isVisible"
|
|
153
|
+
],
|
|
154
|
+
outputs: ["isVisibleChange", "afterOpenedOrClosed"]
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
kind: "component",
|
|
158
|
+
type: BsCardComponent,
|
|
159
|
+
selector: "bs-card",
|
|
160
|
+
inputs: ["color", "outline"]
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
kind: "component",
|
|
164
|
+
type: BsCardHeaderComponent,
|
|
165
|
+
selector: "bs-card-header",
|
|
166
|
+
inputs: ["color", "navStyle"]
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
kind: "component",
|
|
170
|
+
type: BsFormComponent,
|
|
171
|
+
selector: "bs-form",
|
|
172
|
+
inputs: ["action", "method"],
|
|
173
|
+
outputs: ["submitted"]
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
kind: "directive",
|
|
177
|
+
type: BsFormControlDirective,
|
|
178
|
+
selector: "bs-form input:not(.no-form-control), bs-form textarea:not(.no-form-control)"
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
kind: "component",
|
|
182
|
+
type: BsSpinnerComponent,
|
|
183
|
+
selector: "bs-spinner",
|
|
184
|
+
inputs: ["type", "color"]
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
kind: "pipe",
|
|
188
|
+
type: TranslateKeyPipe,
|
|
189
|
+
name: "t"
|
|
190
|
+
}
|
|
191
|
+
],
|
|
192
|
+
changeDetection: i0.ChangeDetectionStrategy.OnPush
|
|
193
|
+
});
|
|
194
|
+
};
|
|
195
|
+
i0.ɵɵngDeclareClassMetadata({
|
|
196
|
+
minVersion: "12.0.0",
|
|
197
|
+
version: "22.2.0",
|
|
198
|
+
ngImport: i0,
|
|
199
|
+
type: SparkResetPasswordComponent,
|
|
200
|
+
decorators: [{
|
|
201
|
+
type: Component,
|
|
202
|
+
args: [{
|
|
203
|
+
selector: "spark-reset-password",
|
|
204
|
+
standalone: true,
|
|
205
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
206
|
+
imports: [
|
|
207
|
+
ReactiveFormsModule,
|
|
208
|
+
RouterLink,
|
|
209
|
+
BsAlertComponent,
|
|
210
|
+
BsCardComponent,
|
|
211
|
+
BsCardHeaderComponent,
|
|
212
|
+
BsFormComponent,
|
|
213
|
+
BsFormControlDirective,
|
|
214
|
+
BsSpinnerComponent,
|
|
215
|
+
TranslateKeyPipe
|
|
216
|
+
],
|
|
217
|
+
template: "<div class=\"d-flex justify-content-center\">\n <bs-card style=\"width: 100%; max-width: 400px;\">\n <bs-card-header>\n <h3 class=\"mb-0 text-center\">{{ 'auth.resetPassword' | t }}</h3>\n </bs-card-header>\n <div class=\"p-4\">\n @if (successMessage()) {\n <bs-alert [type]=\"colors.success\" class=\"mb-3\">\n {{ successMessage() }}\n <div class=\"mt-2\">\n <a [routerLink]=\"routePaths.login\">{{ 'auth.goToLogin' | t }}</a>\n </div>\n </bs-alert>\n }\n\n @if (errorMessage()) {\n <bs-alert [type]=\"colors.danger\" class=\"mb-3\">{{ errorMessage() }}</bs-alert>\n }\n\n @if (!successMessage()) {\n <bs-form>\n <form [formGroup]=\"form\" (ngSubmit)=\"onSubmit()\">\n <div class=\"mb-3\">\n <label for=\"newPassword\" class=\"form-label\">{{ 'auth.newPassword' | t }}</label>\n <input\n type=\"password\"\n id=\"newPassword\"\n formControlName=\"newPassword\"\n autocomplete=\"new-password\"\n />\n </div>\n\n <div class=\"mb-3\">\n <label for=\"confirmPassword\" class=\"form-label\">{{ 'auth.confirmPassword' | t }}</label>\n <input\n type=\"password\"\n id=\"confirmPassword\"\n formControlName=\"confirmPassword\"\n autocomplete=\"new-password\"\n />\n @if (form.touched && form.hasError('passwordMismatch')) {\n <div class=\"text-danger mt-1\">{{ 'auth.passwordMismatch' | t }}</div>\n }\n </div>\n\n <button\n type=\"submit\"\n class=\"btn btn-primary w-100\"\n [disabled]=\"loading()\"\n >\n @if (loading()) {\n <bs-spinner class=\"me-1\" />\n }\n {{ 'auth.resetPassword' | t }}\n </button>\n </form>\n </bs-form>\n\n <div class=\"mt-3 text-center\">\n <a [routerLink]=\"routePaths.login\">{{ 'auth.backToLogin' | t }}</a>\n </div>\n }\n </div>\n </bs-card>\n</div>\n"
|
|
218
|
+
}]
|
|
219
|
+
}]
|
|
220
|
+
});
|
|
221
|
+
export { SparkResetPasswordComponent };
|
|
222
|
+
|
|
223
|
+
//# sourceMappingURL=mintplayer-ng-spark-auth-reset-password.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mintplayer-ng-spark-auth-reset-password.mjs","names":[],"sources":["../../auth/reset-password/src/spark-reset-password.component.ts","../../auth/reset-password/src/spark-reset-password.component.html"],"sourcesContent":["import { ChangeDetectionStrategy, Component, inject, OnInit, signal } from '@angular/core';\nimport { ReactiveFormsModule, FormBuilder, Validators, AbstractControl, ValidationErrors } from '@angular/forms';\nimport { RouterLink, ActivatedRoute, Router } from '@angular/router';\nimport { HttpErrorResponse } from '@angular/common/http';\nimport { Color } from '@mintplayer/ng-bootstrap';\nimport { BsAlertComponent } from '@mintplayer/ng-bootstrap/alert';\nimport { BsCardComponent, BsCardHeaderComponent } from '@mintplayer/ng-bootstrap/card';\nimport { BsFormComponent, BsFormControlDirective } from '@mintplayer/ng-bootstrap/form';\nimport { BsSpinnerComponent } from '@mintplayer/ng-bootstrap/spinner';\nimport { SPARK_AUTH_ROUTE_PATHS } from '@mintplayer/ng-spark/auth/models';\nimport { SparkAuthService, SparkAuthTranslationService } from '@mintplayer/ng-spark/auth/core';\nimport { TranslateKeyPipe } from '@mintplayer/ng-spark/auth/pipes';\n\nfunction passwordMatchValidator(control: AbstractControl): ValidationErrors | null {\n const password = control.get('newPassword');\n const confirmPassword = control.get('confirmPassword');\n if (password && confirmPassword && password.value !== confirmPassword.value) {\n return { passwordMismatch: true };\n }\n return null;\n}\n\n@Component({\n selector: 'spark-reset-password',\n standalone: true,\n changeDetection: ChangeDetectionStrategy.OnPush,\n imports: [ReactiveFormsModule, RouterLink, BsAlertComponent, BsCardComponent, BsCardHeaderComponent, BsFormComponent, BsFormControlDirective, BsSpinnerComponent, TranslateKeyPipe],\n templateUrl: './spark-reset-password.component.html',\n})\nexport class SparkResetPasswordComponent implements OnInit {\n private readonly fb = inject(FormBuilder);\n private readonly authService = inject(SparkAuthService);\n private readonly router = inject(Router);\n private readonly route = inject(ActivatedRoute);\n private readonly translation = inject(SparkAuthTranslationService);\n readonly routePaths = inject(SPARK_AUTH_ROUTE_PATHS);\n\n colors = Color;\n readonly loading = signal(false);\n readonly errorMessage = signal('');\n readonly successMessage = signal('');\n\n private email = '';\n private code = '';\n\n readonly form = this.fb.group({\n newPassword: ['', Validators.required],\n confirmPassword: ['', Validators.required],\n }, { validators: passwordMatchValidator });\n\n ngOnInit(): void {\n this.email = this.route.snapshot.queryParamMap.get('email') ?? '';\n this.code = this.route.snapshot.queryParamMap.get('code') ?? '';\n\n if (!this.email || !this.code) {\n this.errorMessage.set(this.translation.t('auth.invalidResetLink'));\n }\n }\n\n async onSubmit(): Promise<void> {\n if (this.form.invalid) {\n this.form.markAllAsTouched();\n return;\n }\n\n if (!this.email || !this.code) {\n this.errorMessage.set(this.translation.t('auth.invalidResetLink'));\n return;\n }\n\n this.loading.set(true);\n this.errorMessage.set('');\n this.successMessage.set('');\n\n const { newPassword } = this.form.value;\n\n try {\n await this.authService.resetPassword(this.email, this.code, newPassword!);\n this.successMessage.set(this.translation.t('auth.resetSuccess'));\n } catch (err: any) {\n if (err instanceof HttpErrorResponse && err.error?.detail) {\n this.errorMessage.set(err.error.detail);\n } else {\n this.errorMessage.set(this.translation.t('auth.resetFailed'));\n }\n } finally {\n this.loading.set(false);\n }\n }\n}\n\nexport default SparkResetPasswordComponent;\n","<div class=\"d-flex justify-content-center\">\n <bs-card style=\"width: 100%; max-width: 400px;\">\n <bs-card-header>\n <h3 class=\"mb-0 text-center\">{{ 'auth.resetPassword' | t }}</h3>\n </bs-card-header>\n <div class=\"p-4\">\n @if (successMessage()) {\n <bs-alert [type]=\"colors.success\" class=\"mb-3\">\n {{ successMessage() }}\n <div class=\"mt-2\">\n <a [routerLink]=\"routePaths.login\">{{ 'auth.goToLogin' | t }}</a>\n </div>\n </bs-alert>\n }\n\n @if (errorMessage()) {\n <bs-alert [type]=\"colors.danger\" class=\"mb-3\">{{ errorMessage() }}</bs-alert>\n }\n\n @if (!successMessage()) {\n <bs-form>\n <form [formGroup]=\"form\" (ngSubmit)=\"onSubmit()\">\n <div class=\"mb-3\">\n <label for=\"newPassword\" class=\"form-label\">{{ 'auth.newPassword' | t }}</label>\n <input\n type=\"password\"\n id=\"newPassword\"\n formControlName=\"newPassword\"\n autocomplete=\"new-password\"\n />\n </div>\n\n <div class=\"mb-3\">\n <label for=\"confirmPassword\" class=\"form-label\">{{ 'auth.confirmPassword' | t }}</label>\n <input\n type=\"password\"\n id=\"confirmPassword\"\n formControlName=\"confirmPassword\"\n autocomplete=\"new-password\"\n />\n @if (form.touched && form.hasError('passwordMismatch')) {\n <div class=\"text-danger mt-1\">{{ 'auth.passwordMismatch' | t }}</div>\n }\n </div>\n\n <button\n type=\"submit\"\n class=\"btn btn-primary w-100\"\n [disabled]=\"loading()\"\n >\n @if (loading()) {\n <bs-spinner class=\"me-1\" />\n }\n {{ 'auth.resetPassword' | t }}\n </button>\n </form>\n </bs-form>\n\n <div class=\"mt-3 text-center\">\n <a [routerLink]=\"routePaths.login\">{{ 'auth.backToLogin' | t }}</a>\n </div>\n }\n </div>\n </bs-card>\n</div>\n"],"mappings":"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"}
|