Improve usability

pull/82/head
Thomas 4 years ago
parent ea96e54168
commit 4e6920b6d1

@ -89,7 +89,8 @@ export class HeaderComponent implements OnChanges {
autoFocus: false,
data: {
accessToken: '',
hasPermissionToUseSocialLogin: this.hasPermissionForSocialLogin
hasPermissionToUseSocialLogin: this.hasPermissionForSocialLogin,
title: 'Sign in'
},
width: '30rem'
});

@ -1,5 +1,5 @@
import { ChangeDetectionStrategy, Component, Inject } from '@angular/core';
import { MAT_DIALOG_DATA } from '@angular/material/dialog';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
@Component({
selector: 'gf-login-with-access-token-dialog',
@ -8,7 +8,14 @@ import { MAT_DIALOG_DATA } from '@angular/material/dialog';
templateUrl: 'login-with-access-token-dialog.html'
})
export class LoginWithAccessTokenDialog {
public constructor(@Inject(MAT_DIALOG_DATA) public data: any) {}
public constructor(
public dialogRef: MatDialogRef<LoginWithAccessTokenDialog>,
@Inject(MAT_DIALOG_DATA) public data: any
) {}
ngOnInit() {}
public onClose(): void {
this.dialogRef.close();
}
}

@ -1,4 +1,9 @@
<h1 mat-dialog-title i18n>Sign in</h1>
<gf-dialog-header
mat-dialog-title
[title]="data.title"
(closeButtonClicked)="onClose()"
></gf-dialog-header>
<div mat-dialog-content>
<div>
<ng-container *ngIf="data.hasPermissionToUseSocialLogin">
@ -19,20 +24,23 @@
[(ngModel)]="data.accessToken"
></textarea>
</mat-form-field>
</div>
</div>
<div mat-dialog-actions>
<div class="flex-grow-1">
<mat-checkbox i18n [(ngModel)]="data.staySignedIn"
>Stay signed in</mat-checkbox
>
</div>
</div>
<div class="float-right" mat-dialog-actions>
<button i18n mat-flat-button [mat-dialog-close]="undefined">Cancel</button>
<button
color="primary"
i18n
mat-flat-button
[disabled]="!data.accessToken"
[mat-dialog-close]="data"
>
Sign in
</button>
<div>
<button
color="primary"
i18n
mat-flat-button
[disabled]="!data.accessToken"
[mat-dialog-close]="data"
>
Sign in
</button>
</div>
</div>

