1
0
mirror of https://github.com/bitwarden/web synced 2025-12-10 13:23:15 +00:00

Compare commits

...

13 Commits

Author SHA1 Message Date
addison
220f8a8e46 [fix] Ran prettier 2022-06-06 09:09:37 -04:00
Addison Beck
f7a24ad8e3 Update src/app/modules/vault-filter/organization-vault-filter.component.ts
Co-authored-by: Thomas Rittson <31796059+eliykat@users.noreply.github.com>
2022-06-06 08:57:22 -04:00
Addison Beck
49f02bf20b Update src/app/modules/vault-filter/vault-filter.component.ts
Co-authored-by: Thomas Rittson <31796059+eliykat@users.noreply.github.com>
2022-06-06 08:57:12 -04:00
addison
cd174283ed Revert "[refactor] Establish pattern for interfaces in module scoped services"
This reverts commit f1edae5a3e.
2022-06-03 21:56:14 -04:00
addison
e07deff505 [fix] Simplify hiding unwanted filters in the org vault 2022-06-02 13:14:31 -04:00
addison
2af429249c [fix] Rename skipFilterCollectionRefresh to firstLoaded 2022-06-02 13:02:42 -04:00
addison
3c0d78c61c [fix] Remove access modifiers from constructor params for an extended service 2022-06-02 13:01:22 -04:00
addison
f1edae5a3e [refactor] Establish pattern for interfaces in module scoped services 2022-06-02 12:55:09 -04:00
addison
6f3f1a3d47 Merge branch 'master' into fix/orgAdminCollections 2022-06-02 09:34:02 -04:00
Oscar Hinton
e1ffca07ba Add archive notice (#1724) 2022-06-02 09:09:08 -04:00
Oscar Hinton
fb35805202 [CL-38] Follow Angular styleguide naming convention (#1655) 2022-06-02 11:34:27 +02:00
dwbit
b6b7298980 Adding missing code for Serbian Latin (#1713) 2022-06-02 11:23:48 +02:00
addison
91e8d6d506 [fix] Pull org admin vault collections directly from the API 2022-05-20 12:36:39 -04:00
30 changed files with 171 additions and 134 deletions

View File

@@ -1,8 +1,6 @@
> **Repository Reorganization in Progress** > **Archived**
> >
> We are currently migrating some projects over to a mono repository. For existing PR's we will be providing documentation on how to move/migrate them. To minimize the overhead we are actively reviewing open PRs. If possible please ensure any pending comments are resolved as soon as possible. > This repository is archived, please go to https://github.com/bitwarden/clients for future development.
>
> New pull requests created during this transition period may not get addressed —if needed, please create a new PR after the reorganization is complete.
<p align="center"> <p align="center">
<img src="https://raw.githubusercontent.com/bitwarden/brand/master/screenshots/web-vault-macbook.png" alt="" width="600" height="358" /> <img src="https://raw.githubusercontent.com/bitwarden/brand/master/screenshots/web-vault-macbook.png" alt="" width="600" height="358" />

View File

@@ -15,3 +15,4 @@ files:
en-GB: en_GB en-GB: en_GB
en-IN: en_IN en-IN: en_IN
sr-CY: sr_CY sr-CY: sr_CY
sr-CS: sr_CS

2
jslib

Submodule jslib updated: 0d658ba26d...f4066b4f58

View File

@@ -46,7 +46,7 @@
<bit-menu #orgPickerMenu> <bit-menu #orgPickerMenu>
<ul aria-labelledby="pickerButton" class="tw-p-0 tw-m-0"> <ul aria-labelledby="pickerButton" class="tw-p-0 tw-m-0">
<li *ngFor="let org of organizations" class="tw-list-none tw-flex tw-flex-col" role="none"> <li *ngFor="let org of organizations" class="tw-list-none tw-flex tw-flex-col" role="none">
<a bit-menu-item [routerLink]="['/organizations', org.id]"> <a bitMenuItem [routerLink]="['/organizations', org.id]">
<i <i
class="bwi bwi-check mr-2" class="bwi bwi-check mr-2"
[ngClass]="org.id === activeOrganization.id ? 'visible' : 'invisible'" [ngClass]="org.id === activeOrganization.id ? 'visible' : 'invisible'"
@@ -58,7 +58,7 @@
</li> </li>
<bit-menu-divider></bit-menu-divider> <bit-menu-divider></bit-menu-divider>
<li class="tw-list-none" role="none"> <li class="tw-list-none" role="none">
<a bit-menu-item routerLink="/create-organization"> <a bitMenuItem routerLink="/create-organization">
<i class="bwi bwi-plus mr-2"></i> <i class="bwi bwi-plus mr-2"></i>
{{ "newOrganization" | i18n }}</a {{ "newOrganization" | i18n }}</a
> >

View File

@@ -5,7 +5,7 @@ import { MessagingService } from "jslib-common/abstractions/messaging.service";
@Component({ @Component({
selector: "app-premium-badge", selector: "app-premium-badge",
template: ` template: `
<button *appNotPremium bit-badge badgeType="success" (click)="premiumRequired()"> <button *appNotPremium bitBadge badgeType="success" (click)="premiumRequired()">
{{ "premium" | i18n }} {{ "premium" | i18n }}
</button> </button>
`, `,

View File

@@ -65,24 +65,24 @@
</div> </div>
</div> </div>
<bit-menu-divider></bit-menu-divider> <bit-menu-divider></bit-menu-divider>
<a bit-menu-item routerLink="/settings/account"> <a bitMenuItem routerLink="/settings/account">
<i class="bwi bwi-fw bwi-user" aria-hidden="true"></i> <i class="bwi bwi-fw bwi-user" aria-hidden="true"></i>
{{ "accountSettings" | i18n }} {{ "accountSettings" | i18n }}
</a> </a>
<a bit-menu-item href="https://bitwarden.com/help/" target="_blank" rel="noopener"> <a bitMenuItem href="https://bitwarden.com/help/" target="_blank" rel="noopener">
<i class="bwi bwi-fw bwi-question-circle" aria-hidden="true"></i> <i class="bwi bwi-fw bwi-question-circle" aria-hidden="true"></i>
{{ "getHelp" | i18n }} {{ "getHelp" | i18n }}
</a> </a>
<a bit-menu-item href="https://bitwarden.com/download/" target="_blank" rel="noopener"> <a bitMenuItem href="https://bitwarden.com/download/" target="_blank" rel="noopener">
<i class="bwi bwi-fw bwi-download" aria-hidden="true"></i> <i class="bwi bwi-fw bwi-download" aria-hidden="true"></i>
{{ "getApps" | i18n }} {{ "getApps" | i18n }}
</a> </a>
<bit-menu-divider></bit-menu-divider> <bit-menu-divider></bit-menu-divider>
<button bit-menu-item type="button" (click)="lock()"> <button bitMenuItem type="button" (click)="lock()">
<i class="bwi bwi-fw bwi-lock" aria-hidden="true"></i> <i class="bwi bwi-fw bwi-lock" aria-hidden="true"></i>
{{ "lockNow" | i18n }} {{ "lockNow" | i18n }}
</button> </button>
<button bit-menu-item type="button" (click)="logOut()"> <button bitMenuItem type="button" (click)="logOut()">
<i class="bwi bwi-fw bwi-sign-out" aria-hidden="true"></i> <i class="bwi bwi-fw bwi-sign-out" aria-hidden="true"></i>
{{ "logOut" | i18n }} {{ "logOut" | i18n }}
</button> </button>

View File

@@ -32,7 +32,7 @@
<app-user-verification [(ngModel)]="verification" name="secret"> </app-user-verification> <app-user-verification [(ngModel)]="verification" name="secret"> </app-user-verification>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<button bit-button buttonType="primary" type="submit" [disabled]="form.loading"> <button bitButton buttonType="primary" type="submit" [disabled]="form.loading">
<i <i
class="bwi bwi-spinner bwi-spin" class="bwi bwi-spinner bwi-spin"
title="{{ 'loading' | i18n }}" title="{{ 'loading' | i18n }}"
@@ -43,7 +43,7 @@
</span> </span>
</button> </button>
<button <button
bit-button bitButton
buttonType="secondary" buttonType="secondary"
type="button" type="button"
data-dismiss="modal" data-dismiss="modal"

View File

@@ -0,0 +1,28 @@
import { Component, Input } from "@angular/core";
import { Organization } from "jslib-common/models/domain/organization";
import { VaultFilterComponent } from "./vault-filter.component";
@Component({
selector: "app-organization-vault-filter",
templateUrl: "vault-filter.component.html",
})
export class OrganizationVaultFilterComponent extends VaultFilterComponent {
hideOrganizations = true;
hideFavorites = true;
hideFolders = true;
organization: Organization;
async initCollections() {
if (this.organization.canEditAnyCollection) {
return await this.vaultFilterService.buildAdminCollections(this.organization.id);
}
return await this.vaultFilterService.buildCollections(this.organization.id);
}
async reloadCollectionsAndFolders() {
this.collections = await this.initCollections();
}
}

View File

@@ -27,7 +27,6 @@
appAutofocus appAutofocus
/> />
<app-organization-filter <app-organization-filter
*ngIf="showOrgFilter"
[hide]="hideOrganizations" [hide]="hideOrganizations"
[activeFilter]="activeFilter" [activeFilter]="activeFilter"
[collapsedFilterNodes]="collapsedFilterNodes" [collapsedFilterNodes]="collapsedFilterNodes"
@@ -39,7 +38,7 @@
></app-organization-filter> ></app-organization-filter>
<div class="filter"> <div class="filter">
<app-status-filter <app-status-filter
[hideFavorites]="!showFavorites" [hideFavorites]="hideFavorites"
[hideTrash]="hideTrash" [hideTrash]="hideTrash"
[activeFilter]="activeFilter" [activeFilter]="activeFilter"
(onFilterChange)="applyFilter($event)" (onFilterChange)="applyFilter($event)"
@@ -55,7 +54,7 @@
</div> </div>
<div class="filter"> <div class="filter">
<app-folder-filter <app-folder-filter
[hide]="!showFolders" [hide]="hideFolders"
[activeFilter]="activeFilter" [activeFilter]="activeFilter"
[collapsedFilterNodes]="collapsedFilterNodes" [collapsedFilterNodes]="collapsedFilterNodes"
[folderNodes]="folders" [folderNodes]="folders"

View File

@@ -1,34 +1,26 @@
import { Component, EventEmitter, Input, Output } from "@angular/core"; import { Component, EventEmitter, Output } from "@angular/core";
import { VaultFilterComponent as BaseVaultFilterComponent } from "jslib-angular/modules/vault-filter/vault-filter.component"; import { VaultFilterComponent as BaseVaultFilterComponent } from "jslib-angular/modules/vault-filter/vault-filter.component";
import { VaultFilterService } from "jslib-angular/modules/vault-filter/vault-filter.service";
import { Organization } from "jslib-common/models/domain/organization"; import { VaultFilterService } from "./vault-filter.service";
@Component({ @Component({
selector: "app-vault-filter", selector: "app-vault-filter",
templateUrl: "vault-filter.component.html", templateUrl: "vault-filter.component.html",
}) })
export class VaultFilterComponent extends BaseVaultFilterComponent { export class VaultFilterComponent extends BaseVaultFilterComponent {
@Input() showOrgFilter = true;
@Input() showFolders = true;
@Input() showFavorites = true;
@Output() onSearchTextChanged = new EventEmitter<string>(); @Output() onSearchTextChanged = new EventEmitter<string>();
searchPlaceholder: string; searchPlaceholder: string;
searchText = ""; searchText = "";
organization: Organization; constructor(protected vaultFilterService: VaultFilterService) {
// This empty constructor is required to provide the web vaultFilterService subclass to super()
constructor(vaultFilterService: VaultFilterService) { // TODO: refactor this to use proper dependency injection
super(vaultFilterService); super(vaultFilterService);
} }
searchTextChanged() { searchTextChanged() {
this.onSearchTextChanged.emit(this.searchText); this.onSearchTextChanged.emit(this.searchText);
} }
async initCollections() {
return await this.vaultFilterService.buildCollections(this.organization?.id);
}
} }

View File

@@ -1,13 +1,5 @@
import { NgModule } from "@angular/core"; import { NgModule } from "@angular/core";
import { VaultFilterService } from "jslib-angular/modules/vault-filter/vault-filter.service";
import { CipherService } from "jslib-common/abstractions/cipher.service";
import { CollectionService } from "jslib-common/abstractions/collection.service";
import { FolderService } from "jslib-common/abstractions/folder.service";
import { OrganizationService } from "jslib-common/abstractions/organization.service";
import { PolicyService } from "jslib-common/abstractions/policy.service";
import { StateService } from "jslib-common/abstractions/state.service";
import { SharedModule } from "../shared.module"; import { SharedModule } from "../shared.module";
import { CollectionFilterComponent } from "./components/collection-filter.component"; import { CollectionFilterComponent } from "./components/collection-filter.component";
@@ -17,7 +9,9 @@ import { OrganizationFilterComponent } from "./components/organization-filter.co
import { OrganizationOptionsComponent } from "./components/organization-options.component"; import { OrganizationOptionsComponent } from "./components/organization-options.component";
import { StatusFilterComponent } from "./components/status-filter.component"; import { StatusFilterComponent } from "./components/status-filter.component";
import { TypeFilterComponent } from "./components/type-filter.component"; import { TypeFilterComponent } from "./components/type-filter.component";
import { OrganizationVaultFilterComponent } from "./organization-vault-filter.component";
import { VaultFilterComponent } from "./vault-filter.component"; import { VaultFilterComponent } from "./vault-filter.component";
import { VaultFilterService } from "./vault-filter.service";
@NgModule({ @NgModule({
imports: [SharedModule], imports: [SharedModule],
@@ -29,22 +23,10 @@ import { VaultFilterComponent } from "./vault-filter.component";
OrganizationOptionsComponent, OrganizationOptionsComponent,
StatusFilterComponent, StatusFilterComponent,
TypeFilterComponent, TypeFilterComponent,
OrganizationVaultFilterComponent,
LinkSsoComponent, LinkSsoComponent,
], ],
exports: [VaultFilterComponent], exports: [VaultFilterComponent, OrganizationVaultFilterComponent],
providers: [ providers: [VaultFilterService],
{
provide: VaultFilterService,
useClass: VaultFilterService,
deps: [
StateService,
OrganizationService,
FolderService,
CipherService,
CollectionService,
PolicyService,
],
},
],
}) })
export class VaultFilterModule {} export class VaultFilterModule {}

View File

@@ -1,3 +1,54 @@
import { VaultFilterService as BaseVaultFilterService } from "jslib-angular/modules/vault-filter/vault-filter.service"; import { Injectable } from "@angular/core";
export class VaultFilterService extends BaseVaultFilterService {} import { DynamicTreeNode } from "jslib-angular/modules/vault-filter/models/dynamic-tree-node.model";
import { VaultFilterService as BaseVaultFilterService } from "jslib-angular/modules/vault-filter/vault-filter.service";
import { ApiService } from "jslib-common/abstractions/api.service";
import { CipherService } from "jslib-common/abstractions/cipher.service";
import { CollectionService } from "jslib-common/abstractions/collection.service";
import { FolderService } from "jslib-common/abstractions/folder.service";
import { OrganizationService } from "jslib-common/abstractions/organization.service";
import { PolicyService } from "jslib-common/abstractions/policy.service";
import { StateService } from "jslib-common/abstractions/state.service";
import { CollectionData } from "jslib-common/models/data/collectionData";
import { Collection } from "jslib-common/models/domain/collection";
import { CollectionDetailsResponse } from "jslib-common/models/response/collectionResponse";
import { CollectionView } from "jslib-common/models/view/collectionView";
@Injectable()
export class VaultFilterService extends BaseVaultFilterService {
constructor(
stateService: StateService,
organizationService: OrganizationService,
folderService: FolderService,
cipherService: CipherService,
collectionService: CollectionService,
policyService: PolicyService,
protected apiService: ApiService
) {
super(
stateService,
organizationService,
folderService,
cipherService,
collectionService,
policyService
);
}
async buildAdminCollections(organizationId: string) {
let result: CollectionView[] = [];
const collectionResponse = await this.apiService.getCollections(organizationId);
if (collectionResponse?.data != null && collectionResponse.data.length) {
const collectionDomains = collectionResponse.data.map(
(r: CollectionDetailsResponse) => new Collection(new CollectionData(r))
);
result = await this.collectionService.decryptMany(collectionDomains);
}
const nestedCollections = await this.collectionService.getAllNested(result);
return new DynamicTreeNode<CollectionView>({
fullList: result,
nestedList: nestedCollections,
});
}
}

View File

@@ -1,5 +1,5 @@
<button <button
bit-badge bitBadge
[style.color]="textColor" [style.color]="textColor"
[style.background-color]="color" [style.background-color]="color"
appA11yTitle="{{ organizationName }}" appA11yTitle="{{ organizationName }}"

View File

@@ -4,15 +4,12 @@
<div class="groupings"> <div class="groupings">
<div class="content"> <div class="content">
<div class="inner-content"> <div class="inner-content">
<app-vault-filter <app-organization-vault-filter
#vaultFilter #vaultFilter
[showFolders]="false"
[showFavorites]="false"
[activeFilter]="activeFilter" [activeFilter]="activeFilter"
[showOrgFilter]="false"
(onFilterChange)="applyVaultFilter($event)" (onFilterChange)="applyVaultFilter($event)"
(onSearchTextChanged)="filterSearchText($event)" (onSearchTextChanged)="filterSearchText($event)"
></app-vault-filter> ></app-organization-vault-filter>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -29,7 +29,7 @@ import { AddEditComponent } from "../../../../organizations/vault/add-edit.compo
import { AttachmentsComponent } from "../../../../organizations/vault/attachments.component"; import { AttachmentsComponent } from "../../../../organizations/vault/attachments.component";
import { CiphersComponent } from "../../../../organizations/vault/ciphers.component"; import { CiphersComponent } from "../../../../organizations/vault/ciphers.component";
import { CollectionsComponent } from "../../../../organizations/vault/collections.component"; import { CollectionsComponent } from "../../../../organizations/vault/collections.component";
import { VaultFilterComponent } from "../../../vault-filter/vault-filter.component"; import { OrganizationVaultFilterComponent } from "../../../vault-filter/organization-vault-filter.component";
import { VaultService } from "../../vault.service"; import { VaultService } from "../../vault.service";
const BroadcasterSubscriptionId = "OrgVaultComponent"; const BroadcasterSubscriptionId = "OrgVaultComponent";
@@ -39,7 +39,8 @@ const BroadcasterSubscriptionId = "OrgVaultComponent";
templateUrl: "organization-vault.component.html", templateUrl: "organization-vault.component.html",
}) })
export class OrganizationVaultComponent implements OnInit, OnDestroy { export class OrganizationVaultComponent implements OnInit, OnDestroy {
@ViewChild("vaultFilter", { static: true }) vaultFilterComponent: VaultFilterComponent; @ViewChild("vaultFilter", { static: true })
vaultFilterComponent: OrganizationVaultFilterComponent;
@ViewChild(CiphersComponent, { static: true }) ciphersComponent: CiphersComponent; @ViewChild(CiphersComponent, { static: true }) ciphersComponent: CiphersComponent;
@ViewChild("attachments", { read: ViewContainerRef, static: true }) @ViewChild("attachments", { read: ViewContainerRef, static: true })
attachmentsModalRef: ViewContainerRef; attachmentsModalRef: ViewContainerRef;
@@ -57,6 +58,11 @@ export class OrganizationVaultComponent implements OnInit, OnDestroy {
trashCleanupWarning: string = null; trashCleanupWarning: string = null;
activeFilter: VaultFilter = new VaultFilter(); activeFilter: VaultFilter = new VaultFilter();
// This is a hack to avoid redundant api calls that fetch OrganizationVaultFilterComponent collections
// When it makes sense to do so we should leverage some other communication method for change events that isn't directly tied to the query param for organizationId
// i.e. exposing the VaultFiltersService to the OrganizationSwitcherComponent to make relevant updates from a change event instead of just depending on the router
firstLoaded = true;
constructor( constructor(
private route: ActivatedRoute, private route: ActivatedRoute,
private organizationService: OrganizationService, private organizationService: OrganizationService,
@@ -95,11 +101,7 @@ export class OrganizationVaultComponent implements OnInit, OnDestroy {
case "syncCompleted": case "syncCompleted":
if (message.successfully) { if (message.successfully) {
await Promise.all([ await Promise.all([
this.vaultFilterComponent.reloadCollectionsAndFolders( this.vaultFilterComponent.reloadCollectionsAndFolders(),
new VaultFilter({
selectedOrganizationId: this.organization.id,
} as Partial<VaultFilter>)
),
this.ciphersComponent.refresh(), this.ciphersComponent.refresh(),
]); ]);
this.changeDetectorRef.detectChanges(); this.changeDetectorRef.detectChanges();
@@ -109,9 +111,12 @@ export class OrganizationVaultComponent implements OnInit, OnDestroy {
}); });
}); });
} }
await this.vaultFilterComponent.reloadCollectionsAndFolders(
new VaultFilter({ selectedOrganizationId: this.organization.id } as Partial<VaultFilter>) if (!this.firstLoaded) {
); await this.vaultFilterComponent.reloadCollectionsAndFolders();
}
this.firstLoaded = false;
await this.ciphersComponent.reload(); await this.ciphersComponent.reload();
if (qParams.viewEvents != null) { if (qParams.viewEvents != null) {

View File

@@ -17,13 +17,7 @@
<small class="form-text text-muted">{{ "breachCheckUsernameEmail" | i18n }}</small> <small class="form-text text-muted">{{ "breachCheckUsernameEmail" | i18n }}</small>
</div> </div>
</div> </div>
<button <button bitButton buttonType="primary" class="btn-submit" type="submit" [disabled]="form.loading">
bit-button
buttonType="primary"
class="btn-submit"
type="submit"
[disabled]="form.loading"
>
<i class="bwi bwi-spinner bwi-spin" title="{{ 'loading' | i18n }}" aria-hidden="true"></i> <i class="bwi bwi-spinner bwi-spin" title="{{ 'loading' | i18n }}" aria-hidden="true"></i>
<span>{{ "checkBreaches" | i18n }}</span> <span>{{ "checkBreaches" | i18n }}</span>
</button> </button>

View File

@@ -3,7 +3,7 @@
</div> </div>
<p>{{ "exposedPasswordsReportDesc" | i18n }}</p> <p>{{ "exposedPasswordsReportDesc" | i18n }}</p>
<button <button
bit-button bitButton
buttonType="primary" buttonType="primary"
type="button" type="button"
class="btn-submit" class="btn-submit"

View File

@@ -15,7 +15,7 @@
<p class="tw-mb-0">{{ report.description | i18n }}</p> <p class="tw-mb-0">{{ report.description | i18n }}</p>
</div> </div>
<span <span
bit-badge bitBadge
badgeType="success" badgeType="success"
class="tw-absolute tw-left-2 tw-top-2 tw-leading-none" class="tw-absolute tw-left-2 tw-top-2 tw-leading-none"
*ngIf="premium" *ngIf="premium"

View File

@@ -3,7 +3,7 @@
<div class="row mt-4"> <div class="row mt-4">
<div class="col"> <div class="col">
<a bit-button routerLink="./" *ngIf="!homepage"> <a bitButton routerLink="./" *ngIf="!homepage">
<i class="bwi bwi-angle-left" aria-hidden="true"></i> <i class="bwi bwi-angle-left" aria-hidden="true"></i>
{{ "backToReports" | i18n }} {{ "backToReports" | i18n }}
</a> </a>

View File

@@ -23,7 +23,7 @@
<ul class="filter-options"> <ul class="filter-options">
<li class="filter-option" [ngClass]="{ active: selectedAll }"> <li class="filter-option" [ngClass]="{ active: selectedAll }">
<span class="filter-buttons"> <span class="filter-buttons">
<button bit-button class="filter-button" appStopClick (click)="selectAll()"> <button bitButton class="filter-button" appStopClick (click)="selectAll()">
<i class="bwi bwi-fw bwi-filter"></i>{{ "allSends" | i18n }} <i class="bwi bwi-fw bwi-filter"></i>{{ "allSends" | i18n }}
</button> </button>
</span> </span>
@@ -38,7 +38,7 @@
<li class="filter-option" [ngClass]="{ active: selectedType === sendType.Text }"> <li class="filter-option" [ngClass]="{ active: selectedType === sendType.Text }">
<span class="filter-buttons"> <span class="filter-buttons">
<button <button
bit-button bitButton
class="filter-button" class="filter-button"
appStopClick appStopClick
(click)="selectType(sendType.Text)" (click)="selectType(sendType.Text)"
@@ -50,7 +50,7 @@
<li class="filter-option" [ngClass]="{ active: selectedType === sendType.File }"> <li class="filter-option" [ngClass]="{ active: selectedType === sendType.File }">
<span class="filter-buttons"> <span class="filter-buttons">
<button <button
bit-button bitButton
class="filter-button" class="filter-button"
appStopClick appStopClick
(click)="selectType(sendType.File)" (click)="selectType(sendType.File)"
@@ -160,19 +160,15 @@
<i class="bwi bwi-ellipsis-v bwi-lg" aria-hidden="true"></i> <i class="bwi bwi-ellipsis-v bwi-lg" aria-hidden="true"></i>
</button> </button>
<bit-menu #sendOptions> <bit-menu #sendOptions>
<button bit-menu-item (click)="copy(s)"> <button bitMenuItem (click)="copy(s)">
<i class="bwi bwi-fw bwi-clone" aria-hidden="true"></i> <i class="bwi bwi-fw bwi-clone" aria-hidden="true"></i>
{{ "copySendLink" | i18n }} {{ "copySendLink" | i18n }}
</button> </button>
<button <button bitMenuItem (click)="removePassword(s)" *ngIf="s.password && !disableSend">
bit-menu-item
(click)="removePassword(s)"
*ngIf="s.password && !disableSend"
>
<i class="bwi bwi-fw bwi-close" aria-hidden="true"></i> <i class="bwi bwi-fw bwi-close" aria-hidden="true"></i>
{{ "removePassword" | i18n }} {{ "removePassword" | i18n }}
</button> </button>
<button bit-menu-item (click)="delete(s)"> <button bitMenuItem (click)="delete(s)">
<span class="tw-text-danger"> <span class="tw-text-danger">
<i class="bwi bwi-fw bwi-trash" aria-hidden="true"></i> <i class="bwi bwi-fw bwi-trash" aria-hidden="true"></i>
{{ "delete" | i18n }} {{ "delete" | i18n }}

View File

@@ -14,13 +14,13 @@
<div class="card border-danger"> <div class="card border-danger">
<div class="card-body"> <div class="card-body">
<p>{{ "dangerZoneDesc" | i18n }}</p> <p>{{ "dangerZoneDesc" | i18n }}</p>
<button bit-button buttonType="danger" (click)="deauthorizeSessions()"> <button bitButton buttonType="danger" (click)="deauthorizeSessions()">
{{ "deauthorizeSessions" | i18n }} {{ "deauthorizeSessions" | i18n }}
</button> </button>
<button bit-button buttonType="danger" (click)="purgeVault()"> <button bitButton buttonType="danger" (click)="purgeVault()">
{{ "purgeVault" | i18n }} {{ "purgeVault" | i18n }}
</button> </button>
<button bit-button buttonType="danger" (click)="deleteAccount()"> <button bitButton buttonType="danger" (click)="deleteAccount()">
{{ "deleteAccount" | i18n }} {{ "deleteAccount" | i18n }}
</button> </button>
</div> </div>

View File

@@ -71,7 +71,7 @@
</div> </div>
</div> </div>
</div> </div>
<button bit-button buttonType="primary" class="btn-submit" [disabled]="form.loading"> <button bitButton buttonType="primary" class="btn-submit" [disabled]="form.loading">
<i class="bwi bwi-spinner bwi-spin" title="{{ 'loading' | i18n }}" aria-hidden="true"></i> <i class="bwi bwi-spinner bwi-spin" title="{{ 'loading' | i18n }}" aria-hidden="true"></i>
<span>{{ "changeKdf" | i18n }}</span> <span>{{ "changeKdf" | i18n }}</span>
</button> </button>

View File

@@ -87,7 +87,7 @@
</a> </a>
</div> </div>
</div> </div>
<button bit-button buttonType="primary" class="btn-submit" [disabled]="form.loading"> <button bitButton buttonType="primary" class="btn-submit" [disabled]="form.loading">
<i class="bwi bwi-spinner bwi-spin" title="{{ 'loading' | i18n }}" aria-hidden="true"></i> <i class="bwi bwi-spinner bwi-spin" title="{{ 'loading' | i18n }}" aria-hidden="true"></i>
<span>{{ "changeMasterPassword" | i18n }}</span> <span>{{ "changeMasterPassword" | i18n }}</span>
</button> </button>

View File

@@ -3,7 +3,7 @@
{{ "paymentMethod" | i18n }} {{ "paymentMethod" | i18n }}
</h1> </h1>
<button <button
bit-button bitButton
buttonType="secondary" buttonType="secondary"
(click)="load()" (click)="load()"
class="tw-ml-auto" class="tw-ml-auto"
@@ -28,7 +28,7 @@
<strong>{{ creditOrBalance | currency: "$" }}</strong> <strong>{{ creditOrBalance | currency: "$" }}</strong>
</p> </p>
<p>{{ "creditAppliedDesc" | i18n }}</p> <p>{{ "creditAppliedDesc" | i18n }}</p>
<button bit-button buttonType="secondary" (click)="addCredit()" *ngIf="!showAddCredit"> <button bitButton buttonType="secondary" (click)="addCredit()" *ngIf="!showAddCredit">
{{ "addCredit" | i18n }} {{ "addCredit" | i18n }}
</button> </button>
<app-add-credit <app-add-credit
@@ -56,7 +56,7 @@
{{ paymentSource.description }} {{ paymentSource.description }}
</p> </p>
</ng-container> </ng-container>
<button bit-button buttonType="secondary" (click)="changePayment()" *ngIf="!showAdjustPayment"> <button bitButton buttonType="secondary" (click)="changePayment()" *ngIf="!showAdjustPayment">
{{ (paymentSource ? "changePaymentMethod" : "addPaymentMethod") | i18n }} {{ (paymentSource ? "changePaymentMethod" : "addPaymentMethod") | i18n }}
</button> </button>
<app-adjust-payment <app-adjust-payment

View File

@@ -48,7 +48,7 @@
{{ "premiumPrice" | i18n: (premiumPrice | currency: "$") }} {{ "premiumPrice" | i18n: (premiumPrice | currency: "$") }}
</p> </p>
<a <a
bit-button bitButton
href="https://vault.bitwarden.com/#/settings/premium" href="https://vault.bitwarden.com/#/settings/premium"
target="_blank" target="_blank"
rel="noopener" rel="noopener"
@@ -69,7 +69,7 @@
}}</small> }}</small>
</div> </div>
<button <button
bit-button bitButton
buttonType="primary" buttonType="primary"
type="submit" type="submit"
class="btn-submit" class="btn-submit"
@@ -125,13 +125,7 @@
</p> </p>
</div> </div>
<small class="text-muted font-italic">{{ "paymentChargedAnnually" | i18n }}</small> <small class="text-muted font-italic">{{ "paymentChargedAnnually" | i18n }}</small>
<button <button bitButton buttonType="primary" type="submit" class="btn-submit" [disabled]="form.loading">
bit-button
buttonType="primary"
type="submit"
class="btn-submit"
[disabled]="form.loading"
>
<i class="bwi bwi-spinner bwi-spin" title="{{ 'loading' | i18n }}" aria-hidden="true"></i> <i class="bwi bwi-spinner bwi-spin" title="{{ 'loading' | i18n }}" aria-hidden="true"></i>
<span>{{ "submit" | i18n }}</span> <span>{{ "submit" | i18n }}</span>
</button> </button>

