combine edit into add/edit component

This commit is contained in:
Kyle Spearrin 2018-01-26 14:56:54 -05:00
parent 298b12bf0d
commit eee5f6ff32
11 changed files with 94 additions and 110 deletions

View File

@ -10,10 +10,9 @@ import { NgModule } from '@angular/core';
import { ServicesModule } from './services/services.module'; import { ServicesModule } from './services/services.module';
import { ToasterModule } from 'angular2-toaster'; import { ToasterModule } from 'angular2-toaster';
import { AddComponent } from './vault/add.component'; import { AddEditComponent } from './vault/add-edit.component';
import { AppComponent } from './app.component'; import { AppComponent } from './app.component';
import { CiphersComponent } from './vault/ciphers.component'; import { CiphersComponent } from './vault/ciphers.component';
import { EditComponent } from './vault/edit.component';
import { FallbackSrcDirective } from './directives/fallback-src.directive'; import { FallbackSrcDirective } from './directives/fallback-src.directive';
import { GroupingsComponent } from './vault/groupings.component'; import { GroupingsComponent } from './vault/groupings.component';
import { I18nPipe } from './pipes/i18n.pipe'; import { I18nPipe } from './pipes/i18n.pipe';
@ -38,10 +37,9 @@ import { ViewComponent } from './vault/view.component';
ToasterModule, ToasterModule,
], ],
declarations: [ declarations: [
AddComponent, AddEditComponent,
AppComponent, AppComponent,
CiphersComponent, CiphersComponent,
EditComponent,
FallbackSrcDirective, FallbackSrcDirective,
GroupingsComponent, GroupingsComponent,
I18nPipe, I18nPipe,

View File

@ -5,7 +5,7 @@
{{'itemInformation' | i18n}} {{'itemInformation' | i18n}}
</div> </div>
<div class="box-content"> <div class="box-content">
<div class="box-content-row"> <div class="box-content-row" *ngIf="!editMode">
<label for="type">{{'type' | i18n}}</label> <label for="type">{{'type' | i18n}}</label>
<select id="type" name="Type" [(ngModel)]="cipher.type"> <select id="type" name="Type" [(ngModel)]="cipher.type">
<option *ngFor="let o of typeOptions" [ngValue]="o.value">{{o.name}}</option> <option *ngFor="let o of typeOptions" [ngValue]="o.value">{{o.name}}</option>
@ -176,6 +176,10 @@
<label for="favorite">{{'favorite' | i18n}}</label> <label for="favorite">{{'favorite' | i18n}}</label>
<input id="favorite" type="checkbox" name="Favorite" [(ngModel)]="cipher.favorite"> <input id="favorite" type="checkbox" name="Favorite" [(ngModel)]="cipher.favorite">
</div> </div>
<a class="box-content-row" href="#" appStopClick (click)="attachments()" *ngIf="editMode">
{{'attachments' | i18n}}
<i class="fa fa-chevron-right icon-right"></i>
</a>
</div> </div>
</div> </div>
<div class="box"> <div class="box">
@ -233,7 +237,7 @@
<button (click)="cancel()" title="{{'cancel' | i18n}}"> <button (click)="cancel()" title="{{'cancel' | i18n}}">
{{'cancel' | i18n}} {{'cancel' | i18n}}
</button> </button>
<button (click)="delete()" class="danger right" title="{{'delete' | i18n}}"> <button (click)="delete()" class="danger right" title="{{'delete' | i18n}}" *ngIf="editMode">
<i class="fa fa-trash-o fa-lg"></i> <i class="fa fa-trash-o fa-lg"></i>
</button> </button>
</div> </div>

View File

@ -1,9 +1,11 @@
import * as template from './add.component.html'; import * as template from './add-edit.component.html';
import { import {
Component, Component,
EventEmitter,
Input, Input,
OnChanges, OnChanges,
Output,
} from '@angular/core'; } from '@angular/core';
import { Angulartics2 } from 'angulartics2'; import { Angulartics2 } from 'angulartics2';
@ -27,11 +29,17 @@ import { LoginView } from 'jslib/models/view/loginView';
import { SecureNoteView } from 'jslib/models/view/secureNoteView'; import { SecureNoteView } from 'jslib/models/view/secureNoteView';
@Component({ @Component({
selector: 'app-vault-add', selector: 'app-vault-add-edit',
template: template, template: template,
}) })
export class AddComponent implements OnChanges { export class AddEditComponent implements OnChanges {
@Input() folderId: string; @Input() folderId: string;
@Input() cipherId: string;
@Output() onSavedCipher = new EventEmitter<CipherView>();
@Output() onCancelled = new EventEmitter<CipherView>();
@Output() onEditAttachments = new EventEmitter<CipherView>();
editMode: boolean = false;
cipher: CipherView; cipher: CipherView;
folders: FolderView[]; folders: FolderView[];
cipherType = CipherType; cipherType = CipherType;
@ -94,14 +102,22 @@ export class AddComponent implements OnChanges {
} }
async ngOnChanges() { async ngOnChanges() {
this.cipher = new CipherView(); this.editMode = this.cipherId != null;
this.cipher.folderId = null; // TODO
this.cipher.type = CipherType.Login; if (this.editMode) {
this.cipher.login = new LoginView(); this.editMode = true;
this.cipher.card = new CardView(); const cipher = await this.cipherService.get(this.cipherId);
this.cipher.identity = new IdentityView(); this.cipher = await cipher.decrypt();
this.cipher.secureNote = new SecureNoteView(); } else {
this.cipher.secureNote.type = SecureNoteType.Generic; this.cipher = new CipherView();
this.cipher.folderId = null; // TODO
this.cipher.type = CipherType.Login;
this.cipher.login = new LoginView();
this.cipher.card = new CardView();
this.cipher.identity = new IdentityView();
this.cipher.secureNote = new SecureNoteView();
this.cipher.secureNote.type = SecureNoteType.Generic;
}
this.folders = await this.folderService.getAllDecrypted(); this.folders = await this.folderService.getAllDecrypted();
} }
@ -115,8 +131,9 @@ export class AddComponent implements OnChanges {
const cipher = await this.cipherService.encrypt(this.cipher); const cipher = await this.cipherService.encrypt(this.cipher);
await this.cipherService.saveWithServer(cipher); await this.cipherService.saveWithServer(cipher);
this.analytics.eventTrack.next({ action: 'Added Cipher' }); this.analytics.eventTrack.next({ action: this.editMode ? 'Edited Cipher' : 'Added Cipher' });
this.toasterService.popAsync('success', null, this.i18nService.t('addedItem')); this.toasterService.popAsync('success', null, this.i18nService.t(this.editMode ? 'editedItem' : 'addedItem'));
this.onSavedCipher.emit(this.cipher);
}; };
addField() { addField() {
@ -135,4 +152,12 @@ export class AddComponent implements OnChanges {
this.cipher.fields.splice(i, 1); this.cipher.fields.splice(i, 1);
} }
}; };
cancel() {
this.onCancelled.emit(this.cipher);
};
attachments() {
this.onEditAttachments.emit(this.cipher);
};
} }