@ -8,6 +8,7 @@ import { MatDialogModule } from '@angular/material/dialog';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { GfDialogHeaderModule } from '../dialog-header/dialog-header.module';
import { LoginWithAccessTokenDialog } from './login-with-access-token-dialog.component';
@NgModule({
@ -16,6 +17,7 @@ import { LoginWithAccessTokenDialog } from './login-with-access-token-dialog.com
imports: [
CommonModule,
FormsModule,
GfDialogHeaderModule,
MatButtonModule,
MatCheckboxModule,
MatDialogModule,

@ -1,5 +1,15 @@
:host {
display: block;
textarea.mat-input-element.cdk-textarea-autosize {
box-sizing: content-box;
}
.mat-checkbox {
::ng-deep {
label {
margin-bottom: 0;
}
}
}
}

@ -1,5 +1,14 @@
import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import {
ChangeDetectorRef,
Component,
OnDestroy,
OnInit,
ViewChild
} from '@angular/core';
import {
MatSlideToggle,
MatSlideToggleChange
} from '@angular/material/slide-toggle';
import { DataService } from '@ghostfolio/client/services/data.service';
import { UserService } from '@ghostfolio/client/services/user/user.service';
import { WebAuthnService } from '@ghostfolio/client/services/web-authn.service';
@ -7,8 +16,8 @@ import { DEFAULT_DATE_FORMAT } from '@ghostfolio/common/config';
import { Access, User } from '@ghostfolio/common/interfaces';
import { hasPermission, permissions } from '@ghostfolio/common/permissions';
import { Currency } from '@prisma/client';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { EMPTY, Subject } from 'rxjs';
import { catchError, takeUntil } from 'rxjs/operators';
@Component({
selector: 'gf-account-page',
@ -16,6 +25,9 @@ import { takeUntil } from 'rxjs/operators';
styleUrls: ['./account-page.scss']
})
export class AccountPageComponent implements OnDestroy, OnInit {
@ViewChild('toggleSignInWithFingerprintEnabledElement')
signInWithFingerprintElement: MatSlideToggle;
public accesses: Access[];
public baseCurrency: Currency;
public currencies: Currency[] = [];
@ -30,7 +42,6 @@ export class AccountPageComponent implements OnDestroy, OnInit {
*/
public constructor(
private changeDetectorRef: ChangeDetectorRef,
private dialog: MatDialog,
private dataService: DataService,
private userService: UserService,
public webAuthnService: WebAuthnService
@ -88,21 +99,55 @@ export class AccountPageComponent implements OnDestroy, OnInit {
});
}
public onSignInWithFingerprintChange(aEvent: MatSlideToggleChange) {
if (aEvent.checked) {
this.registerDevice();
} else {
const confirmation = confirm(
'Do you really want to remove this sign in method?'
);
if (confirmation) {
this.deregisterDevice();
} else {
this.update();
}
}
}
public ngOnDestroy() {
this.unsubscribeSubject.next();
this.unsubscribeSubject.complete();
}
public registerDevice() {
private deregisterDevice() {
this.webAuthnService
.register()
.subscribe(() => this.changeDetectorRef.markForCheck());
.deregister()
.pipe(
catchError(() => {
this.update();
return EMPTY;
})
)
.subscribe(() => {
this.update();
});
}
public deregisterDevice() {
private registerDevice() {
this.webAuthnService
.deregister()
.subscribe(() => this.changeDetectorRef.markForCheck());
.register()
.pipe(
catchError(() => {
this.update();
return EMPTY;
})
)
.subscribe(() => {
this.update();
});
}
private update() {
@ -112,6 +157,11 @@ export class AccountPageComponent implements OnDestroy, OnInit {
.subscribe((response) => {
this.accesses = response;
if (this.signInWithFingerprintElement) {
this.signInWithFingerprintElement.checked =
this.webAuthnService.isEnabled() ?? false;
}
this.changeDetectorRef.markForCheck();
});
}

@ -66,29 +66,14 @@
</form>
</div>
</div>
<div class="d-flex mt-4 py-1">
<div class="pt-4 w-50" i18n>Authenticator</div>
<div class="align-items-center d-flex mt-4 py-1">
<div class="w-50" i18n>Sign in with fingerprint</div>
<div class="w-50">
<button
*ngIf="!webAuthnService.isEnabled()"
class="d-inline-block"
color="primary"
i18n
mat-flat-button
(click)="registerDevice()"
>
Setup
</button>
<button
*ngIf="webAuthnService.isEnabled()"
class="d-inline-block"
<mat-slide-toggle
#toggleSignInWithFingerprintEnabledElement
color="primary"
i18n
mat-flat-button
(click)="deregisterDevice()"
>
Remove
</button>
(change)="onSignInWithFingerprintChange($event)"
></mat-slide-toggle>
</div>
</div>
</mat-card-content>

@ -7,6 +7,7 @@ import { MatDialogModule } from '@angular/material/dialog';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { MatSelectModule } from '@angular/material/select';
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
import { GfPortfolioAccessTableModule } from '@ghostfolio/client/components/access-table/access-table.module';
import { AccountPageRoutingModule } from './account-page-routing.module';
@ -26,6 +27,7 @@ import { AccountPageComponent } from './account-page.component';
MatFormFieldModule,
MatInputModule,
MatSelectModule,
MatSlideToggleModule,
ReactiveFormsModule
],
providers: []

@ -36,6 +36,10 @@ export class WebAuthnService {
{}
)
.pipe(
catchError((error) => {
console.warn('Could not register device', error);
return of(null);
}),
switchMap((attOps) => {
return startAttestation(attOps);
}),
@ -59,8 +63,8 @@ export class WebAuthnService {
public deregister() {
const deviceId = this.getDeviceId();
return this.http.delete<AuthDeviceDto>(`/api/auth-device/${deviceId}`).pipe(
catchError((e) => {
console.warn(`Could not deregister device ${deviceId}`, e);
catchError((error) => {
console.warn(`Could not deregister device ${deviceId}`, error);
return of(null);
}),
tap(() =>

Loading…
Cancel
Save