import { css } from '@emotion/css'; import { useEffect } from 'react'; import { useLocation } from 'react-router-dom-v5-compat'; import { DataSourceSettings, GrafanaTheme2 } from '@grafana/data'; import { config } from '@grafana/runtime'; import { EmptyState, LinkButton, TextLink, useStyles2 } from '@grafana/ui'; import { contextSrv } from 'app/core/core'; import { Trans, t } from 'app/core/internationalization'; import { StoreState, AccessControlAction, useSelector } from 'app/types'; import { ROUTES } from '../../connections/constants'; import { getDataSources, getDataSourcesCount, useLoadDataSources } from '../state'; import { trackDataSourcesListViewed } from '../tracking'; import { DataSourcesListCard } from './DataSourcesListCard'; import { DataSourcesListHeader } from './DataSourcesListHeader'; export function DataSourcesList() { const { isLoading } = useLoadDataSources(); const dataSources = useSelector((state) => getDataSources(state.dataSources)); const dataSourcesCount = useSelector(({ dataSources }: StoreState) => getDataSourcesCount(dataSources)); const hasCreateRights = contextSrv.hasPermission(AccessControlAction.DataSourcesCreate); const hasWriteRights = contextSrv.hasPermission(AccessControlAction.DataSourcesWrite); const hasExploreRights = contextSrv.hasAccessToExplore(); return ( ); } export type ViewProps = { dataSources: DataSourceSettings[]; dataSourcesCount: number; isLoading: boolean; hasCreateRights: boolean; hasWriteRights: boolean; hasExploreRights: boolean; }; export function DataSourcesListView({ dataSources, dataSourcesCount, isLoading, hasCreateRights, hasWriteRights, hasExploreRights, }: ViewProps) { const styles = useStyles2(getStyles); const location = useLocation(); useEffect(() => { trackDataSourcesListViewed({ grafana_version: config.buildInfo.version, path: location.pathname, }); }, [location]); if (!isLoading && dataSourcesCount === 0) { return ( Add data source } message={t('data-source-list.empty-state.title', 'No data sources defined')} > You can also define data sources through configuration files.{' '} Learn more ); } const getDataSourcesList = () => { if (isLoading) { return new Array(20) .fill(null) .map((_, index) => ); } return dataSources.map((dataSource) => (
  • )); }; return ( <> {/* List Header */} {/* List */} {dataSources.length === 0 && !isLoading ? ( ) : (
      {getDataSourcesList()}
    )} ); } const getStyles = (theme: GrafanaTheme2) => { return { list: css({ listStyle: 'none', display: 'grid', // gap: '8px', Add back when legacy support for old Card interface is dropped }), }; };