mirror of https://github.com/ghostfolio/ghostfolio
				
				
			
							committed by
							
								
								GitHub
							
						
					
				
				 32 changed files with 323 additions and 121 deletions
			
			
		@ -0,0 +1,25 @@ | 
				
			|||||
 | 
					import { CommonModule } from '@angular/common'; | 
				
			||||
 | 
					import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; | 
				
			||||
 | 
					import { MatButtonModule } from '@angular/material/button'; | 
				
			||||
 | 
					import { RouterModule } from '@angular/router'; | 
				
			||||
 | 
					import { GfLineChartModule } from '@ghostfolio/client/components/line-chart/line-chart.module'; | 
				
			||||
 | 
					import { GfLogoModule } from '@ghostfolio/client/components/logo/logo.module'; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					import { LandingPageRoutingModule } from './landing-page-routing.module'; | 
				
			||||
 | 
					import { LandingPageComponent } from './landing-page.component'; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					@NgModule({ | 
				
			||||
 | 
					  declarations: [LandingPageComponent], | 
				
			||||
 | 
					  exports: [], | 
				
			||||
 | 
					  imports: [ | 
				
			||||
 | 
					    CommonModule, | 
				
			||||
 | 
					    GfLineChartModule, | 
				
			||||
 | 
					    GfLogoModule, | 
				
			||||
 | 
					    LandingPageRoutingModule, | 
				
			||||
 | 
					    MatButtonModule, | 
				
			||||
 | 
					    RouterModule | 
				
			||||
 | 
					  ], | 
				
			||||
 | 
					  providers: [], | 
				
			||||
 | 
					  schemas: [CUSTOM_ELEMENTS_SCHEMA] | 
				
			||||
 | 
					}) | 
				
			||||
 | 
					export class LandingPageModule {} | 
				
			||||
@ -0,0 +1,15 @@ | 
				
			|||||
 | 
					import { NgModule } from '@angular/core'; | 
				
			||||
 | 
					import { RouterModule, Routes } from '@angular/router'; | 
				
			||||
 | 
					import { AuthGuard } from '@ghostfolio/client/core/auth.guard'; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					import { RegisterPageComponent } from './register-page.component'; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					const routes: Routes = [ | 
				
			||||
 | 
					  { path: '', component: RegisterPageComponent, canActivate: [AuthGuard] } | 
				
			||||
 | 
					]; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					@NgModule({ | 
				
			||||
 | 
					  imports: [RouterModule.forChild(routes)], | 
				
			||||
 | 
					  exports: [RouterModule] | 
				
			||||
 | 
					}) | 
				
			||||
 | 
					export class RegisterPageRoutingModule {} | 
				
			||||
