Parcourir la source

Merge branch 'master' into page-layout-component

Torkel Ödegaard il y a 7 ans
Parent
commit
bfadcd2968

+ 1 - 1
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)

+ 24 - 0
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(<FormField {...props} />);
+};
+
+describe('Render', () => {
+  it('should render component', () => {
+    const wrapper = setup();
+
+    expect(wrapper).toMatchSnapshot();
+  });
+});

+ 25 - 0
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<HTMLInputElement> {
+  label: string;
+  labelWidth?: number;
+  inputWidth?: number;
+}
+
+const defaultProps = {
+  labelWidth: 6,
+  inputWidth: 12,
+};
+
+const FormField: FunctionComponent<Props> = ({ label, labelWidth, inputWidth, ...inputProps }) => {
+  return (
+    <div className="form-field">
+      <FormLabel width={labelWidth}>{label}</FormLabel>
+      <input type="text" className={`gf-form-input width-${inputWidth}`} {...inputProps} />
+    </div>
+  );
+};
+
+FormField.defaultProps = defaultProps;
+export { FormField };

+ 12 - 0
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;
+  }
+}

+ 19 - 0
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`] = `
+<div
+  className="form-field"
+>
+  <Component
+    width={11}
+  >
+    Test
+  </Component>
+  <input
+    className="gf-form-input width-12"
+    onChange={[MockFunction]}
+    type="text"
+    value={10}
+  />
+</div>
+`;

+ 42 - 0
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<Props> = ({
+  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 (
+    <label className={classes} {...rest} htmlFor={htmlFor}>
+      {children}
+      {tooltip && (
+        <Tooltip placement="auto" content={tooltip}>
+          <div className="gf-form-help-icon--right-normal">
+            <i className="gicon gicon-question gicon--has-hover" />
+          </div>
+        </Tooltip>
+      )}
+    </label>
+  );
+};

+ 0 - 23
packages/grafana-ui/src/components/GfFormLabel/GfFormLabel.tsx

@@ -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<Props> = ({ 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 (
-    <label className={classes} {...rest} htmlFor={htmlFor}>
-      {children}
-    </label>
-  );
-};

+ 0 - 25
packages/grafana-ui/src/components/Label/Label.tsx

@@ -1,25 +0,0 @@
-import React, { SFC, ReactNode } from 'react';
-import { Tooltip } from '../Tooltip/Tooltip';
-
-interface Props {
-  tooltip?: string;
-  for?: string;
-  children: ReactNode;
-  width?: number;
-  className?: string;
-}
-
-export const Label: SFC<Props> = props => {
-  return (
-    <span className={`gf-form-label width-${props.width ? props.width : '10'}`}>
-      <span>{props.children}</span>
-      {props.tooltip && (
-        <Tooltip placement="auto" content={props.tooltip}>
-          <div className="gf-form-help-icon--right-normal">
-            <i className="gicon gicon-question gicon--has-hover" />
-          </div>
-        </Tooltip>
-      )}
-    </span>
-  );
-};

+ 1 - 1
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;

+ 1 - 0
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;
   }

+ 36 - 40
packages/grafana-ui/src/components/ValueMappingsEditor/MappingRow.tsx

@@ -1,8 +1,7 @@
-import React, { PureComponent } from 'react';
+import React, { ChangeEvent, PureComponent } from 'react';
 
-import { MappingType, ValueMapping } from '../../types/panel';
-import { Label } from '../Label/Label';
-import { Select } from '../Select/Select';
+import { MappingType, ValueMapping } from '../../types';
+import { FormField, FormLabel, Select } from '..';
 
 export interface Props {
   valueMapping: ValueMapping;
@@ -32,19 +31,19 @@ export default class MappingRow extends PureComponent<Props, State> {
     this.state = { ...props.valueMapping };
   }
 
-  onMappingValueChange = (event: React.ChangeEvent<HTMLInputElement>) => {
+  onMappingValueChange = (event: ChangeEvent<HTMLInputElement>) => {
     this.setState({ value: event.target.value });
   };
 
-  onMappingFromChange = (event: React.ChangeEvent<HTMLInputElement>) => {
+  onMappingFromChange = (event: ChangeEvent<HTMLInputElement>) => {
     this.setState({ from: event.target.value });
   };
 
-  onMappingToChange = (event: React.ChangeEvent<HTMLInputElement>) => {
+  onMappingToChange = (event: ChangeEvent<HTMLInputElement>) => {
     this.setState({ to: event.target.value });
   };
 
-  onMappingTextChange = (event: React.ChangeEvent<HTMLInputElement>) => {
+  onMappingTextChange = (event: ChangeEvent<HTMLInputElement>) => {
     this.setState({ text: event.target.value });
   };
 
@@ -62,30 +61,28 @@ export default class MappingRow extends PureComponent<Props, State> {
     if (type === MappingType.RangeToText) {
       return (
         <>
-          <div className="gf-form">
-            <Label width={4}>From</Label>
-            <input
-              className="gf-form-input width-8"
-              value={from}
-              onBlur={this.updateMapping}
-              onChange={this.onMappingFromChange}
-            />
-          </div>
-          <div className="gf-form">
-            <Label width={4}>To</Label>
+          <FormField
+            label="From"
+            labelWidth={4}
+            inputWidth={8}
+            onBlur={this.updateMapping}
+            onChange={this.onMappingFromChange}
+            value={from}
+          />
+          <FormField
+            label="To"
+            labelWidth={4}
+            inputWidth={8}
+            onBlur={this.updateMapping}
+            onChange={this.onMappingToChange}
+            value={to}
+          />
+          <div className="gf-form gf-form--grow">
+            <FormLabel width={4}>Text</FormLabel>
             <input
-              className="gf-form-input width-8"
-              value={to}
+              className="gf-form-input"
               onBlur={this.updateMapping}
-              onChange={this.onMappingToChange}
-            />
-          </div>
-          <div className="gf-form">
-            <Label width={4}>Text</Label>
-            <input
-              className="gf-form-input width-10"
               value={text}
-              onBlur={this.updateMapping}
               onChange={this.onMappingTextChange}
             />
           </div>
@@ -95,17 +92,16 @@ export default class MappingRow extends PureComponent<Props, State> {
 
     return (
       <>
-        <div className="gf-form">
-          <Label width={4}>Value</Label>
-          <input
-            className="gf-form-input width-8"
-            onBlur={this.updateMapping}
-            onChange={this.onMappingValueChange}
-            value={value}
-          />
-        </div>
+        <FormField
+          label="Value"
+          labelWidth={4}
+          onBlur={this.updateMapping}
+          onChange={this.onMappingValueChange}
+          value={value}
+          inputWidth={8}
+        />
         <div className="gf-form gf-form--grow">
-          <Label width={4}>Text</Label>
+          <FormLabel width={4}>Text</FormLabel>
           <input
             className="gf-form-input"
             onBlur={this.updateMapping}
@@ -123,7 +119,7 @@ export default class MappingRow extends PureComponent<Props, State> {
     return (
       <div className="gf-form-inline">
         <div className="gf-form">
-          <Label width={5}>Type</Label>
+          <FormLabel width={5}>Type</FormLabel>
           <Select
             placeholder="Choose type"
             isSearchable={false}

+ 1 - 0
packages/grafana-ui/src/components/index.scss

@@ -7,3 +7,4 @@
 @import 'PanelOptionsGrid/PanelOptionsGrid';
 @import 'ColorPicker/ColorPicker';
 @import 'ValueMappingsEditor/ValueMappingsEditor';
+@import "FormField/FormField";

+ 4 - 2
packages/grafana-ui/src/components/index.ts

@@ -2,7 +2,6 @@ export { DeleteButton } from './DeleteButton/DeleteButton';
 export { Tooltip } from './Tooltip/Tooltip';
 export { Portal } from './Portal/Portal';
 export { CustomScrollbar } from './CustomScrollbar/CustomScrollbar';
-export { Label } from './Label/Label';
 
 // Select
 export { Select, AsyncSelect, SelectOptionItem } from './Select/Select';
@@ -10,12 +9,15 @@ export { IndicatorsContainer } from './Select/IndicatorsContainer';
 export { NoOptionsMessage } from './Select/NoOptionsMessage';
 export { default as resetSelectStyles } from './Select/resetSelectStyles';
 
+// Forms
+export { FormLabel } from './FormLabel/FormLabel';
+export { FormField } from './FormField/FormField';
+
 export { LoadingPlaceholder } from './LoadingPlaceholder/LoadingPlaceholder';
 export { ColorPicker } from './ColorPicker/ColorPicker';
 export { SeriesColorPickerPopover } from './ColorPicker/SeriesColorPickerPopover';
 export { SeriesColorPicker } from './ColorPicker/SeriesColorPicker';
 export { ThresholdsEditor } from './ThresholdsEditor/ThresholdsEditor';
-export { GfFormLabel } from './GfFormLabel/GfFormLabel';
 export { Graph } from './Graph/Graph';
 export { PanelOptionsGroup } from './PanelOptionsGroup/PanelOptionsGroup';
 export { PanelOptionsGrid } from './PanelOptionsGrid/PanelOptionsGrid';

+ 3 - 3
public/app/core/components/SharedPreferences/SharedPreferences.tsx

@@ -1,6 +1,6 @@
 import React, { PureComponent } from 'react';
-import { Select, Label } from '@grafana/ui';
 
+import { FormLabel, Select } from '@grafana/ui';
 import { getBackendSrv, BackendSrv } from 'app/core/services/backend_srv';
 
 import { DashboardSearchHit } from 'app/types';
@@ -99,12 +99,12 @@ export class SharedPreferences extends PureComponent<Props, State> {
           />
         </div>
         <div className="gf-form">
-          <Label
+          <FormLabel
             width={11}
             tooltip="Not finding dashboard you want? Star it first, then it should appear in this select box."
           >
             Home Dashboard
-          </Label>
+          </FormLabel>
           <Select
             value={dashboards.find(dashboard => dashboard.id === homeDashboardId)}
             getOptionValue={i => i.id}

+ 2 - 2
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<Props, State> {
         {this.renderOptions()}
 
         <div className="gf-form">
-          <GfFormLabel>Relative time</GfFormLabel>
+          <FormLabel>Relative time</FormLabel>
           <Input
             type="text"
             className="width-6"

+ 3 - 4
public/app/features/datasources/settings/BasicSettings.tsx

@@ -1,6 +1,5 @@
 import React, { FC } from 'react';
-import { Label } from '@grafana/ui';
-
+import { FormLabel } from '@grafana/ui';
 import { Switch } from '../../../core/components/Switch/Switch';
 
 export interface Props {
@@ -15,14 +14,14 @@ const BasicSettings: FC<Props> = ({ dataSourceName, isDefault, onDefaultChange,
     <div className="gf-form-group">
       <div className="gf-form-inline">
         <div className="gf-form max-width-30" style={{ marginRight: '3px' }}>
-          <Label
+          <FormLabel
             tooltip={
               'The name is used when you select the data source in panels. The Default data source is ' +
               'preselected in new panels.'
             }
           >
             Name
-          </Label>
+          </FormLabel>
           <input
             className="gf-form-input max-width-23"
             type="text"

+ 4 - 4
public/app/features/teams/TeamSettings.tsx

@@ -1,6 +1,6 @@
 import React from 'react';
 import { connect } from 'react-redux';
-import { Label } from '@grafana/ui';
+import { FormLabel } from '@grafana/ui';
 
 import { SharedPreferences } from 'app/core/components/SharedPreferences/SharedPreferences';
 import { updateTeam } from './state/actions';
@@ -51,7 +51,7 @@ export class TeamSettings extends React.Component<Props, State> {
         <h3 className="page-sub-heading">Team Settings</h3>
         <form name="teamDetailsForm" className="gf-form-group" onSubmit={this.onUpdate}>
           <div className="gf-form max-width-30">
-            <Label>Name</Label>
+            <FormLabel>Name</FormLabel>
             <input
               type="text"
               required
@@ -62,9 +62,9 @@ export class TeamSettings extends React.Component<Props, State> {
           </div>
 
           <div className="gf-form max-width-30">
-            <Label tooltip="This is optional and is primarily used to set the team profile avatar (via gravatar service)">
+            <FormLabel tooltip="This is optional and is primarily used to set the team profile avatar (via gravatar service)">
               Email
-            </Label>
+            </FormLabel>
             <input
               type="email"
               className="gf-form-input max-width-22"

+ 3 - 9
public/app/plugins/panel/gauge/GaugeOptionsEditor.tsx

@@ -1,5 +1,5 @@
 import React, { PureComponent } from 'react';
-import { PanelOptionsProps, PanelOptionsGroup, Label } from '@grafana/ui';
+import { FormField, PanelOptionsProps, PanelOptionsGroup } from '@grafana/ui';
 
 import { Switch } from 'app/core/components/Switch/Switch';
 import { GaugeOptions } from './types';
@@ -21,14 +21,8 @@ export default class GaugeOptionsEditor extends PureComponent<PanelOptionsProps<
 
     return (
       <PanelOptionsGroup title="Gauge">
-        <div className="gf-form">
-          <Label width={8}>Min value</Label>
-          <input type="text" className="gf-form-input width-12" onChange={this.onMinValueChange} value={minValue} />
-        </div>
-        <div className="gf-form">
-          <Label width={8}>Max value</Label>
-          <input type="text" className="gf-form-input width-12" onChange={this.onMaxValueChange} value={maxValue} />
-        </div>
+        <FormField label="Min value" labelWidth={8} onChange={this.onMinValueChange} value={minValue} />
+        <FormField label="Max value" labelWidth={8} onChange={this.onMaxValueChange} value={maxValue} />
         <Switch
           label="Show labels"
           labelClass="width-8"

+ 13 - 22
public/app/plugins/panel/gauge/ValueOptions.tsx

@@ -1,6 +1,5 @@
 import React, { PureComponent } from 'react';
-import { PanelOptionsProps, PanelOptionsGroup, Label, Select } from '@grafana/ui';
-
+import { FormField, FormLabel, PanelOptionsProps, PanelOptionsGroup, Select } from '@grafana/ui';
 import UnitPicker from 'app/core/components/Select/UnitPicker';
 import { GaugeOptions } from './types';
 
@@ -41,7 +40,7 @@ export default class ValueOptions extends PureComponent<PanelOptionsProps<GaugeO
     return (
       <PanelOptionsGroup title="Value">
         <div className="gf-form">
-          <Label width={labelWidth}>Stat</Label>
+          <FormLabel width={labelWidth}>Stat</FormLabel>
           <Select
             width={12}
             options={statOptions}
@@ -50,27 +49,19 @@ export default class ValueOptions extends PureComponent<PanelOptionsProps<GaugeO
           />
         </div>
         <div className="gf-form">
-          <Label width={labelWidth}>Unit</Label>
+          <FormLabel width={labelWidth}>Unit</FormLabel>
           <UnitPicker defaultValue={unit} onChange={this.onUnitChange} />
         </div>
-        <div className="gf-form">
-          <Label width={labelWidth}>Decimals</Label>
-          <input
-            className="gf-form-input width-12"
-            type="number"
-            placeholder="auto"
-            value={decimals || ''}
-            onChange={this.onDecimalChange}
-          />
-        </div>
-        <div className="gf-form">
-          <Label width={labelWidth}>Prefix</Label>
-          <input className="gf-form-input width-12" type="text" value={prefix || ''} onChange={this.onPrefixChange} />
-        </div>
-        <div className="gf-form">
-          <Label width={labelWidth}>Suffix</Label>
-          <input className="gf-form-input width-12" type="text" value={suffix || ''} onChange={this.onSuffixChange} />
-        </div>
+        <FormField
+          label="Decimals"
+          labelWidth={labelWidth}
+          placeholder="auto"
+          onChange={this.onDecimalChange}
+          value={decimals || ''}
+          type="number"
+        />
+        <FormField label="Prefix" labelWidth={labelWidth} onChange={this.onPrefixChange} value={prefix || ''} />
+        <FormField label="Suffix" labelWidth={labelWidth} onChange={this.onSuffixChange} value={suffix || ''} />
       </PanelOptionsGroup>
     );
   }

+ 3 - 3
scripts/build/ci-deploy/Dockerfile

@@ -8,8 +8,6 @@ RUN git clone https://github.com/aptly-dev/aptly $GOPATH/src/github.com/aptly-de
 
 FROM circleci/python:2.7-stretch
 
-ENV PATH=$PATH:/opt/google-cloud-sdk/bin
-
 USER root
 
 RUN pip install awscli && \
@@ -18,7 +16,9 @@ RUN pip install awscli && \
     apt update && \
     apt install -y createrepo expect && \
     apt-get autoremove -y && \
-    rm -rf /var/lib/apt/lists/*
+    rm -rf /var/lib/apt/lists/* && \
+    ln -s /opt/google-cloud-sdk/bin/gsutil /usr/bin/gsutil && \
+    ln -s /opt/google-cloud-sdk/bin/gcloud /usr/bin/gcloud
 
 COPY --from=0 /go/bin/aptly /usr/local/bin/aptly
 

+ 1 - 1
scripts/build/ci-deploy/build-deploy.sh

@@ -1,6 +1,6 @@
 #!/bin/bash
 
-_version="1.1.0"
+_version="1.2.0"
 _tag="grafana/grafana-ci-deploy:${_version}"
 
 docker build -t $_tag .