diff --git a/jslib b/jslib index 8e377050..2f510a79 160000 --- a/jslib +++ b/jslib @@ -1 +1 @@ -Subproject commit 8e377050e9bfddae46fa0a167771b670593eca16 +Subproject commit 2f510a798853ef3adfed7e8285c9d3f54eba493c diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 0d45642d..7cda81e8 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -43,12 +43,14 @@ 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 { CollectionsComponent } from './vault/collections.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'; import { PasswordGeneratorComponent } from './vault/password-generator.component'; import { PasswordHistoryComponent } from './vault/password-history.component'; +import { ShareComponent } from './vault/share.component'; import { VaultComponent } from './vault/vault.component'; import { ViewComponent } from './vault/view.component'; @@ -138,6 +140,7 @@ registerLocaleData(localeZhTw, 'zh-TW'); BlurClickDirective, BoxRowDirective, CiphersComponent, + CollectionsComponent, EnvironmentComponent, ExportComponent, FallbackSrcDirective, @@ -156,6 +159,7 @@ registerLocaleData(localeZhTw, 'zh-TW'); RegisterComponent, SearchCiphersPipe, SettingsComponent, + ShareComponent, StopClickDirective, StopPropDirective, TrueFalseValueDirective, @@ -166,6 +170,7 @@ registerLocaleData(localeZhTw, 'zh-TW'); ], entryComponents: [ AttachmentsComponent, + CollectionsComponent, EnvironmentComponent, ExportComponent, FolderAddEditComponent, @@ -175,6 +180,7 @@ registerLocaleData(localeZhTw, 'zh-TW'); PasswordHistoryComponent, PremiumComponent, SettingsComponent, + ShareComponent, TwoFactorOptionsComponent, ], providers: [], diff --git a/src/app/vault/add-edit.component.html b/src/app/vault/add-edit.component.html index 08ffb4b7..78a2dbe9 100644 --- a/src/app/vault/add-edit.component.html +++ b/src/app/vault/add-edit.component.html @@ -240,6 +240,11 @@
{{'attachments' | i18n}}
+ +
{{'collections' | i18n}}
+ +
@@ -309,6 +314,10 @@ {{'cancel' | i18n}}
+ + +
+ +
+ diff --git a/src/app/vault/collections.component.ts b/src/app/vault/collections.component.ts new file mode 100644 index 00000000..ded2139c --- /dev/null +++ b/src/app/vault/collections.component.ts @@ -0,0 +1,19 @@ +import { Component } from '@angular/core'; + +import { CipherService } from 'jslib/abstractions/cipher.service'; +import { CollectionService } from 'jslib/abstractions/collection.service'; +import { I18nService } from 'jslib/abstractions/i18n.service'; +import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service'; + +import { CollectionsComponent as BaseCollectionsComponent } from 'jslib/angular/components/collections.component'; + +@Component({ + selector: 'app-vault-collections', + templateUrl: 'collections.component.html', +}) +export class CollectionsComponent extends BaseCollectionsComponent { + constructor(cipherService: CipherService, i18nService: I18nService, + collectionService: CollectionService, platformUtilsService: PlatformUtilsService) { + super(collectionService, platformUtilsService, i18nService, cipherService); + } +} diff --git a/src/app/vault/share.component.html b/src/app/vault/share.component.html new file mode 100644 index 00000000..d5668370 --- /dev/null +++ b/src/app/vault/share.component.html @@ -0,0 +1,52 @@ + diff --git a/src/app/vault/share.component.ts b/src/app/vault/share.component.ts new file mode 100644 index 00000000..3e73aa81 --- /dev/null +++ b/src/app/vault/share.component.ts @@ -0,0 +1,21 @@ +import { Component } from '@angular/core'; + +import { CipherService } from 'jslib/abstractions/cipher.service'; +import { CollectionService } from 'jslib/abstractions/collection.service'; +import { I18nService } from 'jslib/abstractions/i18n.service'; +import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service'; +import { UserService } from 'jslib/abstractions/user.service'; + +import { ShareComponent as BaseShareComponent } from 'jslib/angular/components/share.component'; + +@Component({ + selector: 'app-vault-share', + templateUrl: 'share.component.html', +}) +export class ShareComponent extends BaseShareComponent { + constructor(cipherService: CipherService, i18nService: I18nService, + collectionService: CollectionService, userService: UserService, + platformUtilsService: PlatformUtilsService) { + super(collectionService, platformUtilsService, i18nService, userService, cipherService); + } +} diff --git a/src/app/vault/vault.component.html b/src/app/vault/vault.component.html index a5ab83c8..ce441ae8 100644 --- a/src/app/vault/vault.component.html +++ b/src/app/vault/vault.component.html @@ -30,6 +30,8 @@ (onDeletedCipher)="deletedCipher($event)" (onEditAttachments)="editCipherAttachments($event)" (onCancelled)="cancelledAddEdit($event)" + (onShareCipher)="shareCipher($event)" + (onEditCollections)="cipherCollections($event)" (onGeneratePassword)="openPasswordGenerator(true)"> + + diff --git a/src/app/vault/vault.component.ts b/src/app/vault/vault.component.ts index 651dbf03..6794e118 100644 --- a/src/app/vault/vault.component.ts +++ b/src/app/vault/vault.component.ts @@ -26,11 +26,13 @@ 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 { CollectionsComponent } from './collections.component'; import { ExportComponent } from './export.component'; import { FolderAddEditComponent } from './folder-add-edit.component'; import { GroupingsComponent } from './groupings.component'; import { PasswordGeneratorComponent } from './password-generator.component'; import { PasswordHistoryComponent } from './password-history.component'; +import { ShareComponent } from './share.component'; import { CipherType } from 'jslib/enums/cipherType'; @@ -58,6 +60,8 @@ export class VaultComponent implements OnInit, OnDestroy { @ViewChild('folderAddEdit', { read: ViewContainerRef }) folderAddEditModalRef: ViewContainerRef; @ViewChild('passwordHistory', { read: ViewContainerRef }) passwordHistoryModalRef: ViewContainerRef; @ViewChild('exportVault', { read: ViewContainerRef }) exportVaultModalRef: ViewContainerRef; + @ViewChild('share', { read: ViewContainerRef }) shareModalRef: ViewContainerRef; + @ViewChild('collections', { read: ViewContainerRef }) collectionsModalRef: ViewContainerRef; action: string; cipherId: string = null; @@ -353,6 +357,45 @@ export class VaultComponent implements OnInit, OnDestroy { }); } + shareCipher(cipher: CipherView) { + if (this.modal != null) { + this.modal.close(); + } + + const factory = this.componentFactoryResolver.resolveComponentFactory(ModalComponent); + this.modal = this.shareModalRef.createComponent(factory).instance; + const childComponent = this.modal.show(ShareComponent, this.shareModalRef); + childComponent.cipherId = cipher.id; + + childComponent.onSharedCipher.subscribe(async () => { + this.modal.close(); + this.viewCipher(cipher); + await this.ciphersComponent.refresh(); + }); + this.modal.onClosed.subscribe(async () => { + this.modal = null; + }); + } + + cipherCollections(cipher: CipherView) { + if (this.modal != null) { + this.modal.close(); + } + + const factory = this.componentFactoryResolver.resolveComponentFactory(ModalComponent); + this.modal = this.collectionsModalRef.createComponent(factory).instance; + const childComponent = this.modal.show(CollectionsComponent, this.collectionsModalRef); + childComponent.cipherId = cipher.id; + + childComponent.onSavedCollections.subscribe(() => { + this.modal.close(); + this.viewCipher(cipher); + }); + this.modal.onClosed.subscribe(async () => { + this.modal = null; + }); + } + viewCipherPasswordHistory(cipher: CipherView) { if (this.modal != null) { this.modal.close(); diff --git a/src/locales/en/messages.json b/src/locales/en/messages.json index 311249b1..32ee5891 100644 --- a/src/locales/en/messages.json +++ b/src/locales/en/messages.json @@ -38,6 +38,18 @@ "shared": { "message": "Shared" }, + "share": { + "message": "Share" + }, + "shareItem": { + "message": "Share Item" + }, + "sharedItem": { + "message": "Shared Item" + }, + "shareDesc": { + "message": "Choose an organization that you wish to share this item with. Sharing transfers ownership of the item to the organization. You will no longer be the direct owner of this item once it has been shared." + }, "attachments": { "message": "Attachments" }, @@ -1100,5 +1112,11 @@ }, "exportMasterPassword": { "message": "Enter your master password to export your vault data." + }, + "noOrganizationsList": { + "message": "You do not belong to any organizations. Organizations allow you to securely share items with other users." + }, + "noCollectionsInList": { + "message": "There are no collections to list." } }