diff --git a/docs/sources/features/datasources/cloudwatch.md b/docs/sources/features/datasources/cloudwatch.md index e2bcb50bb1d..22f9f38c854 100644 --- a/docs/sources/features/datasources/cloudwatch.md +++ b/docs/sources/features/datasources/cloudwatch.md @@ -38,7 +38,7 @@ Name | Description ### IAM Roles -Currently all access to CloudWatch is done server side by the Grafana backend using the official AWS SDK. If you grafana +Currently all access to CloudWatch is done server side by the Grafana backend using the official AWS SDK. If your Grafana server is running on AWS you can use IAM Roles and authentication will be handled automatically. Checkout AWS docs on [IAM Roles](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html) diff --git a/packages/grafana-ui/src/components/CustomScrollbar/CustomScrollbar.tsx b/packages/grafana-ui/src/components/CustomScrollbar/CustomScrollbar.tsx index 50b16dbb98e..c3fb3f0f0ab 100644 --- a/packages/grafana-ui/src/components/CustomScrollbar/CustomScrollbar.tsx +++ b/packages/grafana-ui/src/components/CustomScrollbar/CustomScrollbar.tsx @@ -11,6 +11,7 @@ interface Props { hideTracksWhenNotNeeded?: boolean; scrollTop?: number; setScrollTop: (value: React.MouseEvent) => void; + autoHeightMin?: number | string; } /** @@ -26,6 +27,7 @@ export class CustomScrollbar extends PureComponent { hideTracksWhenNotNeeded: false, scrollTop: 0, setScrollTop: () => {}, + autoHeightMin: '0' }; private ref: React.RefObject; @@ -65,7 +67,6 @@ export class CustomScrollbar extends PureComponent { autoHeight={true} // These autoHeightMin & autoHeightMax options affect firefox and chrome differently. // Before these where set to inhert but that caused problems with cut of legends in firefox - autoHeightMin={'0'} autoHeightMax={autoMaxHeight} renderTrackHorizontal={props =>
} renderTrackVertical={props =>
} diff --git a/packages/grafana-ui/src/components/CustomScrollbar/__snapshots__/CustomScrollbar.test.tsx.snap b/packages/grafana-ui/src/components/CustomScrollbar/__snapshots__/CustomScrollbar.test.tsx.snap index 60b4a2e0aa5..aabe3dd98c5 100644 --- a/packages/grafana-ui/src/components/CustomScrollbar/__snapshots__/CustomScrollbar.test.tsx.snap +++ b/packages/grafana-ui/src/components/CustomScrollbar/__snapshots__/CustomScrollbar.test.tsx.snap @@ -7,7 +7,7 @@ exports[`CustomScrollbar renders correctly 1`] = ` Object { "height": "auto", "maxHeight": "100%", - "minHeight": "0", + "minHeight": 0, "overflow": "hidden", "position": "relative", "width": "100%", @@ -24,7 +24,7 @@ exports[`CustomScrollbar renders correctly 1`] = ` "marginBottom": 0, "marginRight": 0, "maxHeight": "calc(100% + 0px)", - "minHeight": "calc(0 + 0px)", + "minHeight": 0, "overflow": "scroll", "position": "relative", "right": undefined, diff --git a/packages/grafana-ui/src/components/FormField/FormField.test.tsx b/packages/grafana-ui/src/components/FormField/FormField.test.tsx new file mode 100644 index 00000000000..3c89a347e86 --- /dev/null +++ b/packages/grafana-ui/src/components/FormField/FormField.test.tsx @@ -0,0 +1,24 @@ +import React from 'react'; +import { shallow } from 'enzyme'; +import { FormField, Props } from './FormField'; + +const setup = (propOverrides?: object) => { + const props: Props = { + label: 'Test', + labelWidth: 11, + value: 10, + onChange: jest.fn(), + }; + + Object.assign(props, propOverrides); + + return shallow(); +}; + +describe('Render', () => { + it('should render component', () => { + const wrapper = setup(); + + expect(wrapper).toMatchSnapshot(); + }); +}); diff --git a/packages/grafana-ui/src/components/FormField/FormField.tsx b/packages/grafana-ui/src/components/FormField/FormField.tsx new file mode 100644 index 00000000000..593678c7383 --- /dev/null +++ b/packages/grafana-ui/src/components/FormField/FormField.tsx @@ -0,0 +1,25 @@ +import React, { InputHTMLAttributes, FunctionComponent } from 'react'; +import { FormLabel } from '..'; + +export interface Props extends InputHTMLAttributes { + label: string; + labelWidth?: number; + inputWidth?: number; +} + +const defaultProps = { + labelWidth: 6, + inputWidth: 12, +}; + +const FormField: FunctionComponent = ({ label, labelWidth, inputWidth, ...inputProps }) => { + return ( +
+ {label} + +
+ ); +}; + +FormField.defaultProps = defaultProps; +export { FormField }; diff --git a/packages/grafana-ui/src/components/FormField/_FormField.scss b/packages/grafana-ui/src/components/FormField/_FormField.scss new file mode 100644 index 00000000000..36955e2fca6 --- /dev/null +++ b/packages/grafana-ui/src/components/FormField/_FormField.scss @@ -0,0 +1,12 @@ +.form-field { + margin-bottom: $gf-form-margin; + display: flex; + flex-direction: row; + align-items: center; + text-align: left; + position: relative; + + &--grow { + flex-grow: 1; + } +} diff --git a/packages/grafana-ui/src/components/FormField/__snapshots__/FormField.test.tsx.snap b/packages/grafana-ui/src/components/FormField/__snapshots__/FormField.test.tsx.snap new file mode 100644 index 00000000000..99eb0803149 --- /dev/null +++ b/packages/grafana-ui/src/components/FormField/__snapshots__/FormField.test.tsx.snap @@ -0,0 +1,19 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Render should render component 1`] = ` +
+ + Test + + +
+`; diff --git a/packages/grafana-ui/src/components/FormLabel/FormLabel.tsx b/packages/grafana-ui/src/components/FormLabel/FormLabel.tsx new file mode 100644 index 00000000000..2bd4fbc153b --- /dev/null +++ b/packages/grafana-ui/src/components/FormLabel/FormLabel.tsx @@ -0,0 +1,42 @@ +import React, { FunctionComponent, ReactNode } from 'react'; +import classNames from 'classnames'; +import { Tooltip } from '..'; + +interface Props { + children: ReactNode; + className?: string; + htmlFor?: string; + isFocused?: boolean; + isInvalid?: boolean; + tooltip?: string; + width?: number; +} + +export const FormLabel: FunctionComponent = ({ + children, + isFocused, + isInvalid, + className, + htmlFor, + tooltip, + width, + ...rest +}) => { + const classes = classNames(`gf-form-label width-${width ? width : '10'}`, className, { + 'gf-form-label--is-focused': isFocused, + 'gf-form-label--is-invalid': isInvalid, + }); + + return ( + + ); +}; diff --git a/packages/grafana-ui/src/components/GfFormLabel/GfFormLabel.tsx b/packages/grafana-ui/src/components/GfFormLabel/GfFormLabel.tsx deleted file mode 100644 index 8b80de64696..00000000000 --- a/packages/grafana-ui/src/components/GfFormLabel/GfFormLabel.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import React, { SFC, ReactNode } from 'react'; -import classNames from 'classnames'; - -interface Props { - children: ReactNode; - htmlFor?: string; - className?: string; - isFocused?: boolean; - isInvalid?: boolean; -} - -export const GfFormLabel: SFC = ({ children, isFocused, isInvalid, className, htmlFor, ...rest }) => { - const classes = classNames('gf-form-label', className, { - 'gf-form-label--is-focused': isFocused, - 'gf-form-label--is-invalid': isInvalid, - }); - - return ( - - ); -}; diff --git a/packages/grafana-ui/src/components/PanelOptionsGroup/_PanelOptionsGroup.scss b/packages/grafana-ui/src/components/PanelOptionsGroup/_PanelOptionsGroup.scss index 9f5d4f02695..87d5b00f3b1 100644 --- a/packages/grafana-ui/src/components/PanelOptionsGroup/_PanelOptionsGroup.scss +++ b/packages/grafana-ui/src/components/PanelOptionsGroup/_PanelOptionsGroup.scss @@ -6,7 +6,7 @@ } .panel-options-group__header { - padding: 4px 20px; + padding: 4px 8px; font-size: 1.1rem; background: $panel-options-group-header-bg; position: relative; diff --git a/packages/grafana-ui/src/components/Select/Select.tsx b/packages/grafana-ui/src/components/Select/Select.tsx index 348133c6c28..0d9d7478bed 100644 --- a/packages/grafana-ui/src/components/Select/Select.tsx +++ b/packages/grafana-ui/src/components/Select/Select.tsx @@ -16,7 +16,7 @@ import SelectOptionGroup from './SelectOptionGroup'; import IndicatorsContainer from './IndicatorsContainer'; import NoOptionsMessage from './NoOptionsMessage'; import resetSelectStyles from './resetSelectStyles'; -import { CustomScrollbar } from '@grafana/ui'; +import { CustomScrollbar } from '..'; export interface SelectOptionItem { label?: string; diff --git a/packages/grafana-ui/src/components/Select/_Select.scss b/packages/grafana-ui/src/components/Select/_Select.scss index bf18125d7b8..bc18ed9d369 100644 --- a/packages/grafana-ui/src/components/Select/_Select.scss +++ b/packages/grafana-ui/src/components/Select/_Select.scss @@ -102,6 +102,7 @@ $select-input-bg-disabled: $input-bg-disabled; .gf-form-select-box__value-container { display: table-cell; padding: 6px 10px; + vertical-align: middle; > div { display: inline-block; } diff --git a/packages/grafana-ui/src/components/ThresholdsEditor/_ThresholdsEditor.scss b/packages/grafana-ui/src/components/ThresholdsEditor/_ThresholdsEditor.scss index 50c92a6bcc5..61278321572 100644 --- a/packages/grafana-ui/src/components/ThresholdsEditor/_ThresholdsEditor.scss +++ b/packages/grafana-ui/src/components/ThresholdsEditor/_ThresholdsEditor.scss @@ -8,6 +8,12 @@ height: 70px; } +.thresholds-row:first-child > .thresholds-row-color-indicator { + border-top-left-radius: $border-radius; + border-top-right-radius: $border-radius; + overflow: hidden; +} + .thresholds-row:last-child > .thresholds-row-color-indicator { border-bottom-left-radius: $border-radius; border-bottom-right-radius: $border-radius; @@ -33,7 +39,7 @@ } .thresholds-row-color-indicator { - width: 20px; + width: 10px; } .thresholds-row-input { @@ -45,18 +51,6 @@ display: flex; justify-content: center; flex-direction: row; - height: 42px; -} - -.thresholds-row-input-inner > div { - border-left: 1px solid $input-label-border-color; - border-top: 1px solid $input-label-border-color; - border-bottom: 1px solid $input-label-border-color; -} - -.thresholds-row-input-inner > *:nth-child(2) { - border-top-left-radius: $border-radius; - border-bottom-left-radius: $border-radius; } .thresholds-row-input-inner > *:last-child { @@ -74,9 +68,11 @@ } .thresholds-row-input-inner-value > input { - height: 100%; - padding: 8px 10px; + height: $gf-form-input-height; + padding: $input-padding-y $input-padding-x; width: 150px; + border-top: 1px solid $input-label-border-color; + border-bottom: 1px solid $input-label-border-color; } .thresholds-row-input-inner-color { @@ -85,6 +81,7 @@ align-items: center; justify-content: center; background-color: $input-bg; + border: 1px solid $input-label-border-color; } .thresholds-row-input-inner-color-colorpicker { @@ -99,8 +96,10 @@ display: flex; align-items: center; justify-content: center; - height: 42px; + height: $gf-form-input-height; + padding: $input-padding-y $input-padding-x; width: 42px; - background-color: $input-label-border-color; + background-color: $input-label-bg; + border: 1px solid $input-label-border-color; cursor: pointer; } diff --git a/public/app/plugins/panel/gauge/MappingRow.tsx b/packages/grafana-ui/src/components/ValueMappingsEditor/MappingRow.tsx similarity index 51% rename from public/app/plugins/panel/gauge/MappingRow.tsx rename to packages/grafana-ui/src/components/ValueMappingsEditor/MappingRow.tsx index b975821f27a..c5704e8bc88 100644 --- a/public/app/plugins/panel/gauge/MappingRow.tsx +++ b/packages/grafana-ui/src/components/ValueMappingsEditor/MappingRow.tsx @@ -1,22 +1,22 @@ -import React, { PureComponent } from 'react'; -import { MappingType, RangeMap, Select, ValueMap } from '@grafana/ui'; +import React, { ChangeEvent, PureComponent } from 'react'; -import { Label } from 'app/core/components/Label/Label'; +import { MappingType, ValueMapping } from '../../types'; +import { FormField, FormLabel, Select } from '..'; -interface Props { - mapping: ValueMap | RangeMap; - updateMapping: (mapping) => void; - removeMapping: () => void; +export interface Props { + valueMapping: ValueMapping; + updateValueMapping: (valueMapping: ValueMapping) => void; + removeValueMapping: () => void; } interface State { - from: string; + from?: string; id: number; operator: string; text: string; - to: string; + to?: string; type: MappingType; - value: string; + value?: string; } const mappingOptions = [ @@ -25,36 +25,34 @@ const mappingOptions = [ ]; export default class MappingRow extends PureComponent { - constructor(props) { + constructor(props: Props) { super(props); - this.state = { - ...props.mapping, - }; + this.state = { ...props.valueMapping }; } - onMappingValueChange = event => { + onMappingValueChange = (event: ChangeEvent) => { this.setState({ value: event.target.value }); }; - onMappingFromChange = event => { + onMappingFromChange = (event: ChangeEvent) => { this.setState({ from: event.target.value }); }; - onMappingToChange = event => { + onMappingToChange = (event: ChangeEvent) => { this.setState({ to: event.target.value }); }; - onMappingTextChange = event => { + onMappingTextChange = (event: ChangeEvent) => { this.setState({ text: event.target.value }); }; - onMappingTypeChange = mappingType => { + onMappingTypeChange = (mappingType: MappingType) => { this.setState({ type: mappingType }); }; updateMapping = () => { - this.props.updateMapping({ ...this.state }); + this.props.updateValueMapping({ ...this.state } as ValueMapping); }; renderRow() { @@ -63,30 +61,28 @@ export default class MappingRow extends PureComponent { if (type === MappingType.RangeToText) { return ( <> -
- + + +
+ Text -
-
- - -
-
- -
@@ -96,17 +92,16 @@ export default class MappingRow extends PureComponent { return ( <> -
- - -
+
- + Text { return (
- + Type dashboard.id === homeDashboardId)} getOptionValue={i => i.id} diff --git a/public/app/core/components/ToggleButtonGroup/ToggleButtonGroup.tsx b/public/app/core/components/ToggleButtonGroup/ToggleButtonGroup.tsx index 86e15923bda..a2c06eef9f5 100644 --- a/public/app/core/components/ToggleButtonGroup/ToggleButtonGroup.tsx +++ b/public/app/core/components/ToggleButtonGroup/ToggleButtonGroup.tsx @@ -1,4 +1,4 @@ -import React, { SFC, ReactNode, PureComponent } from 'react'; +import React, { FC, ReactNode, PureComponent } from 'react'; import { Tooltip } from '@grafana/ui'; interface ToggleButtonGroupProps { @@ -29,7 +29,7 @@ interface ToggleButtonProps { tooltip?: string; } -export const ToggleButton: SFC = ({ +export const ToggleButton: FC = ({ children, selected, className = '', diff --git a/public/app/core/components/sidemenu/DropDownChild.tsx b/public/app/core/components/sidemenu/DropDownChild.tsx index 1a577d185e5..41aa794999e 100644 --- a/public/app/core/components/sidemenu/DropDownChild.tsx +++ b/public/app/core/components/sidemenu/DropDownChild.tsx @@ -1,10 +1,10 @@ -import React, { SFC } from 'react'; +import React, { FC } from 'react'; export interface Props { child: any; } -const DropDownChild: SFC = props => { +const DropDownChild: FC = props => { const { child } = props; const listItemClassName = child.divider ? 'divider' : ''; diff --git a/public/app/core/components/sidemenu/SideMenuDropDown.tsx b/public/app/core/components/sidemenu/SideMenuDropDown.tsx index 7cd7554f82c..4231e992b19 100644 --- a/public/app/core/components/sidemenu/SideMenuDropDown.tsx +++ b/public/app/core/components/sidemenu/SideMenuDropDown.tsx @@ -1,11 +1,11 @@ -import React, { SFC } from 'react'; +import React, { FC } from 'react'; import DropDownChild from './DropDownChild'; interface Props { link: any; } -const SideMenuDropDown: SFC = props => { +const SideMenuDropDown: FC = props => { const { link } = props; return (
    diff --git a/public/app/core/components/sidemenu/SignIn.tsx b/public/app/core/components/sidemenu/SignIn.tsx index 17dd913823a..50b3aef2d9b 100644 --- a/public/app/core/components/sidemenu/SignIn.tsx +++ b/public/app/core/components/sidemenu/SignIn.tsx @@ -1,6 +1,6 @@ -import React, { SFC } from 'react'; +import React, { FC } from 'react'; -const SignIn: SFC = () => { +const SignIn: FC = () => { const loginUrl = `login?redirect=${encodeURIComponent(window.location.pathname)}`; return (
    diff --git a/public/app/core/components/sidemenu/TopSection.tsx b/public/app/core/components/sidemenu/TopSection.tsx index c6bf5df8242..827b868ea67 100644 --- a/public/app/core/components/sidemenu/TopSection.tsx +++ b/public/app/core/components/sidemenu/TopSection.tsx @@ -1,9 +1,9 @@ -import React, { SFC } from 'react'; +import React, { FC } from 'react'; import _ from 'lodash'; import TopSectionItem from './TopSectionItem'; import config from '../../config'; -const TopSection: SFC = () => { +const TopSection: FC = () => { const navTree = _.cloneDeep(config.bootData.navTree); const mainLinks = _.filter(navTree, item => !item.hideFromMenu); diff --git a/public/app/core/components/sidemenu/TopSectionItem.tsx b/public/app/core/components/sidemenu/TopSectionItem.tsx index 7b3bf96dce8..0aca32c3ba3 100644 --- a/public/app/core/components/sidemenu/TopSectionItem.tsx +++ b/public/app/core/components/sidemenu/TopSectionItem.tsx @@ -1,11 +1,11 @@ -import React, { SFC } from 'react'; +import React, { FC } from 'react'; import SideMenuDropDown from './SideMenuDropDown'; export interface Props { link: any; } -const TopSectionItem: SFC = props => { +const TopSectionItem: FC = props => { const { link } = props; return (
    diff --git a/public/app/core/config.ts b/public/app/core/config.ts index 13d84772ecf..0aa159af84d 100644 --- a/public/app/core/config.ts +++ b/public/app/core/config.ts @@ -6,6 +6,8 @@ export interface BuildInfo { commit: string; isEnterprise: boolean; env: string; + latestVersion: string; + hasUpdate: boolean; } export class Settings { diff --git a/public/app/core/selectors/navModel.ts b/public/app/core/selectors/navModel.ts index aa508616962..7d745b58002 100644 --- a/public/app/core/selectors/navModel.ts +++ b/public/app/core/selectors/navModel.ts @@ -41,3 +41,7 @@ export function getNavModel(navIndex: NavIndex, id: string, fallback?: NavModel) return getNotFoundModel(); } + +export const getTitleFromNavModel = (navModel: NavModel) => { + return `${navModel.main.text}${navModel.node.text ? ': ' + navModel.node.text : '' }`; +}; diff --git a/public/app/features/api-keys/ApiKeysPage.test.tsx b/public/app/features/api-keys/ApiKeysPage.test.tsx index 54200234ddc..cd640b5a357 100644 --- a/public/app/features/api-keys/ApiKeysPage.test.tsx +++ b/public/app/features/api-keys/ApiKeysPage.test.tsx @@ -6,7 +6,14 @@ import { getMultipleMockKeys, getMockKey } from './__mocks__/apiKeysMock'; const setup = (propOverrides?: object) => { const props: Props = { - navModel: {} as NavModel, + navModel: { + main: { + text: 'Configuration' + }, + node: { + text: 'Api Keys' + } + } as NavModel, apiKeys: [] as ApiKey[], searchQuery: '', hasFetched: false, diff --git a/public/app/features/api-keys/ApiKeysPage.tsx b/public/app/features/api-keys/ApiKeysPage.tsx index e14873fa9f6..41b9b0c8a55 100644 --- a/public/app/features/api-keys/ApiKeysPage.tsx +++ b/public/app/features/api-keys/ApiKeysPage.tsx @@ -6,8 +6,7 @@ import { NavModel, ApiKey, NewApiKey, OrgRole } from 'app/types'; import { getNavModel } from 'app/core/selectors/navModel'; import { getApiKeys, getApiKeysCount } from './state/selectors'; import { loadApiKeys, deleteApiKey, setSearchQuery, addApiKey } from './state/actions'; -import PageHeader from 'app/core/components/PageHeader/PageHeader'; -import PageLoader from 'app/core/components/PageLoader/PageLoader'; +import Page from 'app/core/components/Page/Page'; import SlideDown from 'app/core/components/Animations/SlideDown'; import ApiKeysAddedModal from './ApiKeysAddedModal'; import config from 'app/core/config'; @@ -240,18 +239,17 @@ export class ApiKeysPage extends PureComponent { const { hasFetched, navModel, apiKeysCount } = this.props; return ( -
    - - {hasFetched ? ( - apiKeysCount > 0 ? ( - this.renderApiKeyList() - ) : ( - this.renderEmptyList() - ) - ) : ( - - )} -
    + + + {hasFetched && ( + apiKeysCount > 0 ? ( + this.renderApiKeyList() + ) : ( + this.renderEmptyList() + ) + )} + + ); } } diff --git a/public/app/features/api-keys/__snapshots__/ApiKeysPage.test.tsx.snap b/public/app/features/api-keys/__snapshots__/ApiKeysPage.test.tsx.snap index 7ede9618250..f40894426ae 100644 --- a/public/app/features/api-keys/__snapshots__/ApiKeysPage.test.tsx.snap +++ b/public/app/features/api-keys/__snapshots__/ApiKeysPage.test.tsx.snap @@ -1,132 +1,152 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Render should render API keys table if there are any keys 1`] = ` -
    - + - -
    + `; exports[`Render should render CTA if there are no API keys 1`] = ` -
    - -
    + - - -
    + - -
    - Add API Key -
    -
    -
    + + +
    + Add API Key +
    +
    - - Key name - - -
    -
    - - Role - - - +
    +
    + + Role + + + - -
    -
    -
    +
    - Add - + +
    -
    - -
    - -
    -
    + +
    + +
+ + `; diff --git a/public/app/features/dashboard/dashgrid/PanelHeader/PanelHeaderMenuItem.tsx b/public/app/features/dashboard/dashgrid/PanelHeader/PanelHeaderMenuItem.tsx index d42b48fe1d6..66a942f0afc 100644 --- a/public/app/features/dashboard/dashgrid/PanelHeader/PanelHeaderMenuItem.tsx +++ b/public/app/features/dashboard/dashgrid/PanelHeader/PanelHeaderMenuItem.tsx @@ -1,11 +1,11 @@ -import React, { SFC } from 'react'; +import React, { FC } from 'react'; import { PanelMenuItem } from '@grafana/ui'; interface Props { children: any; } -export const PanelHeaderMenuItem: SFC = props => { +export const PanelHeaderMenuItem: FC = props => { const isSubMenu = props.type === 'submenu'; const isDivider = props.type === 'divider'; return isDivider ? ( diff --git a/public/app/features/dashboard/panel_editor/DataSourceOption.tsx b/public/app/features/dashboard/panel_editor/DataSourceOption.tsx index 9a3ce527510..e4bbcfffe1d 100644 --- a/public/app/features/dashboard/panel_editor/DataSourceOption.tsx +++ b/public/app/features/dashboard/panel_editor/DataSourceOption.tsx @@ -1,4 +1,4 @@ -import React, { SFC } from 'react'; +import React, { FC } from 'react'; import { Tooltip } from '@grafana/ui'; interface Props { @@ -10,7 +10,7 @@ interface Props { tooltipInfo?: any; } -export const DataSourceOptions: SFC = ({ label, placeholder, name, value, onChange, tooltipInfo }) => { +export const DataSourceOptions: FC = ({ label, placeholder, name, value, onChange, tooltipInfo }) => { const dsOption = (
diff --git a/public/app/features/dashboard/panel_editor/QueryOptions.tsx b/public/app/features/dashboard/panel_editor/QueryOptions.tsx index fad70d92990..d6187a89b7b 100644 --- a/public/app/features/dashboard/panel_editor/QueryOptions.tsx +++ b/public/app/features/dashboard/panel_editor/QueryOptions.tsx @@ -10,7 +10,7 @@ import { Input } from 'app/core/components/Form'; import { EventsWithValidation } from 'app/core/components/Form/Input'; import { InputStatus } from 'app/core/components/Form/Input'; import DataSourceOption from './DataSourceOption'; -import { GfFormLabel } from '@grafana/ui'; +import { FormLabel } from '@grafana/ui'; // Types import { PanelModel } from '../panel_model'; @@ -164,7 +164,7 @@ export class QueryOptions extends PureComponent { {this.renderOptions()}
- Relative time + Relative time void; } -const DashboardsTable: SFC = ({ dashboards, onImport, onRemove }) => { +const DashboardsTable: FC = ({ dashboards, onImport, onRemove }) => { function buttonText(dashboard: PluginDashboard) { return dashboard.revision !== dashboard.importedRevision ? 'Update' : 'Re-import'; } diff --git a/public/app/features/datasources/DataSourcesListPage.test.tsx b/public/app/features/datasources/DataSourcesListPage.test.tsx index 0ea716d62c9..33f5790978d 100644 --- a/public/app/features/datasources/DataSourcesListPage.test.tsx +++ b/public/app/features/datasources/DataSourcesListPage.test.tsx @@ -10,7 +10,14 @@ const setup = (propOverrides?: object) => { dataSources: [] as DataSource[], layoutMode: LayoutModes.Grid, loadDataSources: jest.fn(), - navModel: {} as NavModel, + navModel: { + main: { + text: 'Configuration' + }, + node: { + text: 'Data Sources' + } + } as NavModel, dataSourcesCount: 0, searchQuery: '', setDataSourcesSearchQuery: jest.fn(), diff --git a/public/app/features/datasources/DataSourcesListPage.tsx b/public/app/features/datasources/DataSourcesListPage.tsx index 6a292d63e53..884df929319 100644 --- a/public/app/features/datasources/DataSourcesListPage.tsx +++ b/public/app/features/datasources/DataSourcesListPage.tsx @@ -1,15 +1,15 @@ import React, { PureComponent } from 'react'; import { connect } from 'react-redux'; import { hot } from 'react-hot-loader'; -import PageHeader from '../../core/components/PageHeader/PageHeader'; -import PageLoader from 'app/core/components/PageLoader/PageLoader'; -import OrgActionBar from '../../core/components/OrgActionBar/OrgActionBar'; -import EmptyListCTA from '../../core/components/EmptyListCTA/EmptyListCTA'; +import Page from 'app/core/components/Page/Page'; +import OrgActionBar from 'app/core/components/OrgActionBar/OrgActionBar'; +import EmptyListCTA from 'app/core/components/EmptyListCTA/EmptyListCTA'; import DataSourcesList from './DataSourcesList'; -import { DataSource, NavModel } from 'app/types'; -import { LayoutMode } from '../../core/components/LayoutSelector/LayoutSelector'; +import { DataSource, NavModel, StoreState } from 'app/types'; +import { LayoutMode } from 'app/core/components/LayoutSelector/LayoutSelector'; import { loadDataSources, setDataSourcesLayoutMode, setDataSourcesSearchQuery } from './state/actions'; -import { getNavModel } from '../../core/selectors/navModel'; +import { getNavModel } from 'app/core/selectors/navModel'; + import { getDataSources, getDataSourcesCount, @@ -67,30 +67,30 @@ export class DataSourcesListPage extends PureComponent { }; return ( -
- -
- {!hasFetched && } - {hasFetched && dataSourcesCount === 0 && } - {hasFetched && - dataSourcesCount > 0 && [ - setDataSourcesLayoutMode(mode)} - setSearchQuery={query => setDataSourcesSearchQuery(query)} - linkButton={linkButton} - key="action-bar" - />, - , - ]} -
-
+ + + <> + {hasFetched && dataSourcesCount === 0 && } + {hasFetched && + dataSourcesCount > 0 && [ + setDataSourcesLayoutMode(mode)} + setSearchQuery={query => setDataSourcesSearchQuery(query)} + linkButton={linkButton} + key="action-bar" + />, + , + ]} + + + ); } } -function mapStateToProps(state) { +function mapStateToProps(state: StoreState) { return { navModel: getNavModel(state.navIndex, 'datasources'), dataSources: getDataSources(state.dataSources), diff --git a/public/app/features/datasources/__snapshots__/DataSourcesListPage.test.tsx.snap b/public/app/features/datasources/__snapshots__/DataSourcesListPage.test.tsx.snap index c26ac50fed8..63998d43870 100644 --- a/public/app/features/datasources/__snapshots__/DataSourcesListPage.test.tsx.snap +++ b/public/app/features/datasources/__snapshots__/DataSourcesListPage.test.tsx.snap @@ -1,12 +1,20 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Render should render action bar and datasources 1`] = ` -
- -
+ -
-
+ + `; exports[`Render should render component 1`] = ` -
- + -
- -
-
+ `; diff --git a/public/app/features/datasources/settings/BasicSettings.tsx b/public/app/features/datasources/settings/BasicSettings.tsx index 120e002ac68..77c4f3d13c6 100644 --- a/public/app/features/datasources/settings/BasicSettings.tsx +++ b/public/app/features/datasources/settings/BasicSettings.tsx @@ -1,5 +1,5 @@ -import React, { SFC } from 'react'; -import { Label } from 'app/core/components/Label/Label'; +import React, { FC } from 'react'; +import { FormLabel } from '@grafana/ui'; import { Switch } from '../../../core/components/Switch/Switch'; export interface Props { @@ -9,19 +9,19 @@ export interface Props { onDefaultChange: (value: boolean) => void; } -const BasicSettings: SFC = ({ dataSourceName, isDefault, onDefaultChange, onNameChange }) => { +const BasicSettings: FC = ({ dataSourceName, isDefault, onDefaultChange, onNameChange }) => { return (
- + void; } -const ButtonRow: SFC = ({ isReadOnly, onDelete, onSubmit }) => { +const ButtonRow: FC = ({ isReadOnly, onDelete, onSubmit }) => { return (