1
0
mirror of https://github.com/bitwarden/browser.git synced 2024-11-21 11:35:34 +01:00

[AC-2860] Revise unassigned and purchased seat warning for CB (#10077)

* Rework create-client-dialog seat warning

* Rework manage-client-subscription-dialog seat warning

* Fix create client purchased seats label

* Fix manage client subscription purchased seats label logic

* Another manage subscription purchased seats fix
This commit is contained in:
Alex Morask 2024-07-17 10:12:40 -04:00 committed by GitHub
parent 83d141c914
commit e27d698d4b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 59 additions and 17 deletions

View File

@ -8564,5 +8564,8 @@
"example": "Organization name"
}
}
},
"purchasedSeatsRemoved": {
"message": "purchased seats removed"
}
}

View File

@ -58,13 +58,16 @@
</bit-label>
<input type="number" bitInput formControlName="seats" min="1" />
<bit-hint
class="tw-text-muted tw-grid tw-grid-flow-col tw-gap-1 tw-grid-cols-1 tw-grid-rows-2"
*ngIf="openSeats > 0"
class="tw-text-muted tw-grid tw-grid-flow-col tw-gap-1 tw-grid-cols-1"
[ngClass]="{
'tw-grid-rows-1': additionalSeatsPurchased <= 0,
'tw-grid-rows-2': additionalSeatsPurchased > 0
}"
>
<span class="tw-col-span-1"
>{{ unassignedSeats }} {{ "unassignedSeatsDescription" | i18n | lowercase }}</span
>
<span class="tw-col-span-1"
<span class="tw-col-span-1" *ngIf="additionalSeatsPurchased > 0"
>{{ additionalSeatsPurchased }}
{{ "purchaseSeatDescription" | i18n | lowercase }}</span
>

View File

@ -162,18 +162,16 @@ export class CreateClientDialogComponent implements OnInit {
this.dialogRef.close(this.ResultType.Submitted);
};
protected get openSeats(): number {
protected get unassignedSeats(): number {
const selectedProviderPlan = this.getSelectedProviderPlan();
if (selectedProviderPlan === null) {
return 0;
}
return selectedProviderPlan.seatMinimum - selectedProviderPlan.assignedSeats;
}
const openSeats = selectedProviderPlan.seatMinimum - selectedProviderPlan.assignedSeats;
protected get unassignedSeats(): number {
const unassignedSeats = this.openSeats - this.formGroup.value.seats;
const unassignedSeats = openSeats - this.formGroup.value.seats;
return unassignedSeats > 0 ? unassignedSeats : 0;
}
@ -185,11 +183,16 @@ export class CreateClientDialogComponent implements OnInit {
return 0;
}
const selectedSeats = this.formGroup.value.seats ?? 0;
if (selectedProviderPlan.purchasedSeats > 0) {
return this.formGroup.value.seats;
}
const purchased = selectedSeats - this.openSeats;
const additionalSeatsPurchased =
this.formGroup.value.seats +
selectedProviderPlan.assignedSeats -
selectedProviderPlan.seatMinimum;
return purchased > 0 ? purchased : 0;
return additionalSeatsPurchased > 0 ? additionalSeatsPurchased : 0;
}
private getSelectedProviderPlan(): ProviderPlanResponse {

View File

@ -16,21 +16,27 @@
formControlName="assignedSeats"
[min]="dialogParams.organization.occupiedSeats"
/>
<bit-hint class="tw-text-muted" *ngIf="openSeats > 0 || isServiceUserWithPurchasedSeats">
<bit-hint class="tw-text-muted" *ngIf="!isServiceUserWithPurchasedSeats">
<div
*ngIf="!this.isServiceUserWithPurchasedSeats"
class="tw-grid tw-grid-flow-col tw-gap-1 tw-grid-cols-1"
[ngClass]="{ 'tw-grid-rows-2': this.isProviderAdmin }"
[ngClass]="{
'tw-grid-rows-1': additionalSeatsPurchased === 0,
'tw-grid-rows-2': purchasingSeats || sellingSeats
}"
>
<span class="tw-col-span-1">
{{ unassignedSeats }} {{ "unassignedSeatsDescription" | i18n | lowercase }}
</span>
<span *ngIf="this.isProviderAdmin" class="tw-col-span-1"
<span *ngIf="purchasingSeats" class="tw-col-span-1"
>{{ additionalSeatsPurchased }}
{{ "purchaseSeatDescription" | i18n | lowercase }}</span
>
<span *ngIf="sellingSeats" class="tw-col-span-1"
>{{ purchasedSeatsRemoved }} {{ "purchasedSeatsRemoved" | i18n | lowercase }}</span
>
</div>
</bit-hint>
<bit-hint *ngIf="isServiceUserWithPurchasedSeats"></bit-hint>
</bit-form-field>
</div>
<ng-container bitDialogFooter>

View File

@ -36,7 +36,10 @@ export const openManageClientSubscriptionDialog = (
export class ManageClientSubscriptionDialogComponent implements OnInit {
protected loading = true;
protected providerPlan: ProviderPlanResponse;
protected assignedSeats: number;
protected openSeats: number;
protected purchasedSeats: number;
protected seatMinimum: number;
protected readonly ResultType = ManageClientSubscriptionDialogResultType;
protected formGroup = new FormGroup({
@ -63,7 +66,10 @@ export class ManageClientSubscriptionDialogComponent implements OnInit {
(plan) => plan.planName === this.dialogParams.organization.plan,
);
this.assignedSeats = this.providerPlan.assignedSeats;
this.openSeats = this.providerPlan.seatMinimum - this.providerPlan.assignedSeats;
this.purchasedSeats = this.providerPlan.purchasedSeats;
this.seatMinimum = this.providerPlan.seatMinimum;
this.formGroup.controls.assignedSeats.addValidators(
this.isServiceUserWithPurchasedSeats
@ -165,9 +171,22 @@ export class ManageClientSubscriptionDialogComponent implements OnInit {
const seatDifference =
this.formGroup.value.assignedSeats - this.dialogParams.organization.seats;
const purchasedSeats = seatDifference - this.openSeats;
if (this.purchasedSeats > 0) {
return seatDifference;
}
return purchasedSeats > 0 ? purchasedSeats : 0;
return seatDifference - this.openSeats;
}
get purchasedSeatsRemoved(): number {
const seatDifference =
this.dialogParams.organization.seats - this.formGroup.value.assignedSeats;
if (this.purchasedSeats >= seatDifference) {
return seatDifference;
}
return this.purchasedSeats;
}
get isProviderAdmin(): boolean {
@ -177,4 +196,12 @@ export class ManageClientSubscriptionDialogComponent implements OnInit {
get isServiceUserWithPurchasedSeats(): boolean {
return !this.isProviderAdmin && this.providerPlan && this.providerPlan.purchasedSeats > 0;
}
get purchasingSeats(): boolean {
return this.additionalSeatsPurchased > 0;
}
get sellingSeats(): boolean {
return this.purchasedSeats > 0 && this.additionalSeatsPurchased < 0;
}
}