diff --git a/jslib b/jslib
index 76c89f01ef9..6f64c5cb5a9 160000
--- a/jslib
+++ b/jslib
@@ -1 +1 @@
-Subproject commit 76c89f01ef993e572d8c2cbb057cf11f1ea21742
+Subproject commit 6f64c5cb5a90354d1a76b5270378030dc99d325b
diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index 2563272e55e..72ad8a8be51 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -43,6 +43,7 @@ import { SearchCiphersPipe } from 'jslib/angular/pipes/search-ciphers.pipe';
import { AddEditComponent } from './vault/add-edit.component';
import { AttachmentsComponent } from './vault/attachments.component';
import { CiphersComponent } from './vault/ciphers.component';
+import { ExportComponent } from './vault/export.component';
import { FolderAddEditComponent } from './vault/folder-add-edit.component';
import { GroupingsComponent } from './vault/groupings.component';
import { PasswordGeneratorHistoryComponent } from './vault/password-generator-history.component';
@@ -75,6 +76,7 @@ import { ViewComponent } from './vault/view.component';
BoxRowDirective,
CiphersComponent,
EnvironmentComponent,
+ ExportComponent,
FallbackSrcDirective,
FolderAddEditComponent,
GroupingsComponent,
@@ -102,6 +104,7 @@ import { ViewComponent } from './vault/view.component';
entryComponents: [
AttachmentsComponent,
EnvironmentComponent,
+ ExportComponent,
FolderAddEditComponent,
ModalComponent,
PasswordGeneratorComponent,
diff --git a/src/app/vault/export.component.html b/src/app/vault/export.component.html
new file mode 100644
index 00000000000..f9b8f034a30
--- /dev/null
+++ b/src/app/vault/export.component.html
@@ -0,0 +1,40 @@
+
diff --git a/src/app/vault/export.component.ts b/src/app/vault/export.component.ts
new file mode 100644
index 00000000000..2b431e2cf95
--- /dev/null
+++ b/src/app/vault/export.component.ts
@@ -0,0 +1,26 @@
+import { ToasterService } from 'angular2-toaster';
+import { Angulartics2 } from 'angulartics2';
+
+import { Component } from '@angular/core';
+
+import { CryptoService } from 'jslib/abstractions/crypto.service';
+import { ExportService } from 'jslib/abstractions/export.service';
+import { I18nService } from 'jslib/abstractions/i18n.service';
+import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
+import { UserService } from 'jslib/abstractions/user.service';
+
+import { ExportComponent as BaseExportComponent } from 'jslib/angular/components/export.component';
+
+@Component({
+ selector: 'app-export',
+ templateUrl: 'export.component.html',
+})
+export class ExportComponent extends BaseExportComponent {
+ constructor(analytics: Angulartics2, toasterService: ToasterService,
+ cryptoService: CryptoService, userService: UserService,
+ i18nService: I18nService, platformUtilsService: PlatformUtilsService,
+ exportService: ExportService) {
+ super(analytics, toasterService, cryptoService, userService, i18nService, platformUtilsService,
+ exportService, window);
+ }
+}
diff --git a/src/app/vault/folder-add-edit.component.html b/src/app/vault/folder-add-edit.component.html
index b6dce984f72..5c11d956b18 100644
--- a/src/app/vault/folder-add-edit.component.html
+++ b/src/app/vault/folder-add-edit.component.html
@@ -20,7 +20,7 @@
-
+
-
+
diff --git a/src/app/vault/vault.component.html b/src/app/vault/vault.component.html
index add0f511908..a5ab83c876a 100644
--- a/src/app/vault/vault.component.html
+++ b/src/app/vault/vault.component.html
@@ -43,4 +43,5 @@
+
diff --git a/src/app/vault/vault.component.ts b/src/app/vault/vault.component.ts
index 55bbe5dd703..8a2bf0ac087 100644
--- a/src/app/vault/vault.component.ts
+++ b/src/app/vault/vault.component.ts
@@ -26,6 +26,7 @@ import { ModalComponent } from 'jslib/angular/components/modal.component';
import { AddEditComponent } from './add-edit.component';
import { AttachmentsComponent } from './attachments.component';
import { CiphersComponent } from './ciphers.component';
+import { ExportComponent } from './export.component';
import { FolderAddEditComponent } from './folder-add-edit.component';
import { GroupingsComponent } from './groupings.component';
import { PasswordGeneratorComponent } from './password-generator.component';
@@ -56,6 +57,7 @@ export class VaultComponent implements OnInit, OnDestroy {
@ViewChild('attachments', { read: ViewContainerRef }) attachmentsModalRef: ViewContainerRef;
@ViewChild('folderAddEdit', { read: ViewContainerRef }) folderAddEditModalRef: ViewContainerRef;
@ViewChild('passwordHistory', { read: ViewContainerRef }) passwordHistoryModalRef: ViewContainerRef;
+ @ViewChild('exportVault', { read: ViewContainerRef }) exportVaultModalRef: ViewContainerRef;
action: string;
cipherId: string = null;
@@ -102,6 +104,9 @@ export class VaultComponent implements OnInit, OnDestroy {
case 'openPasswordGenerator':
await this.openPasswordGenerator(false);
break;
+ case 'exportVault':
+ await this.openExportVault();
+ break;
case 'syncVault':
try {
await this.syncService.fullSync(true);
@@ -434,6 +439,24 @@ export class VaultComponent implements OnInit, OnDestroy {
});
}
+ async openExportVault() {
+ if (this.modal != null) {
+ this.modal.close();
+ }
+
+ const factory = this.componentFactoryResolver.resolveComponentFactory(ModalComponent);
+ this.modal = this.exportVaultModalRef.createComponent(factory).instance;
+ const childComponent = this.modal.show(ExportComponent, this.exportVaultModalRef);
+
+ childComponent.onSaved.subscribe(() => {
+ this.modal.close();
+ });
+
+ this.modal.onClosed.subscribe(() => {
+ this.modal = null;
+ });
+ }
+
async addFolder() {
if (this.modal != null) {
this.modal.close();
diff --git a/src/locales/en/messages.json b/src/locales/en/messages.json
index e70bf5451ee..3addc13beff 100644
--- a/src/locales/en/messages.json
+++ b/src/locales/en/messages.json
@@ -1075,5 +1075,18 @@
"datePasswordUpdated": {
"message": "Password Updated",
"description": "ex. Date this password was updated"
+ },
+ "exportVault": {
+ "message": "Export Vault"
+ },
+ "warning": {
+ "message": "WARNING",
+ "description": "WARNING (should stay in capitalized letters if the language permits)"
+ },
+ "exportWarning": {
+ "message": "This export contains your unencrypted data in .csv format. You should not store or send it over unsecure channels (such as email). Delete it immediately after your are done using it."
+ },
+ "exportMasterPassword": {
+ "message": "Enter your master password to export your vault data."
}
}
diff --git a/src/main/menu.main.ts b/src/main/menu.main.ts
index fc14888c1a3..95e4d00c1d5 100644
--- a/src/main/menu.main.ts
+++ b/src/main/menu.main.ts
@@ -25,6 +25,7 @@ export class MenuMain extends BaseMenu {
addNewItem: MenuItem;
addNewFolder: MenuItem;
syncVault: MenuItem;
+ exportVault: MenuItem;
settings: MenuItem;
lockNow: MenuItem;
logOut: MenuItem;
@@ -51,6 +52,7 @@ export class MenuMain extends BaseMenu {
this.addNewItem = this.menu.getMenuItemById('addNewItem');
this.addNewFolder = this.menu.getMenuItemById('addNewFolder');
this.syncVault = this.menu.getMenuItemById('syncVault');
+ this.exportVault = this.menu.getMenuItemById('exportVault');
this.settings = this.menu.getMenuItemById('settings');
this.lockNow = this.menu.getMenuItemById('lockNow');
this.logOut = this.menu.getMenuItemById('logOut');
@@ -64,7 +66,7 @@ export class MenuMain extends BaseMenu {
this.unlockedRequiredMenuItems = [
this.addNewLogin, this.addNewItem, this.addNewFolder,
- this.syncVault, this.settings, this.lockNow, this.twoStepLogin, this.changeEmail,
+ this.syncVault, this.exportVault, this.settings, this.lockNow, this.twoStepLogin, this.changeEmail,
this.changeMasterPass, this.premiumMembership, this.passwordGenerator, this.passwordHistory,
this.searchVault];
this.updateApplicationMenuState(false, true);
@@ -210,6 +212,11 @@ export class MenuMain extends BaseMenu {
id: 'syncVault',
click: () => this.main.messagingService.send('syncVault'),
},
+ {
+ label: this.main.i18nService.t('exportVault'),
+ id: 'exportVault',
+ click: () => this.main.messagingService.send('exportVault'),
+ },
],
},
this.editMenuItemOptions,