View File

@@ -8,10 +8,10 @@
<p> <p>
{{ "userApiKeyDesc" | i18n }} {{ "userApiKeyDesc" | i18n }}
</p> </p>
<button bit-button buttonType="secondary" (click)="viewUserApiKey()"> <button bitButton buttonType="secondary" (click)="viewUserApiKey()">
{{ "viewApiKey" | i18n }} {{ "viewApiKey" | i18n }}
</button> </button>
<button bit-button buttonType="secondary" (click)="rotateUserApiKey()"> <button bitButton buttonType="secondary" (click)="rotateUserApiKey()">
{{ "rotateApiKey" | i18n }} {{ "rotateApiKey" | i18n }}
</button> </button>
<ng-template #viewUserApiKeyTemplate></ng-template> <ng-template #viewUserApiKeyTemplate></ng-template>

View File

@@ -5,7 +5,7 @@
<p *ngIf="organizationId">{{ "twoStepLoginOrganizationDesc" | i18n }}</p> <p *ngIf="organizationId">{{ "twoStepLoginOrganizationDesc" | i18n }}</p>
<bit-callout type="warning" *ngIf="!organizationId"> <bit-callout type="warning" *ngIf="!organizationId">
<p>{{ "twoStepLoginRecoveryWarning" | i18n }}</p> <p>{{ "twoStepLoginRecoveryWarning" | i18n }}</p>
<button bit-button buttonType="secondary" (click)="recoveryCode()"> <button bitButton buttonType="secondary" (click)="recoveryCode()">
{{ "viewRecoveryCode" | i18n }} {{ "viewRecoveryCode" | i18n }}
</button> </button>
</bit-callout> </bit-callout>
@@ -45,7 +45,7 @@
</div> </div>
<div class="ml-auto"> <div class="ml-auto">
<button <button
bit-button bitButton
buttonType="secondary" buttonType="secondary"
[disabled]="!canAccessPremium && p.premium" [disabled]="!canAccessPremium && p.premium"
(click)="manage(p.type)" (click)="manage(p.type)"

