[PM 5012] migrate adjust subscription component (#8239)

* adjust subscription component migration

* adjust subscription component migration

* adjust subscription component migration
This commit is contained in:
vinith-kovan 2024-05-09 21:01:00 +05:30 committed by GitHub
parent 30ef66139e
commit 0c2e8c15dc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 106 additions and 89 deletions

View File

@ -1,65 +1,57 @@
<form #form (ngSubmit)="submit()" [appApiAction]="formPromise" ngNativeValidate> <form [formGroup]="adjustSubscriptionForm" [bitSubmit]="submit">
<div> <div class="tw-grid tw-grid-cols-12 tw-gap-4">
<div class="row"> <div class="tw-col-span-8">
<div class="form-group col-8"> <bit-form-field>
<label for="newSeatCount">{{ "subscriptionSeats" | i18n }}</label> <bit-label>{{ "subscriptionSeats" | i18n }}</bit-label>
<input <input bitInput formControlName="newSeatCount" type="number" min="0" step="1" />
id="newSeatCount" <bit-hint>
class="form-control"
type="number"
name="NewSeatCount"
[(ngModel)]="newSeatCount"
min="0"
step="1"
required
/>
<small class="d-block text-muted mb-4">
<strong>{{ "total" | i18n }}:</strong> {{ additionalSeatCount || 0 }} &times; <strong>{{ "total" | i18n }}:</strong> {{ additionalSeatCount || 0 }} &times;
{{ seatPrice | currency: "$" }} = {{ adjustedSeatTotal | currency: "$" }} / {{ seatPrice | currency: "$" }} = {{ adjustedSeatTotal | currency: "$" }} /
{{ interval | i18n }} {{ interval | i18n }}</bit-hint
</small> >
</div> </bit-form-field>
</div> </div>
<div class="row mb-4"> </div>
<div class="form-group col-sm"> <div>
<div class="form-check"> <bit-form-control>
<input <input
id="limitSubscription" bitCheckbox
class="form-check-input" formControlName="limitSubscription"
type="checkbox" type="checkbox"
name="LimitSubscription" (change)="limitSubscriptionChanged()"
[(ngModel)]="limitSubscription" />
(change)="limitSubscriptionChanged()" <bit-label>{{ "limitSubscription" | i18n }}</bit-label>
/> <bit-hint> {{ "limitSubscriptionDesc" | i18n }}</bit-hint>
<label for="limitSubscription">{{ "limitSubscription" | i18n }}</label> </bit-form-control>
</div> </div>
<small class="d-block text-muted">{{ "limitSubscriptionDesc" | i18n }}</small> <div
</div> class="tw-grid tw-grid-cols-12 tw-gap-4 tw-mb-4"
</div> [hidden]="!adjustSubscriptionForm.value.limitSubscription"
<div class="row mb-4" [hidden]="!limitSubscription"> >
<div class="form-group col-sm"> <div class="tw-col-span-8">
<label for="maxAutoscaleSeats">{{ "maxSeatLimit" | i18n }}</label> <bit-form-field>
<bit-label>{{ "maxSeatLimit" | i18n }}</bit-label>
<input <input
id="maxAutoscaleSeats" bitInput
class="form-control col-8" formControlName="newMaxSeats"
type="number" type="number"
name="MaxAutoscaleSeats" [min]="
[(ngModel)]="newMaxSeats" adjustSubscriptionForm.value.newSeatCount == null
[min]="newSeatCount == null ? 1 : newSeatCount" ? 1
: adjustSubscriptionForm.value.newSeatCount
"
step="1" step="1"
[required]="limitSubscription"
/> />
<small class="d-block text-muted"> <bit-hint>
<strong>{{ "maxSeatCost" | i18n }}:</strong> {{ additionalMaxSeatCount || 0 }} &times; <strong>{{ "maxSeatCost" | i18n }}:</strong> {{ additionalMaxSeatCount || 0 }} &times;
{{ seatPrice | currency: "$" }} = {{ maxSeatTotal | currency: "$" }} / {{ seatPrice | currency: "$" }} = {{ maxSeatTotal | currency: "$" }} /
{{ interval | i18n }} {{ interval | i18n }}</bit-hint
</small> >
</div> </bit-form-field>
</div> </div>
<button type="submit" class="btn btn-primary btn-submit" [disabled]="form.loading">
<i class="bwi bwi-spinner bwi-spin" title="{{ 'loading' | i18n }}" aria-hidden="true"></i>
<span>{{ "save" | i18n }}</span>
</button>
</div> </div>
<button bitButton buttonType="primary" bitFormButton type="submit">
{{ "save" | i18n }}
</button>
</form> </form>
<app-payment [showMethods]="false"></app-payment> <app-payment [showMethods]="false"></app-payment>

View File

@ -1,77 +1,102 @@
import { Component, EventEmitter, Input, Output } from "@angular/core"; import { Component, EventEmitter, Input, OnDestroy, OnInit, Output } from "@angular/core";
import { FormBuilder, Validators } from "@angular/forms";
import { Subject, takeUntil } from "rxjs";
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction"; import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
import { OrganizationSubscriptionUpdateRequest } from "@bitwarden/common/billing/models/request/organization-subscription-update.request"; import { OrganizationSubscriptionUpdateRequest } from "@bitwarden/common/billing/models/request/organization-subscription-update.request";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service"; import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
@Component({ @Component({
selector: "app-adjust-subscription", selector: "app-adjust-subscription",
templateUrl: "adjust-subscription.component.html", templateUrl: "adjust-subscription.component.html",
}) })
export class AdjustSubscription { export class AdjustSubscription implements OnInit, OnDestroy {
@Input() organizationId: string; @Input() organizationId: string;
@Input() maxAutoscaleSeats: number; @Input() maxAutoscaleSeats: number;
@Input() currentSeatCount: number; @Input() currentSeatCount: number;
@Input() seatPrice = 0; @Input() seatPrice = 0;
@Input() interval = "year"; @Input() interval = "year";
@Output() onAdjusted = new EventEmitter(); @Output() onAdjusted = new EventEmitter();
private destroy$ = new Subject<void>();
formPromise: Promise<void>; adjustSubscriptionForm = this.formBuilder.group({
limitSubscription: boolean; newSeatCount: [0, [Validators.min(0)]],
newSeatCount: number; limitSubscription: [false],
newMaxSeats: number; newMaxSeats: [0, [Validators.min(0)]],
});
get limitSubscription(): boolean {
return this.adjustSubscriptionForm.value.limitSubscription;
}
constructor( constructor(
private i18nService: I18nService, private i18nService: I18nService,
private platformUtilsService: PlatformUtilsService, private platformUtilsService: PlatformUtilsService,
private logService: LogService,
private organizationApiService: OrganizationApiServiceAbstraction, private organizationApiService: OrganizationApiServiceAbstraction,
private formBuilder: FormBuilder,
) {} ) {}
ngOnInit() { ngOnInit() {
this.limitSubscription = this.maxAutoscaleSeats != null; this.adjustSubscriptionForm.patchValue({
this.newSeatCount = this.currentSeatCount; newSeatCount: this.currentSeatCount,
this.newMaxSeats = this.maxAutoscaleSeats; limitSubscription: this.maxAutoscaleSeats != null,
newMaxSeats: this.maxAutoscaleSeats,
});
this.adjustSubscriptionForm
.get("limitSubscription")
.valueChanges.pipe(takeUntil(this.destroy$))
.subscribe((value: boolean) => {
if (value) {
this.adjustSubscriptionForm
.get("newMaxSeats")
.addValidators([
Validators.min(
this.adjustSubscriptionForm.value.newSeatCount == null
? 1
: this.adjustSubscriptionForm.value.newSeatCount,
),
Validators.required,
]);
}
this.adjustSubscriptionForm.get("newMaxSeats").updateValueAndValidity();
});
} }
async submit() { ngOnDestroy() {
try { this.destroy$.next();
const request = new OrganizationSubscriptionUpdateRequest( this.destroy$.complete();
this.additionalSeatCount, }
this.newMaxSeats, submit = async () => {
); this.adjustSubscriptionForm.markAllAsTouched();
this.formPromise = this.organizationApiService.updatePasswordManagerSeats( if (this.adjustSubscriptionForm.invalid) {
this.organizationId, return;
request,
);
await this.formPromise;
this.platformUtilsService.showToast(
"success",
null,
this.i18nService.t("subscriptionUpdated"),
);
} catch (e) {
this.logService.error(e);
} }
const request = new OrganizationSubscriptionUpdateRequest(
this.additionalSeatCount,
this.adjustSubscriptionForm.value.newMaxSeats,
);
await this.organizationApiService.updatePasswordManagerSeats(this.organizationId, request);
this.platformUtilsService.showToast("success", null, this.i18nService.t("subscriptionUpdated"));
this.onAdjusted.emit(); this.onAdjusted.emit();
} };
limitSubscriptionChanged() { limitSubscriptionChanged() {
if (!this.limitSubscription) { if (!this.adjustSubscriptionForm.value.limitSubscription) {
this.newMaxSeats = null; this.adjustSubscriptionForm.value.newMaxSeats = null;
} }
} }
get additionalSeatCount(): number { get additionalSeatCount(): number {
return this.newSeatCount ? this.newSeatCount - this.currentSeatCount : 0; return this.adjustSubscriptionForm.value.newSeatCount
? this.adjustSubscriptionForm.value.newSeatCount - this.currentSeatCount
: 0;
} }
get additionalMaxSeatCount(): number { get additionalMaxSeatCount(): number {
return this.newMaxSeats ? this.newMaxSeats - this.currentSeatCount : 0; return this.adjustSubscriptionForm.value.newMaxSeats
? this.adjustSubscriptionForm.value.newMaxSeats - this.currentSeatCount
: 0;
} }
get adjustedSeatTotal(): number { get adjustedSeatTotal(): number {