-
-
{{ "downloadLicense" | i18n }}
-
-
+
+
+
+
+
+
diff --git a/apps/web/src/app/billing/organizations/download-license.component.ts b/apps/web/src/app/billing/organizations/download-license.component.ts
index 88a37a28aa..6b3a93548b 100644
--- a/apps/web/src/app/billing/organizations/download-license.component.ts
+++ b/apps/web/src/app/billing/organizations/download-license.component.ts
@@ -1,50 +1,61 @@
-import { Component, EventEmitter, Input, Output } from "@angular/core";
+import { DialogConfig, DIALOG_DATA, DialogRef } from "@angular/cdk/dialog";
+import { Component, Inject } from "@angular/core";
+import { FormBuilder, Validators } from "@angular/forms";
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service";
-import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
+import { DialogService } from "@bitwarden/components";
+
+export enum DownloadLicenseDialogResult {
+ Cancelled = "cancelled",
+ Downloaded = "downloaded",
+}
+type DownloadLicenseDialogData = {
+ /** current organization id */
+ organizationId: string;
+};
@Component({
- selector: "app-download-license",
templateUrl: "download-license.component.html",
})
-export class DownloadLicenseComponent {
- @Input() organizationId: string;
- @Output() onDownloaded = new EventEmitter();
- @Output() onCanceled = new EventEmitter();
-
- installationId: string;
- formPromise: Promise
;
-
+export class DownloadLicenceDialogComponent {
+ licenseForm = this.formBuilder.group({
+ installationId: ["", [Validators.required]],
+ });
constructor(
+ @Inject(DIALOG_DATA) protected data: DownloadLicenseDialogData,
+ private dialogRef: DialogRef,
private fileDownloadService: FileDownloadService,
- private logService: LogService,
private organizationApiService: OrganizationApiServiceAbstraction,
+ protected formBuilder: FormBuilder,
) {}
- async submit() {
- if (this.installationId == null || this.installationId === "") {
+ submit = async () => {
+ this.licenseForm.markAllAsTouched();
+ const installationId = this.licenseForm.get("installationId").value;
+ if (installationId == null || installationId === "") {
return;
}
-
- try {
- this.formPromise = this.organizationApiService.getLicense(
- this.organizationId,
- this.installationId,
- );
- const license = await this.formPromise;
- const licenseString = JSON.stringify(license, null, 2);
- this.fileDownloadService.download({
- fileName: "bitwarden_organization_license.json",
- blobData: licenseString,
- });
- this.onDownloaded.emit();
- } catch (e) {
- this.logService.error(e);
- }
- }
-
- cancel() {
- this.onCanceled.emit();
+ const license = await this.organizationApiService.getLicense(
+ this.data.organizationId,
+ installationId,
+ );
+ const licenseString = JSON.stringify(license, null, 2);
+ this.fileDownloadService.download({
+ fileName: "bitwarden_organization_license.json",
+ blobData: licenseString,
+ });
+ this.dialogRef.close(DownloadLicenseDialogResult.Downloaded);
+ };
+ /**
+ * Strongly typed helper to open a DownloadLicenceDialogComponent
+ * @param dialogService Instance of the dialog service that will be used to open the dialog
+ * @param config Configuration for the dialog
+ */
+ static open(dialogService: DialogService, config: DialogConfig) {
+ return dialogService.open(DownloadLicenceDialogComponent, config);
}
+ cancel = () => {
+ this.dialogRef.close(DownloadLicenseDialogResult.Cancelled);
+ };
}
diff --git a/apps/web/src/app/billing/organizations/organization-billing.module.ts b/apps/web/src/app/billing/organizations/organization-billing.module.ts
index 490ebafbff..a95efe32e4 100644
--- a/apps/web/src/app/billing/organizations/organization-billing.module.ts
+++ b/apps/web/src/app/billing/organizations/organization-billing.module.ts
@@ -8,7 +8,7 @@ import { AdjustSubscription } from "./adjust-subscription.component";
import { BillingSyncApiKeyComponent } from "./billing-sync-api-key.component";
import { BillingSyncKeyComponent } from "./billing-sync-key.component";
import { ChangePlanComponent } from "./change-plan.component";
-import { DownloadLicenseComponent } from "./download-license.component";
+import { DownloadLicenceDialogComponent } from "./download-license.component";
import { OrgBillingHistoryViewComponent } from "./organization-billing-history-view.component";
import { OrganizationBillingRoutingModule } from "./organization-billing-routing.module";
import { OrganizationPlansComponent } from "./organization-plans.component";
@@ -32,7 +32,7 @@ import { SubscriptionStatusComponent } from "./subscription-status.component";
BillingSyncApiKeyComponent,
BillingSyncKeyComponent,
ChangePlanComponent,
- DownloadLicenseComponent,
+ DownloadLicenceDialogComponent,
OrganizationSubscriptionCloudComponent,
OrganizationSubscriptionSelfhostComponent,
OrgBillingHistoryViewComponent,
diff --git a/apps/web/src/app/billing/organizations/organization-subscription-cloud.component.html b/apps/web/src/app/billing/organizations/organization-subscription-cloud.component.html
index 25ac3a7a15..e11cf602ad 100644
--- a/apps/web/src/app/billing/organizations/organization-subscription-cloud.component.html
+++ b/apps/web/src/app/billing/organizations/organization-subscription-cloud.component.html
@@ -246,13 +246,6 @@
{{ (hasBillingSyncToken ? "manageBillingSync" : "setUpBillingSync") | i18n }}
-
{{ "additionalOptions" | i18n }}
diff --git a/apps/web/src/app/billing/organizations/organization-subscription-cloud.component.ts b/apps/web/src/app/billing/organizations/organization-subscription-cloud.component.ts
index a0db7b5a20..b6282f1e7b 100644
--- a/apps/web/src/app/billing/organizations/organization-subscription-cloud.component.ts
+++ b/apps/web/src/app/billing/organizations/organization-subscription-cloud.component.ts
@@ -29,6 +29,7 @@ import {
} from "../shared/offboarding-survey.component";
import { BillingSyncApiKeyComponent } from "./billing-sync-api-key.component";
+import { DownloadLicenceDialogComponent } from "./download-license.component";
import { ManageBilling } from "./icons/manage-billing.icon";
import { SecretsManagerSubscriptionOptions } from "./sm-adjust-subscription.component";
@@ -354,8 +355,12 @@ export class OrganizationSubscriptionCloudComponent implements OnInit, OnDestroy
this.showChangePlan = false;
}
- downloadLicense() {
- this.showDownloadLicense = !this.showDownloadLicense;
+ async downloadLicense() {
+ DownloadLicenceDialogComponent.open(this.dialogService, {
+ data: {
+ organizationId: this.organizationId,
+ },
+ });
}
async manageBillingSync() {
From cb0927ac5d9e338cf0282dbb4ea01211698f3b3a Mon Sep 17 00:00:00 2001
From: Jason Ng
Date: Wed, 5 Jun 2024 10:06:52 -0400
Subject: [PATCH 2/8] [PM-8553] browser v2 search bar defects (#9506)
* update no results icon and no results scrolling
* update v2 search so the term persist when the user clicks into an item and exits the item
---
.../vault-search/vault-v2-search.component.ts | 35 ++++++++++++++-----
.../components/vault/vault-v2.component.html | 13 +++----
.../components/vault/vault-v2.component.ts | 5 +--
.../services/vault-popup-items.service.ts | 9 ++---
libs/components/src/icon/icons/index.ts | 1 +
libs/components/src/icon/icons/no-results.ts | 18 ++++++++++
6 files changed, 56 insertions(+), 25 deletions(-)
create mode 100644 libs/components/src/icon/icons/no-results.ts
diff --git a/apps/browser/src/vault/popup/components/vault-v2/vault-search/vault-v2-search.component.ts b/apps/browser/src/vault/popup/components/vault-v2/vault-search/vault-v2-search.component.ts
index 321717285a..e610032160 100644
--- a/apps/browser/src/vault/popup/components/vault-v2/vault-search/vault-v2-search.component.ts
+++ b/apps/browser/src/vault/popup/components/vault-v2/vault-search/vault-v2-search.component.ts
@@ -1,12 +1,14 @@
import { CommonModule } from "@angular/common";
-import { Component, Output, EventEmitter } from "@angular/core";
+import { Component } from "@angular/core";
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
import { FormsModule } from "@angular/forms";
-import { Subject, debounceTime } from "rxjs";
+import { Subject, Subscription, debounceTime, filter } from "rxjs";
import { JslibModule } from "@bitwarden/angular/jslib.module";
import { SearchModule } from "@bitwarden/components";
+import { VaultPopupItemsService } from "../../../services/vault-popup-items.service";
+
const SearchTextDebounceInterval = 200;
@Component({
@@ -17,19 +19,34 @@ const SearchTextDebounceInterval = 200;
})
export class VaultV2SearchComponent {
searchText: string;
- @Output() searchTextChanged = new EventEmitter();
private searchText$ = new Subject();
- constructor() {
- this.searchText$
- .pipe(debounceTime(SearchTextDebounceInterval), takeUntilDestroyed())
- .subscribe((data) => {
- this.searchTextChanged.emit(data);
- });
+ constructor(private vaultPopupItemsService: VaultPopupItemsService) {
+ this.subscribeToLatestSearchText();
+ this.subscribeToApplyFilter();
}
onSearchTextChanged() {
this.searchText$.next(this.searchText);
}
+
+ subscribeToLatestSearchText(): Subscription {
+ return this.vaultPopupItemsService.latestSearchText$
+ .pipe(
+ takeUntilDestroyed(),
+ filter((data) => !!data),
+ )
+ .subscribe((text) => {
+ this.searchText = text;
+ });
+ }
+
+ subscribeToApplyFilter(): Subscription {
+ return this.searchText$
+ .pipe(debounceTime(SearchTextDebounceInterval), takeUntilDestroyed())
+ .subscribe((data) => {
+ this.vaultPopupItemsService.applyFilter(data);
+ });
+ }
}
diff --git a/apps/browser/src/vault/popup/components/vault/vault-v2.component.html b/apps/browser/src/vault/popup/components/vault/vault-v2.component.html
index f99d3cbb30..9f38fd61fa 100644
--- a/apps/browser/src/vault/popup/components/vault/vault-v2.component.html
+++ b/apps/browser/src/vault/popup/components/vault/vault-v2.component.html
@@ -22,18 +22,15 @@