diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 5ccb1f646f..6dbb1d3bfe 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -10,6 +10,7 @@ import { NgZone, OnDestroy, OnInit, + Type, ViewChild, ViewContainerRef, } from '@angular/core'; @@ -19,6 +20,7 @@ import { ModalComponent } from './modal.component'; import { PremiumComponent } from './accounts/premium.component'; import { SettingsComponent } from './accounts/settings.component'; +import { PasswordGeneratorHistoryComponent } from './vault/password-generator-history.component'; import { ToasterService } from 'angular2-toaster'; import { Angulartics2 } from 'angulartics2'; @@ -51,11 +53,13 @@ const BroadcasterSubscriptionId = 'AppComponent'; + `, }) export class AppComponent implements OnInit { @ViewChild('settings', { read: ViewContainerRef }) settingsRef: ViewContainerRef; @ViewChild('premium', { read: ViewContainerRef }) premiumRef: ViewContainerRef; + @ViewChild('passwordHistory', { read: ViewContainerRef }) passwordHistoryRef: ViewContainerRef; toasterConfig: ToasterConfig = new ToasterConfig({ showCloseButton: true, @@ -114,10 +118,14 @@ export class AppComponent implements OnInit { case 'syncCompleted': break; case 'openSettings': - this.openSettings(); + this.openModal(SettingsComponent, this.settingsRef); break; case 'openPremium': - this.openPremium(); + this.openModal(PremiumComponent, this.premiumRef); + break; + case 'openPasswordHistory': + this.openModal( + PasswordGeneratorHistoryComponent, this.passwordHistoryRef); break; default: } @@ -170,28 +178,14 @@ export class AppComponent implements OnInit { this.storageService.save(ConstantsService.lastActiveKey, now); } - private openSettings() { + private openModal(type: Type, ref: ViewContainerRef) { if (this.modal != null) { this.modal.close(); } const factory = this.componentFactoryResolver.resolveComponentFactory(ModalComponent); - this.modal = this.settingsRef.createComponent(factory).instance; - const childComponent = this.modal.show(SettingsComponent, this.settingsRef); - - this.modal.onClosed.subscribe(() => { - this.modal = null; - }); - } - - private openPremium() { - if (this.modal != null) { - this.modal.close(); - } - - const factory = this.componentFactoryResolver.resolveComponentFactory(ModalComponent); - this.modal = this.premiumRef.createComponent(factory).instance; - const childComponent = this.modal.show(PremiumComponent, this.premiumRef); + this.modal = ref.createComponent(factory).instance; + const childComponent = this.modal.show(type, ref); this.modal.onClosed.subscribe(() => { this.modal = null; diff --git a/src/app/app.module.ts b/src/app/app.module.ts index e1bb7a4230..67d3197483 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -43,6 +43,7 @@ import { CiphersComponent } from './vault/ciphers.component'; import { FolderAddEditComponent } from './vault/folder-add-edit.component'; import { GroupingsComponent } from './vault/groupings.component'; import { IconComponent } from './vault/icon.component'; +import { PasswordGeneratorHistoryComponent } from './vault/password-generator-history.component'; import { PasswordGeneratorComponent } from './vault/password-generator.component'; import { VaultComponent } from './vault/vault.component'; import { ViewComponent } from './vault/view.component'; @@ -81,6 +82,7 @@ import { ViewComponent } from './vault/view.component'; LoginComponent, ModalComponent, PasswordGeneratorComponent, + PasswordGeneratorHistoryComponent, PremiumComponent, RegisterComponent, SearchCiphersPipe, @@ -98,6 +100,7 @@ import { ViewComponent } from './vault/view.component'; FolderAddEditComponent, ModalComponent, PasswordGeneratorComponent, + PasswordGeneratorHistoryComponent, PremiumComponent, SettingsComponent, TwoFactorOptionsComponent, diff --git a/src/app/vault/password-generator-history.component.html b/src/app/vault/password-generator-history.component.html new file mode 100644 index 0000000000..9f10487638 --- /dev/null +++ b/src/app/vault/password-generator-history.component.html @@ -0,0 +1,40 @@ + diff --git a/src/app/vault/password-generator-history.component.ts b/src/app/vault/password-generator-history.component.ts new file mode 100644 index 0000000000..c8978c25fc --- /dev/null +++ b/src/app/vault/password-generator-history.component.ts @@ -0,0 +1,38 @@ +import * as template from './password-generator-history.component.html'; + +import { Angulartics2 } from 'angulartics2'; + +import { + Component, + OnInit, +} from '@angular/core'; + +import { PasswordGenerationService } from 'jslib/abstractions/passwordGeneration.service'; +import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service'; + +import { PasswordHistory } from 'jslib/models/domain/passwordHistory'; + +@Component({ + selector: 'app-password-generator-history', + template: template, +}) +export class PasswordGeneratorHistoryComponent implements OnInit { + history: PasswordHistory[]; + + constructor(private passwordGenerationService: PasswordGenerationService, private analytics: Angulartics2, + private platformUtilsService: PlatformUtilsService) { } + + async ngOnInit() { + this.history = await this.passwordGenerationService.getHistory(); + } + + clear() { + this.history = []; + this.passwordGenerationService.clear(); + } + + copy(password: string) { + this.analytics.eventTrack.next({ action: 'Copied Historical Password' }); + this.platformUtilsService.copyToClipboard(password); + } +} diff --git a/src/app/vault/password-generator.component.ts b/src/app/vault/password-generator.component.ts index ef11452504..bbbcf42229 100644 --- a/src/app/vault/password-generator.component.ts +++ b/src/app/vault/password-generator.component.ts @@ -15,7 +15,7 @@ import { PasswordGenerationService } from 'jslib/abstractions/passwordGeneration import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service'; @Component({ - selector: 'password-generator', + selector: 'app-password-generator', template: template, }) export class PasswordGeneratorComponent implements OnInit { @@ -60,14 +60,13 @@ export class PasswordGeneratorComponent implements OnInit { await this.passwordGenerationService.saveOptions(this.options); if (regenerate) { - this.password = this.passwordGenerationService.generatePassword(this.options); - await this.passwordGenerationService.addHistory(this.password); - this.analytics.eventTrack.next({ action: 'Regenerated Password' }); + await this.regenerate(); } } - regenerate() { + async regenerate() { this.password = this.passwordGenerationService.generatePassword(this.options); + await this.passwordGenerationService.addHistory(this.password); this.analytics.eventTrack.next({ action: 'Regenerated Password' }); } diff --git a/src/locales/en/messages.json b/src/locales/en/messages.json index ee92177dfa..628624de93 100644 --- a/src/locales/en/messages.json +++ b/src/locales/en/messages.json @@ -868,5 +868,11 @@ }, "refreshComplete": { "message": "Refresh complete" + }, + "passwordHistory": { + "message": "Password History" + }, + "clear": { + "message": "Clear" } } diff --git a/src/main/menu.main.ts b/src/main/menu.main.ts index 9ab0a3385e..2e3d7b3c10 100644 --- a/src/main/menu.main.ts +++ b/src/main/menu.main.ts @@ -27,6 +27,7 @@ export class MenuMain { changeMasterPass: MenuItem; premiumMembership: MenuItem; passwordGenerator: MenuItem; + passwordHistory: MenuItem; searchVault: MenuItem; unlockedRequiredMenuItems: MenuItem[] = []; @@ -49,12 +50,14 @@ export class MenuMain { this.changeMasterPass = this.menu.getMenuItemById('changeMasterPass'); this.premiumMembership = this.menu.getMenuItemById('premiumMembership'); this.passwordGenerator = this.menu.getMenuItemById('passwordGenerator'); + this.passwordHistory = this.menu.getMenuItemById('passwordHistory'); this.searchVault = this.menu.getMenuItemById('searchVault'); this.unlockedRequiredMenuItems = [ this.addNewLogin, this.addNewItem, this.addNewFolder, this.syncVault, this.settings, this.lockNow, this.twoStepLogin, this.changeEmail, - this.changeMasterPass, this.premiumMembership, this.passwordGenerator, this.searchVault]; + this.changeMasterPass, this.premiumMembership, this.passwordGenerator, this.passwordHistory, + this.searchVault]; this.updateApplicationMenuState(false, true); } @@ -174,6 +177,13 @@ export class MenuMain { { label: this.main.i18nService.t('view'), submenu: [ + { + label: this.main.i18nService.t('searchVault'), + id: 'searchVault', + click: () => this.main.messagingService.send('focusSearch'), + accelerator: 'CmdOrCtrl+F', + }, + { type: 'separator' }, { label: this.main.i18nService.t('passwordGenerator'), id: 'passwordGenerator', @@ -181,10 +191,9 @@ export class MenuMain { accelerator: 'CmdOrCtrl+G', }, { - label: this.main.i18nService.t('searchVault'), - id: 'searchVault', - click: () => this.main.messagingService.send('focusSearch'), - accelerator: 'CmdOrCtrl+F', + label: this.main.i18nService.t('passwordHistory'), + id: 'passwordHistory', + click: () => this.main.messagingService.send('openPasswordHistory'), }, { type: 'separator' }, { role: 'zoomin', accelerator: 'CmdOrCtrl+=' }, diff --git a/src/scss/box.scss b/src/scss/box.scss index 30cce4aac8..d61f6ffcc9 100644 --- a/src/scss/box.scss +++ b/src/scss/box.scss @@ -98,6 +98,7 @@ &.box-content-row-slider, &.box-content-row-cf { display: flex; align-items: center; + word-break: break-word; } &.box-content-row-cf {