diff --git a/public/app/features/connections/Connections.test.tsx b/public/app/features/connections/Connections.test.tsx index 1d3519426f7..3778042af10 100644 --- a/public/app/features/connections/Connections.test.tsx +++ b/public/app/features/connections/Connections.test.tsx @@ -95,8 +95,6 @@ describe('Connections', () => { test('renders the core "Add new connection" page in case there is no standalone plugin page override for it', async () => { renderPage(ROUTES.AddNewConnection); - // We expect to see no results and "Data sources" as a header (we only have data sources in OSS Grafana at this point) - expect(await screen.findByText('Data sources')).toBeVisible(); expect(await screen.findByText('No results matching your query were found')).toBeVisible(); }); diff --git a/public/app/features/connections/tabs/ConnectData/ConnectData.test.tsx b/public/app/features/connections/tabs/ConnectData/ConnectData.test.tsx index a4dabd2bbf9..3588aa64305 100644 --- a/public/app/features/connections/tabs/ConnectData/ConnectData.test.tsx +++ b/public/app/features/connections/tabs/ConnectData/ConnectData.test.tsx @@ -33,6 +33,12 @@ const mockCatalogDataSourcePlugin = getCatalogPluginMock({ id: 'sample-data-source', }); +const mockCatalogAppPlugin = getCatalogPluginMock({ + type: PluginType.app, + name: 'Sample app', + id: 'sample-app', +}); + describe('Badges', () => { test('shows enterprise and deprecated badges for plugins', async () => { renderPage([ @@ -64,8 +70,8 @@ describe('Add new connection', () => { expect(screen.queryByText('No results matching your query were found')).toBeInTheDocument(); }); - test('renders no results if there is no data source plugin in the list', async () => { - renderPage([getCatalogPluginMock()]); + test('renders no results if there are no datasource or app plugins in the list', async () => { + renderPage([getCatalogPluginMock({ type: PluginType.panel })]); expect(screen.queryByText('No results matching your query were found')).toBeInTheDocument(); }); @@ -75,6 +81,20 @@ describe('Add new connection', () => { expect(await screen.findByText('Sample data source')).toBeVisible(); }); + + test('renders app plugins when list is populated', async () => { + renderPage([getCatalogPluginMock(), mockCatalogAppPlugin]); + + expect(await screen.findByText('Sample app')).toBeVisible(); + }); + + test('renders app plugin and datasource plugin when list is populated', async () => { + renderPage([getCatalogPluginMock(), mockCatalogAppPlugin, mockCatalogDataSourcePlugin]); + + expect(await screen.findByText('Sample app')).toBeVisible(); + expect(await screen.findByText('Sample data source')).toBeVisible(); + }); + test('should list plugins with update when filtering by update', async () => { const { queryByText } = renderPage( [ diff --git a/public/app/features/connections/tabs/ConnectData/ConnectData.tsx b/public/app/features/connections/tabs/ConnectData/ConnectData.tsx index 3668047af9f..c2957147241 100644 --- a/public/app/features/connections/tabs/ConnectData/ConnectData.tsx +++ b/public/app/features/connections/tabs/ConnectData/ConnectData.tsx @@ -61,7 +61,6 @@ export function AddNewConnection() { const { error, plugins, isLoading } = useGetAll( { keyword: searchTerm, - type: PluginType.datasource, isInstalled: filterBy === 'installed' ? true : undefined, hasUpdate: filterBy === 'has-update' ? true : undefined, }, @@ -100,14 +99,34 @@ export function AddNewConnection() { setFocusedItem(null); }; - const cardGridItems = useMemo( + const getPluginsByType = useMemo(() => { + return { + [PluginType.datasource]: plugins.filter((plugin) => plugin.type === PluginType.datasource), + [PluginType.app]: plugins.filter((plugin) => plugin.type === PluginType.app), + }; + }, [plugins]); + + const dataSourcesPlugins = getPluginsByType[PluginType.datasource]; + const appsPlugins = getPluginsByType[PluginType.app]; + + const datasourceCardGridItems = useMemo( () => - plugins.map((plugin) => ({ + dataSourcesPlugins.map((plugin) => ({ ...plugin, logo: plugin.info.logos.small, url: ROUTES.DataSourcesDetails.replace(':id', plugin.id), })), - [plugins] + [dataSourcesPlugins] + ); + + const appsCardGridItems = useMemo( + () => + appsPlugins.map((plugin) => ({ + ...plugin, + logo: plugin.info.logos.small, + url: `/plugins/${plugin.id}`, + })), + [appsPlugins] ); const onSortByChange = (value: SelectableValue) => { @@ -118,8 +137,10 @@ export function AddNewConnection() { history.push({ query: { filterBy: value } }); }; - const showNoResults = useMemo(() => !isLoading && !error && plugins.length < 1, [isLoading, error, plugins]); - const categoryHeaderLabel = t('connections.connect-data.category-header-label', 'Data sources'); + const showNoResults = useMemo( + () => !isLoading && !error && dataSourcesPlugins.length < 1 && appsPlugins.length < 1, + [isLoading, error, dataSourcesPlugins, appsPlugins] + ); return ( <> @@ -179,7 +200,7 @@ export function AddNewConnection() { - + {isLoading ? ( ) : !!error ? ( @@ -187,8 +208,29 @@ export function AddNewConnection() { Error message: "{{ error: error.message }}" ) : ( - + <> + {/* Data Sources Section */} + {dataSourcesPlugins.length > 0 && ( + <> + + + + )} + + {/* Apps Section */} + {appsPlugins.length > 0 && ( + <> +
+ + + + )} + )} + {showNoResults && (