Skip to content

Commit

Permalink
feat: Separate out apps management tab (#18013)
Browse files Browse the repository at this point in the history
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
  • Loading branch information
2 people authored and daibhin committed Oct 23, 2023
1 parent 786d748 commit f6123c2
Show file tree
Hide file tree
Showing 8 changed files with 340 additions and 238 deletions.
Binary file modified frontend/__snapshots__/scenes-app-apps--installed.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 7 additions & 1 deletion frontend/src/scenes/plugins/AppsScene.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useEffect } from 'react'
import { useActions, useValues } from 'kea'
import { pluginsLogic } from './pluginsLogic'
import { PageHeader } from 'lib/components/PageHeader'
import { canViewPlugins } from './access'
import { canGloballyManagePlugins, canViewPlugins } from './access'
import { userLogic } from 'scenes/userLogic'
import { SceneExport } from 'scenes/sceneTypes'
import { ActivityLog } from 'lib/components/ActivityLog/ActivityLog'
Expand All @@ -15,6 +15,7 @@ import { LemonButton } from '@posthog/lemon-ui'
import { urls } from 'scenes/urls'

import './Plugins.scss'
import { AppsManagementTab } from './tabs/apps/AppsManagementTab'

export const scene: SceneExport = {
component: AppsScene,
Expand Down Expand Up @@ -61,6 +62,11 @@ export function AppsScene(): JSX.Element | null {
label: 'History',
content: <ActivityLog scope={ActivityScope.PLUGIN} />,
},
canGloballyManagePlugins(user?.organization) && {
key: PluginTab.AppsManagement,
label: 'Apps Management',
content: <AppsManagementTab />,
},
]}
/>
</>
Expand Down
138 changes: 138 additions & 0 deletions frontend/src/scenes/plugins/tabs/apps/AppManagementView.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
import { LemonButton, Link } from '@posthog/lemon-ui'
import { useActions, useValues } from 'kea'
import { IconCheckmark, IconCloudDownload } from 'lib/lemon-ui/icons'
import { PluginImage } from 'scenes/plugins/plugin/PluginImage'
import { pluginsLogic } from 'scenes/plugins/pluginsLogic'
import { PluginTypeWithConfig, PluginRepositoryEntry, PluginInstallationType } from 'scenes/plugins/types'
import { PluginType } from '~/types'
import { PluginTags } from './components'
import { Tooltip } from 'lib/lemon-ui/Tooltip'
import { Popconfirm } from 'antd'
import { DeleteOutlined, GlobalOutlined, RollbackOutlined } from '@ant-design/icons'
import { canGloballyManagePlugins } from 'scenes/plugins/access'
import { userLogic } from 'scenes/userLogic'

