forked from grafana/grafana
-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'data-sources-list-to-react'
- Loading branch information
Showing
23 changed files
with
831 additions
and
129 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import React from 'react'; | ||
import { shallow } from 'enzyme'; | ||
import DataSourcesList from './DataSourcesList'; | ||
import { getMockDataSources } from './__mocks__/dataSourcesMocks'; | ||
import { LayoutModes } from '../../core/components/LayoutSelector/LayoutSelector'; | ||
|
||
const setup = () => { | ||
const props = { | ||
dataSources: getMockDataSources(3), | ||
layoutMode: LayoutModes.Grid, | ||
}; | ||
|
||
return shallow(<DataSourcesList {...props} />); | ||
}; | ||
|
||
describe('Render', () => { | ||
it('should render component', () => { | ||
const wrapper = setup(); | ||
|
||
expect(wrapper).toMatchSnapshot(); | ||
}); | ||
}); |
23 changes: 23 additions & 0 deletions
23
public/app/features/datasources/DataSourcesActionBar.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import React from 'react'; | ||
import { shallow } from 'enzyme'; | ||
import { DataSourcesActionBar, Props } from './DataSourcesActionBar'; | ||
import { LayoutModes } from '../../core/components/LayoutSelector/LayoutSelector'; | ||
|
||
const setup = (propOverrides?: object) => { | ||
const props: Props = { | ||
layoutMode: LayoutModes.Grid, | ||
searchQuery: '', | ||
setDataSourcesLayoutMode: jest.fn(), | ||
setDataSourcesSearchQuery: jest.fn(), | ||
}; | ||
|
||
return shallow(<DataSourcesActionBar {...props} />); | ||
}; | ||
|
||
describe('Render', () => { | ||
it('should render component', () => { | ||
const wrapper = setup(); | ||
|
||
expect(wrapper).toMatchSnapshot(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
import React, { PureComponent } from 'react'; | ||
import { connect } from 'react-redux'; | ||
import LayoutSelector, { LayoutMode } from '../../core/components/LayoutSelector/LayoutSelector'; | ||
import { setDataSourcesLayoutMode, setDataSourcesSearchQuery } from './state/actions'; | ||
import { getDataSourcesLayoutMode, getDataSourcesSearchQuery } from './state/selectors'; | ||
|
||
export interface Props { | ||
searchQuery: string; | ||
layoutMode: LayoutMode; | ||
setDataSourcesLayoutMode: typeof setDataSourcesLayoutMode; | ||
setDataSourcesSearchQuery: typeof setDataSourcesSearchQuery; | ||
} | ||
|
||
export class DataSourcesActionBar extends PureComponent<Props> { | ||
onSearchQueryChange = event => { | ||
this.props.setDataSourcesSearchQuery(event.target.value); | ||
}; | ||
|
||
render() { | ||
const { searchQuery, layoutMode, setDataSourcesLayoutMode } = this.props; | ||
|
||
return ( | ||
<div className="page-action-bar"> | ||
<div className="gf-form gf-form--grow"> | ||
<label className="gf-form--has-input-icon"> | ||
<input | ||
type="text" | ||
className="gf-form-input width-20" | ||
value={searchQuery} | ||
onChange={this.onSearchQueryChange} | ||
placeholder="Filter by name or type" | ||
/> | ||
<i className="gf-form-input-icon fa fa-search" /> | ||
</label> | ||
<LayoutSelector | ||
mode={layoutMode} | ||
onLayoutModeChanged={(mode: LayoutMode) => setDataSourcesLayoutMode(mode)} | ||
/> | ||
</div> | ||
<div className="page-action-bar__spacer" /> | ||
<a className="page-header__cta btn btn-success" href="datasources/new"> | ||
<i className="fa fa-plus" /> | ||
Add data source | ||
</a> | ||
</div> | ||
); | ||
} | ||
} | ||
|
||
function mapStateToProps(state) { | ||
return { | ||
searchQuery: getDataSourcesSearchQuery(state.dataSources), | ||
layoutMode: getDataSourcesLayoutMode(state.dataSources), | ||
}; | ||
} | ||
|
||
const mapDispatchToProps = { | ||
setDataSourcesLayoutMode, | ||
setDataSourcesSearchQuery, | ||
}; | ||
|
||
export default connect(mapStateToProps, mapDispatchToProps)(DataSourcesActionBar); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import React, { PureComponent } from 'react'; | ||
import classNames from 'classnames/bind'; | ||
import DataSourcesListItem from './DataSourcesListItem'; | ||
import { DataSource } from 'app/types'; | ||
import { LayoutMode, LayoutModes } from '../../core/components/LayoutSelector/LayoutSelector'; | ||
|
||
export interface Props { | ||
dataSources: DataSource[]; | ||
layoutMode: LayoutMode; | ||
} | ||
|
||
export class DataSourcesList extends PureComponent<Props> { | ||
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, | ||
}); | ||
|
||
return ( | ||
<section className={listStyle}> | ||
<ol className="card-list"> | ||
{dataSources.map((dataSource, index) => { | ||
return <DataSourcesListItem dataSource={dataSource} key={`${dataSource.id}-${index}`} />; | ||
})} | ||
</ol> | ||
</section> | ||
); | ||
} | ||
} | ||
|
||
export default DataSourcesList; |
20 changes: 20 additions & 0 deletions
20
public/app/features/datasources/DataSourcesListItem.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
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(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import React, { PureComponent } from 'react'; | ||
import { DataSource } from 'app/types'; | ||
|
||
export interface Props { | ||
dataSource: DataSource; | ||
} | ||
|
||
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} /> | ||
</figure> | ||
<div className="card-item-details"> | ||
<div className="card-item-name"> | ||
{dataSource.name} | ||
{dataSource.isDefault && <span className="btn btn-secondary btn-mini">default</span>} | ||
</div> | ||
<div className="card-item-sub-name">{dataSource.url}</div> | ||
</div> | ||
</div> | ||
</a> | ||
</li> | ||
); | ||
} | ||
} | ||
|
||
export default DataSourcesListItem; |
37 changes: 37 additions & 0 deletions
37
public/app/features/datasources/DataSourcesListPage.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import React from 'react'; | ||
import { shallow } from 'enzyme'; | ||
import { DataSourcesListPage, Props } from './DataSourcesListPage'; | ||
import { DataSource, NavModel } from 'app/types'; | ||
import { LayoutModes } from '../../core/components/LayoutSelector/LayoutSelector'; | ||
import { getMockDataSources } from './__mocks__/dataSourcesMocks'; | ||
|
||
const setup = (propOverrides?: object) => { | ||
const props: Props = { | ||
dataSources: [] as DataSource[], | ||
layoutMode: LayoutModes.Grid, | ||
loadDataSources: jest.fn(), | ||
navModel: {} as NavModel, | ||
dataSourcesCount: 0, | ||
}; | ||
|
||
Object.assign(props, propOverrides); | ||
|
||
return shallow(<DataSourcesListPage {...props} />); | ||
}; | ||
|
||
describe('Render', () => { | ||
it('should render component', () => { | ||
const wrapper = setup(); | ||
|
||
expect(wrapper).toMatchSnapshot(); | ||
}); | ||
|
||
it('should render action bar and datasources', () => { | ||
const wrapper = setup({ | ||
dataSources: getMockDataSources(5), | ||
dataSourcesCount: 5, | ||
}); | ||
|
||
expect(wrapper).toMatchSnapshot(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
import React, { PureComponent } from 'react'; | ||
import { connect } from 'react-redux'; | ||
import { hot } from 'react-hot-loader'; | ||
import PageHeader from '../../core/components/PageHeader/PageHeader'; | ||
import DataSourcesActionBar from './DataSourcesActionBar'; | ||
import DataSourcesList from './DataSourcesList'; | ||
import { loadDataSources } from './state/actions'; | ||
import { getDataSources, getDataSourcesCount, getDataSourcesLayoutMode } from './state/selectors'; | ||
import { getNavModel } from '../../core/selectors/navModel'; | ||
import { DataSource, NavModel } from 'app/types'; | ||
import { LayoutMode } from '../../core/components/LayoutSelector/LayoutSelector'; | ||
import EmptyListCTA from '../../core/components/EmptyListCTA/EmptyListCTA'; | ||
|
||
export interface Props { | ||
navModel: NavModel; | ||
dataSources: DataSource[]; | ||
dataSourcesCount: number; | ||
layoutMode: LayoutMode; | ||
loadDataSources: typeof loadDataSources; | ||
} | ||
|
||
const emptyListModel = { | ||
title: 'There are no data sources defined yet', | ||
buttonIcon: 'gicon gicon-add-datasources', | ||
buttonLink: 'datasources/new', | ||
buttonTitle: 'Add data source', | ||
proTip: 'You can also define data sources through configuration files.', | ||
proTipLink: 'http://docs.grafana.org/administration/provisioning/#datasources?utm_source=grafana_ds_list', | ||
proTipLinkTitle: 'Learn more', | ||
proTipTarget: '_blank', | ||
}; | ||
|
||
export class DataSourcesListPage extends PureComponent<Props> { | ||
componentDidMount() { | ||
this.fetchDataSources(); | ||
} | ||
|
||
async fetchDataSources() { | ||
return await this.props.loadDataSources(); | ||
} | ||
|
||
render() { | ||
const { dataSources, dataSourcesCount, navModel, layoutMode } = this.props; | ||
|
||
return ( | ||
<div> | ||
<PageHeader model={navModel} /> | ||
<div className="page-container page-body"> | ||
{dataSourcesCount === 0 ? ( | ||
<EmptyListCTA model={emptyListModel} /> | ||
) : ( | ||
[ | ||
<DataSourcesActionBar key="action-bar" />, | ||
<DataSourcesList dataSources={dataSources} layoutMode={layoutMode} key="list" />, | ||
] | ||
)} | ||
</div> | ||
</div> | ||
); | ||
} | ||
} | ||
|
||
function mapStateToProps(state) { | ||
return { | ||
navModel: getNavModel(state.navIndex, 'datasources'), | ||
dataSources: getDataSources(state.dataSources), | ||
layoutMode: getDataSourcesLayoutMode(state.dataSources), | ||
dataSourcesCount: getDataSourcesCount(state.dataSources), | ||
}; | ||
} | ||
|
||
const mapDispatchToProps = { | ||
loadDataSources, | ||
}; | ||
|
||
export default hot(module)(connect(mapStateToProps, mapDispatchToProps)(DataSourcesListPage)); |
45 changes: 45 additions & 0 deletions
45
public/app/features/datasources/__mocks__/dataSourcesMocks.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import { DataSource } from 'app/types'; | ||
|
||
export const getMockDataSources = (amount: number): DataSource[] => { | ||
const dataSources = []; | ||
|
||
for (let i = 0; i <= amount; i++) { | ||
dataSources.push({ | ||
access: '', | ||
basicAuth: false, | ||
database: `database-${i}`, | ||
id: i, | ||
isDefault: false, | ||
jsonData: { authType: 'credentials', defaultRegion: 'eu-west-2' }, | ||
name: `dataSource-${i}`, | ||
orgId: 1, | ||
password: '', | ||
readOnly: false, | ||
type: 'cloudwatch', | ||
typeLogoUrl: 'public/app/plugins/datasource/cloudwatch/img/amazon-web-services.png', | ||
url: '', | ||
user: '', | ||
}); | ||
} | ||
|
||
return dataSources; | ||
}; | ||
|
||
export const getMockDataSource = (): DataSource => { | ||
return { | ||
access: '', | ||
basicAuth: false, | ||
database: '', | ||
id: 13, | ||
isDefault: false, | ||
jsonData: { authType: 'credentials', defaultRegion: 'eu-west-2' }, | ||
name: 'gdev-cloudwatch', | ||
orgId: 1, | ||
password: '', | ||
readOnly: false, | ||
type: 'cloudwatch', | ||
typeLogoUrl: 'public/app/plugins/datasource/cloudwatch/img/amazon-web-services.png', | ||
url: '', | ||
user: '', | ||
}; | ||
}; |
Oops, something went wrong.