Skip to content

Commit

Permalink
use normal upgrad modal for editableField paywall
Browse files Browse the repository at this point in the history
  • Loading branch information
raquelmsmith committed Mar 20, 2024
1 parent 7425927 commit 1a144d4
Show file tree
Hide file tree
Showing 6 changed files with 129 additions and 127 deletions.
230 changes: 115 additions & 115 deletions frontend/src/lib/components/EditableField/EditableField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import './EditableField.scss'
import { useMergeRefs } from '@floating-ui/react'
import { IconPencil } from '@posthog/icons'
import clsx from 'clsx'
import { useValues } from 'kea'
import { useResizeObserver } from 'lib/hooks/useResizeObserver'
import { IconMarkdown } from 'lib/lemon-ui/icons'
import { LemonButton } from 'lib/lemon-ui/LemonButton'
Expand All @@ -12,6 +13,10 @@ import { pluralize } from 'lib/utils'
import React, { useEffect, useLayoutEffect, useRef, useState } from 'react'
import TextareaAutosize from 'react-textarea-autosize'

import { AvailableFeature } from '~/types'

import { upgradeModalLogic } from '../UpgradeModal/upgradeModalLogic'

export interface EditableFieldProps {
/** What this field stands for. */
name: string
Expand All @@ -28,7 +33,7 @@ export interface EditableFieldProps {
markdown?: boolean
compactButtons?: boolean | 'xsmall' // The 'xsmall' is somewhat hacky, but necessary for 3000 breadcrumbs
/** Whether this field should be gated behind a "paywall". */
paywall?: boolean
paywallFeature?: AvailableFeature
/** Controlled mode. */
mode?: 'view' | 'edit'
onModeToggle?: (newMode: 'view' | 'edit') => void
Expand Down Expand Up @@ -58,7 +63,7 @@ export function EditableField({
multiline = false,
markdown = false,
compactButtons = false,
paywall = false,
paywallFeature,
mode,
onModeToggle,
editingIndication = 'outlined',
Expand All @@ -68,6 +73,7 @@ export function EditableField({
saveButtonText = 'Save',
notice,
}: EditableFieldProps): JSX.Element {
const { guardAvailableFeature } = useValues(upgradeModalLogic)
const [localIsEditing, setLocalIsEditing] = useState(mode === 'edit')
const [localTentativeValue, setLocalTentativeValue] = useState(value)
const [isDisplayTooltipNeeded, setIsDisplayTooltipNeeded] = useState(false)
Expand Down Expand Up @@ -125,7 +131,7 @@ export function EditableField({
onModeToggle?.('view')
}

const isEditing = !paywall && (mode === 'edit' || localIsEditing)
const isEditing = mode === 'edit' || localIsEditing

const handleKeyDown = (e: React.KeyboardEvent<HTMLElement>): void => {
if (isEditing) {
Expand Down Expand Up @@ -156,123 +162,117 @@ export function EditableField({
style={style}
ref={containerRef}
>
<Tooltip
placement="right"
title={
paywall
? "This field is part of PostHog's collaboration feature set and requires a premium plan."
: undefined
}
>
<div className="EditableField__highlight">
{isEditing ? (
<>
{multiline ? (
<TextareaAutosize
name={name}
value={localTentativeValue}
onChange={(e) => {
onChange?.(e.target.value)
setLocalTentativeValue(e.target.value)
}}
onBlur={saveOnBlur ? (localTentativeValue !== value ? save : cancel) : undefined}
onKeyDown={handleKeyDown}
placeholder={placeholder}
minLength={minLength}
maxLength={maxLength}
autoFocus={autoFocus}
ref={inputRef as React.RefObject<HTMLTextAreaElement>}
/>
) : (
<AutosizeInput
name={name}
value={localTentativeValue}
onChange={(e) => {
<div className="EditableField__highlight">
{isEditing ? (
<>
{multiline ? (
<TextareaAutosize
name={name}
value={localTentativeValue}
onChange={(e) => {
onChange?.(e.target.value)
setLocalTentativeValue(e.target.value)
}}
onBlur={saveOnBlur ? (localTentativeValue !== value ? save : cancel) : undefined}
onKeyDown={handleKeyDown}
placeholder={placeholder}
minLength={minLength}
maxLength={maxLength}
autoFocus={autoFocus}
ref={inputRef as React.RefObject<HTMLTextAreaElement>}
/>
) : (
<AutosizeInput
name={name}
value={localTentativeValue}
onChange={(e) => {
guardAvailableFeature(paywallFeature, () => {
onChange?.(e.target.value)
setLocalTentativeValue(e.target.value)
}}
onBlur={saveOnBlur ? (localTentativeValue !== value ? save : cancel) : undefined}
onKeyDown={handleKeyDown}
placeholder={placeholder}
minLength={minLength}
maxLength={maxLength}
autoFocus={autoFocus}
ref={inputRef as React.RefObject<HTMLInputElement>}
/>
)}
{(!mode || !!onModeToggle) && (
<div className="EditableField__actions">
{markdown && (
<Tooltip title="Markdown formatting support">
<span className="flex items-center">
<IconMarkdown className="text-muted text-2xl" />
</span>
</Tooltip>
)}
<LemonButton
title="Cancel editing"
size={typeof compactButtons === 'string' ? compactButtons : 'small'}
onClick={cancel}
type="secondary"
onMouseDown={mouseDownOnCancelButton}
>
Cancel
</LemonButton>
<LemonButton
title={
!minLength
? 'Save'
: `Save (at least ${pluralize(
minLength,
'character',
'characters'
)} required)`
}
size={typeof compactButtons === 'string' ? compactButtons : 'small'}
disabled={!isSaveable}
onClick={save}
type="primary"
>
{saveButtonText}
</LemonButton>
</div>
)}
</>
) : (
<>
{localTentativeValue && markdown ? (
<LemonMarkdown lowKeyHeadings>{localTentativeValue}</LemonMarkdown>
) : (
<Tooltip
title={isDisplayTooltipNeeded ? localTentativeValue : undefined}
placement="bottom-start"
delayMs={0}
})
}}
onBlur={saveOnBlur ? (localTentativeValue !== value ? save : cancel) : undefined}
onKeyDown={handleKeyDown}
placeholder={placeholder}
minLength={minLength}
maxLength={maxLength}
autoFocus={autoFocus}
ref={inputRef as React.RefObject<HTMLInputElement>}
/>
)}
{(!mode || !!onModeToggle) && (
<div className="EditableField__actions">
{markdown && (
<Tooltip title="Markdown formatting support">
<span className="flex items-center">
<IconMarkdown className="text-muted text-2xl" />
</span>
</Tooltip>
)}
<LemonButton
title="Cancel editing"
size={typeof compactButtons === 'string' ? compactButtons : 'small'}
onClick={cancel}
type="secondary"
onMouseDown={mouseDownOnCancelButton}
>
Cancel
</LemonButton>
<LemonButton
title={
!minLength
? 'Save'
: `Save (at least ${pluralize(
minLength,
'character',
'characters'
)} required)`
}
size={typeof compactButtons === 'string' ? compactButtons : 'small'}
disabled={!isSaveable}
onClick={save}
type="primary"
>
<span className="EditableField__display" ref={displayRef}>
{localTentativeValue || <i>{placeholder}</i>}
</span>
</Tooltip>
)}
{(!mode || !!onModeToggle) && (
<div className="EditableField__actions">
<LemonButton
title="Edit"
icon={<IconPencil />}
size={compactButtons ? 'small' : undefined}
onClick={() => {
{saveButtonText}
</LemonButton>
</div>
)}
</>
) : (
<>
{localTentativeValue && markdown ? (
<LemonMarkdown lowKeyHeadings>{localTentativeValue}</LemonMarkdown>
) : (
<Tooltip
title={isDisplayTooltipNeeded ? localTentativeValue : undefined}
placement="bottom-start"
delayMs={0}
>
<span className="EditableField__display" ref={displayRef}>
{localTentativeValue || <i>{placeholder}</i>}
</span>
</Tooltip>
)}
{(!mode || !!onModeToggle) && (
<div className="EditableField__actions">
<LemonButton
title="Edit"
icon={<IconPencil />}
size={compactButtons ? 'small' : undefined}
onClick={() => {
guardAvailableFeature(paywallFeature, () => {
setLocalIsEditing(true)
onModeToggle?.('edit')
}}
data-attr={`edit-prop-${name}`}
disabled={paywall}
noPadding
/>
</div>
)}
</>
)}
</div>
</Tooltip>
})
}}
data-attr={`edit-prop-${name}`}
noPadding
/>
</div>
)}
</>
)}
</div>
{!isEditing && notice && (
<Tooltip title={notice.tooltip} placement="right">
<span className="flex items-center">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { AvailableFeature } from '~/types'
import type { upgradeModalLogicType } from './upgradeModalLogicType'

export type GuardAvailableFeatureFn = (
featureKey: AvailableFeature,
featureKey?: AvailableFeature,
featureAvailableCallback?: () => void,
options?: {
guardOnCloud?: boolean
Expand Down Expand Up @@ -60,6 +60,10 @@ export const upgradeModalLogic = kea<upgradeModalLogicType>([
(s) => [s.preflight, s.hasAvailableFeature],
(preflight, hasAvailableFeature): GuardAvailableFeatureFn => {
return (featureKey, featureAvailableCallback, options): boolean => {
if (!featureKey) {
featureAvailableCallback?.()
return true
}
const {
guardOnCloud = true,
guardOnSelfHosted = true,
Expand Down
4 changes: 1 addition & 3 deletions frontend/src/scenes/actions/ActionEdit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import { Spinner } from 'lib/lemon-ui/Spinner/Spinner'
import { compactNumber, uuid } from 'lib/utils'
import { teamLogic } from 'scenes/teamLogic'
import { urls } from 'scenes/urls'
import { userLogic } from 'scenes/userLogic'

import { tagsModel } from '~/models/tagsModel'
import { ActionStepType, AvailableFeature } from '~/types'
Expand All @@ -32,7 +31,6 @@ export function ActionEdit({ action: loadedAction, id }: ActionEditLogicProps):
const { action, actionLoading, actionCount, actionCountLoading } = useValues(logic)
const { submitAction, deleteAction } = useActions(logic)
const { currentTeam } = useValues(teamLogic)
const { hasAvailableFeature } = useValues(userLogic)
const { tags } = useValues(tagsModel)

const slackEnabled = currentTeam?.slack_incoming_webhook
Expand Down Expand Up @@ -96,7 +94,7 @@ export function ActionEdit({ action: loadedAction, id }: ActionEditLogicProps):
className="action-description"
compactButtons
maxLength={600} // No limit on backend model, but enforce shortish description
paywall={!hasAvailableFeature(AvailableFeature.INGESTION_TAXONOMY)}
paywallFeature={AvailableFeature.INGESTION_TAXONOMY}
/>
)}
</LemonField>
Expand Down
8 changes: 6 additions & 2 deletions frontend/src/scenes/dashboard/DashboardHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -308,15 +308,19 @@ export function DashboardHeader(): JSX.Element | null {
multiline
name="description"
markdown
value={dashboard.description || ''}
value={
(hasAvailableFeature(AvailableFeature.TEAM_COLLABORATION) &&
dashboard.description) ||
''
}
placeholder="Description (optional)"
onSave={(value) =>
updateDashboard({ id: dashboard.id, description: value, allowUndo: true })
}
saveOnBlur={true}
compactButtons
mode={!canEditDashboard ? 'view' : undefined}
paywall={!hasAvailableFeature(AvailableFeature.TEAM_COLLABORATION)}
paywallFeature={AvailableFeature.TEAM_COLLABORATION}
/>
)}
{dashboard?.tags && (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import { definitionLogic, DefinitionLogicProps } from 'scenes/data-management/de
import { EventDefinitionProperties } from 'scenes/data-management/events/EventDefinitionProperties'
import { SceneExport } from 'scenes/sceneTypes'
import { urls } from 'scenes/urls'
import { userLogic } from 'scenes/userLogic'

import { defaultDataTableColumns } from '~/queries/nodes/DataTable/utils'
import { Query } from '~/queries/Query/Query'
Expand All @@ -37,7 +36,6 @@ export function DefinitionView(props: DefinitionLogicProps = {}): JSX.Element {
const { definition, definitionLoading, definitionMissing, hasTaxonomyFeatures, singular, isEvent, isProperty } =
useValues(logic)
const { deleteDefinition } = useActions(logic)
const { hasAvailableFeature } = useValues(userLogic)

if (definitionLoading) {
return <SpinnerOverlay sceneLevel />
Expand Down Expand Up @@ -146,7 +144,7 @@ export function DefinitionView(props: DefinitionLogicProps = {}): JSX.Element {
className="definition-description"
compactButtons
maxLength={600}
paywall={!hasAvailableFeature(AvailableFeature.INGESTION_TAXONOMY)}
paywallFeature={AvailableFeature.INGESTION_TAXONOMY}
/>

<ObjectTags
Expand Down
Loading

0 comments on commit 1a144d4

Please sign in to comment.