[AC-3023] Resolve the capitalization here (#11019)
* Resolve the capitalization here * Resolve the returned issue on A11y * Fix the storage bug
This commit is contained in:
parent
b713e18b1a
commit
f816e80314
|
@ -53,10 +53,19 @@
|
||||||
[class]="'tw-grid-cols-' + selectableProducts.length"
|
[class]="'tw-grid-cols-' + selectableProducts.length"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
*ngFor="let selectableProduct of selectableProducts; let i = index"
|
*ngFor="
|
||||||
|
let selectableProduct of selectableProducts;
|
||||||
|
trackBy: manageSelectableProduct;
|
||||||
|
let i = index
|
||||||
|
"
|
||||||
[ngClass]="getPlanCardContainerClasses(selectableProduct, i)"
|
[ngClass]="getPlanCardContainerClasses(selectableProduct, i)"
|
||||||
(click)="selectPlan(selectableProduct)"
|
(click)="selectPlan(selectableProduct)"
|
||||||
tabindex="0"
|
[attr.tabindex]="focusedIndex !== i || isCardDisabled(i) ? '-1' : '0'"
|
||||||
|
class="product-card"
|
||||||
|
(keyup)="onKeydown($event, i)"
|
||||||
|
(focus)="onFocus(i)"
|
||||||
|
[attr.aria-disabled]="isCardDisabled(i)"
|
||||||
|
[id]="i + 'a_plan_card'"
|
||||||
>
|
>
|
||||||
<div class="tw-relative">
|
<div class="tw-relative">
|
||||||
<div
|
<div
|
||||||
|
|
|
@ -160,6 +160,9 @@ export class ChangePlanDialogComponent implements OnInit, OnDestroy {
|
||||||
showPayment: boolean = false;
|
showPayment: boolean = false;
|
||||||
totalOpened: boolean = false;
|
totalOpened: boolean = false;
|
||||||
currentPlan: PlanResponse;
|
currentPlan: PlanResponse;
|
||||||
|
currentFocusIndex = 0;
|
||||||
|
isCardStateDisabled = false;
|
||||||
|
focusedIndex: number | null = null;
|
||||||
|
|
||||||
deprecateStripeSourcesAPI: boolean;
|
deprecateStripeSourcesAPI: boolean;
|
||||||
|
|
||||||
|
@ -255,6 +258,7 @@ export class ChangePlanDialogComponent implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
|
|
||||||
setInitialPlanSelection() {
|
setInitialPlanSelection() {
|
||||||
|
this.focusedIndex = this.selectableProducts.length - 1;
|
||||||
this.selectPlan(this.getPlanByType(ProductTierType.Enterprise));
|
this.selectPlan(this.getPlanByType(ProductTierType.Enterprise));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -307,15 +311,22 @@ export class ChangePlanDialogComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
if (plan == this.currentPlan) {
|
if (plan == this.currentPlan) {
|
||||||
cardState = PlanCardState.Disabled;
|
cardState = PlanCardState.Disabled;
|
||||||
|
this.isCardStateDisabled = true;
|
||||||
|
this.focusedIndex = index;
|
||||||
} else if (plan == this.selectedPlan) {
|
} else if (plan == this.selectedPlan) {
|
||||||
cardState = PlanCardState.Selected;
|
cardState = PlanCardState.Selected;
|
||||||
|
this.isCardStateDisabled = false;
|
||||||
|
this.focusedIndex = index;
|
||||||
} else if (
|
} else if (
|
||||||
this.selectedInterval === PlanInterval.Monthly &&
|
this.selectedInterval === PlanInterval.Monthly &&
|
||||||
plan.productTier == ProductTierType.Families
|
plan.productTier == ProductTierType.Families
|
||||||
) {
|
) {
|
||||||
cardState = PlanCardState.Disabled;
|
cardState = PlanCardState.Disabled;
|
||||||
|
this.isCardStateDisabled = true;
|
||||||
|
this.focusedIndex = this.selectableProducts.length - 1;
|
||||||
} else {
|
} else {
|
||||||
cardState = PlanCardState.NotSelected;
|
cardState = PlanCardState.NotSelected;
|
||||||
|
this.isCardStateDisabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (cardState) {
|
switch (cardState) {
|
||||||
|
@ -466,7 +477,7 @@ export class ChangePlanDialogComponent implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
|
|
||||||
get storageGb() {
|
get storageGb() {
|
||||||
return this.sub?.maxStorageGb - 1;
|
return this.sub?.maxStorageGb ? this.sub?.maxStorageGb - 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
passwordManagerSeatTotal(plan: PlanResponse): number {
|
passwordManagerSeatTotal(plan: PlanResponse): number {
|
||||||
|
@ -492,7 +503,8 @@ export class ChangePlanDialogComponent implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
plan.PasswordManager.additionalStoragePricePerGb * Math.abs(this.sub?.maxStorageGb - 1 || 0)
|
plan.PasswordManager.additionalStoragePricePerGb *
|
||||||
|
Math.abs(this.sub?.maxStorageGb ? this.sub?.maxStorageGb - 1 : 0 || 0)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -861,4 +873,44 @@ export class ChangePlanDialogComponent implements OnInit, OnDestroy {
|
||||||
return this.i18nService.t("planNameTeams");
|
return this.i18nService.t("planNameTeams");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onKeydown(event: KeyboardEvent, index: number) {
|
||||||
|
const cardElements = Array.from(document.querySelectorAll(".product-card")) as HTMLElement[];
|
||||||
|
let newIndex = index;
|
||||||
|
const direction = event.key === "ArrowRight" || event.key === "ArrowDown" ? 1 : -1;
|
||||||
|
|
||||||
|
if (["ArrowRight", "ArrowDown", "ArrowLeft", "ArrowUp"].includes(event.key)) {
|
||||||
|
do {
|
||||||
|
newIndex = (newIndex + direction + cardElements.length) % cardElements.length;
|
||||||
|
} while (this.isCardDisabled(newIndex) && newIndex !== index);
|
||||||
|
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
const card = cardElements[newIndex];
|
||||||
|
if (
|
||||||
|
!(
|
||||||
|
card.classList.contains("tw-bg-secondary-100") &&
|
||||||
|
card.classList.contains("tw-text-muted")
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
card?.focus();
|
||||||
|
}
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onFocus(index: number) {
|
||||||
|
this.focusedIndex = index;
|
||||||
|
this.selectPlan(this.selectableProducts[index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
isCardDisabled(index: number): boolean {
|
||||||
|
const card = this.selectableProducts[index];
|
||||||
|
return card === (this.currentPlan || this.isCardStateDisabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
manageSelectableProduct(index: number) {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9062,7 +9062,7 @@
|
||||||
"message": "Directory integration"
|
"message": "Directory integration"
|
||||||
},
|
},
|
||||||
"passwordLessSso": {
|
"passwordLessSso": {
|
||||||
"message": "PasswordLess SSO"
|
"message": "Passwordless SSO"
|
||||||
},
|
},
|
||||||
"accountRecovery": {
|
"accountRecovery": {
|
||||||
"message": "Account recovery"
|
"message": "Account recovery"
|
||||||
|
|
Loading…
Reference in New Issue