diff --git a/src/app/vault/vault.component.ts b/src/app/vault/vault.component.ts
index 3e481172..50775f3b 100644
--- a/src/app/vault/vault.component.ts
+++ b/src/app/vault/vault.component.ts
@@ -189,7 +189,9 @@ export class VaultComponent implements OnInit, OnDestroy {
if (params.cipherId) {
const cipherView = new CipherView();
cipherView.id = params.cipherId;
- if (params.action === 'edit') {
+ if (params.action === 'clone') {
+ await this.cloneCipher(cipherView);
+ } else if (params.action === 'edit') {
await this.editCipher(cipherView);
} else {
await this.viewCipher(cipherView);
@@ -249,6 +251,12 @@ export class VaultComponent implements OnInit, OnDestroy {
this.editCipher(cipher);
}),
}));
+ menu.append(new remote.MenuItem({
+ label: this.i18nService.t('clone'),
+ click: () => this.functionWithChangeDetection(() => {
+ this.cloneCipher(cipher);
+ }),
+ }));
switch (cipher.type) {
case CipherType.Login:
@@ -315,6 +323,18 @@ export class VaultComponent implements OnInit, OnDestroy {
this.go();
}
+ async cloneCipher(cipher: CipherView) {
+ if (this.action === 'clone' && this.cipherId === cipher.id) {
+ return;
+ } else if (this.dirtyInput() && await this.wantsToSaveChanges()) {
+ return;
+ }
+
+ this.cipherId = cipher.id;
+ this.action = 'clone';
+ this.go();
+ }
+
async addCipher(type: CipherType = null) {
if (this.action === 'add') {
return;
diff --git a/src/app/vault/view.component.html b/src/app/vault/view.component.html
index fc7947a6..b197353a 100644
--- a/src/app/vault/view.component.html
+++ b/src/app/vault/view.component.html
@@ -276,4 +276,7 @@
+
diff --git a/src/locales/en/messages.json b/src/locales/en/messages.json
index 613b30a8..a9c8a55d 100644
--- a/src/locales/en/messages.json
+++ b/src/locales/en/messages.json
@@ -1273,5 +1273,8 @@
},
"unsavedChangesTitle": {
"message": "Unsaved Changes"
+ },
+ "clone": {
+ "message": "Clone"
}
}