-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* add event for when pay gate is shown * even when click pay gate CTA * Update UI snapshots for `chromium` (2) * Update UI snapshots for `chromium` (2) * rename some things --------- Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
- Loading branch information
1 parent
2149ec3
commit 1bce547
Showing
3 changed files
with
131 additions
and
35 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,15 +5,17 @@ import { useActions, useValues } from 'kea' | |
import { FEATURE_FLAGS } from 'lib/constants' | ||
import { featureFlagLogic } from 'lib/logic/featureFlagLogic' | ||
import { lowercaseFirstLetter } from 'lib/utils' | ||
import posthog from 'posthog-js' | ||
import { useEffect } from 'react' | ||
import { billingLogic } from 'scenes/billing/billingLogic' | ||
import { preflightLogic } from 'scenes/PreflightCheck/preflightLogic' | ||
import { getProductIcon } from 'scenes/products/Products' | ||
import { sceneLogic } from 'scenes/sceneLogic' | ||
import { userLogic } from 'scenes/userLogic' | ||
|
||
import { AvailableFeature } from '~/types' | ||
|
||
import { PayGateMiniButton } from './PayGateMiniButton' | ||
import { payGateMiniLogic } from './payGateMiniLogic' | ||
|
||
export interface PayGateMiniProps { | ||
feature: AvailableFeature | ||
|
@@ -39,29 +41,23 @@ export function PayGateMini({ | |
background = true, | ||
isGrandfathered, | ||
}: PayGateMiniProps): JSX.Element | null { | ||
const { preflight, isCloudOrDev } = useValues(preflightLogic) | ||
const { hasAvailableFeature, availableFeature } = useValues(userLogic) | ||
const { productWithFeature, featureInfo, featureAvailableOnOrg, gateVariant } = useValues( | ||
payGateMiniLogic({ featureKey: feature, currentUsage }) | ||
) | ||
const { preflight } = useValues(preflightLogic) | ||
const { billing, billingLoading } = useValues(billingLogic) | ||
const { featureFlags } = useValues(featureFlagLogic) | ||
const { hideUpgradeModal } = useActions(sceneLogic) | ||
|
||
const product = billing?.products.find((product) => product.features?.some((f) => f.key === feature)) | ||
const featureInfo = product?.features.find((f) => f.key === feature) | ||
const featureDetailsWithLimit = availableFeature(feature) | ||
const minimumPlan = product?.plans.find((plan) => plan.features?.some((f) => f.key === feature)) | ||
|
||
let gateVariant: 'add-card' | 'contact-sales' | 'move-to-cloud' | null = null | ||
if (!overrideShouldShowGate && !hasAvailableFeature(feature, currentUsage)) { | ||
if (isCloudOrDev) { | ||
if (!minimumPlan || minimumPlan.contact_support) { | ||
gateVariant = 'contact-sales' | ||
} else { | ||
gateVariant = 'add-card' | ||
} | ||
} else { | ||
gateVariant = 'move-to-cloud' | ||
useEffect(() => { | ||
if (gateVariant) { | ||
posthog.capture('pay gate shown', { | ||
product_key: productWithFeature?.type, | ||
feature: feature, | ||
gate_variant: gateVariant, | ||
}) | ||
} | ||
} | ||
}, [gateVariant]) | ||
|
||
if (billingLoading) { | ||
return null | ||
|
@@ -72,17 +68,19 @@ export function PayGateMini({ | |
} | ||
|
||
return featureFlags[FEATURE_FLAGS.SUBSCRIBE_FROM_PAYGATE] === 'test' ? ( | ||
gateVariant && product && featureInfo ? ( | ||
gateVariant && productWithFeature && featureInfo && !overrideShouldShowGate ? ( | ||
<div | ||
className={clsx( | ||
className, | ||
background && 'bg-side border border-border', | ||
'PayGateMini rounded flex flex-col items-center p-4 text-center' | ||
)} | ||
> | ||
<div className="flex text-4xl text-warning">{getProductIcon(product.name, featureInfo.icon_key)}</div> | ||
<div className="flex text-4xl text-warning"> | ||
{getProductIcon(productWithFeature.name, featureInfo.icon_key)} | ||
</div> | ||
<h3>{featureInfo.name}</h3> | ||
{featureDetailsWithLimit?.limit && gateVariant !== 'move-to-cloud' ? ( | ||
{featureAvailableOnOrg?.limit && gateVariant !== 'move-to-cloud' ? ( | ||
<div> | ||
<p> | ||
You've reached your usage limit for{' '} | ||
|
@@ -97,11 +95,11 @@ export function PayGateMini({ | |
<p className="border border-border bg-side rounded p-4"> | ||
<b>Your current plan limit:</b>{' '} | ||
<span> | ||
{featureDetailsWithLimit.limit} {featureDetailsWithLimit.unit} | ||
{featureAvailableOnOrg.limit} {featureAvailableOnOrg.unit} | ||
</span> | ||
</p> | ||
<p> | ||
Please upgrade your <b>{product.name}</b> plan to create more {featureInfo.name} | ||
Please upgrade your <b>{productWithFeature.name}</b> plan to create more {featureInfo.name} | ||
</p> | ||
</div> | ||
) : ( | ||
|
@@ -112,7 +110,7 @@ export function PayGateMini({ | |
<>This feature is only available on PostHog Cloud.</> | ||
) : ( | ||
<> | ||
Upgrade your <b>{product?.name}</b> plan to use this feature. | ||
Upgrade your <b>{productWithFeature?.name}</b> plan to use this feature. | ||
</> | ||
)} | ||
</p> | ||
|
@@ -136,22 +134,24 @@ export function PayGateMini({ | |
</> | ||
</div> | ||
)} | ||
<PayGateMiniButton product={product} featureInfo={featureInfo} gateVariant={gateVariant} /> | ||
<PayGateMiniButton product={productWithFeature} featureInfo={featureInfo} gateVariant={gateVariant} /> | ||
</div> | ||
) : ( | ||
<div className={className}>{children}</div> | ||
) | ||
) : gateVariant && product && featureInfo ? ( | ||
) : gateVariant && productWithFeature && featureInfo && !overrideShouldShowGate ? ( | ||
<div | ||
className={clsx( | ||
className, | ||
background && 'bg-side border border-border', | ||
'PayGateMini rounded flex flex-col items-center p-4 text-center' | ||
)} | ||
> | ||
<div className="flex text-4xl text-warning">{getProductIcon(product.name, featureInfo.icon_key)}</div> | ||
<div className="flex text-4xl text-warning"> | ||
{getProductIcon(productWithFeature.name, featureInfo.icon_key)} | ||
</div> | ||
<h3>{featureInfo.name}</h3> | ||
{featureDetailsWithLimit?.limit && gateVariant !== 'move-to-cloud' ? ( | ||
{featureAvailableOnOrg?.limit && gateVariant !== 'move-to-cloud' ? ( | ||
<div> | ||
<p> | ||
You've reached your usage limit for{' '} | ||
|
@@ -166,11 +166,11 @@ export function PayGateMini({ | |
<p className="border border-border bg-side rounded p-4"> | ||
<b>Your current plan limit:</b>{' '} | ||
<span> | ||
{featureDetailsWithLimit.limit} {featureDetailsWithLimit.unit} | ||
{featureAvailableOnOrg.limit} {featureAvailableOnOrg.unit} | ||
</span> | ||
</p> | ||
<p> | ||
Please upgrade your <b>{product.name}</b> plan to create more {featureInfo.name} | ||
Please upgrade your <b>{productWithFeature.name}</b> plan to create more {featureInfo.name} | ||
</p> | ||
</div> | ||
) : ( | ||
|
@@ -179,7 +179,7 @@ export function PayGateMini({ | |
<>On PostHog Cloud, you can </> | ||
) : ( | ||
<> | ||
Upgrade your <b>{product?.name}</b> plan to{' '} | ||
Upgrade your <b>{productWithFeature?.name}</b> plan to{' '} | ||
</> | ||
)} | ||
{featureInfo.description ? lowercaseFirstLetter(featureInfo.description) : 'use this feature.'} | ||
|
@@ -206,7 +206,7 @@ export function PayGateMini({ | |
<LemonButton | ||
to={ | ||
gateVariant === 'add-card' | ||
? `/organization/billing?products=${product.type}` | ||
? `/organization/billing?products=${productWithFeature.type}` | ||
: gateVariant === 'contact-sales' | ||
? `mailto:[email protected]?subject=Inquiring about ${featureInfo.name}` | ||
: gateVariant === 'move-to-cloud' | ||
|
@@ -215,11 +215,18 @@ export function PayGateMini({ | |
} | ||
type="primary" | ||
center | ||
onClick={hideUpgradeModal} | ||
onClick={() => { | ||
hideUpgradeModal() | ||
posthog.capture('pay gate CTA clicked', { | ||
product_key: productWithFeature?.type, | ||
feature: feature, | ||
gate_variant: gateVariant, | ||
}) | ||
}} | ||
> | ||
{gateVariant === 'add-card' | ||
? billing?.has_active_subscription | ||
? `Upgrade ${product?.name}` | ||
? `Upgrade ${productWithFeature?.name}` | ||
: 'Subscribe now' | ||
: gateVariant === 'contact-sales' | ||
? 'Contact sales' | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
83 changes: 83 additions & 0 deletions
83
frontend/src/lib/components/PayGateMini/payGateMiniLogic.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
import { actions, connect, kea, key, path, props, selectors } from 'kea' | ||
import { billingLogic } from 'scenes/billing/billingLogic' | ||
import { preflightLogic } from 'scenes/PreflightCheck/preflightLogic' | ||
import { userLogic } from 'scenes/userLogic' | ||
|
||
import { AvailableFeature } from '~/types' | ||
|
||
import type { payGateMiniLogicType } from './payGateMiniLogicType' | ||
|
||
export interface PayGateMiniLogicProps { | ||
featureKey: AvailableFeature | ||
currentUsage?: number | ||
} | ||
|
||
export type GateVariantType = 'add-card' | 'contact-sales' | 'move-to-cloud' | null | ||
|
||
export const payGateMiniLogic = kea<payGateMiniLogicType>([ | ||
props({} as PayGateMiniLogicProps), | ||
path(['lib', 'components', 'payGateMini', 'payGateMiniLogic']), | ||
key((props) => props.featureKey), | ||
connect(() => ({ | ||
values: [ | ||
billingLogic, | ||
['billing', 'billingLoading'], | ||
userLogic, | ||
['user', 'hasAvailableFeature', 'availableFeature'], | ||
preflightLogic, | ||
['isCloudOrDev'], | ||
], | ||
actions: [], | ||
})), | ||
actions({ | ||
setGateVariant: (gateVariant: GateVariantType) => ({ gateVariant }), | ||
}), | ||
selectors(({ values, props }) => ({ | ||
productWithFeature: [ | ||
(s) => [s.billing], | ||
(billing) => | ||
billing?.products?.find((product) => product.features?.some((f) => f.key === props.featureKey)), | ||
], | ||
featureInfo: [ | ||
(s) => [s.productWithFeature], | ||
(productWithFeature) => productWithFeature?.features.find((f) => f.key === props.featureKey), | ||
], | ||
featureAvailableOnOrg: [ | ||
(s) => [s.user, (_, props) => props.featureKey], | ||
(_user, featureKey) => { | ||
return values.availableFeature(featureKey) | ||
}, | ||
], | ||
minimumPlanWithFeature: [ | ||
(s) => [s.productWithFeature], | ||
(productWithFeature) => | ||
productWithFeature?.plans.find((plan) => plan.features?.some((f) => f.key === props.featureKey)), | ||
], | ||
gateVariant: [ | ||
(s) => [ | ||
s.billingLoading, | ||
s.hasAvailableFeature, | ||
s.minimumPlanWithFeature, | ||
(_, props) => props.featureKey, | ||
(_, props) => props.currentUsage, | ||
], | ||
(billingLoading, hasAvailableFeature, minimumPlanWithFeature, featureKey, currentUsage) => { | ||
if (hasAvailableFeature(featureKey, currentUsage)) { | ||
return null | ||
} | ||
if (billingLoading) { | ||
return null | ||
} | ||
if (values.isCloudOrDev) { | ||
if (!minimumPlanWithFeature || minimumPlanWithFeature.contact_support) { | ||
return 'contact-sales' | ||
} else { | ||
return 'add-card' | ||
} | ||
} else { | ||
return 'move-to-cloud' | ||
} | ||
}, | ||
], | ||
})), | ||
]) |