diff --git a/packages/grafana-data/src/types/datasource.ts b/packages/grafana-data/src/types/datasource.ts index c66e92c3e54..6a7aff0487a 100644 --- a/packages/grafana-data/src/types/datasource.ts +++ b/packages/grafana-data/src/types/datasource.ts @@ -549,6 +549,7 @@ export interface DataSourceSettings { margin-bottom: 0; font-size: ${theme.typography.size.md}; line-height: ${theme.typography.lineHeight.xs}; + color: ${theme.colors.text}; + font-weight: ${theme.typography.weight.semibold}; `, info: css` display: flex; @@ -221,7 +223,7 @@ export const getCardStyles = stylesFactory((theme: GrafanaTheme) => { `, media: css` margin-right: ${theme.spacing.md}; - max-width: 40px; + width: 40px; & > * { width: 100%; } @@ -299,7 +301,11 @@ const Meta: FC = memo(({ children, styles, // Join meta data elements by separator if (Array.isArray(children) && separator) { - meta = React.Children.toArray(children).reduce((prev, curr, i) => [ + const filtered = React.Children.toArray(children).filter(Boolean); + if (!filtered.length) { + return null; + } + meta = filtered.reduce((prev, curr, i) => [ prev, {separator} diff --git a/packages/grafana-ui/src/components/DataSourceSettings/CustomHeadersSettings.test.tsx b/packages/grafana-ui/src/components/DataSourceSettings/CustomHeadersSettings.test.tsx index 121645c3f40..2848cbdbfbf 100644 --- a/packages/grafana-ui/src/components/DataSourceSettings/CustomHeadersSettings.test.tsx +++ b/packages/grafana-ui/src/components/DataSourceSettings/CustomHeadersSettings.test.tsx @@ -9,6 +9,7 @@ const setup = (propOverrides?: object) => { orgId: 1, name: 'gdev-influxdb', type: 'influxdb', + typeName: 'Influxdb', typeLogoUrl: '', access: 'direct', url: 'http://localhost:8086', diff --git a/packages/grafana-ui/src/components/DataSourceSettings/DataSourceHttpSettings.story.tsx b/packages/grafana-ui/src/components/DataSourceSettings/DataSourceHttpSettings.story.tsx index 8f562623a95..c847eaddaaf 100644 --- a/packages/grafana-ui/src/components/DataSourceSettings/DataSourceHttpSettings.story.tsx +++ b/packages/grafana-ui/src/components/DataSourceSettings/DataSourceHttpSettings.story.tsx @@ -10,6 +10,7 @@ const settingsMock: DataSourceSettings = { orgId: 1, name: 'gdev-influxdb', type: 'influxdb', + typeName: 'Influxdb', typeLogoUrl: '', access: 'direct', url: 'http://localhost:8086', diff --git a/pkg/api/datasources.go b/pkg/api/datasources.go index 9a84c8caec4..3d96f3b7948 100644 --- a/pkg/api/datasources.go +++ b/pkg/api/datasources.go @@ -36,6 +36,7 @@ func (hs *HTTPServer) GetDataSources(c *models.ReqContext) response.Response { Name: ds.Name, Url: ds.Url, Type: ds.Type, + TypeName: ds.Type, Access: ds.Access, Password: ds.Password, Database: ds.Database, @@ -48,6 +49,7 @@ func (hs *HTTPServer) GetDataSources(c *models.ReqContext) response.Response { if plugin, exists := plugins.DataSources[ds.Type]; exists { dsItem.TypeLogoUrl = plugin.Info.Logos.Small + dsItem.TypeName = plugin.Name } else { dsItem.TypeLogoUrl = "public/img/icn-datasource.svg" } diff --git a/pkg/api/dtos/datasource.go b/pkg/api/dtos/datasource.go index 9ab568e4e9d..58a40d8d327 100644 --- a/pkg/api/dtos/datasource.go +++ b/pkg/api/dtos/datasource.go @@ -36,6 +36,7 @@ type DataSourceListItemDTO struct { OrgId int64 `json:"orgId"` Name string `json:"name"` Type string `json:"type"` + TypeName string `json:"typeName"` TypeLogoUrl string `json:"typeLogoUrl"` Access models.DsAccess `json:"access"` Url string `json:"url"` diff --git a/public/app/features/datasources/DataSourceList.test.tsx b/public/app/features/datasources/DataSourceList.test.tsx index 6e097da2c53..0cbe041b949 100644 --- a/public/app/features/datasources/DataSourceList.test.tsx +++ b/public/app/features/datasources/DataSourceList.test.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { shallow } from 'enzyme'; +import { render, screen } from '@testing-library/react'; import DataSourcesList from './DataSourcesList'; import { getMockDataSources } from './__mocks__/dataSourcesMocks'; import { LayoutModes } from '../../core/components/LayoutSelector/LayoutSelector'; @@ -10,13 +10,20 @@ const setup = () => { layoutMode: LayoutModes.Grid, }; - return shallow(); + return render(); }; -describe('Render', () => { - it('should render component', () => { - const wrapper = setup(); +describe('DataSourcesList', () => { + it('should render list of datasources', () => { + setup(); + expect(screen.getAllByRole('listitem')).toHaveLength(3); + expect(screen.getAllByRole('heading')).toHaveLength(3); + }); - expect(wrapper).toMatchSnapshot(); + it('should render all elements in the list item', () => { + setup(); + expect(screen.getByRole('heading', { name: 'dataSource-0' })).toBeInTheDocument(); + expect(screen.getByRole('link', { name: 'dataSource-0 dataSource-0' })).toBeInTheDocument(); + expect(screen.getByAltText('dataSource-0')).toBeInTheDocument(); }); }); diff --git a/public/app/features/datasources/DataSourcesList.tsx b/public/app/features/datasources/DataSourcesList.tsx index de1e9afa762..6899120df1a 100644 --- a/public/app/features/datasources/DataSourcesList.tsx +++ b/public/app/features/datasources/DataSourcesList.tsx @@ -1,39 +1,50 @@ // Libraries -import React, { PureComponent } from 'react'; -import classNames from 'classnames'; - -// Components -import DataSourcesListItem from './DataSourcesListItem'; +import React, { FC } from 'react'; // Types import { DataSourceSettings } from '@grafana/data'; -import { LayoutMode, LayoutModes } from '../../core/components/LayoutSelector/LayoutSelector'; +import { LayoutMode } from '../../core/components/LayoutSelector/LayoutSelector'; +import { Card, Tag, useStyles } from '@grafana/ui'; +import { css } from 'emotion'; export interface Props { dataSources: DataSourceSettings[]; layoutMode: LayoutMode; } -export class DataSourcesList extends PureComponent { - render() { - const { dataSources, layoutMode } = this.props; - - const listStyle = classNames({ - 'card-section': true, - 'card-list-layout-grid': layoutMode === LayoutModes.Grid, - 'card-list-layout-list': layoutMode === LayoutModes.List, - }); +export const DataSourcesList: FC = ({ dataSources, layoutMode }) => { + const styles = useStyles(getStyles); - return ( -
-
    - {dataSources.map((dataSource, index) => { - return ; - })} -
-
- ); - } -} + return ( +
    + {dataSources.map((dataSource, index) => { + return ( +
  • + + + {dataSource.name} + + + {[ + dataSource.typeName, + dataSource.url, + dataSource.isDefault && , + ]} + + +
  • + ); + })} +
+ ); +}; export default DataSourcesList; + +const getStyles = () => { + return { + list: css` + list-style: none; + `, + }; +}; diff --git a/public/app/features/datasources/DataSourcesListItem.test.tsx b/public/app/features/datasources/DataSourcesListItem.test.tsx deleted file mode 100644 index 138c71cb46a..00000000000 --- a/public/app/features/datasources/DataSourcesListItem.test.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import React from 'react'; -import { shallow } from 'enzyme'; -import DataSourcesListItem from './DataSourcesListItem'; -import { getMockDataSource } from './__mocks__/dataSourcesMocks'; - -const setup = () => { - const props = { - dataSource: getMockDataSource(), - }; - - return shallow(); -}; - -describe('Render', () => { - it('should render component', () => { - const wrapper = setup(); - - expect(wrapper).toMatchSnapshot(); - }); -}); diff --git a/public/app/features/datasources/DataSourcesListItem.tsx b/public/app/features/datasources/DataSourcesListItem.tsx deleted file mode 100644 index 2ca2bbd64e2..00000000000 --- a/public/app/features/datasources/DataSourcesListItem.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import React, { PureComponent } from 'react'; -import { DataSourceSettings } from '@grafana/data'; -import { selectors } from '@grafana/e2e-selectors'; - -export interface Props { - dataSource: DataSourceSettings; -} - -export class DataSourcesListItem extends PureComponent { - render() { - const { dataSource } = this.props; - return ( -
  • - -
    -
    {dataSource.type}
    -
    -
    -
    - {dataSource.name} -
    -
    -
    - {dataSource.name} - {dataSource.isDefault && default} -
    -
    {dataSource.url}
    -
    -
    -
    -
  • - ); - } -} - -export default DataSourcesListItem; diff --git a/public/app/features/datasources/DataSourcesListPage.tsx b/public/app/features/datasources/DataSourcesListPage.tsx index 4d509aa199c..4784bdfda40 100644 --- a/public/app/features/datasources/DataSourcesListPage.tsx +++ b/public/app/features/datasources/DataSourcesListPage.tsx @@ -49,11 +49,7 @@ const emptyListModel = { export class DataSourcesListPage extends PureComponent { componentDidMount() { - this.fetchDataSources(); - } - - async fetchDataSources() { - return await this.props.loadDataSources(); + this.props.loadDataSources(); } render() { diff --git a/public/app/features/datasources/__mocks__/dataSourcesMocks.ts b/public/app/features/datasources/__mocks__/dataSourcesMocks.ts index 0c01224af99..cc3eaa361c1 100644 --- a/public/app/features/datasources/__mocks__/dataSourcesMocks.ts +++ b/public/app/features/datasources/__mocks__/dataSourcesMocks.ts @@ -3,7 +3,7 @@ import { DataSourceSettings } from '@grafana/data'; export const getMockDataSources = (amount: number) => { const dataSources = []; - for (let i = 0; i <= amount; i++) { + for (let i = 0; i < amount; i++) { dataSources.push({ access: '', basicAuth: false, @@ -37,6 +37,7 @@ export const getMockDataSource = (): DataSourceSettings => { isDefault: false, jsonData: { authType: 'credentials', defaultRegion: 'eu-west-2' }, name: 'gdev-cloudwatch', + typeName: 'Cloudwatch', orgId: 1, password: '', readOnly: false, diff --git a/public/app/features/datasources/__snapshots__/DataSourceList.test.tsx.snap b/public/app/features/datasources/__snapshots__/DataSourceList.test.tsx.snap deleted file mode 100644 index 7167f59b048..00000000000 --- a/public/app/features/datasources/__snapshots__/DataSourceList.test.tsx.snap +++ /dev/null @@ -1,108 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Render should render component 1`] = ` -
    -
      - - - - -
    -
    -`; diff --git a/public/app/features/datasources/__snapshots__/DataSourcesListItem.test.tsx.snap b/public/app/features/datasources/__snapshots__/DataSourcesListItem.test.tsx.snap deleted file mode 100644 index d051703887e..00000000000 --- a/public/app/features/datasources/__snapshots__/DataSourcesListItem.test.tsx.snap +++ /dev/null @@ -1,47 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Render should render component 1`] = ` -
  • - -
    -
    - cloudwatch -
    -
    -
  • -`; diff --git a/public/app/features/datasources/__snapshots__/DataSourcesListPage.test.tsx.snap b/public/app/features/datasources/__snapshots__/DataSourcesListPage.test.tsx.snap index 9a8b1eaabd2..df1135c44fe 100644 --- a/public/app/features/datasources/__snapshots__/DataSourcesListPage.test.tsx.snap +++ b/public/app/features/datasources/__snapshots__/DataSourcesListPage.test.tsx.snap @@ -125,25 +125,6 @@ exports[`Render should render action bar and datasources 1`] = ` "url": "", "user": "", }, - Object { - "access": "", - "basicAuth": false, - "database": "database-5", - "id": 5, - "isDefault": false, - "jsonData": Object { - "authType": "credentials", - "defaultRegion": "eu-west-2", - }, - "name": "dataSource-5", - "orgId": 1, - "password": "", - "readOnly": false, - "type": "cloudwatch", - "typeLogoUrl": "public/app/plugins/datasource/cloudwatch/img/amazon-web-services.png", - "url": "", - "user": "", - }, ] } key="list" diff --git a/public/app/features/datasources/mocks.ts b/public/app/features/datasources/mocks.ts index d2cc7be296a..bc4f9d0cddc 100644 --- a/public/app/features/datasources/mocks.ts +++ b/public/app/features/datasources/mocks.ts @@ -7,6 +7,7 @@ export function createDatasourceSettings(jsonData: T): DataSourceSettings name: 'datasource-test', typeLogoUrl: '', type: 'datasource', + typeName: 'Datasource', access: 'server', url: 'http://localhost', password: '', diff --git a/public/app/features/datasources/settings/__snapshots__/DataSourceSettingsPage.test.tsx.snap b/public/app/features/datasources/settings/__snapshots__/DataSourceSettingsPage.test.tsx.snap index 831c65adead..01fdf2dd1db 100644 --- a/public/app/features/datasources/settings/__snapshots__/DataSourceSettingsPage.test.tsx.snap +++ b/public/app/features/datasources/settings/__snapshots__/DataSourceSettingsPage.test.tsx.snap @@ -48,6 +48,7 @@ exports[`Render should render alpha info text 1`] = ` "secureJsonFields": Object {}, "type": "cloudwatch", "typeLogoUrl": "public/app/plugins/datasource/cloudwatch/img/amazon-web-services.png", + "typeName": "Cloudwatch", "url": "", "user": "", "withCredentials": false, @@ -81,6 +82,7 @@ exports[`Render should render alpha info text 1`] = ` "secureJsonFields": Object {}, "type": "cloudwatch", "typeLogoUrl": "public/app/plugins/datasource/cloudwatch/img/amazon-web-services.png", + "typeName": "Cloudwatch", "url": "", "user": "", "withCredentials": false, @@ -198,6 +200,7 @@ exports[`Render should render beta info text 1`] = ` "secureJsonFields": Object {}, "type": "cloudwatch", "typeLogoUrl": "public/app/plugins/datasource/cloudwatch/img/amazon-web-services.png", + "typeName": "Cloudwatch", "url": "", "user": "", "withCredentials": false, @@ -257,6 +260,7 @@ exports[`Render should render component 1`] = ` "secureJsonFields": Object {}, "type": "cloudwatch", "typeLogoUrl": "public/app/plugins/datasource/cloudwatch/img/amazon-web-services.png", + "typeName": "Cloudwatch", "url": "", "user": "", "withCredentials": false, @@ -321,6 +325,7 @@ exports[`Render should render is ready only message 1`] = ` "secureJsonFields": Object {}, "type": "cloudwatch", "typeLogoUrl": "public/app/plugins/datasource/cloudwatch/img/amazon-web-services.png", + "typeName": "Cloudwatch", "url": "", "user": "", "withCredentials": false, @@ -354,6 +359,7 @@ exports[`Render should render is ready only message 1`] = ` "secureJsonFields": Object {}, "type": "cloudwatch", "typeLogoUrl": "public/app/plugins/datasource/cloudwatch/img/amazon-web-services.png", + "typeName": "Cloudwatch", "url": "", "user": "", "withCredentials": false, diff --git a/public/app/features/datasources/state/navModel.ts b/public/app/features/datasources/state/navModel.ts index 7a88341babb..479d7a6968a 100644 --- a/public/app/features/datasources/state/navModel.ts +++ b/public/app/features/datasources/state/navModel.ts @@ -83,6 +83,7 @@ export function getDataSourceLoadingNav(pageName: string): NavModel { password: '', readOnly: false, type: 'Loading', + typeName: 'Loading', typeLogoUrl: 'public/img/icn-datasource.svg', url: '', user: '', diff --git a/public/app/features/datasources/state/reducers.test.ts b/public/app/features/datasources/state/reducers.test.ts index 7c135185210..3f8094a8aa7 100644 --- a/public/app/features/datasources/state/reducers.test.ts +++ b/public/app/features/datasources/state/reducers.test.ts @@ -40,7 +40,7 @@ const mockPlugin = () => describe('dataSourcesReducer', () => { describe('when dataSourcesLoaded is dispatched', () => { it('then state should be correct', () => { - const dataSources = getMockDataSources(0); + const dataSources = getMockDataSources(1); reducerTester() .givenReducer(dataSourcesReducer, initialState) diff --git a/public/app/plugins/datasource/cloudwatch/components/ConfigEditor.test.tsx b/public/app/plugins/datasource/cloudwatch/components/ConfigEditor.test.tsx index 8fa5de1c4c5..2320f3c604d 100644 --- a/public/app/plugins/datasource/cloudwatch/components/ConfigEditor.test.tsx +++ b/public/app/plugins/datasource/cloudwatch/components/ConfigEditor.test.tsx @@ -28,6 +28,7 @@ const setup = (propOverrides?: object) => { url: '', database: '', type: 'cloudwatch', + typeName: 'Cloudwatch', user: '', password: '', basicAuth: false, diff --git a/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/AnalyticsConfig.test.tsx b/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/AnalyticsConfig.test.tsx index 0a737cc8512..5ac8d71e6a3 100644 --- a/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/AnalyticsConfig.test.tsx +++ b/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/AnalyticsConfig.test.tsx @@ -9,6 +9,7 @@ const setup = (propOverrides?: object) => { orgId: 1, name: 'Azure Monitor-10-10', type: 'grafana-azure-monitor-datasource', + typeName: 'Azure', typeLogoUrl: '', access: 'proxy', url: '', diff --git a/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/ConfigEditor.test.tsx b/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/ConfigEditor.test.tsx index 1681f5746f7..c3a5272327b 100644 --- a/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/ConfigEditor.test.tsx +++ b/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/ConfigEditor.test.tsx @@ -10,6 +10,7 @@ const setup = () => { name: 'Azure Monitor-10-10', type: 'grafana-azure-monitor-datasource', typeLogoUrl: '', + typeName: 'Azure', access: 'proxy', url: '', password: '', diff --git a/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/InsightsConfig.test.tsx b/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/InsightsConfig.test.tsx index 2446edb3005..cb1e8302ebb 100644 --- a/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/InsightsConfig.test.tsx +++ b/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/InsightsConfig.test.tsx @@ -10,6 +10,7 @@ const setup = (propOverrides?: object) => { name: 'Azure Monitor-10-10', type: 'grafana-azure-monitor-datasource', typeLogoUrl: '', + typeName: 'Azure', access: 'proxy', url: '', password: '', diff --git a/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/__snapshots__/ConfigEditor.test.tsx.snap b/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/__snapshots__/ConfigEditor.test.tsx.snap index f7ee799e71d..271a21c84bd 100644 --- a/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/__snapshots__/ConfigEditor.test.tsx.snap +++ b/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/__snapshots__/ConfigEditor.test.tsx.snap @@ -30,6 +30,7 @@ exports[`Render should render component 1`] = ` "secureJsonFields": Object {}, "type": "grafana-azure-monitor-datasource", "typeLogoUrl": "", + "typeName": "Azure", "url": "", "user": "", "version": 1, @@ -67,6 +68,7 @@ exports[`Render should render component 1`] = ` "secureJsonFields": Object {}, "type": "grafana-azure-monitor-datasource", "typeLogoUrl": "", + "typeName": "Azure", "url": "/api/datasources/proxy/21", "user": "", "version": 1, @@ -106,6 +108,7 @@ exports[`Render should render component 1`] = ` "secureJsonFields": Object {}, "type": "grafana-azure-monitor-datasource", "typeLogoUrl": "", + "typeName": "Azure", "url": "", "user": "", "version": 1, @@ -141,6 +144,7 @@ exports[`Render should render component 1`] = ` "secureJsonFields": Object {}, "type": "grafana-azure-monitor-datasource", "typeLogoUrl": "", + "typeName": "Azure", "url": "", "user": "", "version": 1, diff --git a/public/app/plugins/datasource/influxdb/components/ConfigEditor.test.tsx b/public/app/plugins/datasource/influxdb/components/ConfigEditor.test.tsx index 942dd142563..7c34ba79089 100644 --- a/public/app/plugins/datasource/influxdb/components/ConfigEditor.test.tsx +++ b/public/app/plugins/datasource/influxdb/components/ConfigEditor.test.tsx @@ -9,6 +9,7 @@ const setup = (propOverrides?: object) => { orgId: 1, name: 'InfluxDB-3', type: 'influxdb', + typeName: 'Influx', typeLogoUrl: '', access: 'proxy', url: '', diff --git a/public/app/plugins/datasource/influxdb/components/__snapshots__/ConfigEditor.test.tsx.snap b/public/app/plugins/datasource/influxdb/components/__snapshots__/ConfigEditor.test.tsx.snap index 19c79f995b5..682eba17c8d 100644 --- a/public/app/plugins/datasource/influxdb/components/__snapshots__/ConfigEditor.test.tsx.snap +++ b/public/app/plugins/datasource/influxdb/components/__snapshots__/ConfigEditor.test.tsx.snap @@ -92,6 +92,7 @@ exports[`Render should disable basic auth password input 1`] = ` "secureJsonFields": Object {}, "type": "influxdb", "typeLogoUrl": "", + "typeName": "Influx", "url": "", "user": "", "version": 1, @@ -387,6 +388,7 @@ exports[`Render should hide basic auth fields when switch off 1`] = ` "secureJsonFields": Object {}, "type": "influxdb", "typeLogoUrl": "", + "typeName": "Influx", "url": "", "user": "", "version": 1, @@ -682,6 +684,7 @@ exports[`Render should hide white listed cookies input when browser access chose "secureJsonFields": Object {}, "type": "influxdb", "typeLogoUrl": "", + "typeName": "Influx", "url": "", "user": "", "version": 1, @@ -977,6 +980,7 @@ exports[`Render should render component 1`] = ` "secureJsonFields": Object {}, "type": "influxdb", "typeLogoUrl": "", + "typeName": "Influx", "url": "", "user": "", "version": 1,