View File

@@ -3,7 +3,7 @@
{{ "billingHistory" | i18n }} {{ "billingHistory" | i18n }}
</h1> </h1>
<button <button
bit-button bitButton
buttonType="secondary" buttonType="secondary"
(click)="load()" (click)="load()"
class="tw-ml-auto" class="tw-ml-auto"

View File

@@ -39,7 +39,7 @@
> >
<p>{{ "subscriptionPendingCanceled" | i18n }}</p> <p>{{ "subscriptionPendingCanceled" | i18n }}</p>
<button <button
bit-button bitButton
type="button" type="button"
buttonType="secondary" buttonType="secondary"
#reinstateBtn #reinstateBtn
@@ -63,7 +63,7 @@
<dt>{{ "status" | i18n }}</dt> <dt>{{ "status" | i18n }}</dt>
<dd> <dd>
<span class="text-capitalize">{{ (subscription && subscription.status) || "-" }}</span> <span class="text-capitalize">{{ (subscription && subscription.status) || "-" }}</span>
<span bit-badge badgeType="warning" *ngIf="subscriptionMarkedForCancel">{{ <span bitBadge badgeType="warning" *ngIf="subscriptionMarkedForCancel">{{
"pendingCancellation" | i18n "pendingCancellation" | i18n
}}</span> }}</span>
</dd> </dd>
@@ -96,11 +96,11 @@
</div> </div>
<ng-container *ngIf="selfHosted"> <ng-container *ngIf="selfHosted">
<div> <div>
<button type="button" bit-button buttonType="secondary" (click)="updateLicense()"> <button type="button" bitButton buttonType="secondary" (click)="updateLicense()">
{{ "updateLicense" | i18n }} {{ "updateLicense" | i18n }}
</button> </button>
<a <a
bit-button bitButton
buttonType="secondary" buttonType="secondary"
href="https://vault.bitwarden.com/#/settings/subscription" href="https://vault.bitwarden.com/#/settings/subscription"
target="_blank" target="_blank"
@@ -131,7 +131,7 @@
<ng-container *ngIf="!selfHosted"> <ng-container *ngIf="!selfHosted">
<div class="d-flex"> <div class="d-flex">
<button <button
bit-button bitButton
type="button" type="button"
buttonType="secondary" buttonType="secondary"
(click)="downloadLicense()" (click)="downloadLicense()"
@@ -140,7 +140,7 @@
{{ "downloadLicense" | i18n }} {{ "downloadLicense" | i18n }}
</button> </button>
<button <button
bit-button bitButton
#cancelBtn #cancelBtn
type="button" type="button"
buttonType="danger" buttonType="danger"
@@ -171,11 +171,11 @@
<ng-container *ngIf="subscription && !subscription.cancelled && !subscriptionMarkedForCancel"> <ng-container *ngIf="subscription && !subscription.cancelled && !subscriptionMarkedForCancel">
<div class="mt-3"> <div class="mt-3">
<div class="d-flex" *ngIf="!showAdjustStorage"> <div class="d-flex" *ngIf="!showAdjustStorage">
<button bit-button type="button" buttonType="secondary" (click)="adjustStorage(true)"> <button bitButton type="button" buttonType="secondary" (click)="adjustStorage(true)">
{{ "addStorage" | i18n }} {{ "addStorage" | i18n }}
</button> </button>
<button <button
bit-button bitButton
type="button" type="button"
buttonType="secondary" buttonType="secondary"
class="tw-ml-1" class="tw-ml-1"

