diff --git a/components/dashboard/src/contexts/FeatureFlagContext.tsx b/components/dashboard/src/contexts/FeatureFlagContext.tsx index 7f15ee7cca12a9..61f16c91b05da4 100644 --- a/components/dashboard/src/contexts/FeatureFlagContext.tsx +++ b/components/dashboard/src/contexts/FeatureFlagContext.tsx @@ -17,11 +17,13 @@ interface FeatureFlagConfig { const FeatureFlagContext = createContext<{ showUsageView: boolean; + isUsageBasedBillingEnabled: boolean; showUseLastSuccessfulPrebuild: boolean; usePublicApiTeamsService: boolean; enablePersonalAccessTokens: boolean; }>({ showUsageView: false, + isUsageBasedBillingEnabled: false, showUseLastSuccessfulPrebuild: false, usePublicApiTeamsService: false, enablePersonalAccessTokens: false, @@ -34,6 +36,7 @@ const FeatureFlagContextProvider: React.FC = ({ children }) => { const location = useLocation(); const team = getCurrentTeam(location, teams); const [showUsageView, setShowUsageView] = useState(false); + const [isUsageBasedBillingEnabled, setIsUsageBasedBillingEnabled] = useState(false); const [showUseLastSuccessfulPrebuild, setShowUseLastSuccessfulPrebuild] = useState(false); const [usePublicApiTeamsService, setUsePublicApiTeamsService] = useState(false); const [enablePersonalAccessTokens, setPersonalAccessTokensEnabled] = useState(false); @@ -43,6 +46,7 @@ const FeatureFlagContextProvider: React.FC = ({ children }) => { (async () => { const featureFlags: FeatureFlagConfig = { usage_view: { defaultValue: false, setter: setShowUsageView }, + isUsageBasedBillingEnabled: { defaultValue: false, setter: setIsUsageBasedBillingEnabled }, showUseLastSuccessfulPrebuild: { defaultValue: false, setter: setShowUseLastSuccessfulPrebuild }, publicApiExperimentalTeamsService: { defaultValue: false, setter: setUsePublicApiTeamsService }, personalAccessTokensEnabled: { defaultValue: false, setter: setPersonalAccessTokensEnabled }, @@ -86,6 +90,7 @@ const FeatureFlagContextProvider: React.FC = ({ children }) => { (); const [availableCoupons, setAvailableCoupons] = useState(); const [appliedCoupons, setAppliedCoupons] = useState(); @@ -435,7 +437,7 @@ export default function () { ) : undefined; planCards.push( - {showPlans && ( -
-

- You are currently using the{" "} - - {Plans.getById(assignedTs?.planId)?.name || currentPlan.name} - {" "} - plan. + {isUsageBasedBillingEnabled && ( + + Your account has been enabled for usage-based billing. Discover faster workspace classes and + only pay for what you actually use.{" "} + + Learn more + +
+
+ The old monthly plans are deprecated and will be cancelled by End of March 2023. +
+ )} +

+

+ You are currently using the{" "} + {Plans.getById(assignedTs?.planId)?.name || currentPlan.name}{" "} + plan. +

+ {!isUsageBasedBillingEnabled && !assignedTs && ( +

+ Upgrade your plan to get more hours and more parallel workspaces.

- {!assignedTs && ( -

- Upgrade your plan to get more hours and more parallel workspaces. -

- )} - d.toLocaleDateString()) - .join(" - ")}`} + )} + d.toLocaleDateString()) + .join(" - ")}`} + > +

+ Remaining hours:{" "} + {typeof accountStatement?.remainingHours === "number" + ? Math.floor(accountStatement.remainingHours * 10) / 10 + : accountStatement?.remainingHours} +

+
+ {typeof accountStatement?.remainingHours === "number" && + typeof currentPlan.hoursPerMonth === "number" ? ( + + ) : ( + + )} +

+ { + ChargebeeClient.getOrCreate().then((chargebeeClient) => chargebeeClient.openPortal()); + }} > -

- Remaining hours:{" "} - {typeof accountStatement?.remainingHours === "number" - ? Math.floor(accountStatement.remainingHours * 10) / 10 - : accountStatement?.remainingHours} -

-
- {typeof accountStatement?.remainingHours === "number" && - typeof currentPlan.hoursPerMonth === "number" ? ( - - ) : ( - + Billing + + {!!accountStatement && Plans.isFreePlan(currentPlan.chargebeeId) && ( + + {currency === "EUR" ? ( + <> + € /{" "} + setCurrency("USD")} + > + $ + + + ) : ( + <> + setCurrency("EUR")} + > + € + {" "} + / $ + + )} + )} -

- { - ChargebeeClient.getOrCreate().then((chargebeeClient) => - chargebeeClient.openPortal(), - ); - }} - > - Billing - - {!!accountStatement && Plans.isFreePlan(currentPlan.chargebeeId) && ( - - {currency === "EUR" ? ( - <> - € /{" "} - setCurrency("USD")} - > - $ - - - ) : ( - <> - setCurrency("EUR")} - > - € - {" "} - / $ - - )} - - )} -

-
- )} +

+
{planCards}
{assignedTs && userBillingMode?.mode === "chargebee" && !!userBillingMode.teamNames && ( @@ -717,13 +724,6 @@ export default function () {
    {userBillingMode.teamNames.join(", ")}
)} - - If you are interested in purchasing a plan for a team, purchase a Team plan with one centralized - billing.{" "} - - Learn more - - {!!confirmUpgradeToPlan && ( // TODO: Use title and buttons props setConfirmUpgradeToPlan(undefined)}> @@ -875,7 +875,7 @@ interface PlanCardProps { function PlanCard(p: PlanCardProps) { return ( {}} diff --git a/components/dashboard/src/settings/Teams.tsx b/components/dashboard/src/settings/Teams.tsx index 9ff9002dfb6455..45fc88a9d10e23 100644 --- a/components/dashboard/src/settings/Teams.tsx +++ b/components/dashboard/src/settings/Teams.tsx @@ -4,7 +4,7 @@ * See License-AGPL.txt in the project root for license information. */ -import React, { useContext, useEffect, useRef, useState } from "react"; +import { useContext, useEffect, useRef, useState } from "react"; import ContextMenu, { ContextMenuEntry } from "../components/ContextMenu"; import { getGitpodService } from "../service/service"; import Alert from "../components/Alert"; @@ -23,8 +23,7 @@ import { poll, PollOptions } from "../utils"; import { Disposable } from "@gitpod/gitpod-protocol"; import { PaymentContext } from "../payment-context"; import { PageWithSettingsSubMenu } from "./PageWithSettingsSubMenu"; -import { UserContext } from "../user-context"; -import { BillingMode } from "@gitpod/gitpod-protocol/lib/billing-mode"; +import { FeatureFlagContext } from "../contexts/FeatureFlagContext"; export default function Teams() { return ( @@ -45,7 +44,7 @@ interface Slot extends TeamSubscriptionSlotResolved { } function AllTeams() { - const { userBillingMode } = useContext(UserContext); + const { isUsageBasedBillingEnabled } = useContext(FeatureFlagContext); const { currency, isStudent, isChargebeeCustomer, setIsChargebeeCustomer } = useContext(PaymentContext); const [slots, setSlots] = useState([]); @@ -453,8 +452,20 @@ function AllTeams() { return pendingSlotsPurchase && pendingSlotsPurchase.tsId === ts.id; }; - const renderTeams = () => ( - + return ( +
+ {isUsageBasedBillingEnabled && ( + + Your account has been enabled for usage-based billing. Discover faster workspace classes and only + pay for what you actually use.{" "} + + Learn more + +
+
+ The old monthly plans are deprecated and will be cancelled by End of March 2023. +
+ )}

All Team Plans

@@ -469,7 +480,11 @@ function AllTeams() { {getActiveSubs().length > 0 && (