mirror of https://github.com/grafana/grafana
Data source list: Use Card component (#31326)
* Replace DataSourcesListItem with Card * Add tests * Remove unused styles * Make card heading semi bold * Make heading semi-bold * Show type name instead of type id * Fix key warning * Update Card * Fix tests * Make typeName optional * remove styling that was just a test * Make typeName non-optional and fix tests * Update list key Co-authored-by: Torkel Ödegaard <torkel@grafana.com>pull/31393/head
parent
6e549bc95d
commit
6db4b40d5b
@ -1,39 +1,50 @@ |
|||||||
// Libraries
|
// Libraries
|
||||||
import React, { PureComponent } from 'react'; |
import React, { FC } from 'react'; |
||||||
import classNames from 'classnames'; |
|
||||||
|
|
||||||
// Components
|
|
||||||
import DataSourcesListItem from './DataSourcesListItem'; |
|
||||||
|
|
||||||
// Types
|
// Types
|
||||||
import { DataSourceSettings } from '@grafana/data'; |
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 { |
export interface Props { |
||||||
dataSources: DataSourceSettings[]; |
dataSources: DataSourceSettings[]; |
||||||
layoutMode: LayoutMode; |
layoutMode: LayoutMode; |
||||||
} |
} |
||||||
|
|
||||||
export class DataSourcesList extends PureComponent<Props> { |
export const DataSourcesList: FC<Props> = ({ dataSources, layoutMode }) => { |
||||||
render() { |
const styles = useStyles(getStyles); |
||||||
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, |
|
||||||
}); |
|
||||||
|
|
||||||
return ( |
return ( |
||||||
<section className={listStyle}> |
<ul className={styles.list}> |
||||||
<ol className="card-list"> |
{dataSources.map((dataSource, index) => { |
||||||
{dataSources.map((dataSource, index) => { |
return ( |
||||||
return <DataSourcesListItem dataSource={dataSource} key={`${dataSource.id}-${index}`} />; |
<li key={dataSource.id}> |
||||||
})} |
<Card heading={dataSource.name} href={`datasources/edit/${dataSource.id}`}> |
||||||
</ol> |
<Card.Figure> |
||||||
</section> |
<img src={dataSource.typeLogoUrl} alt={dataSource.name} /> |
||||||
); |
</Card.Figure> |
||||||
} |
<Card.Meta> |
||||||
} |
{[ |
||||||
|
dataSource.typeName, |
||||||
|
dataSource.url, |
||||||
|
dataSource.isDefault && <Tag key="default-tag" name={'default'} colorIndex={1} />, |
||||||
|
]} |
||||||
|
</Card.Meta> |
||||||
|
</Card> |
||||||
|
</li> |
||||||
|
); |
||||||
|
})} |
||||||
|
</ul> |
||||||
|
); |
||||||
|
}; |
||||||
|
|
||||||
export default DataSourcesList; |
export default DataSourcesList; |
||||||
|
|
||||||
|
const getStyles = () => { |
||||||
|
return { |
||||||
|
list: css` |
||||||
|
list-style: none; |
||||||
|
`,
|
||||||
|
}; |
||||||
|
}; |
||||||
|
|||||||
@ -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(<DataSourcesListItem {...props} />); |
|
||||||
}; |
|
||||||
|
|
||||||
describe('Render', () => { |
|
||||||
it('should render component', () => { |
|
||||||
const wrapper = setup(); |
|
||||||
|
|
||||||
expect(wrapper).toMatchSnapshot(); |
|
||||||
}); |
|
||||||
}); |
|
||||||
@ -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<Props> { |
|
||||||
render() { |
|
||||||
const { dataSource } = this.props; |
|
||||||
return ( |
|
||||||
<li className="card-item-wrapper"> |
|
||||||
<a className="card-item" href={`datasources/edit/${dataSource.id}`}> |
|
||||||
<div className="card-item-header"> |
|
||||||
<div className="card-item-type">{dataSource.type}</div> |
|
||||||
</div> |
|
||||||
<div className="card-item-body"> |
|
||||||
<figure className="card-item-figure"> |
|
||||||
<img src={dataSource.typeLogoUrl} alt={dataSource.name} /> |
|
||||||
</figure> |
|
||||||
<div className="card-item-details"> |
|
||||||
<div className="card-item-name" aria-label={selectors.pages.DataSources.dataSources(dataSource.name)}> |
|
||||||
{dataSource.name} |
|
||||||
{dataSource.isDefault && <span className="btn btn-secondary btn-small card-item-label">default</span>} |
|
||||||
</div> |
|
||||||
<div className="card-item-sub-name">{dataSource.url}</div> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</a> |
|
||||||
</li> |
|
||||||
); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
export default DataSourcesListItem; |
|
||||||
@ -1,108 +0,0 @@ |
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP |
|
||||||
|
|
||||||
exports[`Render should render component 1`] = ` |
|
||||||
<section |
|
||||||
className="card-section card-list-layout-grid" |
|
||||||
> |
|
||||||
<ol |
|
||||||
className="card-list" |
|
||||||
> |
|
||||||
<DataSourcesListItem |
|
||||||
dataSource={ |
|
||||||
Object { |
|
||||||
"access": "", |
|
||||||
"basicAuth": false, |
|
||||||
"database": "database-0", |
|
||||||
"id": 0, |
|
||||||
"isDefault": false, |
|
||||||
"jsonData": Object { |
|
||||||
"authType": "credentials", |
|
||||||
"defaultRegion": "eu-west-2", |
|
||||||
}, |
|
||||||
"name": "dataSource-0", |
|
||||||
"orgId": 1, |
|
||||||
"password": "", |
|
||||||
"readOnly": false, |
|
||||||
"type": "cloudwatch", |
|
||||||
"typeLogoUrl": "public/app/plugins/datasource/cloudwatch/img/amazon-web-services.png", |
|
||||||
"url": "", |
|
||||||
"user": "", |
|
||||||
} |
|
||||||
} |
|
||||||
key="0-0" |
|
||||||
/> |
|
||||||
<DataSourcesListItem |
|
||||||
dataSource={ |
|
||||||
Object { |
|
||||||
"access": "", |
|
||||||
"basicAuth": false, |
|
||||||
"database": "database-1", |
|
||||||
"id": 1, |
|
||||||
"isDefault": false, |
|
||||||
"jsonData": Object { |
|
||||||
"authType": "credentials", |
|
||||||
"defaultRegion": "eu-west-2", |
|
||||||
}, |
|
||||||
"name": "dataSource-1", |
|
||||||
"orgId": 1, |
|
||||||
"password": "", |
|
||||||
"readOnly": false, |
|
||||||
"type": "cloudwatch", |
|
||||||
"typeLogoUrl": "public/app/plugins/datasource/cloudwatch/img/amazon-web-services.png", |
|
||||||
"url": "", |
|
||||||
"user": "", |
|
||||||
} |
|
||||||
} |
|
||||||
key="1-1" |
|
||||||
/> |
|
||||||
<DataSourcesListItem |
|
||||||
dataSource={ |
|
||||||
Object { |
|
||||||
"access": "", |
|
||||||
"basicAuth": false, |
|
||||||
"database": "database-2", |
|
||||||
"id": 2, |
|
||||||
"isDefault": false, |
|
||||||
"jsonData": Object { |
|
||||||
"authType": "credentials", |
|
||||||
"defaultRegion": "eu-west-2", |
|
||||||
}, |
|
||||||
"name": "dataSource-2", |
|
||||||
"orgId": 1, |
|
||||||
"password": "", |
|
||||||
"readOnly": false, |
|
||||||
"type": "cloudwatch", |
|
||||||
"typeLogoUrl": "public/app/plugins/datasource/cloudwatch/img/amazon-web-services.png", |
|
||||||
"url": "", |
|
||||||
"user": "", |
|
||||||
} |
|
||||||
} |
|
||||||
key="2-2" |
|
||||||
/> |
|
||||||
<DataSourcesListItem |
|
||||||
dataSource={ |
|
||||||
Object { |
|
||||||
"access": "", |
|
||||||
"basicAuth": false, |
|
||||||
"database": "database-3", |
|
||||||
"id": 3, |
|
||||||
"isDefault": false, |
|
||||||
"jsonData": Object { |
|
||||||
"authType": "credentials", |
|
||||||
"defaultRegion": "eu-west-2", |
|
||||||
}, |
|
||||||
"name": "dataSource-3", |
|
||||||
"orgId": 1, |
|
||||||
"password": "", |
|
||||||
"readOnly": false, |
|
||||||
"type": "cloudwatch", |
|
||||||
"typeLogoUrl": "public/app/plugins/datasource/cloudwatch/img/amazon-web-services.png", |
|
||||||
"url": "", |
|
||||||
"user": "", |
|
||||||
} |
|
||||||
} |
|
||||||
key="3-3" |
|
||||||
/> |
|
||||||
</ol> |
|
||||||
</section> |
|
||||||
`; |
|
||||||
@ -1,47 +0,0 @@ |
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP |
|
||||||
|
|
||||||
exports[`Render should render component 1`] = ` |
|
||||||
<li |
|
||||||
className="card-item-wrapper" |
|
||||||
> |
|
||||||
<a |
|
||||||
className="card-item" |
|
||||||
href="datasources/edit/13" |
|
||||||
> |
|
||||||
<div |
|
||||||
className="card-item-header" |
|
||||||
> |
|
||||||
<div |
|
||||||
className="card-item-type" |
|
||||||
> |
|
||||||
cloudwatch |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
<div |
|
||||||
className="card-item-body" |
|
||||||
> |
|
||||||
<figure |
|
||||||
className="card-item-figure" |
|
||||||
> |
|
||||||
<img |
|
||||||
alt="gdev-cloudwatch" |
|
||||||
src="public/app/plugins/datasource/cloudwatch/img/amazon-web-services.png" |
|
||||||
/> |
|
||||||
</figure> |
|
||||||
<div |
|
||||||
className="card-item-details" |
|
||||||
> |
|
||||||
<div |
|
||||||
aria-label="Data source list item gdev-cloudwatch" |
|
||||||
className="card-item-name" |
|
||||||
> |
|
||||||
gdev-cloudwatch |
|
||||||
</div> |
|
||||||
<div |
|
||||||
className="card-item-sub-name" |
|
||||||
/> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</a> |
|
||||||
</li> |
|
||||||
`; |
|
||||||
Loading…
Reference in new issue