View File

@@ -64,12 +64,12 @@
</button> </button>
<bit-menu #cipherOptions> <bit-menu #cipherOptions>
<ng-container *ngIf="c.type === cipherType.Login && !c.isDeleted"> <ng-container *ngIf="c.type === cipherType.Login && !c.isDeleted">
<button bit-menu-item (click)="copy(c, c.login.username, 'username', 'Username')"> <button bitMenuItem (click)="copy(c, c.login.username, 'username', 'Username')">
<i class="bwi bwi-fw bwi-clone" aria-hidden="true"></i> <i class="bwi bwi-fw bwi-clone" aria-hidden="true"></i>
{{ "copyUsername" | i18n }} {{ "copyUsername" | i18n }}
</button> </button>
<button <button
bit-menu-item bitMenuItem
(click)="copy(c, c.login.password, 'password', 'Password')" (click)="copy(c, c.login.password, 'password', 'Password')"
*ngIf="c.viewPassword" *ngIf="c.viewPassword"
> >
@@ -77,24 +77,24 @@
{{ "copyPassword" | i18n }} {{ "copyPassword" | i18n }}
</button> </button>
<button <button
bit-menu-item bitMenuItem
(click)="copy(c, c.login.totp, 'verificationCodeTotp', 'TOTP')" (click)="copy(c, c.login.totp, 'verificationCodeTotp', 'TOTP')"
*ngIf="displayTotpCopyButton(c)" *ngIf="displayTotpCopyButton(c)"
> >
<i class="bwi bwi-fw bwi-clone" aria-hidden="true"></i> <i class="bwi bwi-fw bwi-clone" aria-hidden="true"></i>
{{ "copyVerificationCode" | i18n }} {{ "copyVerificationCode" | i18n }}
</button> </button>
<button bit-menu-item *ngIf="c.login.canLaunch" (click)="launch(c.login.launchUri)"> <button bitMenuItem *ngIf="c.login.canLaunch" (click)="launch(c.login.launchUri)">
<i class="bwi bwi-fw bwi-share-square" aria-hidden="true"></i> <i class="bwi bwi-fw bwi-share-square" aria-hidden="true"></i>
{{ "launch" | i18n }} {{ "launch" | i18n }}
</button> </button>
</ng-container> </ng-container>
<button bit-menu-item (click)="attachments(c)"> <button bitMenuItem (click)="attachments(c)">
<i class="bwi bwi-fw bwi-paperclip" aria-hidden="true"></i> <i class="bwi bwi-fw bwi-paperclip" aria-hidden="true"></i>
{{ "attachments" | i18n }} {{ "attachments" | i18n }}
</button> </button>
<button <button
bit-menu-item bitMenuItem
*ngIf="((!organization && !c.organizationId) || organization) && !c.isDeleted" *ngIf="((!organization && !c.organizationId) || organization) && !c.isDeleted"
(click)="clone(c)" (click)="clone(c)"
> >
@@ -102,26 +102,26 @@
{{ "clone" | i18n }} {{ "clone" | i18n }}
</button> </button>
<button <button
bit-menu-item bitMenuItem
*ngIf="!organization && !c.organizationId && !c.isDeleted" *ngIf="!organization && !c.organizationId && !c.isDeleted"
(click)="share(c)" (click)="share(c)"
> >
<i class="bwi bwi-fw bwi-arrow-circle-right" aria-hidden="true"></i> <i class="bwi bwi-fw bwi-arrow-circle-right" aria-hidden="true"></i>
{{ "moveToOrganization" | i18n }} {{ "moveToOrganization" | i18n }}
</button> </button>
<button bit-menu-item *ngIf="c.organizationId && !c.isDeleted" (click)="collections(c)"> <button bitMenuItem *ngIf="c.organizationId && !c.isDeleted" (click)="collections(c)">
<i class="bwi bwi-fw bwi-collection" aria-hidden="true"></i> <i class="bwi bwi-fw bwi-collection" aria-hidden="true"></i>
{{ "collections" | i18n }} {{ "collections" | i18n }}
</button> </button>
<button bit-menu-item *ngIf="c.organizationId && accessEvents" (click)="events(c)"> <button bitMenuItem *ngIf="c.organizationId && accessEvents" (click)="events(c)">
<i class="bwi bwi-fw bwi-file-text" aria-hidden="true"></i> <i class="bwi bwi-fw bwi-file-text" aria-hidden="true"></i>
{{ "eventLogs" | i18n }} {{ "eventLogs" | i18n }}
</button> </button>
<button bit-menu-item (click)="restore(c)" *ngIf="c.isDeleted"> <button bitMenuItem (click)="restore(c)" *ngIf="c.isDeleted">
<i class="bwi bwi-fw bwi-undo" aria-hidden="true"></i> <i class="bwi bwi-fw bwi-undo" aria-hidden="true"></i>
{{ "restore" | i18n }} {{ "restore" | i18n }}
</button> </button>
<button bit-menu-item (click)="delete(c)"> <button bitMenuItem (click)="delete(c)">
<span class="tw-text-danger"> <span class="tw-text-danger">
<i class="bwi bwi-fw bwi-trash" aria-hidden="true"></i> <i class="bwi bwi-fw bwi-trash" aria-hidden="true"></i>
{{ (c.isDeleted ? "permanentlyDelete" : "delete") | i18n }} {{ (c.isDeleted ? "permanentlyDelete" : "delete") | i18n }}