Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weโ€™ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PM-14921]Customers managed by a Reseller need to see how many seats are in their subscription, while still obfuscating the cost of subscription. #12726

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
17be729
Add the seats info for reseller managed org
cyprain-okeke Jan 7, 2025
4388245
Merge branch 'main' into pm-14921-customers-managed-by-a-reseller-neeโ€ฆ
cyprain-okeke Jan 7, 2025
1d16265
Merge branch 'main' into pm-14921-customers-managed-by-a-reseller-neeโ€ฆ
cyprain-okeke Jan 15, 2025
bd7de98
Merge branch 'main' into pm-14921-customers-managed-by-a-reseller-neeโ€ฆ
cyprain-okeke Jan 15, 2025
c59a28f
Merge branch 'main' into pm-14921-customers-managed-by-a-reseller-neeโ€ฆ
cyprain-okeke Jan 27, 2025
aa6ed2b
Merge branch 'main' into pm-14921-customers-managed-by-a-reseller-neeโ€ฆ
cyprain-okeke Jan 27, 2025
e12b044
Resolve the remaining seat bug
cyprain-okeke Jan 29, 2025
fefc59d
Merge branch 'main' into pm-14921-customers-managed-by-a-reseller-neeโ€ฆ
cyprain-okeke Jan 29, 2025
22bb892
Resolve pr comments
cyprain-okeke Jan 29, 2025
295e4d3
Merge remote-tracking branch 'refs/remotes/origin/pm-14921-customers-โ€ฆ
cyprain-okeke Jan 29, 2025
fad9662
Merge branch 'main' into pm-14921-customers-managed-by-a-reseller-neeโ€ฆ
cyprain-okeke Jan 29, 2025
21e6761
Merge branch 'main' into pm-14921-customers-managed-by-a-reseller-neeโ€ฆ
cyprain-okeke Jan 29, 2025
08b60d1
code refactoring
cyprain-okeke Jan 29, 2025
9922ed9
Merge branch 'main' into pm-14921-customers-managed-by-a-reseller-neeโ€ฆ
cyprain-okeke Jan 29, 2025
f9fdf9e
Merge branch 'main' into pm-14921-customers-managed-by-a-reseller-neeโ€ฆ
cyprain-okeke Jan 30, 2025
df3b404
Merge branch 'main' into pm-14921-customers-managed-by-a-reseller-neeโ€ฆ
cyprain-okeke Jan 30, 2025
e6e31ad
Merge branch 'main' into pm-14921-customers-managed-by-a-reseller-neeโ€ฆ
cyprain-okeke Feb 3, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,10 @@ <h2 bitTypography="h2">{{ "manageSubscription" | i18n }}</h2>
</ng-template>

<ng-template #setupSelfHost>
<ng-container *ngIf="userOrg.hasReseller && resellerSeatsRemainingMessage">
<h2 bitTypography="h2" class="tw-mt-7">{{ "manageSubscription" | i18n }}</h2>
<p bitTypography="body1">{{ resellerSeatsRemainingMessage }}</p>
</ng-container>
<ng-container *ngIf="showSelfHost">
<h2 bitTypography="h2" class="tw-mt-7">
{{ "selfHostingTitleProper" | i18n }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,17 @@ import { Component, OnDestroy, OnInit } from "@angular/core";
import { ActivatedRoute } from "@angular/router";
import { firstValueFrom, lastValueFrom, Observable, Subject } from "rxjs";

import { OrganizationUserApiService } from "@bitwarden/admin-console/common";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
import {
getOrganizationById,
OrganizationService,
} from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
import { OrganizationApiKeyType } from "@bitwarden/common/admin-console/enums";
import {
OrganizationApiKeyType,
OrganizationUserStatusType,
} from "@bitwarden/common/admin-console/enums";
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { getUserId } from "@bitwarden/common/auth/services/account.service";
Expand Down Expand Up @@ -61,12 +65,15 @@ export class OrganizationSubscriptionCloudComponent implements OnInit, OnDestroy
showSubscription = true;
showSelfHost = false;
organizationIsManagedByConsolidatedBillingMSP = false;
resellerSeatsRemainingMessage: string;

protected readonly subscriptionHiddenIcon = SubscriptionHiddenIcon;
protected readonly teamsStarter = ProductTierType.TeamsStarter;

private destroy$ = new Subject<void>();

private seatsRemainingMessage: string;

constructor(
private apiService: ApiService,
private i18nService: I18nService,
Expand All @@ -79,6 +86,7 @@ export class OrganizationSubscriptionCloudComponent implements OnInit, OnDestroy
private configService: ConfigService,
private toastService: ToastService,
private billingApiService: BillingApiServiceAbstraction,
private organizationUserApiService: OrganizationUserApiService,
) {}

async ngOnInit() {
Expand All @@ -104,6 +112,28 @@ export class OrganizationSubscriptionCloudComponent implements OnInit, OnDestroy
}
}
}

if (this.userOrg.hasReseller) {
const allUsers = await this.organizationUserApiService.getAllUsers(this.userOrg.id);

const userCount = allUsers.data.filter((user) =>
[
OrganizationUserStatusType.Invited,
OrganizationUserStatusType.Accepted,
OrganizationUserStatusType.Confirmed,
].includes(user.status),
).length;

const remainingSeats = this.userOrg.seats - userCount;

const seatsRemaining = this.i18nService.t(
"seatsRemaining",
remainingSeats.toString(),
this.userOrg.seats.toString(),
);

this.resellerSeatsRemainingMessage = seatsRemaining;
}
}

ngOnDestroy() {
Expand Down
13 changes: 13 additions & 0 deletions apps/web/src/locales/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -10333,5 +10333,18 @@
"example": "Acme c"
}
}
},
"seatsRemaining": {
"message": "You have $REMAINING$ seats remaining out of $TOTAL$ seats assigned to this organization. Contact your provider to manage your subscription.",
"placeholders": {
"remaining": {
"content": "$1",
"example": "5"
},
"total": {
"content": "$2",
"example": "10"
}
}
}
}
Loading