@ -0,0 +1,98 @@ | 
				
			|||||
 | 
					import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'; | 
				
			||||
 | 
					import { MatDialog } from '@angular/material/dialog'; | 
				
			||||
 | 
					import { Router } from '@angular/router'; | 
				
			||||
 | 
					import { LineChartItem } from '@ghostfolio/client/components/line-chart/interfaces/line-chart.interface'; | 
				
			||||
 | 
					import { DataService } from '@ghostfolio/client/services/data.service'; | 
				
			||||
 | 
					import { TokenStorageService } from '@ghostfolio/client/services/token-storage.service'; | 
				
			||||
 | 
					import { hasPermission, permissions } from '@ghostfolio/common/permissions'; | 
				
			||||
 | 
					import { format } from 'date-fns'; | 
				
			||||
 | 
					import { Subject } from 'rxjs'; | 
				
			||||
 | 
					import { takeUntil } from 'rxjs/operators'; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					import { ShowAccessTokenDialog } from './show-access-token-dialog/show-access-token-dialog.component'; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					@Component({ | 
				
			||||
 | 
					  selector: 'gf-register-page', | 
				
			||||
 | 
					  templateUrl: './register-page.html', | 
				
			||||
 | 
					  styleUrls: ['./register-page.scss'] | 
				
			||||
 | 
					}) | 
				
			||||
 | 
					export class RegisterPageComponent implements OnDestroy, OnInit { | 
				
			||||
 | 
					  public currentYear = format(new Date(), 'yyyy'); | 
				
			||||
 | 
					  public demoAuthToken: string; | 
				
			||||
 | 
					  public hasPermissionForSocialLogin: boolean; | 
				
			||||
 | 
					  public historicalDataItems: LineChartItem[]; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					  private unsubscribeSubject = new Subject<void>(); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					  /** | 
				
			||||
 | 
					   * @constructor | 
				
			||||
 | 
					   */ | 
				
			||||
 | 
					  public constructor( | 
				
			||||
 | 
					    private changeDetectorRef: ChangeDetectorRef, | 
				
			||||
 | 
					    private dataService: DataService, | 
				
			||||
 | 
					    private dialog: MatDialog, | 
				
			||||
 | 
					    private router: Router, | 
				
			||||
 | 
					    private tokenStorageService: TokenStorageService | 
				
			||||
 | 
					  ) { | 
				
			||||
 | 
					    this.tokenStorageService.signOut(); | 
				
			||||
 | 
					  } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					  /** | 
				
			||||
 | 
					   * Initializes the controller | 
				
			||||
 | 
					   */ | 
				
			||||
 | 
					  public ngOnInit() { | 
				
			||||
 | 
					    this.dataService | 
				
			||||
 | 
					      .fetchInfo() | 
				
			||||
 | 
					      .subscribe(({ demoAuthToken, globalPermissions }) => { | 
				
			||||
 | 
					        this.demoAuthToken = demoAuthToken; | 
				
			||||
 | 
					        this.hasPermissionForSocialLogin = hasPermission( | 
				
			||||
 | 
					          globalPermissions, | 
				
			||||
 | 
					          permissions.enableSocialLogin | 
				
			||||
 | 
					        ); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					        this.changeDetectorRef.markForCheck(); | 
				
			||||
 | 
					      }); | 
				
			||||
 | 
					  } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					  public async createAccount() { | 
				
			||||
 | 
					    this.dataService | 
				
			||||
 | 
					      .postUser() | 
				
			||||
 | 
					      .pipe(takeUntil(this.unsubscribeSubject)) | 
				
			||||
 | 
					      .subscribe(({ accessToken, authToken }) => { | 
				
			||||
 | 
					        this.openShowAccessTokenDialog(accessToken, authToken); | 
				
			||||
 | 
					      }); | 
				
			||||
 | 
					  } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					  public openShowAccessTokenDialog( | 
				
			||||
 | 
					    accessToken: string, | 
				
			||||
 | 
					    authToken: string | 
				
			||||
 | 
					  ): void { | 
				
			||||
 | 
					    const dialogRef = this.dialog.open(ShowAccessTokenDialog, { | 
				
			||||
 | 
					      data: { | 
				
			||||
 | 
					        accessToken, | 
				
			||||
 | 
					        authToken | 
				
			||||
 | 
					      }, | 
				
			||||
 | 
					      disableClose: true, | 
				
			||||
 | 
					      width: '30rem' | 
				
			||||
 | 
					    }); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    dialogRef.afterClosed().subscribe((data) => { | 
				
			||||
 | 
					      if (data?.authToken) { | 
				
			||||
 | 
					        this.tokenStorageService.saveToken(authToken); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					        this.router.navigate(['/']); | 
				
			||||
 | 
					      } | 
				
			||||
 | 
					    }); | 
				
			||||
 | 
					  } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					  public setToken(aToken: string) { | 
				
			||||
 | 
					    this.tokenStorageService.saveToken(aToken); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					    this.router.navigate(['/']); | 
				
			||||
 | 
					  } | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					  public ngOnDestroy() { | 
				
			||||
 | 
					    this.unsubscribeSubject.next(); | 
				
			||||
 | 
					    this.unsubscribeSubject.complete(); | 
				
			||||
 | 
					  } | 
				
			||||
 | 
					} | 
				
			||||
@ -0,0 +1,30 @@ | 
				
			|||||
 | 
					<div class="container"> | 
				
			||||
 | 
					  <div class="row"> | 
				
			||||
 | 
					    <div class="col"> | 
				
			||||
 | 
					      <h3 class="d-flex justify-content-center mb-3 text-center" i18n> | 
				
			||||
 | 
					        Create your Ghostfolio account | 
				
			||||
 | 
					      </h3> | 
				
			||||
 | 
					      <mat-card class="mb-4"> | 
				
			||||
 | 
					        <mat-card-content class="text-center"> | 
				
			||||
 | 
					          <button | 
				
			||||
 | 
					            class="d-inline-block" | 
				
			||||
 | 
					            color="primary" | 
				
			||||
 | 
					            i18n | 
				
			||||
 | 
					            mat-flat-button | 
				
			||||
 | 
					            [disabled]="!demoAuthToken" | 
				
			||||
 | 
					            (click)="createAccount()" | 
				
			||||
 | 
					          > | 
				
			||||
 | 
					            Create Account | 
				
			||||
 | 
					          </button> | 
				
			||||
 | 
					          <ng-container *ngIf="hasPermissionForSocialLogin"> | 
				
			||||
 | 
					            <div class="my-3 text-muted" i18n>or</div> | 
				
			||||
 | 
					            <a color="accent" href="/api/auth/google" mat-flat-button | 
				
			||||
 | 
					              ><ion-icon class="mr-1" name="logo-google"></ion-icon | 
				
			||||
 | 
					              ><span i18n>Continue with Google</span></a | 
				
			||||
 | 
					            > | 
				
			||||
 | 
					          </ng-container> | 
				
			||||
 | 
					        </mat-card-content> | 
				
			||||
 | 
					      </mat-card> | 
				
			||||
 | 
					    </div> | 
				
			||||
 | 
					  </div> | 
				
			||||
 | 
					</div> | 
				
			||||