View File

@ -15,11 +15,11 @@ import { CipherView } from 'jslib/models/view/cipherView';
}) })
export class CiphersComponent { export class CiphersComponent {
@Input() ciphers: CipherView[]; @Input() ciphers: CipherView[];
@Output() onCipherClicked = new EventEmitter<string>(); @Output() onCipherClicked = new EventEmitter<CipherView>();
@Output() onAddCipher = new EventEmitter(); @Output() onAddCipher = new EventEmitter();
cipherClicked(cipher: CipherView) { cipherClicked(cipher: CipherView) {
this.onCipherClicked.emit(cipher.id); this.onCipherClicked.emit(cipher);
} }
addCipher() { addCipher() {

View File

@ -1,32 +0,0 @@
<div class="content">
<div class="inner-content">
<div class="box">
<div class="box-header">
{{'itemInformation' | i18n}}
</div>
<div class="box-content" *ngIf="cipher">
<div class="box-content-row">
<span class="row-label">{{'name' | i18n}}</span>
{{cipher.name}}
</div>
<div *ngIf="cipher.login">
<div class="box-content-row">
<span class="row-label">{{'uri' | i18n}}</span>
{{cipher.login.uri}}
</div>
<div class="box-content-row">
<span class="row-label">{{'username' | i18n}}</span>
{{cipher.login.username}}
</div>
<div class="box-content-row">
<span class="row-label">{{'password' | i18n}}</span>
{{cipher.login.password}}
</div>
</div>
</div>
</div>
</div>
</div>
<div class="footer">
{{'editItem' | i18n}}
</div>

View File

@ -1,35 +0,0 @@
import * as template from './edit.component.html';
import {
Component,
EventEmitter,
Input,
OnChanges,
Output,
} from '@angular/core';
import { CipherService } from 'jslib/abstractions/cipher.service';
import { CipherView } from 'jslib/models/view/cipherView';
@Component({
selector: 'app-vault-edit',
template: template,
})
export class EditComponent implements OnChanges {
@Input() cipherId: string;
@Output() onEditCipherClicked = new EventEmitter<string>();
cipher: CipherView;
constructor(private cipherService: CipherService) {
}
async ngOnChanges() {
const cipher = await this.cipherService.get(this.cipherId);
this.cipher = await cipher.decrypt();
}
editCipherClicked(id: string) {
this.onEditCipherClicked.emit(id);
}
}

View File

@ -11,12 +11,12 @@
[cipherId]="cipherId" [cipherId]="cipherId"
(onEditCipher)="editCipher($event)"> (onEditCipher)="editCipher($event)">
</app-vault-view> </app-vault-view>
<app-vault-edit id="details" <app-vault-add-edit id="details"
*ngIf="cipherId && action === 'edit'" *ngIf="action === 'add' || action === 'edit'"
[cipherId]="cipherId"> [folderId]="null"
</app-vault-edit> [cipherId]="action === 'edit' ? cipherId : null"
<app-vault-add id="details" (onSavedCipher)="savedCipher($event)"
*ngIf="action === 'add'" (onEditAttachments)="editCipherAttachments($event)"
[folderId]="null"> (onCancelled)="cancelledAddEdit($event)">
</app-vault-add> </app-vault-add-edit>
</div> </div>

View File

@ -34,10 +34,12 @@ export class VaultComponent implements OnInit {
this.route.queryParams.subscribe((params) => { this.route.queryParams.subscribe((params) => {
if (params['cipherId']) { if (params['cipherId']) {
const cipherView = new CipherView();
cipherView.id = params['cipherId'];
if (params['action'] === 'edit') { if (params['action'] === 'edit') {
this.editCipher(params['cipherId']); this.editCipher(cipherView);
} else { } else {
this.viewCipher(params['cipherId']); this.viewCipher(cipherView);
} }
} else if (params['action'] === 'add') { } else if (params['action'] === 'add') {
this.addCipher(); this.addCipher();
@ -45,24 +47,24 @@ export class VaultComponent implements OnInit {
}); });
} }
viewCipher(id: string) { viewCipher(cipher: CipherView) {
if (this.action === 'view' && this.cipherId === id) { if (this.action === 'view' && this.cipherId === cipher.id) {
return; return;
} }
this.cipherId = id; this.cipherId = cipher.id;
this.action = 'view'; this.action = 'view';
this.go({ action: this.action, cipherId: id }); this.go({ action: this.action, cipherId: this.cipherId });
} }
editCipher(id: string) { editCipher(cipher: CipherView) {
if (this.action === 'edit' && this.cipherId === id) { if (this.action === 'edit' && this.cipherId === cipher.id) {
return; return;
} }
this.cipherId = id; this.cipherId = cipher.id;
this.action = 'edit'; this.action = 'edit';
this.go({ action: this.action, cipherId: id }); this.go({ action: this.action, cipherId: this.cipherId });
} }
addCipher() { addCipher() {
@ -71,7 +73,28 @@ export class VaultComponent implements OnInit {
} }
this.action = 'add'; this.action = 'add';
this.go({ action: this.action }); this.cipherId = null;
this.go({ action: this.action, cipherId: this.cipherId });
}
savedCipher(cipher: CipherView) {
this.cipherId = cipher.id;
this.action = 'view';
this.go({ action: this.action, cipherId: this.cipherId });
}
deletedCipher(cipher: CipherView) {
}
editCipherAttachments(cipher: CipherView) {
}
cancelledAddEdit(cipher: CipherView) {
this.cipherId = cipher.id;
this.action = this.cipherId != null ? 'view' : null;
this.go({ action: this.action, cipherId: this.cipherId });
} }
private go(queryParams: any) { private go(queryParams: any) {

View File

@ -32,7 +32,7 @@ import { FieldView } from 'jslib/models/view/fieldView';
}) })
export class ViewComponent implements OnChanges, OnDestroy { export class ViewComponent implements OnChanges, OnDestroy {
@Input() cipherId: string; @Input() cipherId: string;
@Output() onEditCipher = new EventEmitter<string>(); @Output() onEditCipher = new EventEmitter<CipherView>();
cipher: CipherView; cipher: CipherView;
showPassword: boolean; showPassword: boolean;
isPremium: boolean; isPremium: boolean;
@ -75,7 +75,7 @@ export class ViewComponent implements OnChanges, OnDestroy {
} }
edit() { edit() {
this.onEditCipher.emit(this.cipher.id); this.onEditCipher.emit(this.cipher);
} }
togglePassword() { togglePassword() {

View File

@ -47,7 +47,7 @@
border-radius: $border-radius; border-radius: $border-radius;
} }
&:last-child { &:last-child:not(.box-content-row-cf) {
&:before { &:before {
border: none; border: none;
height: 0; height: 0;

View File

@ -73,6 +73,7 @@ a {
input, select, textarea, button { input, select, textarea, button {
font-size: $font-size-base; font-size: $font-size-base;
font-family: $font-family-sans-serif;
} }
textarea { textarea {