diff --git a/frontend/src/components/orgs-list.ts b/frontend/src/components/orgs-list.ts index 75c8202315..a49aba26a1 100644 --- a/frontend/src/components/orgs-list.ts +++ b/frontend/src/components/orgs-list.ts @@ -33,6 +33,7 @@ enum OrgFilter { Inactive = "inactive", Trialing = "trialing", ScheduledCancel = "scheduled-cancel", + BadStates = "bad-states", } const none = html` @@ -180,6 +181,11 @@ export class OrgsList extends BtrixElement { icon: "calendar2-x", filter: OrgFilter.ScheduledCancel, }, + { + label: msg("Unexpected States"), + icon: "exclamation-triangle", + filter: OrgFilter.BadStates, + }, ].map((options) => this.renderFilterButton(searchResults, options))} @@ -257,22 +263,54 @@ export class OrgsList extends BtrixElement { !!org.subscription && !( org.subscription.status === SubscriptionStatus.Active || - org.subscription.status === SubscriptionStatus.Trialing + org.subscription.status === SubscriptionStatus.Trialing || + org.subscription.status === SubscriptionStatus.TrialingCanceled ) ); case OrgFilter.Trialing: return ( !!org.subscription && - org.subscription.status === SubscriptionStatus.Trialing + (org.subscription.status === SubscriptionStatus.Trialing || + org.subscription.status === SubscriptionStatus.TrialingCanceled) ); case OrgFilter.ScheduledCancel: return ( !!org.subscription && - org.subscription.status === SubscriptionStatus.Active && - !!org.subscription.futureCancelDate + ((org.subscription.status === SubscriptionStatus.Active && + !!org.subscription.futureCancelDate) || + org.subscription.status === SubscriptionStatus.TrialingCanceled) ); case OrgFilter.All: return true; + case OrgFilter.BadStates: + // Check if org should be disabled but isn't + if ( + !org.readOnly && + org.subscription && + [ + SubscriptionStatus.Cancelled, + SubscriptionStatus.PausedPaymentFailed, + ].includes(org.subscription.status) + ) { + return true; + } + + // Check if org is scheduled to cancel in the past + if ( + org.subscription?.futureCancelDate && + new Date(org.subscription.futureCancelDate).getTime() - + new Date().getTime() < + 0 + ) { + return true; + } + + // Check if org has empty subscription id + if (org.subscription && !org.subscription.subId) { + return true; + } + + return false; } } @@ -740,9 +778,10 @@ export class OrgsList extends BtrixElement { if (org.storageQuotaReached || org.execMinutesQuotaReached) { status = { icon: html` `, description: org.storageQuotaReached @@ -754,9 +793,10 @@ export class OrgsList extends BtrixElement { if (org.readOnly) { status = { icon: html` `, description: org.readOnlyReason @@ -768,6 +808,7 @@ export class OrgsList extends BtrixElement { let subscription: { icon: TemplateResult<1>; description: string | TemplateResult<1>; + unexpectedState?: true; } = { icon: none, description: msg("No Subscription"), @@ -784,16 +825,21 @@ export class OrgsList extends BtrixElement { ) { subscription = { icon: html``, - description: html`${msg("Subscription Cancellation Scheduled")} + description: html`

+ ${msg("Subscription Cancellation Scheduled")} +

+
- ${msg("Subscription will be cancelled in")} + ${msg("Cancels in")} ${this.localize.humanizeDuration( new Date(org.subscription.futureCancelDate).getTime() - new Date().getTime(), + { compact: true, verbose: true }, )} (${this.localize.date(org.subscription.futureCancelDate, { timeStyle: "medium", @@ -808,7 +854,8 @@ export class OrgsList extends BtrixElement { 0 ) { subscription = { - icon: html` + `, - description: html`${msg( - "Subscription Cancellation Scheduled in the Past", - )} -
- ${msg("Subscription was scheduled for cancellation at")} + label=${msg("Issue")} + > +
`, + description: html`

+ ${msg("Subscription Cancellation Scheduled in the Past")} +

+
+ ${msg("Subscription was scheduled for cancellation at")}${" "} ${this.localize.date(org.subscription.futureCancelDate, { timeStyle: "medium", dateStyle: "medium", })} + ${" "}${msg("but is still active.")}
-
+
${msg("This indicates something has gone wrong.")}
`, + unexpectedState: true, }; } else { subscription = { @@ -854,14 +904,82 @@ export class OrgsList extends BtrixElement { }; break; case SubscriptionStatus.TrialingCanceled: - subscription = { - icon: html``, - description: msg("Trial Canceled"), - }; + if ( + org.subscription.futureCancelDate && + new Date(org.subscription.futureCancelDate).getTime() - + new Date().getTime() >= + 0 + ) { + subscription = { + icon: html``, + description: html`

+ ${msg("Trial Cancellation Scheduled")} +

+
+
+ ${msg("Cancels in")} + ${this.localize.humanizeDuration( + new Date(org.subscription.futureCancelDate).getTime() - + new Date().getTime(), + { compact: true, verbose: true }, + )} + (${this.localize.date(org.subscription.futureCancelDate, { + timeStyle: "medium", + dateStyle: "medium", + })}) +
`, + }; + } else if ( + org.subscription.futureCancelDate && + new Date(org.subscription.futureCancelDate).getTime() - + new Date().getTime() < + 0 + ) { + subscription = { + icon: html`
+ + +
`, + description: html`

+ ${msg("Trial Cancellation Scheduled in the Past")} +

+
+ ${msg("Trial was scheduled for cancellation at")} + ${this.localize.date(org.subscription.futureCancelDate, { + timeStyle: "medium", + dateStyle: "medium", + })} + ${msg("but is still active.")} +
+
+ ${msg("This indicates something has gone wrong.")} +
`, + unexpectedState: true, + }; + } else { + subscription = { + icon: html``, + description: msg("Trial Cancelled"), + }; + } + break; case SubscriptionStatus.PausedPaymentFailed: subscription = { @@ -899,6 +1017,7 @@ export class OrgsList extends BtrixElement { break; } } + const useTooltip = typeof subscription.description === "string"; return html` ${status.icon} - - ${subscription.description} - ${subscription.icon} - + ${useTooltip + ? html` + ${subscription.icon} + ` + : html` + ${subscription.description} + ${subscription.icon} + `}