Skip to content

Commit

Permalink
fix: Only show activation panel when needed (#18541)
Browse files Browse the repository at this point in the history
  • Loading branch information
benjackwhite authored Nov 10, 2023
1 parent e3cb9cd commit 8a6444b
Show file tree
Hide file tree
Showing 10 changed files with 133 additions and 73 deletions.
20 changes: 12 additions & 8 deletions frontend/src/layout/navigation-3000/sidepanel/SidePanel.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { LemonButton } from '@posthog/lemon-ui'
import './SidePanel.scss'
import { useActions, useValues } from 'kea'
import { SidePanelTab, sidePanelLogic } from './sidePanelLogic'
import { sidePanelLogic } from './sidePanelLogic'
import clsx from 'clsx'
import { Resizer } from 'lib/components/Resizer/Resizer'
import { useRef } from 'react'
Expand All @@ -12,6 +12,8 @@ import { SidePanelSupport } from './panels/SidePanelSupport'
import { NotebookPanel } from 'scenes/notebooks/NotebookPanel/NotebookPanel'
import { SidePanelActivation, SidePanelActivationIcon } from './panels/SidePanelActivation'
import { SidePanelSettings } from './panels/SidePanelSettings'
import { SidePanelTab } from '~/types'
import { sidePanelStateLogic } from './sidePanelStateLogic'

export const SidePanelTabs: Record<SidePanelTab, { label: string; Icon: any; Content: any }> = {
[SidePanelTab.Notebooks]: {
Expand Down Expand Up @@ -43,8 +45,9 @@ export const SidePanelTabs: Record<SidePanelTab, { label: string; Icon: any; Con
}

export function SidePanel(): JSX.Element | null {
const { selectedTab, sidePanelOpen, enabledTabs } = useValues(sidePanelLogic)
const { openSidePanel, closeSidePanel } = useActions(sidePanelLogic)
const { visibleTabs } = useValues(sidePanelLogic)
const { selectedTab, sidePanelOpen } = useValues(sidePanelStateLogic)
const { openSidePanel, closeSidePanel } = useActions(sidePanelStateLogic)

const activeTab = sidePanelOpen && selectedTab

Expand All @@ -64,7 +67,7 @@ export function SidePanel(): JSX.Element | null {

const { desiredWidth, isResizeInProgress } = useValues(resizerLogic(resizerLogicProps))

if (!enabledTabs.length) {
if (!visibleTabs.length) {
return null
}

Expand All @@ -84,9 +87,9 @@ export function SidePanel(): JSX.Element | null {
<Resizer {...resizerLogicProps} />
<div className="SidePanel3000__bar">
<div className="rotate-90 flex items-center gap-1 px-2">
{Object.entries(SidePanelTabs)
.filter(([tab]) => enabledTabs.includes(tab as SidePanelTab))
.map(([tab, { label, Icon }]) => (
{visibleTabs.map((tab: SidePanelTab) => {
const { Icon, label } = SidePanelTabs[tab]
return (
<LemonButton
key={tab}
icon={<Icon className="rotate-270 w-6" />}
Expand All @@ -98,7 +101,8 @@ export function SidePanel(): JSX.Element | null {
>
{label}
</LemonButton>
))}
)
})}
</div>
</div>
<Resizer {...resizerLogicProps} offset={'3rem'} />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { useActions, useValues } from 'kea'
import { SupportForm, SupportFormButtons } from 'lib/components/Support/SupportForm'
import { SidePanelTab, sidePanelLogic } from '../sidePanelLogic'
import { supportLogic } from 'lib/components/Support/supportLogic'
import { useEffect } from 'react'
import { sidePanelStateLogic } from '../sidePanelStateLogic'
import { SidePanelTab } from '~/types'

export const SidePanelSupport = (): JSX.Element => {
const { closeSidePanel } = useActions(sidePanelLogic)
const { selectedTab } = useValues(sidePanelLogic)
const { closeSidePanel } = useActions(sidePanelStateLogic)
const { selectedTab } = useValues(sidePanelStateLogic)

const theLogic = supportLogic({ onClose: () => closeSidePanel(SidePanelTab.Feedback) })
const { title } = useValues(theLogic)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import { actions, kea, reducers, path, listeners, connect } from 'kea'
import { SidePanelTab, sidePanelLogic } from '../sidePanelLogic'

import type { sidePanelDocsLogicType } from './sidePanelDocsLogicType'
import { sidePanelStateLogic } from '../sidePanelStateLogic'
import { SidePanelTab } from '~/types'

const POSTHOG_COM_DOMAIN = 'https://posthog.com'

export const sidePanelDocsLogic = kea<sidePanelDocsLogicType>([
path(['scenes', 'navigation', 'sidepanel', 'sidePanelDocsLogic']),
connect({
actions: [sidePanelLogic, ['openSidePanel', 'closeSidePanel']],
actions: [sidePanelStateLogic, ['openSidePanel', 'closeSidePanel']],
}),

actions({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import { actions, kea, reducers, path, listeners, connect } from 'kea'
import { SidePanelTab, sidePanelLogic } from '../sidePanelLogic'
import { SettingsLogicProps } from 'scenes/settings/settingsLogic'
import { Settings } from 'scenes/settings/Settings'
import { featureFlagLogic } from 'lib/logic/featureFlagLogic'
import { FEATURE_FLAGS } from 'lib/constants'
import { LemonDialog } from '@posthog/lemon-ui'
import { Settings } from 'scenes/settings/Settings'

import type { sidePanelSettingsLogicType } from './sidePanelSettingsLogicType'
import { sidePanelStateLogic } from '../sidePanelStateLogic'
import { SidePanelTab } from '~/types'
import { SettingsLogicProps } from 'scenes/settings/settingsLogic'

export const sidePanelSettingsLogic = kea<sidePanelSettingsLogicType>([
path(['scenes', 'navigation', 'sidepanel', 'sidePanelSettingsLogic']),
connect({
values: [featureFlagLogic, ['featureFlags']],
actions: [sidePanelLogic, ['openSidePanel', 'closeSidePanel']],
actions: [sidePanelStateLogic, ['openSidePanel', 'closeSidePanel']],
}),

actions({
Expand Down
87 changes: 39 additions & 48 deletions frontend/src/layout/navigation-3000/sidepanel/sidePanelLogic.tsx
Original file line number Diff line number Diff line change
@@ -1,47 +1,19 @@
import { actions, kea, reducers, path, listeners, selectors, connect } from 'kea'
import { kea, path, selectors, connect } from 'kea'

import type { sidePanelLogicType } from './sidePanelLogicType'
import { featureFlagLogic } from 'lib/logic/featureFlagLogic'
import { FEATURE_FLAGS } from 'lib/constants'
import { preflightLogic } from 'scenes/PreflightCheck/preflightLogic'

export enum SidePanelTab {
Notebooks = 'notebook',
Feedback = 'feedback',
Docs = 'docs',
Activation = 'activation',
Settings = 'settings',
}
import { activationLogic } from 'lib/components/ActivationSidebar/activationLogic'
import { SidePanelTab } from '~/types'
import { sidePanelStateLogic } from './sidePanelStateLogic'

export const sidePanelLogic = kea<sidePanelLogicType>([
path(['scenes', 'navigation', 'sidepanel', 'sidePanelLogic']),
actions({
setSidePanelOpen: (open: boolean) => ({ open }),
openSidePanel: (tab: SidePanelTab) => ({ tab }),
closeSidePanel: (tab?: SidePanelTab) => ({ tab }),
}),

connect({
values: [featureFlagLogic, ['featureFlags'], preflightLogic, ['isCloudOrDev']],
}),

reducers(() => ({
selectedTab: [
null as SidePanelTab | null,
{ persist: true },
{
openSidePanel: (_, { tab }) => tab,
},
],
sidePanelOpen: [
false,
{ persist: true },
{
setSidePanelOpen: (_, { open }) => open,
},
],
})),

selectors({
enabledTabs: [
(s) => [s.featureFlags, s.isCloudOrDev],
Expand All @@ -60,26 +32,45 @@ export const sidePanelLogic = kea<sidePanelLogicType>([
tabs.push(SidePanelTab.Docs)
}

tabs.push(SidePanelTab.Activation)
tabs.push(SidePanelTab.Settings)
tabs.push(SidePanelTab.Activation)

return tabs
},
],
}),

listeners(({ actions, values }) => ({
openSidePanel: () => {
actions.setSidePanelOpen(true)
},
closeSidePanel: ({ tab }) => {
if (!tab) {
// If we aren't specifiying the tab we always close
actions.setSidePanelOpen(false)
} else if (values.selectedTab === tab) {
// Otherwise we only close it if the tab is the currently open one
actions.setSidePanelOpen(false)
}
},
})),
visibleTabs: [
(s) => [
s.enabledTabs,
sidePanelStateLogic.selectors.selectedTab,
sidePanelStateLogic.selectors.sidePanelOpen,
activationLogic.selectors.isReady,
activationLogic.selectors.hasCompletedAllTasks,
],
(
enabledTabs,
selectedTab,
sidePanelOpen,
activationIsReady,
activationHasCompletedAllTasks
): SidePanelTab[] => {
return enabledTabs.filter((tab: any) => {
if (tab === selectedTab && sidePanelOpen) {
return true
}

// Hide certain tabs unless they are selected
if ([SidePanelTab.Settings].includes(tab)) {
return false
}

if (tab === SidePanelTab.Activation && (!activationIsReady || activationHasCompletedAllTasks)) {
return false
}

return true
})
},
],
}),
])
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { actions, kea, listeners, path, reducers } from 'kea'
import { SidePanelTab } from '~/types'

import type { sidePanelStateLogicType } from './sidePanelStateLogicType'

// The side panel imports a lot of other components so this allows us to avoid circular dependencies

export const sidePanelStateLogic = kea<sidePanelStateLogicType>([
path(['scenes', 'navigation', 'sidepanel', 'sidePanelStateLogic']),
actions({
openSidePanel: (tab: SidePanelTab) => ({ tab }),
closeSidePanel: (tab?: SidePanelTab) => ({ tab }),
setSidePanelOpen: (open: boolean) => ({ open }),
}),

reducers(() => ({
selectedTab: [
null as SidePanelTab | null,
{ persist: true },
{
openSidePanel: (_, { tab }) => tab,
},
],
sidePanelOpen: [
false,
{ persist: true },
{
setSidePanelOpen: (_, { open }) => open,
},
],
})),
listeners(({ actions, values }) => ({
// NOTE: We explicitly reference the actions instead of connecting so that people don't accidentally
// use this logic instead of sidePanelStateLogic
openSidePanel: () => {
actions.setSidePanelOpen(true)
},
closeSidePanel: ({ tab }) => {
if (!tab) {
// If we aren't specifiying the tab we always close
actions.setSidePanelOpen(false)
} else if (values.selectedTab === tab) {
// Otherwise we only close it if the tab is the currently open one
actions.setSidePanelOpen(false)
}
},
})),
])
6 changes: 3 additions & 3 deletions frontend/src/lib/components/Support/supportLogic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { userLogic } from 'scenes/userLogic'

import type { supportLogicType } from './supportLogicType'
import { forms } from 'kea-forms'
import { Region, TeamType, UserType } from '~/types'
import { Region, SidePanelTab, TeamType, UserType } from '~/types'
import { uuid } from 'lib/utils'
import posthog from 'posthog-js'
import { lemonToast } from 'lib/lemon-ui/lemonToast'
Expand All @@ -12,7 +12,7 @@ import { captureException } from '@sentry/react'
import { preflightLogic } from 'scenes/PreflightCheck/preflightLogic'
import { teamLogic } from 'scenes/teamLogic'
import * as Sentry from '@sentry/react'
import { SidePanelTab, sidePanelLogic } from '~/layout/navigation-3000/sidepanel/sidePanelLogic'
import { sidePanelStateLogic } from '~/layout/navigation-3000/sidepanel/sidePanelStateLogic'

function getSessionReplayLink(): string {
const link = posthog
Expand Down Expand Up @@ -111,7 +111,7 @@ export const supportLogic = kea<supportLogicType>([
path(['lib', 'components', 'support', 'supportLogic']),
connect(() => ({
values: [userLogic, ['user'], preflightLogic, ['preflight']],
actions: [sidePanelLogic, ['openSidePanel', 'closeSidePanel']],
actions: [sidePanelStateLogic, ['openSidePanel']],
})),
actions(() => ({
closeSupportForm: () => true,
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/lib/lemon-ui/Link/Link.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ import clsx from 'clsx'
import './Link.scss'
import { IconOpenInNew } from '../icons'
import { Tooltip } from '../Tooltip'
import { useNotebookDrag } from 'scenes/notebooks/AddToNotebook/DraggableToNotebook'
import { useFeatureFlag } from 'lib/hooks/useFeatureFlag'
import { useActions } from 'kea'

import { useNotebookDrag } from 'scenes/notebooks/AddToNotebook/DraggableToNotebook'
import { sidePanelDocsLogic } from '~/layout/navigation-3000/sidepanel/panels/sidePanelDocsLogic'

type RoutePart = string | Record<string, any>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,29 @@ import { HTMLProps } from 'react'
import { EditorFocusPosition } from '../Notebook/utils'

import type { notebookPanelLogicType } from './notebookPanelLogicType'
import { NotebookNodeResource } from '~/types'
import { SidePanelTab, sidePanelLogic } from '~/layout/navigation-3000/sidepanel/sidePanelLogic'
import { NotebookNodeResource, SidePanelTab } from '~/types'
import { featureFlagLogic } from 'lib/logic/featureFlagLogic'
import { FEATURE_FLAGS } from 'lib/constants'
import { notebookPopoverLogic } from './notebookPopoverLogic'
import { sidePanelStateLogic } from '~/layout/navigation-3000/sidepanel/sidePanelStateLogic'

export const notebookPanelLogic = kea<notebookPanelLogicType>([
path(['scenes', 'notebooks', 'Notebook', 'notebookPanelLogic']),
connect({
values: [
sidePanelLogic,
sidePanelStateLogic,
['sidePanelOpen', 'selectedTab'],
featureFlagLogic,
['featureFlags'],
notebookPopoverLogic,
['popoverVisibility'],
],
actions: [sidePanelLogic, ['openSidePanel', 'closeSidePanel'], notebookPopoverLogic, ['setPopoverVisibility']],
actions: [
sidePanelStateLogic,
['openSidePanel', 'closeSidePanel'],
notebookPopoverLogic,
['setPopoverVisibility'],
],
}),
actions({
selectNotebook: (id: string, autofocus: EditorFocusPosition | undefined = undefined) => ({ id, autofocus }),
Expand Down
8 changes: 8 additions & 0 deletions frontend/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3332,3 +3332,11 @@ export enum SDKTag {
}

export type SDKInstructionsMap = Partial<Record<SDKKey, React.ReactNode>>

export enum SidePanelTab {
Notebooks = 'notebook',
Feedback = 'feedback',
Docs = 'docs',
Activation = 'activation',
Settings = 'settings',
}

0 comments on commit 8a6444b

Please sign in to comment.