mirror of
https://github.com/bitwarden/browser
synced 2026-02-06 11:43:51 +00:00
Add feature flag to the changes
This commit is contained in:
@@ -7,20 +7,20 @@
|
||||
<a
|
||||
bitButton
|
||||
routerLink="create"
|
||||
*ngIf="canAddClients"
|
||||
*ngIf="manageOrganizations && isSuspensionActive"
|
||||
buttonType="primary"
|
||||
[title]="addClientTooltip"
|
||||
[title]="addSuspensionTooltip"
|
||||
>
|
||||
<i class="bwi bwi-plus bwi-fw" aria-hidden="true"></i>
|
||||
{{ "newClient" | i18n }}
|
||||
</a>
|
||||
<button
|
||||
*ngIf="manageOrganizations && !canAddClients"
|
||||
*ngIf="manageOrganizations && isSuspensionActive"
|
||||
type="button"
|
||||
bitButton
|
||||
buttonType="primary"
|
||||
[disabled]="true"
|
||||
[title]="addClientTooltip"
|
||||
[title]="addSuspensionTooltip"
|
||||
>
|
||||
<i class="bwi bwi-plus bwi-fw" aria-hidden="true"></i>
|
||||
{{ "newClient" | i18n }}
|
||||
@@ -28,8 +28,8 @@
|
||||
<button
|
||||
type="button"
|
||||
bitButton
|
||||
[disabled]="!canAddClients"
|
||||
[title]="addClientTooltip"
|
||||
[disabled]="isSuspensionActive"
|
||||
[title]="addSuspensionTooltip"
|
||||
(click)="addExistingOrganization()"
|
||||
*ngIf="manageOrganizations && showAddExisting"
|
||||
>
|
||||
|
||||
@@ -18,6 +18,8 @@ import { ProviderOrganizationOrganizationDetailsResponse } from "@bitwarden/comm
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||
import { PlanType } from "@bitwarden/common/billing/enums";
|
||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { ValidationService } from "@bitwarden/common/platform/abstractions/validation.service";
|
||||
import {
|
||||
@@ -60,26 +62,15 @@ export class ClientsComponent {
|
||||
addableOrganizations: Organization[] = [];
|
||||
loading = true;
|
||||
manageOrganizations = false;
|
||||
isAdminOrServiceUser = false;
|
||||
showAddExisting = false;
|
||||
dataSource: TableDataSource<ProviderOrganizationOrganizationDetailsResponse> =
|
||||
new TableDataSource();
|
||||
protected searchControl = new FormControl("", { nonNullable: true });
|
||||
|
||||
// Computed properties for provider suspension state
|
||||
get isProviderDisabled(): boolean {
|
||||
return !this.provider?.enabled;
|
||||
}
|
||||
|
||||
get canAddClients(): boolean {
|
||||
return this.manageOrganizations && !this.isProviderDisabled;
|
||||
}
|
||||
|
||||
get addClientTooltip(): string {
|
||||
if (this.isProviderDisabled) {
|
||||
return this.i18nService.t("providerIsDisabled");
|
||||
}
|
||||
return "";
|
||||
}
|
||||
protected providerPortalTakeover$ = this.configService.getFeatureFlag$(
|
||||
FeatureFlag.PM21821_ProviderPortalTakeover,
|
||||
);
|
||||
private providerPortalTakeoverEnabled = false;
|
||||
|
||||
constructor(
|
||||
private router: Router,
|
||||
@@ -94,17 +85,28 @@ export class ClientsComponent {
|
||||
private toastService: ToastService,
|
||||
private validationService: ValidationService,
|
||||
private webProviderService: WebProviderService,
|
||||
private configService: ConfigService,
|
||||
) {
|
||||
this.activatedRoute.queryParams.pipe(first(), takeUntilDestroyed()).subscribe((queryParams) => {
|
||||
this.searchControl.setValue(queryParams.search);
|
||||
});
|
||||
|
||||
this.providerPortalTakeover$.pipe(takeUntilDestroyed()).subscribe((enabled) => {
|
||||
this.providerPortalTakeoverEnabled = enabled;
|
||||
});
|
||||
|
||||
this.activatedRoute.parent?.params
|
||||
?.pipe(
|
||||
switchMap((params) => {
|
||||
this.providerId = params.providerId;
|
||||
return this.providerService.get$(this.providerId).pipe(
|
||||
map((provider) => provider?.providerStatus === ProviderStatusType.Billable),
|
||||
map((provider) => {
|
||||
this.provider = provider;
|
||||
this.isAdminOrServiceUser =
|
||||
provider.type === ProviderUserType.ProviderAdmin ||
|
||||
provider.type === ProviderUserType.ServiceUser;
|
||||
return provider?.providerStatus === ProviderStatusType.Billable;
|
||||
}),
|
||||
map((isBillable) => {
|
||||
if (isBillable) {
|
||||
return from(
|
||||
@@ -159,11 +161,6 @@ export class ClientsComponent {
|
||||
const userId = await firstValueFrom(this.accountService.activeAccount$.pipe(getUserId));
|
||||
const clients = response.data != null && response.data.length > 0 ? response.data : [];
|
||||
this.dataSource.data = clients;
|
||||
|
||||
// Store the provider for disabled state checks
|
||||
this.provider = await this.providerService.get(this.providerId);
|
||||
this.manageOrganizations = this.provider.type === ProviderUserType.ProviderAdmin;
|
||||
|
||||
const candidateOrgs = (
|
||||
await firstValueFrom(this.organizationService.organizations$(userId))
|
||||
).filter((o) => o.isOwner && o.providerId == null);
|
||||
@@ -188,4 +185,14 @@ export class ClientsComponent {
|
||||
await this.load();
|
||||
}
|
||||
}
|
||||
|
||||
get isSuspensionActive(): boolean {
|
||||
return (
|
||||
this.isAdminOrServiceUser && this.providerPortalTakeoverEnabled && !this.provider?.enabled
|
||||
);
|
||||
}
|
||||
|
||||
get addSuspensionTooltip(): string {
|
||||
return this.isSuspensionActive ? this.i18nService.t("providerIsDisabled") : "";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
[route]="(isBillable | async) ? 'manage-client-organizations' : 'clients'"
|
||||
>
|
||||
<i
|
||||
*ngIf="!provider.enabled"
|
||||
*ngIf="!provider.enabled && (providerPortalTakeover$ | async)"
|
||||
slot="end"
|
||||
class="bwi bwi-exclamation-triangle tw-text-danger"
|
||||
title="{{ 'providerIsDisabled' | i18n }}"
|
||||
|
||||
@@ -35,6 +35,7 @@ export class ProvidersLayoutComponent implements OnInit, OnDestroy {
|
||||
|
||||
protected clientsTranslationKey$: Observable<string>;
|
||||
protected managePaymentDetailsOutsideCheckout$: Observable<boolean>;
|
||||
protected providerPortalTakeover$: Observable<boolean>;
|
||||
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
@@ -77,6 +78,10 @@ export class ProvidersLayoutComponent implements OnInit, OnDestroy {
|
||||
this.managePaymentDetailsOutsideCheckout$ = this.configService.getFeatureFlag$(
|
||||
FeatureFlag.PM21881_ManagePaymentDetailsOutsideCheckout,
|
||||
);
|
||||
|
||||
this.providerPortalTakeover$ = this.configService.getFeatureFlag$(
|
||||
FeatureFlag.PM21821_ProviderPortalTakeover,
|
||||
);
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
buttonType="primary"
|
||||
type="button"
|
||||
[bitMenuTriggerFor]="clientMenu"
|
||||
[disabled]="!canAddClients"
|
||||
[title]="addClientTooltip"
|
||||
appA11yTitle="{{ canAddClients ? ('add' | i18n) : addClientTooltip }}"
|
||||
[disabled]="isSuspensionActive"
|
||||
[title]="suspendedTooltip"
|
||||
appA11yTitle="{{ isSuspensionActive ? ('add' | i18n) : suspendedTooltip }}"
|
||||
>
|
||||
<i class="bwi bwi-plus bwi-fw" aria-hidden="true"></i>
|
||||
{{ "add" | i18n }}
|
||||
@@ -16,8 +16,8 @@
|
||||
<button
|
||||
type="button"
|
||||
bitMenuItem
|
||||
[disabled]="!canAddClients"
|
||||
[title]="addClientTooltip"
|
||||
[disabled]="isSuspensionActive"
|
||||
[title]="suspendedTooltip"
|
||||
(click)="createClient()"
|
||||
>
|
||||
<i aria-hidden="true" class="bwi bwi-business"></i>
|
||||
@@ -26,8 +26,8 @@
|
||||
<button
|
||||
type="button"
|
||||
bitMenuItem
|
||||
[disabled]="!canAddClients"
|
||||
[title]="addClientTooltip"
|
||||
[disabled]="isSuspensionActive"
|
||||
[title]="suspendedTooltip"
|
||||
(click)="addExistingOrganization()"
|
||||
>
|
||||
<i aria-hidden="true" class="bwi bwi-filter"></i>
|
||||
@@ -90,8 +90,8 @@
|
||||
<button
|
||||
type="button"
|
||||
bitMenuItem
|
||||
[disabled]="!canManageClientNames"
|
||||
[title]="manageClientNameTooltip"
|
||||
[disabled]="isSuspensionActive"
|
||||
[title]="suspendedTooltip"
|
||||
(click)="manageClientName(row)"
|
||||
>
|
||||
<i aria-hidden="true" class="bwi bwi-pencil-square"></i>
|
||||
@@ -100,14 +100,13 @@
|
||||
<button
|
||||
type="button"
|
||||
bitMenuItem
|
||||
[disabled]="!canManageClientSubscriptions"
|
||||
[title]="manageSubscriptionTooltip"
|
||||
[disabled]="isSuspensionActive"
|
||||
[title]="suspendedTooltip"
|
||||
(click)="manageClientSubscription(row)"
|
||||
>
|
||||
<i aria-hidden="true" class="bwi bwi-family"></i>
|
||||
{{ "manageSubscription" | i18n }}
|
||||
</button>
|
||||
<!-- Keep unlink enabled even when provider is suspended -->
|
||||
<button *ngIf="isProviderAdmin" type="button" bitMenuItem (click)="remove(row)">
|
||||
<span class="tw-text-danger">
|
||||
<i aria-hidden="true" class="bwi bwi-close"></i> {{ "unlinkOrganization" | i18n }}
|
||||
@@ -119,7 +118,7 @@
|
||||
</bit-table-scroll>
|
||||
<div *ngIf="dataSource.data.length === 0" class="tw-mt-10">
|
||||
<app-no-clients
|
||||
[showAddOrganizationButton]="canAddClients"
|
||||
[showAddOrganizationButton]="isSuspensionActive"
|
||||
(addNewOrganizationClicked)="createClient()"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -15,6 +15,8 @@ import { Provider } from "@bitwarden/common/admin-console/models/domain/provider
|
||||
import { ProviderOrganizationOrganizationDetailsResponse } from "@bitwarden/common/admin-console/models/response/provider/provider-organization.response";
|
||||
import { BillingApiServiceAbstraction } from "@bitwarden/common/billing/abstractions";
|
||||
import { PlanResponse } from "@bitwarden/common/billing/models/response/plan.response";
|
||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { ValidationService } from "@bitwarden/common/platform/abstractions/validation.service";
|
||||
import {
|
||||
@@ -65,6 +67,7 @@ export class ManageClientsComponent {
|
||||
provider: Provider | undefined;
|
||||
loading = true;
|
||||
isProviderAdmin = false;
|
||||
isServiceUser = false;
|
||||
dataSource: TableDataSource<ProviderOrganizationOrganizationDetailsResponse> =
|
||||
new TableDataSource();
|
||||
|
||||
@@ -75,43 +78,10 @@ export class ManageClientsComponent {
|
||||
clientColumnHeader = this.i18nService.t("client");
|
||||
newClientButtonLabel = this.i18nService.t("newClient");
|
||||
|
||||
// Computed properties for provider suspension state
|
||||
get isProviderDisabled(): boolean {
|
||||
return !this.provider?.enabled;
|
||||
}
|
||||
|
||||
get canAddClients(): boolean {
|
||||
return this.isProviderAdmin && !this.isProviderDisabled;
|
||||
}
|
||||
|
||||
get canManageClientNames(): boolean {
|
||||
return this.isProviderAdmin && !this.isProviderDisabled;
|
||||
}
|
||||
|
||||
get canManageClientSubscriptions(): boolean {
|
||||
return this.isProviderAdmin && !this.isProviderDisabled;
|
||||
}
|
||||
|
||||
get addClientTooltip(): string {
|
||||
if (this.isProviderDisabled) {
|
||||
return this.i18nService.t("providerIsDisabled");
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
get manageClientNameTooltip(): string {
|
||||
if (this.isProviderDisabled) {
|
||||
return this.i18nService.t("providerIsDisabled");
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
get manageSubscriptionTooltip(): string {
|
||||
if (this.isProviderDisabled) {
|
||||
return this.i18nService.t("providerIsDisabled");
|
||||
}
|
||||
return "";
|
||||
}
|
||||
protected providerPortalTakeover$ = this.configService.getFeatureFlag$(
|
||||
FeatureFlag.PM21821_ProviderPortalTakeover,
|
||||
);
|
||||
private providerPortalTakeoverEnabled = false;
|
||||
|
||||
constructor(
|
||||
private billingApiService: BillingApiServiceAbstraction,
|
||||
@@ -124,11 +94,16 @@ export class ManageClientsComponent {
|
||||
private validationService: ValidationService,
|
||||
private webProviderService: WebProviderService,
|
||||
private billingNotificationService: BillingNotificationService,
|
||||
private configService: ConfigService,
|
||||
) {
|
||||
this.activatedRoute.queryParams.pipe(first(), takeUntilDestroyed()).subscribe((queryParams) => {
|
||||
this.searchControl.setValue(queryParams.search);
|
||||
});
|
||||
|
||||
this.providerPortalTakeover$.pipe(takeUntilDestroyed()).subscribe((enabled) => {
|
||||
this.providerPortalTakeoverEnabled = enabled;
|
||||
});
|
||||
|
||||
this.activatedRoute.parent?.params
|
||||
?.pipe(
|
||||
switchMap((params) => {
|
||||
@@ -169,6 +144,7 @@ export class ManageClientsComponent {
|
||||
this.newClientButtonLabel = this.i18nService.t("newBusinessUnit");
|
||||
}
|
||||
this.isProviderAdmin = this.provider?.type === ProviderUserType.ProviderAdmin;
|
||||
this.isServiceUser = this.provider?.type === ProviderUserType.ServiceUser;
|
||||
this.dataSource.data = (
|
||||
await this.billingApiService.getProviderClientOrganizations(this.providerId)
|
||||
).data;
|
||||
@@ -269,4 +245,16 @@ export class ManageClientsComponent {
|
||||
this.validationService.showError(e);
|
||||
}
|
||||
}
|
||||
|
||||
get isSuspensionActive(): boolean {
|
||||
return (
|
||||
(this.isProviderAdmin || this.isServiceUser) &&
|
||||
this.providerPortalTakeoverEnabled &&
|
||||
!this.provider?.enabled
|
||||
);
|
||||
}
|
||||
|
||||
get suspendedTooltip(): string {
|
||||
return this.isSuspensionActive ? this.i18nService.t("providerIsDisabled") : "";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ export enum FeatureFlag {
|
||||
UseOrganizationWarningsService = "use-organization-warnings-service",
|
||||
AllowTrialLengthZero = "pm-20322-allow-trial-length-0",
|
||||
PM21881_ManagePaymentDetailsOutsideCheckout = "pm-21881-manage-payment-details-outside-checkout",
|
||||
PM21821_ProviderPortalTakeover = "pm-21821-provider-portal-takeover",
|
||||
|
||||
/* Data Insights and Reporting */
|
||||
EnableRiskInsightsNotifications = "enable-risk-insights-notifications",
|
||||
@@ -117,6 +118,7 @@ export const DefaultFeatureFlagValue = {
|
||||
[FeatureFlag.UseOrganizationWarningsService]: FALSE,
|
||||
[FeatureFlag.AllowTrialLengthZero]: FALSE,
|
||||
[FeatureFlag.PM21881_ManagePaymentDetailsOutsideCheckout]: FALSE,
|
||||
[FeatureFlag.PM21821_ProviderPortalTakeover]: FALSE,
|
||||
|
||||
/* Key Management */
|
||||
[FeatureFlag.PrivateKeyRegeneration]: FALSE,
|
||||
|
||||
Reference in New Issue
Block a user