combine edit into add/edit component
This commit is contained in:
parent
298b12bf0d
commit
eee5f6ff32
|
@ -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,
|
||||||
|
|
|
@ -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>
|
|
@ -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);
|
||||||
|
};
|
||||||
}
|
}
|
|
@ -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() {
|
||||||
|
|
|
@ -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>
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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>
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Reference in New Issue