Commit 6572aafc authored by Brendan's avatar Brendan

Attempt to add NS new secret form into monorepo

parent ddb74e64
Pipeline #37417439 passed with stage
in 8 minutes and 19 seconds
......@@ -12372,6 +12372,11 @@
"resolved": "https://registry.npmjs.org/nativescript-appversion/-/nativescript-appversion-1.4.1.tgz",
"integrity": "sha1-OpAo4zx35VVTlhk9KLweerdmG40="
},
"nativescript-clipboard": {
"version": "1.1.7",
"resolved": "https://registry.npmjs.org/nativescript-clipboard/-/nativescript-clipboard-1.1.7.tgz",
"integrity": "sha1-luFJvzkR71pJib8V0cOFaXw+tXE="
},
"nativescript-dev-webpack": {
"version": "0.17.0",
"resolved": "https://registry.npmjs.org/nativescript-dev-webpack/-/nativescript-dev-webpack-0.17.0.tgz",
......
......@@ -11,7 +11,7 @@ import { FormGroupState } from "ngrx-forms";
@Component({
selector: "login-component",
styleUrls: ["../account.component.scss"],
styleUrls: ["../account.component.scss", "../shared/auth.styles.css"],
templateUrl: "./login.component.html",
changeDetection: ChangeDetectionStrategy.OnPush
})
......
......@@ -5,6 +5,7 @@ import { Routes } from "@angular/router";
import { LoginContainer } from "./account/login/login.container";
import { RegisterContainer } from "./account/register/register.container";
import { SecretListContainer } from "./list/list.container";
import { SecretNewComponent } from "./list/new.component.tns";
import { AlreadyLoggedInGuard, LoggedInGuard } from "./guards";
export const routes: Routes = [
......@@ -35,7 +36,12 @@ export const routes: Routes = [
path: "list",
component: SecretListContainer,
canActivate: [LoggedInGuard]
}
},
{
path: "list/new",
component: SecretNewComponent,
canActivate: [LoggedInGuard],
},
];
@NgModule({
......
......@@ -9,8 +9,18 @@ import { reducers } from "./list.reducer";
import { SecretFormEffects } from "./secret-form/secret-form.effects";
import { SecretListContainer } from "./list.container";
import { SecretListComponent } from "./list.component";
import { SecretNewComponent } from "./new.component.tns";
import { SecretFormContainer } from "./secret-form/secret-form.container";
import { SecretFormComponent } from "./secret-form/secret-form.component";
export const COMPONENTS = [SecretListContainer, SecretListComponent];
export const COMPONENTS = [
SecretListContainer,
SecretListComponent,
SecretNewComponent,
SecretFormContainer,
SecretFormComponent,
];
@NgModule({
declarations: [COMPONENTS],
......
import { Component } from "@angular/core";
/** This is only used in phone layouts
* It doesn't follow the general smart/dumb component split because
* there is no web version of this - so we just combine it.
*/
@Component({
selector: "secret-new-component",
moduleId: module.id,
template: `
<ns-action-bar-container
title="Add New Password"
></ns-action-bar-container>
<StackLayout>
<secret-form-container isNew="true"></secret-form-container>
</StackLayout>
`,
})
export class SecretNewComponent {
constructor(
) {}
}
import { DeviceType } from "tns-core-modules/ui/enums";
import { device } from "tns-core-modules/platform";
export const IS_TABLET = device.deviceType === DeviceType.Tablet;
<ScrollView>
<FlexboxLayout class="detailPage">
<StackLayout class="form">
<Label class="formLabel" text="Name"></Label>
<TextField [ngrxFormControlState]="form.controls.name" height="60" class="input input-border m-b-10"></TextField>
<Label text="URL"></Label>
<StackLayout orientation="horizontal" height="60" class="input input-border m-b-10">
<TextField [ngrxFormControlState]="form.controls.url" class="detailInput urlInput"></TextField>
<Button width="40" *ngIf="!isNew && form.value.url" (tap)="goToUrl()" class="url-button"></Button>
</StackLayout>
<Label text="Username"></Label>
<StackLayout orientation="horizontal" height="60" class="input input-border m-b-10">
<TextField [ngrxFormControlState]="form.controls.username"
[class.userInputNew]="isNew"
[class.tabletUserInput]="isTablet"
[class.userInput]="!isNew && !isTablet"
class="detailInput"
></TextField>
<Button *ngIf="!isNew" width="40" (tap)="copyUsername()" class="{{ usernameCopied ? 'copied-button' : 'copy-button' }} icons"></Button>
</StackLayout>
<Label text="Password"></Label>
<StackLayout orientation="horizontal" height="60" class="input input-border m-b-10" *ngIf="!isNew && passwordIsMasked">
<TextField
[ngrxFormControlState]="form.controls.password"
secure="true"
(focus)="clickMaskedSecret()"
[class.tabletPasswordInput]="isTablet"
[class.passwordInput]="!isTablet"
class="detailInput"
></TextField>
<FlexboxLayout width="30%">
<Button class="icons eye-button" (tap)="togglePasswordIsMasked.emit()"></Button>
<Button class="icons {{ passwordCopied ? 'copied-button' : 'copy-button' }}" (tap)="copyPassword()"></Button>
</FlexboxLayout>
</StackLayout>
<StackLayout orientation="horizontal" height="60" class="input input-border m-b-10" *ngIf="isNew || !passwordIsMasked">
<TextField
#realPasswordInput
[ngrxFormControlState]="form.controls.password"
[class.newPasswordInput]="isNew"
[class.tabletPasswordInput]="isTablet"
[class.passwordInput]="!isNew && !isTablet"
class="detailInput"
></TextField>
<FlexboxLayout width="30%">
<Button *ngIf="!isNew" class="icons eye-slash-button" (tap)="togglePasswordIsMasked.emit()"></Button>
<Button *ngIf="!isNew" class="{{ passwordCopied ? 'copied-button' : 'copy-button' }} icons" (tap)="copyPassword()"></Button>
</FlexboxLayout>
<Button *ngIf="isNew" (tap)="generatePassword.emit()" class="dice">
<Span style="font-size:38px;" text="&#x2682;"></Span>
</Button>
</StackLayout>
<Label *ngIf="!showNotes" text="Add Notes" (tap)="toggleShowNotes.emit()" class="m-b-10"></Label>
<Label *ngIf="showNotes" text="Notes" (tap)="toggleShowNotes.emit()"></Label>
<TextView *ngIf="showNotes" [ngrxFormControlState]="form.controls.notes" height="100" class="input input-border m-b-10"></TextView>
<Label text="Saved!" class="saved-confirm" *ngIf="isUpdated"></Label>
<Button class="submit-button" [text]="'save'" (tap)="onSubmit()"></Button>
<Button *ngIf="!isNew" text="delete" (tap)="onDeleteSecret()"></Button>
</StackLayout>
</FlexboxLayout>
</ScrollView>
import {
Component,
ChangeDetectorRef,
Input,
Output,
EventEmitter,
ViewChild,
ElementRef
} from "@angular/core";
import * as Clipboard from "nativescript-clipboard";
import * as api from "../../../passit_sdk/api.interfaces";
import { FormGroupState } from "ngrx-forms";
import { ISecretForm } from "./secret-form.reducer";
import { IS_TABLET } from "./constants.tns";
import * as utils from "tns-core-modules/utils/utils";
interface ISelectOptions {
label: string;
value: any;
}
@Component({
selector: "secret-form-component",
moduleId: module.id,
templateUrl: "./secret-form.component.html"
})
export class SecretFormComponent {
@Input() form: FormGroupState<ISecretForm>;
@Input() isNew: boolean;
@Input() isUpdating: boolean;
@Input() isUpdated: boolean;
@Input() passwordIsMasked: boolean;
@Input() showNotes: boolean;
@Input() usernameCopied: boolean;
@Input() passwordCopied: boolean;
@Output() togglePasswordIsMasked = new EventEmitter();
@Output() setPasswordIsMasked = new EventEmitter<boolean>();
@Output() toggleShowNotes = new EventEmitter();
@Output() hideAddSecretForm = new EventEmitter();
@Output() saveSecret = new EventEmitter<boolean>();
@Output() deleteSecret = new EventEmitter();
@Output() generatePassword = new EventEmitter();
@Output() cancel = new EventEmitter();
isTablet = IS_TABLET;
groupOptions: ISelectOptions[] = [];
@Input()
set groups(groups: api.IGroup[]) {
this.groupOptions = groups.map(group => {
return {
label: group.name,
value: group.id
};
});
}
@ViewChild("realPasswordInput") realPasswordInput: ElementRef;
constructor(private cd: ChangeDetectorRef) {}
onSubmit() {
if (this.form.isValid) {
this.saveSecret.emit(this.isNew);
}
}
clickMaskedSecret() {
this.togglePasswordIsMasked.emit();
setTimeout(() => this.realPasswordInput.nativeElement.focus(), 0);
}
toggleViewSecret() {
this.togglePasswordIsMasked.emit();
setTimeout(() => this.realPasswordInput.nativeElement.focus(), 0);
}
togglePassword() {
this.togglePasswordIsMasked.emit();
}
onDeleteSecret() {
const confirmOptions: any = {
title: "Delete " + this.form.value.name + "?",
message: "Once it's deleted, it's gone forever. Is that ok?",
okButtonText: "Delete",
cancelButtonText: "Cancel"
};
(confirm(confirmOptions) as any).then((result: any) => {
if (result) {
this.deleteSecret.emit();
}
});
}
copyUsername() {
Clipboard.setText(this.form.value.username).then(() =>
this.triggerCopied("username")
);
}
copyPassword() {
Clipboard.setText(this.form.value.password).then(() =>
this.triggerCopied("password")
);
}
realPasswordBlur() {
this.setPasswordIsMasked.emit(true);
}
goToUrl() {
let url = this.form.value.url;
if (!url.match(/^https?:\/\//)) {
url = "http://" + url;
}
utils.openUrl(url);
}
triggerCopied(field: string) {
if (field === "username") {
this.usernameCopied = true;
setTimeout(() => {
this.usernameCopied = false;
this.cd.markForCheck();
}, 2000);
}
if (field === "password") {
this.passwordCopied = true;
setTimeout(() => {
this.passwordCopied = false;
this.cd.markForCheck();
}, 2000);
}
}
}
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