Commit a7c502f5 authored by David Burke's avatar David Burke

Added back mobile search

parent 8af33ecb
Pipeline #37839767 failed with stages
in 2 minutes and 55 seconds
......@@ -28,6 +28,12 @@ import { ConfirmEmailGuard } from "./confirm-email/confirm-email.guard";
import { BackupCodeComponent } from "./backup-code/backup-code.component";
import { BackupCodePdfService } from "./backup-code-pdf.service";
import { ConfirmEmailComponent, ConfirmEmailContainer } from "./confirm-email";
import { ErrorReportingComponent } from "./error-reporting/error-reporting.component";
import { ErrorReportingContainer } from "./error-reporting/error-reporting.container";
import {
ChangePasswordComponent,
ChangePasswordContainer
} from "./change-password";
export const COMPONENTS = [
LoginContainer,
......@@ -36,7 +42,11 @@ export const COMPONENTS = [
RegisterContainer,
ConfirmEmailComponent,
ConfirmEmailContainer,
BackupCodeComponent
BackupCodeComponent,
ChangePasswordComponent,
ChangePasswordContainer,
ErrorReportingComponent,
ErrorReportingContainer
];
export const SERVICES = [BackupCodePdfService, UserService, ConfirmEmailGuard];
......
<ns-action-bar-container></ns-action-bar-container>
<GridLayout>
<FlexboxLayount class="page">
<StackLayout orientation="vertical" class="form">
<Label text="Change Account Password"></Label>
<Label [text]="nonFieldErrors"></Label>
<app-non-field-messages [messages]="nonFieldErrors"></app-non-field-messages>
<TextField
[ngrxFormControlState]="form.controls.oldPassword"
hint="Current Password"
autocorrect="false"
autocapitalizationType="none"
secure="true"
></TextField>
<TextField
[ngrxFormControlState]="form.controls.newPassword"
hint="New Password"
autocorrect="false"
autocapitalizationType="none"
secure="true"
></TextField>
<TextField
[ngrxFormControlState]="form.controls.newPasswordConfirm"
hint="New Password (Confirm)"
autocorrect="false"
autocapitalizationType="none"
secure="true"
returnKeyType="done"
(returnPress)="onSubmit()"
></TextField>
<StackLayout class="p-b-10" *ngIf="form.isInvalid && form.isSubmitted && form.errors._newPassword">
<Label *ngIf="form.errors._newPassword.required" text="You must have a password!"></Label>
<Label
*ngIf="form.errors._newPassword.minLength"
text="Password must be at least {{ form.errors._newPassword.minLength.minLength }} characters long!!"
></Label>
<Label
*ngIf="form.errors._newPassword.hasUniqueChars"
text="Password must have more than 5 unique characters."
></Label>
<Label
*ngIf="form.errors._newPassword.notNumeric"
text="Password must not be only numbers."
></Label>
<Label
*ngIf="form.errors._newPassword.notEqualTo"
text="New password is the same as the old password."
></Label>
</StackLayout>
<StackLayout class="p-b-10" *ngIf="form.isInvalid && form.isSubmitted && form.errors._newPasswordConfirm">
<Label
*ngIf="form.errors._newPasswordConfirm.equalTo && form.controls.showConfirm.value"
text="Passwords don't match."
></Label>
</StackLayout>
<Button
class="submit-button"
text="Change Password"
(tap)="onSubmit()"
></Button>
</StackLayout>
</FlexboxLayount>
</GridLayout>
import { Component, EventEmitter, Input, Output } from "@angular/core";
import { FormGroupState, MarkAsSubmittedAction } from "ngrx-forms";
import { ActionsSubject } from "@ngrx/store";
import { IChangePasswordForm } from "../change-password/change-password.reducer";
@Component({
selector: "change-password",
moduleId: module.id,
templateUrl: "./change-password.component.html"
})
export class ChangePasswordComponent {
@Input() form: FormGroupState<IChangePasswordForm>;
@Input() hasStarted: boolean;
@Input() hasFinished: boolean;
@Input() nonFieldErrors: string[];
@Output() changePassword = new EventEmitter();
@Output() toggleConfirm = new EventEmitter();
constructor(private actionsSubject: ActionsSubject) {}
onSubmit() {
if (this.form.isValid) {
this.changePassword.emit();
} else if (this.form.isUnsubmitted) {
this.actionsSubject.next(new MarkAsSubmittedAction(this.form.id));
}
}
}
<ns-action-bar-container></ns-action-bar-container>
<DockLayout stretchLastChild="true">
<FlexboxLayout dock="bottom" class="m-x-10 m-y-25" flexDirection="row" justifyContent="flex-end">
<app-button
text="Save"
(tap)="submit.emit()"
></app-button>
</FlexboxLayout>
<ScrollView>
<StackLayout class="p-x-20 p-y-25">
<StackLayout class="m-b-30">
<app-heading text="Error Reporting"></app-heading>
</StackLayout>
<Label
class="text-label m-b-10"
text="For your safety and privacy, Passit has no in-app tracking by default. However, the Passit developers benefit from receiving error reports, which requires this sort of&nbsp;tracking."
textWrap="true"
></Label>
<Label
class="text-label m-b-20"
text="If you are willing to opt in to share anonymous information, please do! It will help make Passit better for&nbsp;everyone."
textWrap="true"
></Label>
<app-checkbox
title="Enable error reporting"
[control]="form.controls.optInErrorReporting"
></app-checkbox>
</StackLayout>
</ScrollView>
</DockLayout>
......@@ -10,6 +10,8 @@ import { SecretNewComponent } from "./list/new.component.tns";
import { AlreadyLoggedInGuard, LoggedInGuard } from "./guards";
import { ConfirmEmailContainer } from "./account/confirm-email";
import { ConfirmEmailGuard } from "./account/confirm-email/confirm-email.guard";
import { ErrorReportingContainer } from "./account/error-reporting/error-reporting.container";
import { ChangePasswordContainer } from "./account/change-password";
export const routes: Routes = [
{
......@@ -35,6 +37,22 @@ export const routes: Routes = [
showNavBar: false
}
},
{
path: "account/error-reporting",
component: ErrorReportingContainer,
canActivate: [LoggedInGuard],
data: {
title: "Error Reporting"
}
},
{
path: "account/change-password",
component: ChangePasswordContainer,
canActivate: [LoggedInGuard],
data: {
title: "Change Account Password"
}
},
{
path: "confirm-email",
component: ConfirmEmailContainer,
......
<ActionBar class="action-bar" title="Passit">
<NavigationButton
(tap)="menuTap.emit()"
icon="res://ic_menu_white_24dp"
></NavigationButton>
<GridLayout class="search" *ngIf="showSearch" columns="*, 20">
<TextField
#searchBar
id="searchBar"
(textChange)="onSearchChange($event)"
></TextField>
</GridLayout>
<ActionItem *ngIf="showSearch"
(tap)="onClearSearchTap()"
icon="res://ic_close_white_24dp"
></ActionItem>
<ActionItem *ngIf="!showSearch"
(tap)="onSearchTap()"
icon="res://ic_search_white_24dp"
></ActionItem>
</ActionBar>
import {
Component,
Input,
Output,
EventEmitter,
ViewChild,
ElementRef
} from "@angular/core";
import { TextField } from "ui/text-field";
@Component({
selector: "ns-list-action-bar-component",
moduleId: module.id,
templateUrl: "./action-bar.component.html"
})
export class ListActionBarComponent {
@Input() showSearch: boolean;
@Output() menuTap = new EventEmitter();
@Output() searchTap = new EventEmitter();
@Output() search = new EventEmitter<string>();
@Output() clearSearch = new EventEmitter();
@ViewChild("searchBar") searchBar: ElementRef;
public onSearchChange(args: any) {
let textField = <TextField>args.object;
this.search.emit(textField.text);
}
public onClearSearchTap() {
this.clearSearch.emit();
}
public onSearchTap() {
this.searchTap.emit();
setTimeout(() => {
let searchElement: TextField = this.searchBar.nativeElement;
searchElement.focus();
}, 200);
}
constructor() {}
}
import { Component } from "@angular/core";
import { Store } from "@ngrx/store";
import * as fromRoot from "../../app.reducers";
import { ToggleMenu } from "../../mobile-menu/mobile-menu.actions";
import { SetSearchText } from "../../list/list.actions";
@Component({
selector: "ns-list-action-bar-container",
moduleId: module.id,
template: `
<ns-list-action-bar-component
[showSearch]="showSearch"
(menuTap)="menuTap()"
(searchTap)="searchTap()"
(search)="search($event)"
(clearSearch)="clearSearch()"
></ns-list-action-bar-component>
`
})
export class ListActionBarContainer {
showSearch = false;
constructor(private store: Store<fromRoot.IState>) {}
menuTap() {
this.store.dispatch(new ToggleMenu());
}
searchTap() {
this.showSearch = !this.showSearch;
}
search(term: string) {
this.store.dispatch(new SetSearchText(term));
}
clearSearch() {
this.showSearch = false;
this.store.dispatch(new SetSearchText(""));
}
}
export { ListActionBarContainer } from "./action-bar.container";
export { ListActionBarComponent } from "./action-bar.component";
\ No newline at end of file
......@@ -11,9 +11,11 @@ import { SecretListContainer } from "./list.container";
import { SecretListComponent } from "./list.component";
import { SecretDetailComponent } from "./detail.component";
import { SecretNewComponent } from "./new.component.tns";
import { ListActionBarContainer, ListActionBarComponent } from "./actionbar";
import { SecretFormContainer } from "./secret-form/secret-form.container";
import { SecretFormComponent } from "./secret-form/secret-form.component";
import { DirectivesModule } from "../directives";
import { TNSSecretFormEffects } from "./secret-form/tns-secret-form.effects";
export const COMPONENTS = [
SecretListContainer,
......@@ -21,7 +23,9 @@ export const COMPONENTS = [
SecretNewComponent,
SecretFormContainer,
SecretFormComponent,
SecretDetailComponent
SecretDetailComponent,
ListActionBarContainer,
ListActionBarComponent
];
@NgModule({
......@@ -32,7 +36,7 @@ export const COMPONENTS = [
SharedModule,
DirectivesModule,
StoreModule.forFeature("list", reducers),
EffectsModule.forFeature([SecretFormEffects])
EffectsModule.forFeature([SecretFormEffects, TNSSecretFormEffects])
],
schemas: [NO_ERRORS_SCHEMA]
})
......
import { Injectable } from "@angular/core";
import { Effect, Actions, ofType } from "@ngrx/effects";
import { DeviceType } from "ui/enums";
import { device } from "platform";
import { Router } from "@angular/router";
import { tap, filter } from "rxjs/operators";
import {
RemoveSecretAction,
SecretActionTypes
} from "../../secrets/secret.actions";
export const IS_TABLET = device.deviceType === DeviceType.Tablet;
@Injectable()
export class TNSSecretFormEffects {
@Effect({ dispatch: false })
removeSecret$ = this.actions$.pipe(
ofType<RemoveSecretAction>(SecretActionTypes.REMOVE_SECRET),
filter(action => !IS_TABLET),
tap(() => this.router.navigate(["/list"]))
);
constructor(private actions$: Actions, private router: Router) {}
}
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