@ -1,27 +1,27 @@ | 
				
			|||||
import { CommonModule } from '@angular/common'; | 
					import { CommonModule } from '@angular/common'; | 
				
			||||
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; | 
					import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; | 
				
			||||
import { MatButtonModule } from '@angular/material/button'; | 
					import { MatButtonModule } from '@angular/material/button'; | 
				
			||||
 | 
					import { MatCardModule } from '@angular/material/card'; | 
				
			||||
import { RouterModule } from '@angular/router'; | 
					import { RouterModule } from '@angular/router'; | 
				
			||||
import { GfLineChartModule } from '@ghostfolio/client/components/line-chart/line-chart.module'; | 
					 | 
				
			||||
import { GfLogoModule } from '@ghostfolio/client/components/logo/logo.module'; | 
					import { GfLogoModule } from '@ghostfolio/client/components/logo/logo.module'; | 
				
			||||
 | 
					
 | 
				
			||||
import { LoginPageRoutingModule } from './login-page-routing.module'; | 
					import { RegisterPageRoutingModule } from './register-page-routing.module'; | 
				
			||||
import { LoginPageComponent } from './login-page.component'; | 
					import { RegisterPageComponent } from './register-page.component'; | 
				
			||||
import { ShowAccessTokenDialogModule } from './show-access-token-dialog/show-access-token-dialog.module'; | 
					import { ShowAccessTokenDialogModule } from './show-access-token-dialog/show-access-token-dialog.module'; | 
				
			||||
 | 
					
 | 
				
			||||
@NgModule({ | 
					@NgModule({ | 
				
			||||
  declarations: [LoginPageComponent], | 
					  declarations: [RegisterPageComponent], | 
				
			||||
  exports: [], | 
					  exports: [], | 
				
			||||
  imports: [ | 
					  imports: [ | 
				
			||||
    CommonModule, | 
					    CommonModule, | 
				
			||||
    GfLineChartModule, | 
					 | 
				
			||||
    GfLogoModule, | 
					    GfLogoModule, | 
				
			||||
    LoginPageRoutingModule, | 
					 | 
				
			||||
    MatButtonModule, | 
					    MatButtonModule, | 
				
			||||
 | 
					    MatCardModule, | 
				
			||||
 | 
					    RegisterPageRoutingModule, | 
				
			||||
    RouterModule, | 
					    RouterModule, | 
				
			||||
    ShowAccessTokenDialogModule | 
					    ShowAccessTokenDialogModule | 
				
			||||
  ], | 
					  ], | 
				
			||||
  providers: [], | 
					  providers: [], | 
				
			||||
  schemas: [CUSTOM_ELEMENTS_SCHEMA] | 
					  schemas: [CUSTOM_ELEMENTS_SCHEMA] | 
				
			||||
}) | 
					}) | 
				
			||||
export class LoginPageModule {} | 
					export class RegisterPageModule {} | 
				
			||||
@ -0,0 +1,3 @@ | 
				
			|||||
 | 
					:host { | 
				
			||||
 | 
					  display: block; | 
				
			||||
 | 
					} | 
				
			||||
@ -1,5 +1,5 @@ | 
				
			|||||
import { ClipboardModule } from '@angular/cdk/clipboard'; | 
					import { ClipboardModule } from '@angular/cdk/clipboard'; | 
				
			||||
import { CdkTextareaAutosize, TextFieldModule } from '@angular/cdk/text-field'; | 
					import { TextFieldModule } from '@angular/cdk/text-field'; | 
				
			||||
import { CommonModule } from '@angular/common'; | 
					import { CommonModule } from '@angular/common'; | 
				
			||||
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; | 
					import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; | 
				
			||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms'; | 
					import { FormsModule, ReactiveFormsModule } from '@angular/forms'; | 
				
			||||
					Loading…
					
					
				
		Reference in new issue