1
0
mirror of https://github.com/bitwarden/browser.git synced 2024-12-21 16:18:28 +01:00

[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>
<div>
<div class="row">
<div class="form-group col-8">
<label for="newSeatCount">{{ "subscriptionSeats" | i18n }}</label>
<input
id="newSeatCount"
class="form-control"
type="number"
name="NewSeatCount"
[(ngModel)]="newSeatCount"
min="0"
step="1"
required
/>
<small class="d-block text-muted mb-4">
<form [formGroup]="adjustSubscriptionForm" [bitSubmit]="submit">
<div class="tw-grid tw-grid-cols-12 tw-gap-4">
<div class="tw-col-span-8">
<bit-form-field>
<bit-label>{{ "subscriptionSeats" | i18n }}</bit-label>
<input bitInput formControlName="newSeatCount" type="number" min="0" step="1" />
<bit-hint>
<strong>{{ "total" | i18n }}:</strong> {{ additionalSeatCount || 0 }} &times;
{{ seatPrice | currency: "$" }} = {{ adjustedSeatTotal | currency: "$" }} /
{{ interval | i18n }}
</small>
</div>
{{ interval | i18n }}</bit-hint
>
</bit-form-field>
</div>
<div class="row mb-4">
<div class="form-group col-sm">
<div class="form-check">
<input
id="limitSubscription"
class="form-check-input"
type="checkbox"
name="LimitSubscription"
[(ngModel)]="limitSubscription"
(change)="limitSubscriptionChanged()"
/>
<label for="limitSubscription">{{ "limitSubscription" | i18n }}</label>
</div>
<small class="d-block text-muted">{{ "limitSubscriptionDesc" | i18n }}</small>
</div>
</div>
<div class="row mb-4" [hidden]="!limitSubscription">
<div class="form-group col-sm">
<label for="maxAutoscaleSeats">{{ "maxSeatLimit" | i18n }}</label>
</div>
<div>
<bit-form-control>
<input
bitCheckbox
formControlName="limitSubscription"
type="checkbox"
(change)="limitSubscriptionChanged()"
/>
<bit-label>{{ "limitSubscription" | i18n }}</bit-label>
<bit-hint> {{ "limitSubscriptionDesc" | i18n }}</bit-hint>
</bit-form-control>
</div>
<div
class="tw-grid tw-grid-cols-12 tw-gap-4 tw-mb-4"
[hidden]="!adjustSubscriptionForm.value.limitSubscription"
>
<div class="tw-col-span-8">
<bit-form-field>
<bit-label>{{ "maxSeatLimit" | i18n }}</bit-label>
<input
id="maxAutoscaleSeats"
class="form-control col-8"
bitInput
formControlName="newMaxSeats"
type="number"
name="MaxAutoscaleSeats"
[(ngModel)]="newMaxSeats"
[min]="newSeatCount == null ? 1 : newSeatCount"
[min]="
adjustSubscriptionForm.value.newSeatCount == null
? 1
: adjustSubscriptionForm.value.newSeatCount
"
step="1"
[required]="limitSubscription"
/>
<small class="d-block text-muted">
<bit-hint>
<strong>{{ "maxSeatCost" | i18n }}:</strong> {{ additionalMaxSeatCount || 0 }} &times;
{{ seatPrice | currency: "$" }} = {{ maxSeatTotal | currency: "$" }} /
{{ interval | i18n }}
</small>
</div>
{{ interval | i18n }}</bit-hint
>
</bit-form-field>
</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>
<button bitButton buttonType="primary" bitFormButton type="submit">
{{ "save" | i18n }}
</button>
</form>
<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 { OrganizationSubscriptionUpdateRequest } from "@bitwarden/common/billing/models/request/organization-subscription-update.request";
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";
@Component({
selector: "app-adjust-subscription",
templateUrl: "adjust-subscription.component.html",
})
export class AdjustSubscription {
export class AdjustSubscription implements OnInit, OnDestroy {
@Input() organizationId: string;
@Input() maxAutoscaleSeats: number;
@Input() currentSeatCount: number;
@Input() seatPrice = 0;
@Input() interval = "year";
@Output() onAdjusted = new EventEmitter();
private destroy$ = new Subject<void>();
formPromise: Promise<void>;
limitSubscription: boolean;
newSeatCount: number;
newMaxSeats: number;
adjustSubscriptionForm = this.formBuilder.group({
newSeatCount: [0, [Validators.min(0)]],
limitSubscription: [false],
newMaxSeats: [0, [Validators.min(0)]],
});
get limitSubscription(): boolean {
return this.adjustSubscriptionForm.value.limitSubscription;
}
constructor(
private i18nService: I18nService,
private platformUtilsService: PlatformUtilsService,
private logService: LogService,
private organizationApiService: OrganizationApiServiceAbstraction,
private formBuilder: FormBuilder,
) {}
ngOnInit() {
this.limitSubscription = this.maxAutoscaleSeats != null;
this.newSeatCount = this.currentSeatCount;
this.newMaxSeats = this.maxAutoscaleSeats;
this.adjustSubscriptionForm.patchValue({
newSeatCount: this.currentSeatCount,
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() {
try {
const request = new OrganizationSubscriptionUpdateRequest(
this.additionalSeatCount,
this.newMaxSeats,
);
this.formPromise = this.organizationApiService.updatePasswordManagerSeats(
this.organizationId,
request,
);
await this.formPromise;
this.platformUtilsService.showToast(
"success",
null,
this.i18nService.t("subscriptionUpdated"),
);
} catch (e) {
this.logService.error(e);
ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
}
submit = async () => {
this.adjustSubscriptionForm.markAllAsTouched();
if (this.adjustSubscriptionForm.invalid) {
return;
}
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();
}
};
limitSubscriptionChanged() {
if (!this.limitSubscription) {
this.newMaxSeats = null;
if (!this.adjustSubscriptionForm.value.limitSubscription) {
this.adjustSubscriptionForm.value.newMaxSeats = null;
}
}
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 {
return this.newMaxSeats ? this.newMaxSeats - this.currentSeatCount : 0;
return this.adjustSubscriptionForm.value.newMaxSeats
? this.adjustSubscriptionForm.value.newMaxSeats - this.currentSeatCount
: 0;
}
get adjustedSeatTotal(): number {