mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-18 23:43:01 +00:00
[CST-15074][#3355] PR review
This commit is contained in:
@@ -11,6 +11,7 @@ import {
|
||||
} from '@ngrx/store';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { CookieAttributes } from 'js-cookie';
|
||||
import uniqBy from 'lodash/uniqBy';
|
||||
import {
|
||||
Observable,
|
||||
of as observableOf,
|
||||
@@ -38,6 +39,7 @@ import {
|
||||
isNotNull,
|
||||
isNotUndefined,
|
||||
} from '../../shared/empty.util';
|
||||
import { rendersAuthMethodType } from '../../shared/log-in/methods/log-in.methods-decorator';
|
||||
import { NotificationsService } from '../../shared/notifications/notifications.service';
|
||||
import { createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils';
|
||||
import { followLink } from '../../shared/utils/follow-link-config.model';
|
||||
@@ -74,6 +76,7 @@ import {
|
||||
} from './auth.actions';
|
||||
import { AuthRequestService } from './auth-request.service';
|
||||
import { AuthMethod } from './models/auth.method';
|
||||
import { AuthMethodType } from './models/auth.method-type';
|
||||
import { AuthStatus } from './models/auth-status.model';
|
||||
import {
|
||||
AuthTokenInfo,
|
||||
@@ -81,6 +84,7 @@ import {
|
||||
} from './models/auth-token-info.model';
|
||||
import {
|
||||
getAuthenticatedUserId,
|
||||
getAuthenticationMethods,
|
||||
getAuthenticationToken,
|
||||
getExternalAuthCookieStatus,
|
||||
getRedirectUrl,
|
||||
@@ -690,4 +694,18 @@ export class AuthService {
|
||||
}
|
||||
}
|
||||
|
||||
public getAuthMethods(excludedAuthMethod?: AuthMethodType): Observable<AuthMethod[]> {
|
||||
return this.store.pipe(
|
||||
select(getAuthenticationMethods),
|
||||
map((methods: AuthMethod[]) => methods
|
||||
// ignore the given auth method if it should be excluded
|
||||
.filter((authMethod: AuthMethod) => excludedAuthMethod == null || authMethod.authMethodType !== excludedAuthMethod)
|
||||
.filter((authMethod: AuthMethod) => rendersAuthMethodType(authMethod.authMethodType) !== undefined)
|
||||
.sort((method1: AuthMethod, method2: AuthMethod) => method1.position - method2.position),
|
||||
),
|
||||
// ignore the ip authentication method when it's returned by the backend
|
||||
map((authMethods: AuthMethod[]) => uniqBy(authMethods.filter(a => a.authMethodType !== AuthMethodType.Ip), 'authMethodType')),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,9 +1,11 @@
|
||||
<h4 class="mb-3">
|
||||
<h4>
|
||||
{{ "external-login.confirm-email.header" | translate }}
|
||||
</h4>
|
||||
|
||||
<form [formGroup]="emailForm" (ngSubmit)="submitForm()">
|
||||
<div class="form-group">
|
||||
<div class="form-row">
|
||||
<div class="col-12 my-2">
|
||||
<input
|
||||
type="email"
|
||||
id="email"
|
||||
@@ -23,7 +25,13 @@
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<button type="submit" class="btn btn-lg btn-primary btn-block">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="col-12">
|
||||
<button type="submit" class="btn btn-lg btn-primary w-100">
|
||||
{{ "external-login.confirm.button.label" | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
@@ -1,9 +1,11 @@
|
||||
<h4 class="mb-3">
|
||||
<h4>
|
||||
{{ "external-login.provide-email.header" | translate }}
|
||||
</h4>
|
||||
|
||||
<form [formGroup]="emailForm" (ngSubmit)="submitForm()">
|
||||
<div class="form-group">
|
||||
<div class="form-row">
|
||||
<div class="col-12 my-2">
|
||||
<input
|
||||
type="email"
|
||||
id="email"
|
||||
@@ -23,8 +25,13 @@
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-lg btn-primary btn-block">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="col-12">
|
||||
<button type="submit" class="btn btn-lg btn-primary w-100">
|
||||
{{ "external-login.provide-email.button.label" | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
@@ -1,34 +1,38 @@
|
||||
<div class="row">
|
||||
<h4>{{ 'external-login.confirmation.header' | translate}}</h4>
|
||||
<h4>{{ 'external-login.confirmation.header' | translate }}</h4>
|
||||
</div>
|
||||
<div class="row justify-content-center">
|
||||
<ng-container *ngComponentOutlet="getExternalLoginConfirmationType(); injector: objectInjector;">
|
||||
</ng-container>
|
||||
</div>
|
||||
<ds-alert class="row mt-2" [type]="AlertTypeEnum.Info" [attr.data-test]="'info-text'">
|
||||
<ds-alert class="container mt-2" [type]="AlertTypeEnum.Info" [attr.data-test]="'info-text'">
|
||||
{{ informationText }}
|
||||
</ds-alert>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-4 d-flex justify-content-end align-items-center">
|
||||
<div class="row d-flex justify-content-center">
|
||||
<div class="col-6 d-flex">
|
||||
<div class="col d-flex justify-content-center align-items-center">
|
||||
@if (registrationData.email) {
|
||||
<ds-confirm-email [registrationData]="registrationData" [token]="token"></ds-confirm-email>
|
||||
} @else {
|
||||
<ds-provide-email [registrationId]="registrationData.id" [token]="token"></ds-provide-email>
|
||||
}
|
||||
</div>
|
||||
<div class="col-1 align-items-center d-flex justify-content-center">
|
||||
@if (hasAuthMethodTypes | async) {
|
||||
<div class="col-1 d-flex justify-content-center align-items-center">
|
||||
<h4 class="mt-2">{{ 'external-login.component.or' | translate }}</h4>
|
||||
</div>
|
||||
<div class="col-4 align-items-center d-flex justify-content-start">
|
||||
<div class="col d-flex justify-content-center align-items-center">
|
||||
<button class="btn block btn-lg btn-primary" (click)="openLoginModal(loginModal)">
|
||||
{{'external-login.connect-to-existing-account.label' | translate}}
|
||||
{{ 'external-login.connect-to-existing-account.label' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ng-template #loginModal let-c="close" let-d="dismiss">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title text-info"> {{'external-login.connect-to-existing-account.label' | translate}}</h4>
|
||||
<h4 class="modal-title text-info"> {{ 'external-login.connect-to-existing-account.label' | translate }}</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="row justify-content-center">
|
||||
@@ -42,7 +46,7 @@
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-outline-primary btn-sm" (click)="c('Close click');clearRedirectUrl()">
|
||||
<i class="fa fa-times" aria-hidden="true"></i>
|
||||
{{'external-login.modal.label.close' | translate}}
|
||||
{{ 'external-login.modal.label.close' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</ng-template>
|
||||
|
@@ -1,4 +1,7 @@
|
||||
import { NgComponentOutlet } from '@angular/common';
|
||||
import {
|
||||
AsyncPipe,
|
||||
NgComponentOutlet,
|
||||
} from '@angular/common';
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
@@ -15,6 +18,8 @@ import {
|
||||
TranslateModule,
|
||||
TranslateService,
|
||||
} from '@ngx-translate/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
|
||||
import { AuthService } from '../../core/auth/auth.service';
|
||||
import { AuthMethodType } from '../../core/auth/models/auth.method-type';
|
||||
@@ -46,6 +51,7 @@ import { ProvideEmailComponent } from '../email-confirmation/provide-email/provi
|
||||
ConfirmEmailComponent,
|
||||
ThemedLogInComponent,
|
||||
NgComponentOutlet,
|
||||
AsyncPipe,
|
||||
],
|
||||
standalone: true,
|
||||
})
|
||||
@@ -93,13 +99,18 @@ export class ExternalLogInComponent implements OnInit, OnDestroy {
|
||||
* Authentication method related to registration type
|
||||
*/
|
||||
relatedAuthMethod: AuthMethodType;
|
||||
/**
|
||||
* The observable to check if any auth method type is configured
|
||||
*/
|
||||
hasAuthMethodTypes: Observable<boolean>;
|
||||
|
||||
constructor(
|
||||
private injector: Injector,
|
||||
private translate: TranslateService,
|
||||
private modalService: NgbModal,
|
||||
private authService: AuthService,
|
||||
) { }
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide the registration data object to the objectInjector.
|
||||
@@ -121,6 +132,38 @@ export class ExternalLogInComponent implements OnInit, OnDestroy {
|
||||
this.informationText = hasValue(this.registrationData?.email)
|
||||
? this.generateInformationTextWhenEmail(this.registrationType)
|
||||
: this.generateInformationTextWhenNOEmail(this.registrationType);
|
||||
this.hasAuthMethodTypes = this.authService.getAuthMethods(this.relatedAuthMethod).pipe(map(methods => methods.length > 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the registration type to be rendered
|
||||
*/
|
||||
getExternalLoginConfirmationType(): ExternalLoginTypeComponent {
|
||||
return getExternalLoginConfirmationType(this.registrationType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the login modal and sets the redirect URL to '/review-account'.
|
||||
* On modal dismissed/closed, the redirect URL is cleared.
|
||||
* @param content - The content to be displayed in the modal.
|
||||
*/
|
||||
openLoginModal(content: any) {
|
||||
this.modalRef = this.modalService.open(content);
|
||||
this.authService.setRedirectUrl(`/review-account/${this.token}`);
|
||||
this.modalRef.dismissed.subscribe(() => {
|
||||
this.clearRedirectUrl();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the redirect URL stored in the authentication service.
|
||||
*/
|
||||
clearRedirectUrl() {
|
||||
this.authService.clearRedirectUrl();
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.modalRef?.close();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -149,38 +192,4 @@ export class ExternalLogInComponent implements OnInit, OnDestroy {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the registration type to be rendered
|
||||
*/
|
||||
getExternalLoginConfirmationType(): ExternalLoginTypeComponent {
|
||||
return getExternalLoginConfirmationType(this.registrationType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the login modal and sets the redirect URL to '/review-account'.
|
||||
* On modal dismissed/closed, the redirect URL is cleared.
|
||||
* @param content - The content to be displayed in the modal.
|
||||
*/
|
||||
openLoginModal(content: any) {
|
||||
setTimeout(() => {
|
||||
this.authService.setRedirectUrl(`/review-account/${this.token}`);
|
||||
}, 100);
|
||||
this.modalRef = this.modalService.open(content);
|
||||
|
||||
this.modalRef.dismissed.subscribe(() => {
|
||||
this.clearRedirectUrl();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the redirect URL stored in the authentication service.
|
||||
*/
|
||||
clearRedirectUrl() {
|
||||
this.authService.clearRedirectUrl();
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.modalRef?.close();
|
||||
}
|
||||
}
|
||||
|
@@ -23,7 +23,7 @@
|
||||
<td>{{ registrationData.netId }}</td>
|
||||
<td>
|
||||
<span>
|
||||
{{ 'external-login-validation.review-account-info.table.row.not-applicable' }}
|
||||
{{ 'external-login-validation.review-account-info.table.row.not-applicable' | translate }}
|
||||
</span>
|
||||
</td>
|
||||
<td></td>
|
||||
@@ -55,7 +55,7 @@
|
||||
</tbody>
|
||||
</table> <div class="d-flex justify-content-end">
|
||||
<button class="btn btn-primary" (click)="onSave()">
|
||||
{{'confirmation-modal.review-account-info.confirm' | translate}}
|
||||
{{'confirmation-modal.review-account-info.save' | translate}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -9,16 +9,13 @@ import {
|
||||
select,
|
||||
Store,
|
||||
} from '@ngrx/store';
|
||||
import uniqBy from 'lodash/uniqBy';
|
||||
import { Observable } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
|
||||
import { AuthService } from '../../core/auth/auth.service';
|
||||
import { AuthMethod } from '../../core/auth/models/auth.method';
|
||||
import { AuthMethodType } from '../../core/auth/models/auth.method-type';
|
||||
import {
|
||||
getAuthenticationError,
|
||||
getAuthenticationMethods,
|
||||
isAuthenticated,
|
||||
isAuthenticationLoading,
|
||||
} from '../../core/auth/selectors';
|
||||
@@ -26,7 +23,6 @@ import { CoreState } from '../../core/core-state.model';
|
||||
import { hasValue } from '../empty.util';
|
||||
import { ThemedLoadingComponent } from '../loading/themed-loading.component';
|
||||
import { LogInContainerComponent } from './container/log-in-container.component';
|
||||
import { rendersAuthMethodType } from './methods/log-in.methods-decorator';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-base-log-in',
|
||||
@@ -77,17 +73,7 @@ export class LogInComponent implements OnInit {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.authMethods = this.store.pipe(
|
||||
select(getAuthenticationMethods),
|
||||
map((methods: AuthMethod[]) => methods
|
||||
// ignore the given auth method if it should be excluded
|
||||
.filter((authMethod: AuthMethod) => authMethod.authMethodType !== this.excludedAuthMethod)
|
||||
.filter((authMethod: AuthMethod) => rendersAuthMethodType(authMethod.authMethodType) !== undefined)
|
||||
.sort((method1: AuthMethod, method2: AuthMethod) => method1.position - method2.position),
|
||||
),
|
||||
// ignore the ip authentication method when it's returned by the backend
|
||||
map((authMethods: AuthMethod[]) => uniqBy(authMethods.filter(a => a.authMethodType !== AuthMethodType.Ip), 'authMethodType')),
|
||||
);
|
||||
this.authMethods = this.authService.getAuthMethods(this.excludedAuthMethod);
|
||||
|
||||
// set loading
|
||||
this.loading = this.store.pipe(select(isAuthenticationLoading));
|
||||
|
@@ -1826,11 +1826,13 @@
|
||||
|
||||
"confirmation-modal.review-account-info.header": "Save the changes",
|
||||
|
||||
"confirmation-modal.review-account-info.info": "Continue to update your profile",
|
||||
"confirmation-modal.review-account-info.info": "Are you sure you want to save the changes to your profile",
|
||||
|
||||
"confirmation-modal.review-account-info.cancel": "Cancel",
|
||||
|
||||
"confirmation-modal.review-account-info.confirm": "Save",
|
||||
"confirmation-modal.review-account-info.confirm": "Confirm",
|
||||
|
||||
"confirmation-modal.review-account-info.save": "Save",
|
||||
|
||||
"error.bitstream": "Error fetching bitstream",
|
||||
|
||||
|
@@ -2309,17 +2309,21 @@
|
||||
// TODO New key - Add a translation
|
||||
"confirmation-modal.review-account-info.header": "Save the changes",
|
||||
|
||||
// "confirmation-modal.review-account-info.info": "Continue to update your profile",
|
||||
// "confirmation-modal.review-account-info.info": "Are you sure you want to save the changes to your profile",
|
||||
// TODO New key - Add a translation
|
||||
"confirmation-modal.review-account-info.info": "Continue to update your profile",
|
||||
"confirmation-modal.review-account-info.info": "Are you sure you want to save the changes to your profile?",
|
||||
|
||||
// "confirmation-modal.review-account-info.cancel": "Cancel",
|
||||
// TODO New key - Add a translation
|
||||
"confirmation-modal.review-account-info.cancel": "Cancel",
|
||||
|
||||
// "confirmation-modal.review-account-info.confirm": "Save",
|
||||
// "confirmation-modal.review-account-info.confirm": "Confirm",
|
||||
// TODO New key - Add a translation
|
||||
"confirmation-modal.review-account-info.confirm": "Save",
|
||||
"confirmation-modal.review-account-info.confirm": "Confirm",
|
||||
|
||||
// "confirmation-modal.review-account-info.save": "Save",
|
||||
// TODO New key - Add a translation
|
||||
"confirmation-modal.review-account-info.save": "Save",
|
||||
|
||||
// "error.bitstream": "Error fetching bitstream",
|
||||
"error.bitstream": "Errore durante il recupero del bitstream",
|
||||
|
Reference in New Issue
Block a user