Commit ce55e695 authored by David Burke's avatar David Burke

Added basic registration page

parent c09326f1
Pipeline #36977291 failed with stage
in 2 minutes and 30 seconds
......@@ -11,8 +11,15 @@ import { reducers } from "./account.reducer";
import { SharedModule } from "../shared/shared.module";
import { DirectivesModule } from "../directives";
import { ProgressIndicatorModule } from "../progress-indicator";
import { RegisterComponent } from "./register/register.component";
import { RegisterContainer } from "./register/register.container";
export const COMPONENTS = [LoginContainer, LoginComponent];
export const COMPONENTS = [
LoginContainer,
LoginComponent,
RegisterComponent,
RegisterContainer
];
export const SERVICES = [];
......
This diff is collapsed.
import {
Component,
EventEmitter,
Input,
Output,
ViewChild,
ElementRef
} from "@angular/core";
import { IRegisterForm, IUrlForm } from "~/app/account/register/interfaces";
import { FormGroupState, MarkAsSubmittedAction } from "ngrx-forms";
import { RegisterStages } from "~/app/account/constants";
import { ActionsSubject } from "@ngrx/store";
import { TextFieldComponent } from "../../shared/text-field/text-field.component";
import { FormattedString, Span } from "tns-core-modules/text/formatted-string";
import { SimpleChanges } from "@angular/core";
import { CheckboxComponent } from "../../shared/checkbox/checkbox.component";
@Component({
selector: "register-component",
moduleId: module.id,
templateUrl: "./register.component.html",
styleUrls: ["./register.component.css", "../shared/auth.styles.css"]
})
export class RegisterComponent {
@Input()
errorMessage: string;
@Input()
form: FormGroupState<IRegisterForm>;
@Input()
urlForm: FormGroupState<IUrlForm>;
@Input()
backupCode: string | null;
@Input()
isEmailTaken: boolean;
@Input()
isUrlValid: boolean | undefined;
@Input()
showUrl: string;
@Input()
isExtension: boolean;
@Input()
urlDisplayName: string;
@Input()
hasSubmitStarted: boolean;
@Input()
hasSubmitFinished: boolean;
@Output()
register = new EventEmitter();
@Output()
goToLogin = new EventEmitter<string>();
@Output()
checkEmail = new EventEmitter();
@Output()
checkUrl = new EventEmitter<string>();
@Output()
toggleShowConfirm = new EventEmitter();
@Output()
markAsSubmitted = new EventEmitter();
@Output()
incrementStage = new EventEmitter();
@Output()
switchStage = new EventEmitter<number>();
@Output()
displayUrlInput = new EventEmitter();
@Output()
hideUrlInput = new EventEmitter();
@Output()
setNewsletterSubscribe = new EventEmitter();
@Output()
registrationFinished = new EventEmitter();
_stageValue: number;
passwordFocused = false;
checked: boolean;
stages = RegisterStages;
passwordLengthHintText: FormattedString;
scrollableHeight: number;
@ViewChild("emailInput")
emailInput: TextFieldComponent;
@ViewChild("passwordInput")
passwordInput: TextFieldComponent;
@ViewChild("newsletterInput")
newsletterInput: CheckboxComponent;
@ViewChild("registerScrollView")
registerScrollView: ElementRef;
constructor(private actionsSubject: ActionsSubject) {}
@Input()
set stageValue(value: RegisterStages) {
this._stageValue = value;
setTimeout(() => this.focusNextInput(value));
}
get stageValue(): RegisterStages {
return this._stageValue;
}
focusNextInput(value: RegisterStages) {
switch (value) {
case this.stages.Email:
this.emailInput.focusInput();
return;
case this.stages.Password:
this.passwordInput.focusInput();
return;
case this.stages.Newsletter:
this.newsletterInput.focusInput();
return;
}
}
submit() {
switch (this.stageValue) {
case this.stages.Email:
this.submitEmail();
this.passwordLengthHintText = this.buildPasswordLengthHintText();
return;
case this.stages.Password:
if (!this.form.errors._password && !this.form.errors._passwordConfirm) {
this.incrementStage.emit();
} else if (this.form.isUnsubmitted) {
this.actionsSubject.next(new MarkAsSubmittedAction(this.form.id));
}
return;
case this.stages.Newsletter:
this.setNewsletterSubscribe.emit();
this.submitForm();
return;
case this.stages.Verified:
this.registrationFinished.emit();
return;
}
}
submitEmail() {
if (this.form.controls.email.isValid) {
this.checkEmail.emit();
} else if (this.form.isUnsubmitted) {
this.actionsSubject.next(new MarkAsSubmittedAction(this.form.id));
}
}
urlSubmit() {
if (this.urlForm.isValid) {
this.checkUrl.emit();
} else {
this.actionsSubject.next(new MarkAsSubmittedAction(this.urlForm.id));
}
}
switchCurrentStage(value: number) {
this.switchStage.emit(value);
}
displayUrl() {
this.displayUrlInput.emit();
}
hideUrl() {
this.hideUrlInput.emit();
}
submitForm() {
if (this.form.isValid) {
this.register.emit();
} else {
this.markAsSubmitted.emit();
}
}
toggleDisplay() {
this.goToLogin.emit();
}
goToLoginWith() {
this.goToLogin.emit(this.form.value.email);
}
// https://github.com/NativeScript/nativescript-angular/issues/1119 makes this necessary
ngOnChanges(changes: SimpleChanges) {
if (
changes &&
changes.form &&
changes.form.currentValue &&
changes.form.previousValue
) {
if (
changes.form.currentValue.value.password !==
changes.form.previousValue.value.password
) {
this.passwordLengthHintText = this.buildPasswordLengthHintText();
}
if (
changes.form.currentValue.controls.passwordConfirm &&
changes.form.currentValue.controls.passwordConfirm.isValid &&
changes.form.previousValue.controls.passwordConfirm.isInvalid
) {
setTimeout(() => this.scrollToBottom(), 100);
}
}
}
buildPasswordLengthHintText() {
const formattedString = new FormattedString();
if (this.form.errors._password && this.form.errors._password.minLength) {
const makeA = new Span(),
long = new Span(),
password = new Span(),
characterCount = new Span();
makeA.text = "Make a ";
long.text = "long";
long.fontWeight = "bold";
password.text = " password. ";
if (this.form.value.password.length < 1) {
characterCount.text = "We require at least 10\xa0characters.";
} else if (this.form.value.password.length >= 1) {
characterCount.text = `Enter at least ${this.form.errors._password
.minLength.minLength -
this.form.value.password.length} more\xa0character${
this.form.errors._password.minLength.minLength -
this.form.value.password.length !==
1
? "s"
: ""
}.`;
}
formattedString.spans.push(makeA, long, password, characterCount);
} else if (
this.form.controls.password.isValid ||
!this.form.errors._password.minLength
) {
return null;
}
return formattedString;
}
// Want users to see the text under confirm password
scrollToBottom() {
this.scrollableHeight = this.registerScrollView.nativeElement.scrollableHeight;
this.registerScrollView.nativeElement.scrollToVerticalOffset(
this.registerScrollView.nativeElement.scrollableHeight,
false
);
}
}
.auth-form-body {
padding: 20 25;
}
.auth-actions {
margin: 10 25;
}
.auth-header {
margin-bottom: 30;
}
......@@ -9,13 +9,10 @@ import {
makeSalt,
toBase64,
makeRandomTypableString
} from "simple-asymmetric-js/js/crypto";
import { ILoginResonse } from "passit-sdk-js/js/api.interfaces";
import {
KeyPair,
Password
} from "simple-asymmetric-js/js/asymmetric_encryption";
import { hashPassword } from "passit-sdk-js/js/hash";
} from "../../../simple_asym/crypto";
import { ILoginResonse } from "../../../passit_sdk/api.interfaces";
import { KeyPair, Password } from "../../../simple_asym/asymmetric_encryption";
import { hashPassword } from "../../../passit_sdk/hash";
import { forkJoin, from } from "rxjs";
import { IPassitSDKError } from "../../ngsdk";
......
......@@ -3,6 +3,8 @@ import { NativeScriptRouterModule } from "nativescript-angular/router";
import { Routes } from "@angular/router";
import { LoginContainer } from "./account/login/login.container";
import { RegisterContainer } from "./account/register/register.container";
import { AlreadyLoggedInGuard } from "./guards";
export const routes: Routes = [
{
......@@ -12,7 +14,21 @@ export const routes: Routes = [
},
{
path: "login",
component: LoginContainer
component: LoginContainer,
canActivate: [AlreadyLoggedInGuard],
data: {
title: "Log In",
showNavBar: false
}
},
{
path: "register",
component: RegisterContainer,
canActivate: [AlreadyLoggedInGuard],
data: {
title: "Register",
showNavBar: false
}
}
];
......
......@@ -9,6 +9,7 @@ import { AppRoutingModule } from "./app-routing.module.tns";
import { AppComponent } from "./app.component";
import { AccountModule } from "./account";
import { reducers, metaReducers } from "./app.reducers";
import { AlreadyLoggedInGuard, LoggedInGuard } from "./guards";
// Uncomment and add to NgModule imports if you need to use two-way binding
// import { NativeScriptFormsModule } from 'nativescript-angular/forms';
......@@ -24,7 +25,7 @@ import { reducers, metaReducers } from "./app.reducers";
AccountModule,
StoreModule.forRoot(reducers, { metaReducers })
],
providers: [],
providers: [AlreadyLoggedInGuard, LoggedInGuard],
bootstrap: [AppComponent],
schemas: [NO_ERRORS_SCHEMA]
})
......
......@@ -57,7 +57,6 @@ import { AppDataService } from "./shared/app-data/app-data.service";
import { PopupLoggedInGuard } from "./guards/popup-logged-in.guard";
import { RavenErrorHandler } from "./error-handler";
import { AuthInterceptor } from "./api/auth.interceptor";
import { AutoGeneratedComponent } from "./auto-generated/auto-generated.component";
// Why is this not default ngrx store, why is crashing default?
export interface IRouterStateUrl {
......@@ -85,8 +84,7 @@ export class CustomSerializer
ImporterComponent,
NoContentContainer,
NoContentComponent,
ExporterComponent,
AutoGeneratedComponent
ExporterComponent
],
imports: [
BrowserModule,
......
......@@ -5,7 +5,7 @@ import { Store, select } from "@ngrx/store";
import { getToken, getUrl, IAuthState } from "../account/account.reducer";
import { API_URL } from "../constants";
import sdkAPI, { IHeaders } from "passit-sdk-js/js/api";
import sdkAPI, { IHeaders } from "../../passit_sdk/api";
@Injectable()
export class Api extends sdkAPI {
......
import { Injectable } from "@angular/core";
import PassitSDK from "passit-sdk-js";
import PassitSDK from "../../passit_sdk";
import { Api } from "./api";
import { HttpHeaders, HttpClient } from "@angular/common/http";
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment