Skip to content

Commit

Permalink
Refactored guardAvailableFeature
Browse files Browse the repository at this point in the history
  • Loading branch information
benjackwhite committed Mar 18, 2024
1 parent abd11bc commit 52da597
Show file tree
Hide file tree
Showing 8 changed files with 67 additions and 74 deletions.
5 changes: 2 additions & 3 deletions frontend/src/layout/navigation/OrganizationSwitcher.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export function OtherOrganizationButton({
export function NewOrganizationButton(): JSX.Element {
const { closeAccountPopover } = useActions(navigationLogic)
const { showCreateOrganizationModal } = useActions(globalModalsLogic)
const { guardAvailableFeature } = useActions(upgradeModalLogic)
const { guardAvailableFeature } = useValues(upgradeModalLogic)

return (
<LemonButton
Expand All @@ -61,8 +61,7 @@ export function NewOrganizationButton(): JSX.Element {
showCreateOrganizationModal()
},
{
cloud: false,
selfHosted: true,
guardOnCloud: false,
}
)
}
Expand Down
11 changes: 4 additions & 7 deletions frontend/src/layout/navigation/ProjectSwitcher.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export function ProjectName({ team }: { team: TeamBasicType }): JSX.Element {
export function ProjectSwitcherOverlay({ onClickInside }: { onClickInside?: () => void }): JSX.Element {
const { currentOrganization, projectCreationForbiddenReason } = useValues(organizationLogic)
const { currentTeam } = useValues(teamLogic)
const { guardAvailableFeature } = useActions(upgradeModalLogic)
const { guardAvailableFeature } = useValues(upgradeModalLogic)
const { showCreateProjectModal } = useActions(globalModalsLogic)

return (
Expand All @@ -48,12 +48,9 @@ export function ProjectSwitcherOverlay({ onClickInside }: { onClickInside?: () =
tooltip={projectCreationForbiddenReason}
onClick={() => {
onClickInside?.()
guardAvailableFeature(
AvailableFeature.ORGANIZATIONS_PROJECTS,
showCreateProjectModal,
undefined,
currentOrganization?.teams?.length
)
guardAvailableFeature(AvailableFeature.ORGANIZATIONS_PROJECTS, showCreateProjectModal, {
currentUsage: currentOrganization?.teams?.length,
})
}}
>
New project
Expand Down
87 changes: 45 additions & 42 deletions frontend/src/lib/components/UpgradeModal/upgradeModalLogic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,17 @@ import { AvailableFeature } from '~/types'

import type { upgradeModalLogicType } from './upgradeModalLogicType'

export type GuardAvailableFeatureFn = (
featureKey: AvailableFeature,
featureAvailableCallback?: () => void,
options?: {
guardOnCloud?: boolean
guardOnSelfHosted?: boolean
currentUsage?: number
isGrandfathered?: boolean
}
) => boolean

export const upgradeModalLogic = kea<upgradeModalLogicType>([
path(['lib', 'components', 'UpgradeModal', 'upgradeModalLogic']),
connect(() => ({
Expand All @@ -19,21 +30,6 @@ export const upgradeModalLogic = kea<upgradeModalLogicType>([
currentUsage,
isGrandfathered,
}),
guardAvailableFeature: (
featureKey: AvailableFeature,
featureAvailableCallback?: () => void,
guardOn: {
cloud: boolean
selfHosted: boolean
} = {
cloud: true,
selfHosted: true,
},
// how much of the feature has been used (eg. number of recording playlists created),
// which will be compared to the limit for their subscriptions
currentUsage?: number,
isGrandfathered?: boolean
) => ({ featureKey, featureAvailableCallback, guardOn, currentUsage, isGrandfathered }),
hideUpgradeModal: true,
}),
reducers({
Expand All @@ -59,35 +55,42 @@ export const upgradeModalLogic = kea<upgradeModalLogicType>([
},
],
}),
selectors({
// sceneConfig: [
// (s) => [s.scene],
// (scene: Scene): SceneConfig | null => {
// return sceneConfigurations[scene] || null
// },
// ],
}),
listeners(({ actions }) => ({
selectors(({ actions }) => ({
guardAvailableFeature: [
(s) => [s.preflight, s.hasAvailableFeature],
(preflight, hasAvailableFeature): GuardAvailableFeatureFn => {
return (featureKey, featureAvailableCallback, options): boolean => {
const {
guardOnCloud = true,
guardOnSelfHosted = true,
currentUsage,
isGrandfathered,
} = options || {}
let featureAvailable: boolean
if (!preflight) {
featureAvailable = false
} else if (!guardOnCloud && preflight.cloud) {
featureAvailable = true
} else if (!guardOnSelfHosted && !preflight.cloud) {
featureAvailable = true
} else {
featureAvailable = hasAvailableFeature(featureKey, currentUsage)
}

if (!featureAvailable) {
actions.showUpgradeModal(featureKey, currentUsage, isGrandfathered)
} else {
featureAvailableCallback?.()
}

return featureAvailable
}
},
],
})),
listeners(() => ({
showUpgradeModal: ({ featureKey }) => {
eventUsageLogic.actions.reportUpgradeModalShown(featureKey)
},
guardAvailableFeature: ({ featureKey, featureAvailableCallback, guardOn, currentUsage, isGrandfathered }) => {
const { preflight } = preflightLogic.values
let featureAvailable: boolean
if (!preflight) {
featureAvailable = false
} else if (!guardOn.cloud && preflight.cloud) {
featureAvailable = true
} else if (!guardOn.selfHosted && !preflight.cloud) {
featureAvailable = true
} else {
featureAvailable = userLogic.values.hasAvailableFeature(featureKey, currentUsage)
}
if (featureAvailable) {
featureAvailableCallback?.()
} else {
actions.showUpgradeModal(featureKey, currentUsage, isGrandfathered)
}
},
})),
])
8 changes: 3 additions & 5 deletions frontend/src/scenes/session-recordings/SessionRecordings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export function SessionsRecordings(): JSX.Element {
const { tab } = useValues(sessionRecordingsLogic)
const recordingsDisabled = currentTeam && !currentTeam?.session_recording_opt_in
const { reportRecordingPlaylistCreated } = useActions(eventUsageLogic)
const { guardAvailableFeature } = useActions(upgradeModalLogic)
const { guardAvailableFeature } = useValues(upgradeModalLogic)
const playlistsLogic = savedSessionRecordingPlaylistsLogic({ tab: ReplayTabs.Recent })
const { playlists } = useValues(playlistsLogic)
const { openSettingsPanel } = useActions(sidePanelSettingsLogic)
Expand Down Expand Up @@ -87,8 +87,7 @@ export function SessionsRecordings(): JSX.Element {
? newPlaylistHandler.onEvent?.(e)
: saveFiltersPlaylistHandler.onEvent?.(e)
},
undefined,
playlists.count
{ currentUsage: playlists.count }
)
}
>
Expand All @@ -111,8 +110,7 @@ export function SessionsRecordings(): JSX.Element {
guardAvailableFeature(
AvailableFeature.RECORDINGS_PLAYLISTS,
() => newPlaylistHandler.onEvent?.(e),
undefined,
playlists.count
{ currentUsage: playlists.count }
)
}
data-attr="save-recordings-playlist-button"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { IconPlus } from '@posthog/icons'
import { useActions, useValues } from 'kea'
import { useValues } from 'kea'
import { upgradeModalLogic } from 'lib/components/UpgradeModal/upgradeModalLogic'
import { LemonBanner } from 'lib/lemon-ui/LemonBanner'
import { LemonButton } from 'lib/lemon-ui/LemonButton'
Expand All @@ -10,7 +10,7 @@ import { createPlaylist } from '../playlist/playlistUtils'
import { savedSessionRecordingPlaylistsLogic } from './savedSessionRecordingPlaylistsLogic'

export function SavedSessionRecordingPlaylistsEmptyState(): JSX.Element {
const { guardAvailableFeature } = useActions(upgradeModalLogic)
const { guardAvailableFeature } = useValues(upgradeModalLogic)
const playlistsLogic = savedSessionRecordingPlaylistsLogic({ tab: ReplayTabs.Recent })
const { playlists, loadPlaylistsFailed } = useValues(playlistsLogic)
return loadPlaylistsFailed ? (
Expand All @@ -28,8 +28,7 @@ export function SavedSessionRecordingPlaylistsEmptyState(): JSX.Element {
guardAvailableFeature(
AvailableFeature.RECORDINGS_PLAYLISTS,
() => void createPlaylist({}, true),
undefined,
playlists.count
{ currentUsage: playlists.count }
)
}
>
Expand Down
17 changes: 7 additions & 10 deletions frontend/src/scenes/settings/project/AddMembersModal.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { IconPlus } from '@posthog/icons'
import { LemonButton, LemonModal, LemonSelect, LemonSelectOption } from '@posthog/lemon-ui'
import { useActions, useValues } from 'kea'
import { useValues } from 'kea'
import { Form } from 'kea-forms'
import { RestrictedComponentProps } from 'lib/components/RestrictedArea'
import { upgradeModalLogic } from 'lib/components/UpgradeModal/upgradeModalLogic'
Expand All @@ -20,7 +20,7 @@ import { teamMembersLogic } from './teamMembersLogic'
export function AddMembersModalWithButton({ isRestricted }: RestrictedComponentProps): JSX.Element {
const { addableMembers, allMembersLoading } = useValues(teamMembersLogic)
const { currentTeam } = useValues(teamLogic)
const { guardAvailableFeature } = useActions(upgradeModalLogic)
const { guardAvailableFeature } = useValues(upgradeModalLogic)
const { hasAvailableFeature } = useValues(userLogic)

const [isVisible, setIsVisible] = useState(false)
Expand All @@ -35,14 +35,11 @@ export function AddMembersModalWithButton({ isRestricted }: RestrictedComponentP
type="primary"
data-attr="add-project-members-button"
onClick={() =>
guardAvailableFeature(
AvailableFeature.PROJECT_BASED_PERMISSIONING,
() => setIsVisible(true),
undefined,
undefined,
!hasAvailableFeature(AvailableFeature.PROJECT_BASED_PERMISSIONING) &&
currentTeam?.access_control
)
guardAvailableFeature(AvailableFeature.PROJECT_BASED_PERMISSIONING, () => setIsVisible(true), {
isGrandfathered:
!hasAvailableFeature(AvailableFeature.PROJECT_BASED_PERMISSIONING) &&
currentTeam?.access_control,
})
}
icon={<IconPlus />}
disabled={isRestricted}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ export function ProjectAccessControl(): JSX.Element {
const { currentOrganization, currentOrganizationLoading } = useValues(organizationLogic)
const { currentTeam, currentTeamLoading } = useValues(teamLogic)
const { updateCurrentTeam } = useActions(teamLogic)
const { guardAvailableFeature } = useActions(upgradeModalLogic)
const { guardAvailableFeature } = useValues(upgradeModalLogic)

const isRestricted = !!useRestrictedArea({
minimumAccessLevel: OrganizationMembershipLevel.Admin,
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/scenes/surveys/SurveyAppearance.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import './SurveyAppearance.scss'

import { LemonButton, LemonCheckbox, LemonInput, LemonSelect, Link } from '@posthog/lemon-ui'
import { useActions, useValues } from 'kea'
import { useValues } from 'kea'
import { PayGateMini } from 'lib/components/PayGateMini/PayGateMini'
import { upgradeModalLogic } from 'lib/components/UpgradeModal/upgradeModalLogic'
import React, { useEffect, useRef, useState } from 'react'
Expand Down Expand Up @@ -138,7 +138,7 @@ export function SurveyAppearance({

export function Customization({ appearance, surveyQuestionItem, onAppearanceChange }: CustomizationProps): JSX.Element {
const { surveysStylingAvailable } = useValues(surveysLogic)
const { guardAvailableFeature } = useActions(upgradeModalLogic)
const { guardAvailableFeature } = useValues(upgradeModalLogic)
return (
<>
<div className="flex flex-col">
Expand Down

0 comments on commit 52da597

Please sign in to comment.