export function AppManagementView({
plugin,
}: {
plugin: PluginTypeWithConfig | PluginType | PluginRepositoryEntry
}): JSX.Element {
const { user } = useValues(userLogic)

if (!canGloballyManagePlugins(user?.organization)) {
return <></>
}
const { installingPluginUrl, pluginsNeedingUpdates, pluginsUpdating, loading, unusedPlugins } =
useValues(pluginsLogic)
const { installPlugin, editPlugin, updatePlugin, uninstallPlugin, patchPlugin } = useActions(pluginsLogic)

return (
<div className="flex justify-between items-center">
<div className="flex items-center gap-4">
<PluginImage plugin={plugin} />
<div>
<div className="flex gap-2 items-center">
<span className="font-semibold truncate">
<Link to={plugin.url} target={'blank'}>
{plugin.name}
</Link>
</span>
<PluginTags plugin={plugin} />
</div>
<div className="text-sm">{plugin.description}</div>
</div>
</div>

<div className="flex gap-2 whitespace-nowrap items-center justify-end">
{'id' in plugin ? (
<>
{'updateStatus' in plugin && pluginsNeedingUpdates.find((x) => x.id === plugin.id) && (
<LemonButton
type="secondary"
size="small"
onClick={() => {
plugin.updateStatus?.updated ? editPlugin(plugin.id) : updatePlugin(plugin.id)
}}
loading={pluginsUpdating.includes(plugin.id)}
icon={plugin.updateStatus?.updated ? <IconCheckmark /> : <IconCloudDownload />}
>
{plugin.updateStatus?.updated ? 'Updated' : 'Update'}
</LemonButton>
)}
<Popconfirm
placement="topLeft"
title="Are you sure you wish to uninstall this app completely?"
onConfirm={() => uninstallPlugin(plugin.id)}
okText="Uninstall"
cancelText="Cancel"
className="Plugins__Popconfirm"
>
<LemonButton
type="primary"
status="danger"
size="small"
icon={<DeleteOutlined />}
disabledReason={
unusedPlugins.includes(plugin.id) ? undefined : 'This app is still in use.'
}
data-attr="plugin-uninstall"
>
Uninstall
</LemonButton>
</Popconfirm>
{plugin.is_global ? (
<Tooltip
title={
<>
This app can currently be used by other organizations in this instance of
PostHog. This action will <b>disable and hide it</b> for all organizations other
than yours.
</>
}
>
<LemonButton
type="secondary"
size="small"
icon={<RollbackOutlined />}
onClick={() => patchPlugin(plugin.id, { is_global: false })}
>
Make local
</LemonButton>
</Tooltip>
) : (
<Tooltip
title={
<>
This action will mark this app as installed for <b>all organizations</b> in this
instance of PostHog.
</>
}
>
<LemonButton
type="secondary"
size="small"
icon={<GlobalOutlined />}
onClick={() => patchPlugin(plugin.id, { is_global: true })}
>
Make global
</LemonButton>
</Tooltip>
)}
</>
) : (
<LemonButton
type="primary"
loading={loading && installingPluginUrl === plugin.url}
icon={<IconCloudDownload />}
size="small"
onClick={() =>
plugin.url ? installPlugin(plugin.url, PluginInstallationType.Repository) : undefined
}
>
Install
</LemonButton>
)}
</div>
</div>
)
}
97 changes: 2 additions & 95 deletions frontend/src/scenes/plugins/tabs/apps/AppView.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import { Link, LemonButton, LemonBadge } from '@posthog/lemon-ui'
import { useActions, useValues } from 'kea'
import { DeleteOutlined, GlobalOutlined, RollbackOutlined } from '@ant-design/icons'
import { LemonMenuItem, LemonMenu } from 'lib/lemon-ui/LemonMenu'
import {
IconLink,
IconCheckmark,
IconCloudDownload,
IconSettings,
IconEllipsis,
Expand All @@ -19,27 +17,14 @@ import { urls } from 'scenes/urls'
import { PluginType } from '~/types'
import { PluginTags } from './components'
import { Tooltip } from 'lib/lemon-ui/Tooltip'
import { userLogic } from 'scenes/userLogic'
import { canGloballyManagePlugins } from 'scenes/plugins/access'
import { Popconfirm } from 'antd'

export function AppView({
plugin,
}: {
plugin: PluginTypeWithConfig | PluginType | PluginRepositoryEntry
}): JSX.Element {
const {
installingPluginUrl,
pluginsNeedingUpdates,
pluginsUpdating,
showAppMetricsForPlugin,
loading,
sortableEnabledPlugins,
unusedPlugins,
} = useValues(pluginsLogic)
const { installPlugin, editPlugin, toggleEnabled, updatePlugin, openReorderModal, patchPlugin, uninstallPlugin } =
useActions(pluginsLogic)
const { user } = useValues(userLogic)
const { installingPluginUrl, showAppMetricsForPlugin, loading, sortableEnabledPlugins } = useValues(pluginsLogic)
const { installPlugin, editPlugin, toggleEnabled, openReorderModal } = useActions(pluginsLogic)

const pluginConfig = 'pluginConfig' in plugin ? plugin.pluginConfig : null
const isConfigured = !!pluginConfig?.id
Expand Down Expand Up @@ -144,84 +129,6 @@ export function AppView({
</LemonButton>
)}

{'updateStatus' in plugin && pluginsNeedingUpdates.find((x) => x.id === plugin.id) && (
<LemonButton
type="secondary"
size="small"
onClick={() => {
plugin.updateStatus?.updated ? editPlugin(plugin.id) : updatePlugin(plugin.id)
}}
loading={pluginsUpdating.includes(plugin.id)}
icon={plugin.updateStatus?.updated ? <IconCheckmark /> : <IconCloudDownload />}
>
{plugin.updateStatus?.updated ? 'Updated' : 'Update'}
</LemonButton>
)}

{canGloballyManagePlugins(user?.organization) && (
<>
<Popconfirm
placement="topLeft"
title="Are you sure you wish to uninstall this app completely?"
onConfirm={() => uninstallPlugin(plugin.id)}
okText="Uninstall"
cancelText="Cancel"
className="Plugins__Popconfirm"
>
<LemonButton
type="primary"
status="danger"
size="small"
icon={<DeleteOutlined />}
disabledReason={
unusedPlugins.includes(plugin.id) ? undefined : 'This app is still in use.'
}
data-attr="plugin-uninstall"
>
Uninstall
</LemonButton>
</Popconfirm>
{plugin.is_global ? (
<Tooltip
title={
<>
This app can currently be used by other organizations in this instance
of PostHog. This action will <b>disable and hide it</b> for all
organizations other than yours.
</>
}
>
<LemonButton
type="secondary"
size="small"
icon={<RollbackOutlined />}
onClick={() => patchPlugin(plugin.id, { is_global: false })}
>
Make local
</LemonButton>
</Tooltip>
) : (
<Tooltip
title={
<>
This action will mark this app as installed for <b>all organizations</b>{' '}
in this instance of PostHog.
</>
}
>
<LemonButton
type="secondary"
size="small"
icon={<GlobalOutlined />}
onClick={() => patchPlugin(plugin.id, { is_global: true })}
>
Make global
</LemonButton>
</Tooltip>
)}
</>
)}

{pluginConfig.id &&
(pluginConfig.error ? (
<LemonButton
Expand Down
Loading

0 comments on commit f6123c2

Please sign in to comment.