diff --git a/packages/grafana-ui/src/components/Link/TextLink.tsx b/packages/grafana-ui/src/components/Link/TextLink.tsx index 4a57b04ff6c..6bf83ce3454 100644 --- a/packages/grafana-ui/src/components/Link/TextLink.tsx +++ b/packages/grafana-ui/src/components/Link/TextLink.tsx @@ -27,7 +27,7 @@ interface TextLinkProps extends Omit, 't weight?: 'light' | 'regular' | 'medium' | 'bold'; /** Set the icon to be shown. An external link will show the 'external-link-alt' icon as default.*/ icon?: IconName; - children: string; + children: React.ReactNode; } const svgSizes: { diff --git a/public/app/features/connections/tabs/ConnectData/ConnectData.test.tsx b/public/app/features/connections/tabs/ConnectData/ConnectData.test.tsx index 027831a24ed..30faaeeea0a 100644 --- a/public/app/features/connections/tabs/ConnectData/ConnectData.test.tsx +++ b/public/app/features/connections/tabs/ConnectData/ConnectData.test.tsx @@ -116,4 +116,11 @@ describe('Add new connection', () => { await userEvent.click(await screen.findByText('Sample data source')); expect(screen.queryByText(new RegExp(exampleSentenceInModal))).toBeInTheDocument(); }); + + test('Show request data source and roadmap links', async () => { + renderPage([getCatalogPluginMock(), mockCatalogDataSourcePlugin]); + + expect(await screen.findByText('Request a new data source')).toBeInTheDocument(); + expect(await screen.findByText('View roadmap')).toBeInTheDocument(); + }); }); diff --git a/public/app/features/connections/tabs/ConnectData/ConnectData.tsx b/public/app/features/connections/tabs/ConnectData/ConnectData.tsx index 1ea3c727a48..63737f4cdff 100644 --- a/public/app/features/connections/tabs/ConnectData/ConnectData.tsx +++ b/public/app/features/connections/tabs/ConnectData/ConnectData.tsx @@ -7,6 +7,7 @@ import { useStyles2, LoadingPlaceholder, EmptyState } from '@grafana/ui'; import { contextSrv } from 'app/core/core'; import { useQueryParams } from 'app/core/hooks/useQueryParams'; import { t } from 'app/core/internationalization'; +import { RoadmapLinks } from 'app/features/plugins/admin/components/RoadmapLinks'; import { useGetAll } from 'app/features/plugins/admin/state/hooks'; import { AccessControlAction } from 'app/types'; @@ -103,6 +104,7 @@ export function AddNewConnection() { message={t('connections.connect-data.empty-message', 'No results matching your query were found')} /> )} + ); } diff --git a/public/app/features/plugins/admin/components/RoadmapLinks.tsx b/public/app/features/plugins/admin/components/RoadmapLinks.tsx new file mode 100644 index 00000000000..86bca4275f7 --- /dev/null +++ b/public/app/features/plugins/admin/components/RoadmapLinks.tsx @@ -0,0 +1,26 @@ +import { reportInteraction } from '@grafana/runtime'; +import { Space, TextLink } from '@grafana/ui'; +import { Trans } from 'app/core/internationalization'; + +export const RoadmapLinks = () => { + return ( +
+ + reportInteraction('connections_data_source_request_clicked')} + external + > + Request a new data source + +
+ reportInteraction('connections_data_source_roadmap_clicked')} + external + > + View roadmap + +
+ ); +}; diff --git a/public/app/features/plugins/admin/pages/Browse.test.tsx b/public/app/features/plugins/admin/pages/Browse.test.tsx index befdf53783d..00f0e89f1a4 100644 --- a/public/app/features/plugins/admin/pages/Browse.test.tsx +++ b/public/app/features/plugins/admin/pages/Browse.test.tsx @@ -180,6 +180,17 @@ describe('Browse list of plugins', () => { expect(queryByText('Plugin 2')).not.toBeInTheDocument(); expect(queryByText('Plugin 3')).not.toBeInTheDocument(); }); + + test('Show request data source and roadmap links', async () => { + const { queryByText } = renderBrowse('/plugins', [ + getCatalogPluginMock({ id: 'plugin-1', name: 'Plugin 1', type: PluginType.datasource }), + getCatalogPluginMock({ id: 'plugin-2', name: 'Plugin 2', type: PluginType.panel }), + getCatalogPluginMock({ id: 'plugin-3', name: 'Plugin 3', type: PluginType.datasource }), + ]); + + expect(queryByText('Request a new data source')).toBeInTheDocument(); + expect(queryByText('View roadmap')).toBeInTheDocument(); + }); }); describe('when searching', () => { diff --git a/public/app/features/plugins/admin/pages/Browse.tsx b/public/app/features/plugins/admin/pages/Browse.tsx index 72343daff4d..4c08f91dde1 100644 --- a/public/app/features/plugins/admin/pages/Browse.tsx +++ b/public/app/features/plugins/admin/pages/Browse.tsx @@ -13,6 +13,7 @@ import { useSelector } from 'app/types'; import { HorizontalGroup } from '../components/HorizontalGroup'; import { PluginList } from '../components/PluginList'; +import { RoadmapLinks } from '../components/RoadmapLinks'; import { SearchField } from '../components/SearchField'; import { Sorters } from '../helpers'; import { useHistory } from '../hooks/useHistory'; @@ -162,6 +163,7 @@ export default function Browse({ route }: GrafanaRouteComponentProps): ReactElem
+ ); diff --git a/public/locales/en-US/grafana.json b/public/locales/en-US/grafana.json index d38e110f275..0d3ffbf1355 100644 --- a/public/locales/en-US/grafana.json +++ b/public/locales/en-US/grafana.json @@ -307,7 +307,9 @@ "connections": { "connect-data": { "category-header-label": "Data sources", - "empty-message": "No results matching your query were found" + "empty-message": "No results matching your query were found", + "request-data-source": "Request a new data source", + "roadmap": "View roadmap" }, "search": { "placeholder": "Search all" diff --git a/public/locales/pseudo-LOCALE/grafana.json b/public/locales/pseudo-LOCALE/grafana.json index 176c116f3ed..6d51883b9a1 100644 --- a/public/locales/pseudo-LOCALE/grafana.json +++ b/public/locales/pseudo-LOCALE/grafana.json @@ -307,7 +307,9 @@ "connections": { "connect-data": { "category-header-label": "Đäŧä şőūřčęş", - "empty-message": "Ńő řęşūľŧş mäŧčĥįʼnģ yőūř qūęřy ŵęřę ƒőūʼnđ" + "empty-message": "Ńő řęşūľŧş mäŧčĥįʼnģ yőūř qūęřy ŵęřę ƒőūʼnđ", + "request-data-source": "Ŗęqūęşŧ ä ʼnęŵ đäŧä şőūřčę", + "roadmap": "Vįęŵ řőäđmäp" }, "search": { "placeholder": "Ŝęäřčĥ äľľ"