mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Form migrations: Last components from Forms namespace (#23556)
* Migrate RadioButtonGroup * Migrate Label * Migrate Form * Migrate Field * Missing Form import * Migrate InputControl * Migrate Checkbox * Move InputControl and uncomment * Fix small issues * inor fix * Fix import * Fix stuff
This commit is contained in:
parent
a28dfaf177
commit
f15593684a
@ -2,7 +2,7 @@ import React from 'react';
|
||||
import { GrafanaTheme } from '@grafana/data';
|
||||
import { css } from 'emotion';
|
||||
import { selectThemeVariant, stylesFactory, useTheme } from '../../themes';
|
||||
import Forms from '../Forms';
|
||||
import { Label } from '../Forms/Label';
|
||||
import { Icon } from '../Icon/Icon';
|
||||
|
||||
interface FieldConfigItemHeaderTitleProps {
|
||||
@ -24,7 +24,7 @@ export const FieldConfigItemHeaderTitle: React.FC<FieldConfigItemHeaderTitleProp
|
||||
return (
|
||||
<div className={!transparent ? styles.headerWrapper : ''}>
|
||||
<div className={styles.header}>
|
||||
<Forms.Label description={description}>{title}</Forms.Label>
|
||||
<Label description={description}>{title}</Label>
|
||||
<div className={styles.remove} onClick={() => onRemove()} aria-label="FieldConfigItemHeaderTitle remove button">
|
||||
<Icon name="trash-alt" />
|
||||
</div>
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Meta, Story, Preview, Props } from '@storybook/addon-docs/blocks';
|
||||
import { Checkbox } from './Checkbox';
|
||||
import { Meta, Story, Preview, Props } from "@storybook/addon-docs/blocks";
|
||||
import { Checkbox } from "./Checkbox";
|
||||
|
||||
<Meta title="MDX|Checkbox" component={Checkbox} />
|
||||
|
||||
@ -10,9 +10,9 @@ import { Checkbox } from './Checkbox';
|
||||
```jsx
|
||||
import { Forms } from '@grafana/ui';
|
||||
|
||||
<Forms.Checkbox value={true|false} label={...} description={...} onChange={...} />
|
||||
<Checkbox value={true|false} label={...} description={...} onChange={...} />
|
||||
```
|
||||
|
||||
### Props
|
||||
<Props of={Checkbox} />
|
||||
|
||||
<Props of={Checkbox} />
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Meta, Story, Preview, Props } from '@storybook/addon-docs/blocks';
|
||||
import { Field } from './Field';
|
||||
import { Meta, Story, Preview, Props } from "@storybook/addon-docs/blocks";
|
||||
import { Field } from "./Field";
|
||||
|
||||
<Meta title="MDX|Field" component={Field} />
|
||||
|
||||
@ -12,11 +12,11 @@ import { Field } from './Field';
|
||||
```jsx
|
||||
import { Forms } from '@grafana/ui';
|
||||
|
||||
<Forms.Field label={...} description={...}>
|
||||
<Forms.Input id="userName" onChange={...}/>
|
||||
</Forms.Field>
|
||||
<Field label={...} description={...}>
|
||||
<Input id="userName" onChange={...}/>
|
||||
</Field>
|
||||
```
|
||||
|
||||
### Props
|
||||
<Props of={Field} />
|
||||
|
||||
<Props of={Field} />
|
||||
|
@ -23,18 +23,18 @@ const defaultUser: Partial<UserDTO> = {
|
||||
// ...
|
||||
}
|
||||
|
||||
<Forms.Form
|
||||
<Form
|
||||
defaultValues={defaultUser}
|
||||
onSubmit={async (user: UserDTO) => await createUser(user)}
|
||||
>{({register, errors}) => {
|
||||
return (
|
||||
<Forms.Field>
|
||||
<Field>
|
||||
<Forms.Input name="name" ref={register}/>
|
||||
<Forms.Input type="email" name="email" ref={register({required: true})}/>
|
||||
<Button type="submit">Create User</Button>
|
||||
</Forms.Field>
|
||||
</Field>
|
||||
)
|
||||
}}</Forms.Form>
|
||||
}}</Form>
|
||||
```
|
||||
|
||||
### Form API
|
||||
@ -66,28 +66,28 @@ See [Validation](#validation) for examples on validation and validation rules.
|
||||
|
||||
#### `errors`
|
||||
|
||||
`errors` is an object that contains validation errors of the form. To show error message and invalid input indication in your form, wrap input element with `<Forms.Field ...>` component and pass `invalid` and `error` props to it:
|
||||
`errors` is an object that contains validation errors of the form. To show error message and invalid input indication in your form, wrap input element with `<Field ...>` component and pass `invalid` and `error` props to it:
|
||||
|
||||
```jsx
|
||||
<Forms.Field label="Name" invalid={!!errors.name} error="Name is required">
|
||||
<Field label="Name" invalid={!!errors.name} error="Name is required">
|
||||
<Forms.Input name="name" ref={register({ required: true })} />
|
||||
</Forms.Field>
|
||||
</Field>
|
||||
```
|
||||
|
||||
#### `control`
|
||||
|
||||
By default `Form` component assumes form elements are uncontrolled (https://reactjs.org/docs/glossary.html#controlled-vs-uncontrolled-components).
|
||||
There are some components like `RadioButton` or `Select` that are controlled-only and require some extra work. To make
|
||||
them work with the form, you need to render those using `Forms.InputControl` component:
|
||||
them work with the form, you need to render those using `InputControl` component:
|
||||
|
||||
```jsx
|
||||
import { Forms } from '@grafana/ui';
|
||||
import { Form, Field, InputControl } from '@grafana/ui';
|
||||
|
||||
// render function
|
||||
<Forms.Form ...>{({register, errors, control}) => (
|
||||
<Form ...>{({register, errors, control}) => (
|
||||
<>
|
||||
<Field label="RadioButtonExample">
|
||||
<Forms.InputControl
|
||||
<InputControl
|
||||
{/* Render InputControl as controlled input (RadioButtonGroup) */}
|
||||
as={RadioButtonGroup}
|
||||
{/* Pass control exposed from Form render prop */}
|
||||
@ -98,7 +98,7 @@ import { Forms } from '@grafana/ui';
|
||||
</Field>
|
||||
|
||||
<Field label="SelectExample">
|
||||
<Forms.InputControl
|
||||
<InputControl
|
||||
{/* Render InputControl as controlled input (Select) */}
|
||||
as={Select}
|
||||
{/* Pass control exposed from Form render prop */}
|
||||
@ -109,10 +109,10 @@ import { Forms } from '@grafana/ui';
|
||||
</Field>
|
||||
</>
|
||||
)}
|
||||
</Forms.Form>
|
||||
</Form>
|
||||
```
|
||||
|
||||
Note that when using `Forms.InputControl`, it expects the name of the prop that handles input change to be called `onChange`.
|
||||
Note that when using `InputControl`, it expects the name of the prop that handles input change to be called `onChange`.
|
||||
If the property is named differently for any specific component, additional `onChangeName` prop has to be provided, specifying the name.
|
||||
Additionally, the `onChange` arguments passed as an array. Check [react-hook-form docs](https://react-hook-form.com/api/#Controller)
|
||||
for more prop options.
|
||||
@ -128,7 +128,7 @@ const onSelectChange = ([value]) => {
|
||||
}
|
||||
|
||||
<Field label="SelectExample">
|
||||
<Forms.InputControl
|
||||
<InputControl
|
||||
as={DashboardPicker}
|
||||
control={control}
|
||||
name="select"
|
||||
@ -160,7 +160,7 @@ const defaultValues: FormDto {
|
||||
isAdmin: false,
|
||||
}
|
||||
|
||||
<Forms.Form defaultValues={defaultValues} ...>{...}</Forms.Form>
|
||||
<Form defaultValues={defaultValues} ...>{...}</Form>
|
||||
```
|
||||
|
||||
```jsx
|
||||
@ -176,13 +176,13 @@ const defaultValues: FormDto {
|
||||
isAdmin: false,
|
||||
}
|
||||
|
||||
<Forms.Form ...>{
|
||||
<Form ...>{
|
||||
({register}) => (
|
||||
<>
|
||||
<Forms.Input defaultValue={default.name} name="name" ref={register} />
|
||||
</>
|
||||
)}
|
||||
</Forms.Form>
|
||||
</Form>
|
||||
```
|
||||
|
||||
### Validation
|
||||
@ -192,10 +192,10 @@ Validation can be performed either synchronously or asynchronously. What's impor
|
||||
#### Basic required example
|
||||
|
||||
```jsx
|
||||
<Forms.Form ...>{
|
||||
<Form ...>{
|
||||
({register, errors}) => (
|
||||
<>
|
||||
<Forms.Field invalid={!!errors.name} error={errors.name && 'Name is required'}
|
||||
<Field invalid={!!errors.name} error={errors.name && 'Name is required'}
|
||||
<Forms.Input
|
||||
defaultValue={default.name}
|
||||
name="name"
|
||||
@ -203,7 +203,7 @@ Validation can be performed either synchronously or asynchronously. What's impor
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</Forms.Form>
|
||||
</Form>
|
||||
```
|
||||
|
||||
#### Required with synchronous custom validation
|
||||
@ -211,10 +211,10 @@ Validation can be performed either synchronously or asynchronously. What's impor
|
||||
One important thing to note is that if you want to provide different error messages for different kind of validation errors you'll need to return a `string` instead of a `boolean`.
|
||||
|
||||
```jsx
|
||||
<Forms.Form ...>{
|
||||
<Form ...>{
|
||||
({register, errors}) => (
|
||||
<>
|
||||
<Forms.Field invalid={!!errors.name} error={errors.name?.message }
|
||||
<Field invalid={!!errors.name} error={errors.name?.message }
|
||||
<Forms.Input
|
||||
defaultValue={default.name}
|
||||
name="name"
|
||||
@ -227,7 +227,7 @@ One important thing to note is that if you want to provide different error messa
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</Forms.Form>
|
||||
</Form>
|
||||
```
|
||||
|
||||
#### Asynchronous validation
|
||||
@ -252,10 +252,10 @@ validateAsync = (newValue: string) => {
|
||||
```
|
||||
|
||||
```jsx
|
||||
<Forms.Form ...>{
|
||||
<Form ...>{
|
||||
({register, errors}) => (
|
||||
<>
|
||||
<Forms.Field invalid={!!errors.name} error={errors.name?.message}
|
||||
<Field invalid={!!errors.name} error={errors.name?.message}
|
||||
<Forms.Input
|
||||
defaultValue={default.name}
|
||||
name="name"
|
||||
@ -268,7 +268,7 @@ validateAsync = (newValue: string) => {
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</Forms.Form>
|
||||
</Form>
|
||||
```
|
||||
|
||||
### Props
|
||||
|
@ -12,7 +12,7 @@ import { Checkbox } from './Checkbox';
|
||||
|
||||
import { RadioButtonGroup } from './RadioButtonGroup/RadioButtonGroup';
|
||||
import { Select } from '../Select/Select';
|
||||
import Forms from './index';
|
||||
import { InputControl } from '../InputControl';
|
||||
import mdx from './Form.mdx';
|
||||
import { ValidateResult } from 'react-hook-form';
|
||||
import { boolean } from '@storybook/addon-knobs';
|
||||
@ -103,11 +103,11 @@ const renderForm = (defaultValues?: Partial<FormDTO>) => (
|
||||
</Field>
|
||||
|
||||
<Field label="RadioButton">
|
||||
<Forms.InputControl name="radio" control={control} options={selectOptions} as={RadioButtonGroup} />
|
||||
<InputControl name="radio" control={control} options={selectOptions} as={RadioButtonGroup} />
|
||||
</Field>
|
||||
|
||||
<Field label="Select" invalid={!!errors.select} error="Select is required">
|
||||
<Forms.InputControl
|
||||
<InputControl
|
||||
name="select"
|
||||
control={control}
|
||||
rules={{
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Meta, Story, Preview, Props } from '@storybook/addon-docs/blocks';
|
||||
import { RadioButtonGroup } from './RadioButtonGroup';
|
||||
import { Meta, Story, Preview, Props } from "@storybook/addon-docs/blocks";
|
||||
import { RadioButtonGroup } from "./RadioButtonGroup";
|
||||
|
||||
<Meta title="MDX|RadioButtonGroup" component={RadioButtonGroup} />
|
||||
|
||||
@ -12,9 +12,9 @@ Use `RadioButtonGroup` if there are up to four options available. Otherwise use
|
||||
### Usage
|
||||
|
||||
```jsx
|
||||
import { Forms } from '@grafana/ui';
|
||||
import { RadioButtonGroup } from '@grafana/ui';
|
||||
|
||||
<Forms.RadioButtonGroup options={...} value={...} onChange={...} />
|
||||
<RadioButtonGroup options={...} value={...} onChange={...} />
|
||||
```
|
||||
|
||||
#### Disabling options
|
||||
@ -33,7 +33,7 @@ const options = [
|
||||
const disabledOptions = ['prometheus', 'elastic'];
|
||||
|
||||
|
||||
<Forms.RadioButtonGroup
|
||||
<RadioButtonGroup
|
||||
options={options}
|
||||
disabledOptions={disabledOptions}
|
||||
value={...}
|
||||
|
@ -1,4 +1,3 @@
|
||||
import { Controller as InputControl } from 'react-hook-form';
|
||||
import { getFormStyles } from './getFormStyles';
|
||||
import { Label } from './Label';
|
||||
import { RadioButtonGroup } from './RadioButtonGroup/RadioButtonGroup';
|
||||
@ -6,7 +5,7 @@ import { Form } from './Form';
|
||||
import { Field } from './Field';
|
||||
import { Legend } from './Legend';
|
||||
import { Checkbox } from './Checkbox';
|
||||
import { TextArea } from '../TextArea/TextArea';
|
||||
import { InputControl } from '../InputControl';
|
||||
|
||||
const Forms = {
|
||||
RadioButtonGroup,
|
||||
@ -17,7 +16,6 @@ const Forms = {
|
||||
InputControl,
|
||||
Checkbox,
|
||||
Legend,
|
||||
TextArea,
|
||||
};
|
||||
|
||||
export default Forms;
|
||||
|
1
packages/grafana-ui/src/components/InputControl.tsx
Normal file
1
packages/grafana-ui/src/components/InputControl.tsx
Normal file
@ -0,0 +1 @@
|
||||
export { Controller as InputControl } from 'react-hook-form';
|
@ -3,7 +3,7 @@ import { TIME_FORMAT, TimeZone, isDateTime, TimeRange, DateTime, dateMath } from
|
||||
import { stringToDateTimeType, isValidTimeString } from '../time';
|
||||
import { mapStringsToTimeRange } from './mapper';
|
||||
import { TimePickerCalendar } from './TimePickerCalendar';
|
||||
import Forms from '../../Forms';
|
||||
import { Field } from '../../Forms/Field';
|
||||
import { Input } from '../../Input/Input';
|
||||
import { Button } from '../../Button';
|
||||
|
||||
@ -66,7 +66,7 @@ export const TimeRangeForm: React.FC<Props> = props => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<Forms.Field label="From" invalid={from.invalid} error={errorMessage}>
|
||||
<Field label="From" invalid={from.invalid} error={errorMessage}>
|
||||
<Input
|
||||
onClick={event => event.stopPropagation()}
|
||||
onFocus={onFocus}
|
||||
@ -74,8 +74,8 @@ export const TimeRangeForm: React.FC<Props> = props => {
|
||||
addonAfter={icon}
|
||||
value={from.value}
|
||||
/>
|
||||
</Forms.Field>
|
||||
<Forms.Field label="To" invalid={to.invalid} error={errorMessage}>
|
||||
</Field>
|
||||
<Field label="To" invalid={to.invalid} error={errorMessage}>
|
||||
<Input
|
||||
onClick={event => event.stopPropagation()}
|
||||
onFocus={onFocus}
|
||||
@ -83,7 +83,7 @@ export const TimeRangeForm: React.FC<Props> = props => {
|
||||
addonAfter={icon}
|
||||
value={to.value}
|
||||
/>
|
||||
</Forms.Field>
|
||||
</Field>
|
||||
<Button onClick={onApply}>Apply time range</Button>
|
||||
|
||||
<TimePickerCalendar
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React, { ChangeEvent } from 'react';
|
||||
import { HorizontalGroup } from '../Layout/Layout';
|
||||
import { Select } from '../index';
|
||||
import Forms from '../Forms';
|
||||
import { Field } from '../Forms/Field';
|
||||
import { Input } from '../Input/Input';
|
||||
import { MappingType, RangeMap, ValueMap, ValueMapping } from '@grafana/data';
|
||||
import * as styleMixins from '../../themes/mixins';
|
||||
@ -48,30 +48,30 @@ export const MappingRow: React.FC<Props> = ({ valueMapping, updateValueMapping,
|
||||
return (
|
||||
<>
|
||||
<HorizontalGroup>
|
||||
<Forms.Field label="From">
|
||||
<Field label="From">
|
||||
<Input type="number" defaultValue={(valueMapping as RangeMap).from!} onBlur={onMappingFromChange} />
|
||||
</Forms.Field>
|
||||
<Forms.Field label="To">
|
||||
</Field>
|
||||
<Field label="To">
|
||||
<Input type="number" defaultValue={(valueMapping as RangeMap).to} onBlur={onMappingToChange} />
|
||||
</Forms.Field>
|
||||
</Field>
|
||||
</HorizontalGroup>
|
||||
|
||||
<Forms.Field label="Text">
|
||||
<Field label="Text">
|
||||
<Input defaultValue={valueMapping.text} onBlur={onMappingTextChange} />
|
||||
</Forms.Field>
|
||||
</Field>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Forms.Field label="Value">
|
||||
<Field label="Value">
|
||||
<Input type="number" defaultValue={(valueMapping as ValueMap).value} onBlur={onMappingValueChange} />
|
||||
</Forms.Field>
|
||||
</Field>
|
||||
|
||||
<Forms.Field label="Text">
|
||||
<Field label="Text">
|
||||
<Input defaultValue={valueMapping.text} onBlur={onMappingTextChange} />
|
||||
</Forms.Field>
|
||||
</Field>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
@ -124,9 +124,16 @@ export { FieldConfigItemHeaderTitle } from './FieldConfigs/FieldConfigItemHeader
|
||||
|
||||
// Next-gen forms
|
||||
export { default as Forms } from './Forms';
|
||||
export { Form } from './Forms/Form';
|
||||
export { InputControl } from './InputControl';
|
||||
export * from './Button';
|
||||
export { ValuePicker } from './ValuePicker/ValuePicker';
|
||||
export { fieldMatchersUI } from './MatchersUI/fieldMatchersUI';
|
||||
export { getFormStyles } from './Forms/getFormStyles';
|
||||
|
||||
export { Label } from './Forms/Label';
|
||||
export { Field } from './Forms/Field';
|
||||
export { Legend } from './Forms/Legend';
|
||||
|
||||
export { default as resetSelectStyles } from './Select/resetSelectStyles';
|
||||
export * from './Select/Select';
|
||||
@ -137,6 +144,7 @@ export { RadioButtonGroup } from './Forms/RadioButtonGroup/RadioButtonGroup';
|
||||
|
||||
export { Input } from './Input/Input';
|
||||
export { Switch } from './Forms/Switch';
|
||||
export { Checkbox } from './Forms/Checkbox';
|
||||
export { TextArea } from './TextArea/TextArea';
|
||||
|
||||
// Legacy forms
|
||||
|
@ -19,7 +19,7 @@ import {
|
||||
valueMappingsOverrideProcessor,
|
||||
ThresholdsMode,
|
||||
} from '@grafana/data';
|
||||
import { NumberValueEditor, Forms, StringValueEditor, Select } from '../components';
|
||||
import { NumberValueEditor, RadioButtonGroup, StringValueEditor, Select } from '../components';
|
||||
import { Switch } from '../components/Forms/Switch';
|
||||
import { ValueMappingsValueEditor } from '../components/OptionsUI/mappings';
|
||||
import { ThresholdsValueEditor } from '../components/OptionsUI/thresholds';
|
||||
@ -248,7 +248,7 @@ export const getStandardOptionEditors = () => {
|
||||
id: 'radio',
|
||||
name: 'Radio',
|
||||
description: 'Allows option selection',
|
||||
editor: props => <Forms.RadioButtonGroup {...props} options={props.item.settings?.options} fullWidth />,
|
||||
editor: props => <RadioButtonGroup {...props} options={props.item.settings?.options} fullWidth />,
|
||||
};
|
||||
|
||||
const unit: StandardEditorsRegistryItem<string> = {
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React, { useCallback } from 'react';
|
||||
import { hot } from 'react-hot-loader';
|
||||
import { connect } from 'react-redux';
|
||||
import { Forms, Button, Input } from '@grafana/ui';
|
||||
import { Form, Button, Input, Field } from '@grafana/ui';
|
||||
import { NavModel } from '@grafana/data';
|
||||
import { getBackendSrv } from '@grafana/runtime';
|
||||
import { StoreState } from '../../types';
|
||||
@ -32,22 +32,22 @@ const UserCreatePage: React.FC<UserCreatePageProps> = ({ navModel, updateLocatio
|
||||
<Page navModel={navModel}>
|
||||
<Page.Contents>
|
||||
<h1>Add new user</h1>
|
||||
<Forms.Form onSubmit={onSubmit} validateOn="onBlur">
|
||||
<Form onSubmit={onSubmit} validateOn="onBlur">
|
||||
{({ register, errors }) => {
|
||||
return (
|
||||
<>
|
||||
<Forms.Field label="Name" required invalid={!!errors.name} error={!!errors.name && 'Name is required'}>
|
||||
<Field label="Name" required invalid={!!errors.name} error={!!errors.name && 'Name is required'}>
|
||||
<Input name="name" size="md" ref={register({ required: true })} />
|
||||
</Forms.Field>
|
||||
</Field>
|
||||
|
||||
<Forms.Field label="E-mail">
|
||||
<Field label="E-mail">
|
||||
<Input name="email" size="md" ref={register} />
|
||||
</Forms.Field>
|
||||
</Field>
|
||||
|
||||
<Forms.Field label="Username">
|
||||
<Field label="Username">
|
||||
<Input name="login" size="md" ref={register} />
|
||||
</Forms.Field>
|
||||
<Forms.Field
|
||||
</Field>
|
||||
<Field
|
||||
label="Password"
|
||||
required
|
||||
invalid={!!errors.password}
|
||||
@ -61,12 +61,12 @@ const UserCreatePage: React.FC<UserCreatePageProps> = ({ navModel, updateLocatio
|
||||
validate: value => value.trim() !== '' && value.length >= 4,
|
||||
})}
|
||||
/>
|
||||
</Forms.Field>
|
||||
</Field>
|
||||
<Button type="submit">Create user</Button>
|
||||
</>
|
||||
);
|
||||
}}
|
||||
</Forms.Form>
|
||||
</Form>
|
||||
</Page.Contents>
|
||||
</Page>
|
||||
);
|
||||
|
@ -7,9 +7,9 @@ import {
|
||||
withTheme,
|
||||
ConfirmButton,
|
||||
Button,
|
||||
Forms,
|
||||
HorizontalGroup,
|
||||
Container,
|
||||
Field,
|
||||
} from '@grafana/ui';
|
||||
import { GrafanaTheme } from '@grafana/data';
|
||||
import { UserOrg, Organization, OrgRole } from 'app/types';
|
||||
@ -225,12 +225,12 @@ export class AddToOrgModal extends PureComponent<AddToOrgModalProps, AddToOrgMod
|
||||
|
||||
return (
|
||||
<Modal className={styles.modal} title="Add to an organization" isOpen={isOpen} onDismiss={this.onCancel}>
|
||||
<Forms.Field label="Organisation">
|
||||
<Field label="Organisation">
|
||||
<OrgPicker onSelected={this.onOrgSelect} />
|
||||
</Forms.Field>
|
||||
<Forms.Field label="Role">
|
||||
</Field>
|
||||
<Field label="Role">
|
||||
<OrgRolePicker value={role} onChange={this.onOrgRoleChange} />
|
||||
</Forms.Field>
|
||||
</Field>
|
||||
<Container padding="md">
|
||||
<HorizontalGroup spacing="md" justify="center">
|
||||
<Button variant="primary" onClick={this.onAddUserToOrg}>
|
||||
|
@ -8,7 +8,7 @@ import {
|
||||
PanelPlugin,
|
||||
SelectableValue,
|
||||
} from '@grafana/data';
|
||||
import { Forms, fieldMatchersUI, ValuePicker, useTheme } from '@grafana/ui';
|
||||
import { fieldMatchersUI, ValuePicker, useTheme, Label, Field } from '@grafana/ui';
|
||||
import { getDataLinksVariableSuggestions } from '../../../panel/panellinks/link_srv';
|
||||
import { OverrideEditor } from './OverrideEditor';
|
||||
import { css } from 'emotion';
|
||||
@ -156,13 +156,13 @@ export const DefaultFieldConfigEditor: React.FC<Props> = ({ data, onChange, conf
|
||||
: (defaults as any)[item.path];
|
||||
|
||||
const label = (
|
||||
<Forms.Label description={item.description} category={item.category?.slice(1)}>
|
||||
<Label description={item.description} category={item.category?.slice(1)}>
|
||||
{item.name}
|
||||
</Forms.Label>
|
||||
</Label>
|
||||
);
|
||||
|
||||
return (
|
||||
<Forms.Field label={label} key={`${item.id}/${item.isCustom}`}>
|
||||
<Field label={label} key={`${item.id}/${item.isCustom}`}>
|
||||
<item.editor
|
||||
item={item}
|
||||
value={value}
|
||||
@ -172,7 +172,7 @@ export const DefaultFieldConfigEditor: React.FC<Props> = ({ data, onChange, conf
|
||||
getSuggestions: (scope?: VariableSuggestionsScope) => getDataLinksVariableSuggestions(data, scope),
|
||||
}}
|
||||
/>
|
||||
</Forms.Field>
|
||||
</Field>
|
||||
);
|
||||
},
|
||||
[config]
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import { FieldConfigSource, GrafanaTheme, PanelData, PanelPlugin } from '@grafana/data';
|
||||
import { Button, stylesFactory, Icon, Forms } from '@grafana/ui';
|
||||
import { Button, stylesFactory, Icon, RadioButtonGroup } from '@grafana/ui';
|
||||
import { css, cx } from 'emotion';
|
||||
import config from 'app/core/config';
|
||||
import AutoSizer from 'react-virtualized-auto-sizer';
|
||||
@ -209,7 +209,7 @@ export class PanelEditorUnconnected extends PureComponent<Props> {
|
||||
{this.renderTemplateVariables(styles)}
|
||||
<div className="flex-grow-1" />
|
||||
<div className={styles.toolbarItem}>
|
||||
<Forms.RadioButtonGroup value={uiState.mode} options={displayModes} onChange={this.onDiplayModeChange} />
|
||||
<RadioButtonGroup value={uiState.mode} options={displayModes} onChange={this.onDiplayModeChange} />
|
||||
</div>
|
||||
<div className={styles.toolbarItem}>
|
||||
<DashNavTimeControls dashboard={dashboard} location={location} updateLocation={updateLocation} />
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React, { useMemo } from 'react';
|
||||
import { PanelOptionsEditorItem, PanelPlugin } from '@grafana/data';
|
||||
import { set as lodashSet, get as lodashGet } from 'lodash';
|
||||
import { Forms } from '@grafana/ui';
|
||||
import { Label, Field } from '@grafana/ui';
|
||||
import groupBy from 'lodash/groupBy';
|
||||
import { OptionsGroup } from './OptionsGroup';
|
||||
|
||||
@ -33,18 +33,18 @@ export const PanelOptionsEditor: React.FC<PanelOptionsEditorProps<any>> = ({ plu
|
||||
}
|
||||
|
||||
const label = (
|
||||
<Forms.Label description={e.description} category={e.category?.slice(1)}>
|
||||
<Label description={e.description} category={e.category?.slice(1)}>
|
||||
{e.name}
|
||||
</Forms.Label>
|
||||
</Label>
|
||||
);
|
||||
return (
|
||||
<Forms.Field label={label} key={`${e.id}/${j}`}>
|
||||
<Field label={label} key={`${e.id}/${j}`}>
|
||||
<e.editor
|
||||
value={lodashGet(options, e.path)}
|
||||
onChange={value => onOptionChange(e.path, value)}
|
||||
item={e}
|
||||
/>
|
||||
</Forms.Field>
|
||||
</Field>
|
||||
);
|
||||
})
|
||||
.filter(e => e !== null);
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React, { FC, useMemo } from 'react';
|
||||
import { PanelModel, DashboardModel } from '../../state';
|
||||
import { SelectableValue, PanelPlugin, FieldConfigSource, PanelData } from '@grafana/data';
|
||||
import { Forms, Switch, Select, DataLinksInlineEditor, Input, TextArea } from '@grafana/ui';
|
||||
import { Switch, Select, DataLinksInlineEditor, Input, TextArea, RadioButtonGroup, Field } from '@grafana/ui';
|
||||
import { OptionsGroup } from './OptionsGroup';
|
||||
import { getPanelLinksVariableSuggestions } from '../../../panel/panellinks/link_srv';
|
||||
import { getVariables } from '../../../variables/state/selectors';
|
||||
@ -41,18 +41,18 @@ export const PanelOptionsTab: FC<Props> = ({
|
||||
// Fist common panel settings Title, description
|
||||
elements.push(
|
||||
<OptionsGroup title="Basic" key="basic settings">
|
||||
<Forms.Field label="Panel title">
|
||||
<Field label="Panel title">
|
||||
<Input defaultValue={panel.title} onBlur={e => onPanelConfigChange('title', e.currentTarget.value)} />
|
||||
</Forms.Field>
|
||||
<Forms.Field label="Description" description="Panel description supports markdown and links.">
|
||||
</Field>
|
||||
<Field label="Description" description="Panel description supports markdown and links.">
|
||||
<TextArea
|
||||
defaultValue={panel.description}
|
||||
onBlur={e => onPanelConfigChange('description', e.currentTarget.value)}
|
||||
/>
|
||||
</Forms.Field>
|
||||
<Forms.Field label="Transparent" description="Display panel without a background.">
|
||||
</Field>
|
||||
<Field label="Transparent" description="Display panel without a background.">
|
||||
<Switch value={panel.transparent} onChange={e => onPanelConfigChange('transparent', e.currentTarget.checked)} />
|
||||
</Forms.Field>
|
||||
</Field>
|
||||
</OptionsGroup>
|
||||
);
|
||||
|
||||
@ -101,7 +101,7 @@ export const PanelOptionsTab: FC<Props> = ({
|
||||
|
||||
elements.push(
|
||||
<OptionsGroup title="Panel repeats" key="panel repeats" defaultToClosed={true}>
|
||||
<Forms.Field
|
||||
<Field
|
||||
label="Repeat by variable"
|
||||
description="Repeat this panel for each value in the selected variable.
|
||||
This is not visible while in edit mode. You need to go back to dashboard and then update the variable or
|
||||
@ -112,25 +112,25 @@ export const PanelOptionsTab: FC<Props> = ({
|
||||
onChange={value => onPanelConfigChange('repeat', value.value)}
|
||||
options={variableOptions}
|
||||
/>
|
||||
</Forms.Field>
|
||||
</Field>
|
||||
{panel.repeat && (
|
||||
<Forms.Field label="Repeat direction">
|
||||
<Forms.RadioButtonGroup
|
||||
<Field label="Repeat direction">
|
||||
<RadioButtonGroup
|
||||
options={directionOptions}
|
||||
value={panel.repeatDirection || 'h'}
|
||||
onChange={value => onPanelConfigChange('repeatDirection', value)}
|
||||
/>
|
||||
</Forms.Field>
|
||||
</Field>
|
||||
)}
|
||||
|
||||
{panel.repeat && panel.repeatDirection === 'h' && (
|
||||
<Forms.Field label="Max per row">
|
||||
<Field label="Max per row">
|
||||
<Select
|
||||
options={maxPerRowOptions}
|
||||
value={panel.maxPerRow}
|
||||
onChange={value => onPanelConfigChange('maxPerRow', value.value)}
|
||||
/>
|
||||
</Forms.Field>
|
||||
</Field>
|
||||
)}
|
||||
</OptionsGroup>
|
||||
);
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { Button, Forms, HorizontalGroup, Input, Switch } from '@grafana/ui';
|
||||
import { Button, HorizontalGroup, Input, Switch, Form, Field, InputControl } from '@grafana/ui';
|
||||
import { DashboardModel, PanelModel } from 'app/features/dashboard/state';
|
||||
import { FolderPicker } from 'app/core/components/Select/FolderPicker';
|
||||
import { SaveDashboardFormProps } from '../types';
|
||||
@ -62,7 +62,7 @@ export const SaveDashboardAsForm: React.FC<SaveDashboardFormProps & { isNew?: bo
|
||||
};
|
||||
|
||||
return (
|
||||
<Forms.Form
|
||||
<Form
|
||||
defaultValues={defaultValues}
|
||||
onSubmit={async (data: SaveDashboardAsFormDTO) => {
|
||||
const clone = getSaveAsDashboardClone(dashboard);
|
||||
@ -86,7 +86,7 @@ export const SaveDashboardAsForm: React.FC<SaveDashboardFormProps & { isNew?: bo
|
||||
>
|
||||
{({ register, control, errors, getValues }) => (
|
||||
<>
|
||||
<Forms.Field label="Dashboard name" invalid={!!errors.title} error={errors.title?.message}>
|
||||
<Field label="Dashboard name" invalid={!!errors.title} error={errors.title?.message}>
|
||||
<Input
|
||||
name="title"
|
||||
ref={register({
|
||||
@ -95,9 +95,9 @@ export const SaveDashboardAsForm: React.FC<SaveDashboardFormProps & { isNew?: bo
|
||||
aria-label="Save dashboard title field"
|
||||
autoFocus
|
||||
/>
|
||||
</Forms.Field>
|
||||
<Forms.Field label="Folder">
|
||||
<Forms.InputControl
|
||||
</Field>
|
||||
<Field label="Folder">
|
||||
<InputControl
|
||||
as={FolderPicker}
|
||||
control={control}
|
||||
name="$folder"
|
||||
@ -107,10 +107,10 @@ export const SaveDashboardAsForm: React.FC<SaveDashboardFormProps & { isNew?: bo
|
||||
enableCreateNew
|
||||
useNewForms
|
||||
/>
|
||||
</Forms.Field>
|
||||
<Forms.Field label="Copy tags">
|
||||
</Field>
|
||||
<Field label="Copy tags">
|
||||
<Switch name="copyTags" ref={register} />
|
||||
</Forms.Field>
|
||||
</Field>
|
||||
<HorizontalGroup>
|
||||
<Button type="submit" aria-label="Save dashboard button">
|
||||
Save
|
||||
@ -121,6 +121,6 @@ export const SaveDashboardAsForm: React.FC<SaveDashboardFormProps & { isNew?: bo
|
||||
</HorizontalGroup>
|
||||
</>
|
||||
)}
|
||||
</Forms.Form>
|
||||
</Form>
|
||||
);
|
||||
};
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React, { useMemo } from 'react';
|
||||
|
||||
import { Forms, Button, HorizontalGroup, TextArea } from '@grafana/ui';
|
||||
import { Button, HorizontalGroup, TextArea, Form, Checkbox } from '@grafana/ui';
|
||||
import { e2e } from '@grafana/e2e';
|
||||
import { SaveDashboardFormProps } from '../types';
|
||||
|
||||
@ -15,7 +15,7 @@ export const SaveDashboardForm: React.FC<SaveDashboardFormProps> = ({ dashboard,
|
||||
const hasVariableChanged = useMemo(() => dashboard.hasVariableValuesChanged(), [dashboard]);
|
||||
|
||||
return (
|
||||
<Forms.Form
|
||||
<Form
|
||||
onSubmit={async (data: SaveDashboardFormDTO) => {
|
||||
const result = await onSubmit(dashboard.getSaveModelClone(data), data, dashboard);
|
||||
if (result.status === 'success') {
|
||||
@ -33,7 +33,7 @@ export const SaveDashboardForm: React.FC<SaveDashboardFormProps> = ({ dashboard,
|
||||
<>
|
||||
<div className="gf-form-group">
|
||||
{hasTimeChanged && (
|
||||
<Forms.Checkbox
|
||||
<Checkbox
|
||||
label="Save current time range as dashboard default"
|
||||
name="saveTimerange"
|
||||
ref={register}
|
||||
@ -41,7 +41,7 @@ export const SaveDashboardForm: React.FC<SaveDashboardFormProps> = ({ dashboard,
|
||||
/>
|
||||
)}
|
||||
{hasVariableChanged && (
|
||||
<Forms.Checkbox
|
||||
<Checkbox
|
||||
label="Save current variable values as dashboard default"
|
||||
name="saveVariables"
|
||||
ref={register}
|
||||
@ -63,6 +63,6 @@ export const SaveDashboardForm: React.FC<SaveDashboardFormProps> = ({ dashboard,
|
||||
</HorizontalGroup>
|
||||
</>
|
||||
)}
|
||||
</Forms.Form>
|
||||
</Form>
|
||||
);
|
||||
};
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { css } from 'emotion';
|
||||
import { stylesFactory, useTheme, Forms, Select, Button, Switch } from '@grafana/ui';
|
||||
import { stylesFactory, useTheme, Select, Button, Switch, Field } from '@grafana/ui';
|
||||
import { GrafanaTheme, AppEvents } from '@grafana/data';
|
||||
import appEvents from 'app/core/app_events';
|
||||
import { CoreEvents } from 'app/types';
|
||||
@ -73,7 +73,7 @@ export function RichHistorySettings(props: RichHistorySettingsProps) {
|
||||
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<Forms.Field
|
||||
<Field
|
||||
label="History time span"
|
||||
description="Select the period of time for which Grafana will save your query history"
|
||||
className="space-between"
|
||||
@ -81,19 +81,19 @@ export function RichHistorySettings(props: RichHistorySettingsProps) {
|
||||
<div className={styles.input}>
|
||||
<Select value={selectedOption} options={retentionPeriodOptions} onChange={onChangeRetentionPeriod}></Select>
|
||||
</div>
|
||||
</Forms.Field>
|
||||
<Forms.Field label="Default active tab" description=" " className="space-between">
|
||||
</Field>
|
||||
<Field label="Default active tab" description=" " className="space-between">
|
||||
<div className={styles.switch}>
|
||||
<Switch value={starredTabAsFirstTab} onChange={toggleStarredTabAsFirstTab}></Switch>
|
||||
<div className={styles.label}>Change the default active tab from “Query history” to “Starred”</div>
|
||||
</div>
|
||||
</Forms.Field>
|
||||
<Forms.Field label="Data source behaviour" description=" " className="space-between">
|
||||
</Field>
|
||||
<Field label="Data source behaviour" description=" " className="space-between">
|
||||
<div className={styles.switch}>
|
||||
<Switch value={activeDatasourceOnly} onChange={toggleactiveDatasourceOnly}></Switch>
|
||||
<div className={styles.label}>Only show queries for data source currently active in Explore</div>
|
||||
</div>
|
||||
</Forms.Field>
|
||||
</Field>
|
||||
<div
|
||||
className={css`
|
||||
font-weight: ${theme.typography.weight.bold};
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import { connect, MapDispatchToProps, MapStateToProps } from 'react-redux';
|
||||
import { NavModel } from '@grafana/data';
|
||||
import { Forms, Button, Input } from '@grafana/ui';
|
||||
import { Button, Input, Form, Field } from '@grafana/ui';
|
||||
import Page from 'app/core/components/Page/Page';
|
||||
import { createNewFolder } from '../state/actions';
|
||||
import { getNavModel } from 'app/core/selectors/navModel';
|
||||
@ -47,10 +47,10 @@ export class NewDashboardsFolder extends PureComponent<Props> {
|
||||
<Page navModel={this.props.navModel}>
|
||||
<Page.Contents>
|
||||
<h3>New Dashboard Folder</h3>
|
||||
<Forms.Form defaultValues={initialFormModel} onSubmit={this.onSubmit}>
|
||||
<Form defaultValues={initialFormModel} onSubmit={this.onSubmit}>
|
||||
{({ register, errors }) => (
|
||||
<>
|
||||
<Forms.Field
|
||||
<Field
|
||||
label="Folder name"
|
||||
invalid={!!errors.folderName}
|
||||
error={errors.folderName && errors.folderName.message}
|
||||
@ -62,11 +62,11 @@ export class NewDashboardsFolder extends PureComponent<Props> {
|
||||
validate: async v => await this.validateFolderName(v),
|
||||
})}
|
||||
/>
|
||||
</Forms.Field>
|
||||
</Field>
|
||||
<Button type="submit">Create</Button>
|
||||
</>
|
||||
)}
|
||||
</Forms.Form>
|
||||
</Form>
|
||||
</Page.Contents>
|
||||
</Page>
|
||||
);
|
||||
|
@ -2,7 +2,7 @@ import React, { FormEvent, PureComponent } from 'react';
|
||||
import { connect, MapDispatchToProps, MapStateToProps } from 'react-redux';
|
||||
import { css } from 'emotion';
|
||||
import { AppEvents, NavModel } from '@grafana/data';
|
||||
import { Button, Forms, stylesFactory, Input, TextArea } from '@grafana/ui';
|
||||
import { Button, stylesFactory, Input, TextArea, Field, Form, Legend } from '@grafana/ui';
|
||||
import Page from 'app/core/components/Page/Page';
|
||||
import { ImportDashboardOverview } from './components/ImportDashboardOverview';
|
||||
import { DashboardFileUpload } from './components/DashboardFileUpload';
|
||||
@ -80,13 +80,10 @@ class DashboardImportUnConnected extends PureComponent<Props> {
|
||||
<DashboardFileUpload onFileUpload={this.onFileUpload} />
|
||||
</div>
|
||||
<div className={styles.option}>
|
||||
<Forms.Legend>Import via grafana.com</Forms.Legend>
|
||||
<Forms.Form onSubmit={this.getGcomDashboard} defaultValues={{ gcomDashboard: '' }}>
|
||||
<Legend>Import via grafana.com</Legend>
|
||||
<Form onSubmit={this.getGcomDashboard} defaultValues={{ gcomDashboard: '' }}>
|
||||
{({ register, errors }) => (
|
||||
<Forms.Field
|
||||
invalid={!!errors.gcomDashboard}
|
||||
error={errors.gcomDashboard && errors.gcomDashboard.message}
|
||||
>
|
||||
<Field invalid={!!errors.gcomDashboard} error={errors.gcomDashboard && errors.gcomDashboard.message}>
|
||||
<Input
|
||||
size="md"
|
||||
name="gcomDashboard"
|
||||
@ -98,19 +95,16 @@ class DashboardImportUnConnected extends PureComponent<Props> {
|
||||
})}
|
||||
addonAfter={<Button type="submit">Load</Button>}
|
||||
/>
|
||||
</Forms.Field>
|
||||
</Field>
|
||||
)}
|
||||
</Forms.Form>
|
||||
</Form>
|
||||
</div>
|
||||
<div className={styles.option}>
|
||||
<Forms.Legend>Import via panel json</Forms.Legend>
|
||||
<Forms.Form onSubmit={this.getDashboardFromJson} defaultValues={{ dashboardJson: '' }}>
|
||||
<Legend>Import via panel json</Legend>
|
||||
<Form onSubmit={this.getDashboardFromJson} defaultValues={{ dashboardJson: '' }}>
|
||||
{({ register, errors }) => (
|
||||
<>
|
||||
<Forms.Field
|
||||
invalid={!!errors.dashboardJson}
|
||||
error={errors.dashboardJson && errors.dashboardJson.message}
|
||||
>
|
||||
<Field invalid={!!errors.dashboardJson} error={errors.dashboardJson && errors.dashboardJson.message}>
|
||||
<TextArea
|
||||
name="dashboardJson"
|
||||
ref={register({
|
||||
@ -119,11 +113,11 @@ class DashboardImportUnConnected extends PureComponent<Props> {
|
||||
})}
|
||||
rows={10}
|
||||
/>
|
||||
</Forms.Field>
|
||||
</Field>
|
||||
<Button type="submit">Load</Button>
|
||||
</>
|
||||
)}
|
||||
</Forms.Form>
|
||||
</Form>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React, { FC, FormEvent } from 'react';
|
||||
import { Forms, stylesFactory, useTheme } from '@grafana/ui';
|
||||
import { getFormStyles, stylesFactory, useTheme } from '@grafana/ui';
|
||||
import { GrafanaTheme } from '@grafana/data';
|
||||
import { css } from 'emotion';
|
||||
|
||||
@ -8,7 +8,7 @@ interface Props {
|
||||
}
|
||||
|
||||
const getStyles = stylesFactory((theme: GrafanaTheme) => {
|
||||
const buttonFormStyle = Forms.getFormStyles(theme, { variant: 'primary', invalid: false, size: 'md' }).button.button;
|
||||
const buttonFormStyle = getFormStyles(theme, { variant: 'primary', invalid: false, size: 'md' }).button.button;
|
||||
return {
|
||||
fileUpload: css`
|
||||
display: none;
|
||||
|
@ -1,5 +1,15 @@
|
||||
import React, { FC, useEffect, useState } from 'react';
|
||||
import { Button, Forms, FormAPI, FormsOnSubmit, HorizontalGroup, FormFieldErrors, Input } from '@grafana/ui';
|
||||
import {
|
||||
Button,
|
||||
Forms,
|
||||
FormAPI,
|
||||
FormsOnSubmit,
|
||||
HorizontalGroup,
|
||||
FormFieldErrors,
|
||||
Input,
|
||||
Field,
|
||||
InputControl,
|
||||
} from '@grafana/ui';
|
||||
import { FolderPicker } from 'app/core/components/Select/FolderPicker';
|
||||
import DataSourcePicker from 'app/core/components/Select/DataSourcePicker';
|
||||
import { DashboardInput, DashboardInputs, DataSourceInput, ImportDashboardDTO } from '../state/reducers';
|
||||
@ -42,7 +52,7 @@ export const ImportDashboardForm: FC<Props> = ({
|
||||
return (
|
||||
<>
|
||||
<Forms.Legend>Options</Forms.Legend>
|
||||
<Forms.Field label="Name" invalid={!!errors.title} error={errors.title && errors.title.message}>
|
||||
<Field label="Name" invalid={!!errors.title} error={errors.title && errors.title.message}>
|
||||
<Input
|
||||
name="title"
|
||||
size="md"
|
||||
@ -52,17 +62,17 @@ export const ImportDashboardForm: FC<Props> = ({
|
||||
validate: async (v: string) => await validateTitle(v, getValues().folderId),
|
||||
})}
|
||||
/>
|
||||
</Forms.Field>
|
||||
<Forms.Field label="Folder">
|
||||
<Forms.InputControl
|
||||
</Field>
|
||||
<Field label="Folder">
|
||||
<InputControl
|
||||
as={FolderPicker}
|
||||
name="folderId"
|
||||
useNewForms
|
||||
initialFolderId={initialFolderId}
|
||||
control={control}
|
||||
/>
|
||||
</Forms.Field>
|
||||
<Forms.Field
|
||||
</Field>
|
||||
<Field
|
||||
label="Unique identifier (uid)"
|
||||
description="The unique identifier (uid) of a dashboard can be used for uniquely identify a dashboard between multiple Grafana installs.
|
||||
The uid allows having consistent URL’s for accessing dashboards so changing the title of a dashboard will not break any
|
||||
@ -87,18 +97,18 @@ export const ImportDashboardForm: FC<Props> = ({
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
</Forms.Field>
|
||||
</Field>
|
||||
{inputs.dataSources &&
|
||||
inputs.dataSources.map((input: DataSourceInput, index: number) => {
|
||||
const dataSourceOption = `dataSources[${index}]`;
|
||||
return (
|
||||
<Forms.Field
|
||||
<Field
|
||||
label={input.label}
|
||||
key={dataSourceOption}
|
||||
invalid={errors.dataSources && !!errors.dataSources[index]}
|
||||
error={errors.dataSources && errors.dataSources[index] && 'A data source is required'}
|
||||
>
|
||||
<Forms.InputControl
|
||||
<InputControl
|
||||
as={DataSourcePicker}
|
||||
name={`${dataSourceOption}`}
|
||||
datasources={input.options}
|
||||
@ -106,14 +116,14 @@ export const ImportDashboardForm: FC<Props> = ({
|
||||
placeholder={input.info}
|
||||
rules={{ required: true }}
|
||||
/>
|
||||
</Forms.Field>
|
||||
</Field>
|
||||
);
|
||||
})}
|
||||
{inputs.constants &&
|
||||
inputs.constants.map((input: DashboardInput, index) => {
|
||||
const constantIndex = `constants[${index}]`;
|
||||
return (
|
||||
<Forms.Field
|
||||
<Field
|
||||
label={input.label}
|
||||
error={errors.constants && errors.constants[index] && `${input.label} needs a value`}
|
||||
invalid={errors.constants && !!errors.constants[index]}
|
||||
@ -125,7 +135,7 @@ export const ImportDashboardForm: FC<Props> = ({
|
||||
size="md"
|
||||
defaultValue={input.value}
|
||||
/>
|
||||
</Forms.Field>
|
||||
</Field>
|
||||
);
|
||||
})}
|
||||
<HorizontalGroup>
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import { dateTime } from '@grafana/data';
|
||||
import { Forms } from '@grafana/ui';
|
||||
import { Forms, Form } from '@grafana/ui';
|
||||
import { connect, MapDispatchToProps, MapStateToProps } from 'react-redux';
|
||||
import { ImportDashboardForm } from './ImportDashboardForm';
|
||||
import { resetDashboard, saveDashboard } from '../state/actions';
|
||||
@ -79,7 +79,7 @@ class ImportDashboardOverviewUnConnected extends PureComponent<Props, State> {
|
||||
</table>
|
||||
</div>
|
||||
)}
|
||||
<Forms.Form
|
||||
<Form
|
||||
onSubmit={this.onSubmit}
|
||||
defaultValues={{ ...dashboard, constants: [], dataSources: [], folderId }}
|
||||
validateOnMount
|
||||
@ -100,7 +100,7 @@ class ImportDashboardOverviewUnConnected extends PureComponent<Props, State> {
|
||||
initialFolderId={folderId}
|
||||
/>
|
||||
)}
|
||||
</Forms.Form>
|
||||
</Form>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React, { FC } from 'react';
|
||||
import { getBackendSrv } from '@grafana/runtime';
|
||||
import Page from 'app/core/components/Page/Page';
|
||||
import { Forms, Button, Input } from '@grafana/ui';
|
||||
import { Button, Input, Field, Form } from '@grafana/ui';
|
||||
import { getConfig } from 'app/core/config';
|
||||
import { StoreState } from 'app/types';
|
||||
import { hot } from 'react-hot-loader';
|
||||
@ -49,15 +49,11 @@ export const NewOrgPage: FC<PropsWithState> = ({ navModel }) => {
|
||||
deployments.{' '}
|
||||
</p>
|
||||
|
||||
<Forms.Form<CreateOrgFormDTO> onSubmit={createOrg}>
|
||||
<Form<CreateOrgFormDTO> onSubmit={createOrg}>
|
||||
{({ register, errors }) => {
|
||||
return (
|
||||
<>
|
||||
<Forms.Field
|
||||
label="Organization name"
|
||||
invalid={!!errors.name}
|
||||
error={errors.name && errors.name.message}
|
||||
>
|
||||
<Field label="Organization name" invalid={!!errors.name} error={errors.name && errors.name.message}>
|
||||
<Input
|
||||
size="md"
|
||||
placeholder="Org. name"
|
||||
@ -67,12 +63,12 @@ export const NewOrgPage: FC<PropsWithState> = ({ navModel }) => {
|
||||
validate: async orgName => await validateOrg(orgName),
|
||||
})}
|
||||
/>
|
||||
</Forms.Field>
|
||||
</Field>
|
||||
<Button type="submit">Create</Button>
|
||||
</>
|
||||
);
|
||||
}}
|
||||
</Forms.Form>
|
||||
</Form>
|
||||
</Page.Contents>
|
||||
</Page>
|
||||
);
|
||||
|
@ -1,5 +1,15 @@
|
||||
import React, { FC } from 'react';
|
||||
import { Forms, HorizontalGroup, Button, LinkButton, Input, Switch } from '@grafana/ui';
|
||||
import {
|
||||
HorizontalGroup,
|
||||
Button,
|
||||
LinkButton,
|
||||
Input,
|
||||
Switch,
|
||||
RadioButtonGroup,
|
||||
Form,
|
||||
Field,
|
||||
InputControl,
|
||||
} from '@grafana/ui';
|
||||
import { getConfig } from 'app/core/config';
|
||||
import { OrgRole } from 'app/types';
|
||||
import { getBackendSrv } from '@grafana/runtime';
|
||||
@ -45,26 +55,26 @@ export const UserInviteForm: FC<Props> = ({ updateLocation }) => {
|
||||
};
|
||||
|
||||
return (
|
||||
<Forms.Form defaultValues={defaultValues} onSubmit={onSubmit}>
|
||||
<Form defaultValues={defaultValues} onSubmit={onSubmit}>
|
||||
{({ register, control, errors }) => {
|
||||
return (
|
||||
<>
|
||||
<Forms.Field
|
||||
<Field
|
||||
invalid={!!errors.loginOrEmail}
|
||||
error={!!errors.loginOrEmail && 'Email or Username is required'}
|
||||
label="Email or Username"
|
||||
>
|
||||
<Input size="md" name="loginOrEmail" placeholder="email@example.com" ref={register({ required: true })} />
|
||||
</Forms.Field>
|
||||
<Forms.Field invalid={!!errors.name} label="Name">
|
||||
</Field>
|
||||
<Field invalid={!!errors.name} label="Name">
|
||||
<Input size="md" name="name" placeholder="(optional)" ref={register} />
|
||||
</Forms.Field>
|
||||
<Forms.Field invalid={!!errors.role} label="Role">
|
||||
<Forms.InputControl as={Forms.RadioButtonGroup} control={control} options={roles} name="role" />
|
||||
</Forms.Field>
|
||||
<Forms.Field invalid={!!errors.sendEmail} label="Send invite email">
|
||||
</Field>
|
||||
<Field invalid={!!errors.role} label="Role">
|
||||
<InputControl as={RadioButtonGroup} control={control} options={roles} name="role" />
|
||||
</Field>
|
||||
<Field invalid={!!errors.sendEmail} label="Send invite email">
|
||||
<Switch name="sendEmail" ref={register} />
|
||||
</Forms.Field>
|
||||
</Field>
|
||||
<HorizontalGroup>
|
||||
<Button type="submit">Submit</Button>
|
||||
<LinkButton href={assureBaseUrl(getConfig().appSubUrl + '/org/users')} variant="secondary">
|
||||
@ -74,7 +84,7 @@ export const UserInviteForm: FC<Props> = ({ updateLocation }) => {
|
||||
</>
|
||||
);
|
||||
}}
|
||||
</Forms.Form>
|
||||
</Form>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React, { FC } from 'react';
|
||||
import { Forms, Button, LinkButton, Input } from '@grafana/ui';
|
||||
import { Button, LinkButton, Input, Form, Field } from '@grafana/ui';
|
||||
import { css } from 'emotion';
|
||||
|
||||
import { getConfig } from 'app/core/config';
|
||||
@ -60,24 +60,24 @@ export const SignupForm: FC<Props> = props => {
|
||||
};
|
||||
|
||||
return (
|
||||
<Forms.Form defaultValues={defaultValues} onSubmit={onSubmit}>
|
||||
<Form defaultValues={defaultValues} onSubmit={onSubmit}>
|
||||
{({ register, errors }) => {
|
||||
return (
|
||||
<>
|
||||
{verifyEmailEnabled && (
|
||||
<Forms.Field label="Email verification code (sent to your email)">
|
||||
<Field label="Email verification code (sent to your email)">
|
||||
<Input name="code" size="md" ref={register} placeholder="Code" />
|
||||
</Forms.Field>
|
||||
</Field>
|
||||
)}
|
||||
{!autoAssignOrg && (
|
||||
<Forms.Field label="Org. name">
|
||||
<Field label="Org. name">
|
||||
<Input size="md" name="orgName" placeholder="Org. name" ref={register} />
|
||||
</Forms.Field>
|
||||
</Field>
|
||||
)}
|
||||
<Forms.Field label="Your name">
|
||||
<Field label="Your name">
|
||||
<Input size="md" name="name" placeholder="(optional)" ref={register} />
|
||||
</Forms.Field>
|
||||
<Forms.Field label="Email" invalid={!!errors.email} error={!!errors.email && errors.email.message}>
|
||||
</Field>
|
||||
<Field label="Email" invalid={!!errors.email} error={!!errors.email && errors.email.message}>
|
||||
<Input
|
||||
size="md"
|
||||
name="email"
|
||||
@ -91,12 +91,8 @@ export const SignupForm: FC<Props> = props => {
|
||||
},
|
||||
})}
|
||||
/>
|
||||
</Forms.Field>
|
||||
<Forms.Field
|
||||
label="Password"
|
||||
invalid={!!errors.password}
|
||||
error={!!errors.password && errors.password.message}
|
||||
>
|
||||
</Field>
|
||||
<Field label="Password" invalid={!!errors.password} error={!!errors.password && errors.password.message}>
|
||||
<Input
|
||||
size="md"
|
||||
name="password"
|
||||
@ -104,7 +100,7 @@ export const SignupForm: FC<Props> = props => {
|
||||
placeholder="Password"
|
||||
ref={register({ required: 'Password is required' })}
|
||||
/>
|
||||
</Forms.Field>
|
||||
</Field>
|
||||
|
||||
<Button type="submit">Submit</Button>
|
||||
<span className={buttonSpacing}>
|
||||
@ -115,6 +111,6 @@ export const SignupForm: FC<Props> = props => {
|
||||
</>
|
||||
);
|
||||
}}
|
||||
</Forms.Form>
|
||||
</Form>
|
||||
);
|
||||
};
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React, { FC, memo } from 'react';
|
||||
import { css } from 'emotion';
|
||||
import { Forms, stylesFactory } from '@grafana/ui';
|
||||
import { Checkbox, stylesFactory } from '@grafana/ui';
|
||||
|
||||
interface Props {
|
||||
checked?: boolean;
|
||||
@ -13,7 +13,7 @@ export const SearchCheckbox: FC<Props> = memo(({ onClick, checked = false, edita
|
||||
|
||||
return editable ? (
|
||||
<div onClick={onClick} className={styles.wrapper}>
|
||||
<Forms.Checkbox value={checked} />
|
||||
<Checkbox value={checked} />
|
||||
</div>
|
||||
) : null;
|
||||
});
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React, { FC } from 'react';
|
||||
import { css } from 'emotion';
|
||||
import { Button, Select, Forms, stylesFactory, useTheme, HorizontalGroup } from '@grafana/ui';
|
||||
import { Button, Select, Checkbox, stylesFactory, useTheme, HorizontalGroup } from '@grafana/ui';
|
||||
import { GrafanaTheme, SelectableValue } from '@grafana/data';
|
||||
|
||||
type onSelectChange = (value: SelectableValue) => void;
|
||||
@ -43,7 +43,7 @@ export const SearchResultsFilter: FC<Props> = ({
|
||||
|
||||
return (
|
||||
<div className={styles.wrapper}>
|
||||
<Forms.Checkbox value={allChecked} onChange={onSelectAllChanged} />
|
||||
<Checkbox value={allChecked} onChange={onSelectAllChanged} />
|
||||
{showActions ? (
|
||||
<HorizontalGroup spacing="md">
|
||||
<Button disabled={!canMove} onClick={moveTo} icon="exchange-alt" variant="secondary">
|
||||
|
@ -4,7 +4,7 @@ import { connect, MapStateToProps, MapDispatchToProps } from 'react-redux';
|
||||
import { StoreState } from 'app/types';
|
||||
import { updateLocation } from 'app/core/actions';
|
||||
import { UrlQueryValue, getBackendSrv } from '@grafana/runtime';
|
||||
import { Forms, Button, Input } from '@grafana/ui';
|
||||
import { Button, Input, Form, Field } from '@grafana/ui';
|
||||
import { useAsync } from 'react-use';
|
||||
import Page from 'app/core/components/Page/Page';
|
||||
import { contextSrv } from 'app/core/core';
|
||||
@ -69,10 +69,10 @@ const SingupInvitedPageUnconnected: FC<DispatchProps & ConnectedProps> = ({ code
|
||||
<br />
|
||||
Please complete the following and choose a password to accept your invitation and continue:
|
||||
</div>
|
||||
<Forms.Form defaultValues={initFormModel} onSubmit={onSubmit}>
|
||||
<Form defaultValues={initFormModel} onSubmit={onSubmit}>
|
||||
{({ register, errors }) => (
|
||||
<>
|
||||
<Forms.Field invalid={!!errors.email} error={!!errors.email && errors.email.message} label="Email">
|
||||
<Field invalid={!!errors.email} error={!!errors.email && errors.email.message} label="Email">
|
||||
<Input
|
||||
size="md"
|
||||
placeholder="email@example.com"
|
||||
@ -85,27 +85,19 @@ const SingupInvitedPageUnconnected: FC<DispatchProps & ConnectedProps> = ({ code
|
||||
},
|
||||
})}
|
||||
/>
|
||||
</Forms.Field>
|
||||
<Forms.Field invalid={!!errors.name} error={!!errors.name && errors.name.message} label="Name">
|
||||
</Field>
|
||||
<Field invalid={!!errors.name} error={!!errors.name && errors.name.message} label="Name">
|
||||
<Input size="md" placeholder="Name (optional)" name="name" ref={register} />
|
||||
</Forms.Field>
|
||||
<Forms.Field
|
||||
invalid={!!errors.username}
|
||||
error={!!errors.username && errors.username.message}
|
||||
label="Username"
|
||||
>
|
||||
</Field>
|
||||
<Field invalid={!!errors.username} error={!!errors.username && errors.username.message} label="Username">
|
||||
<Input
|
||||
size="md"
|
||||
placeholder="Username"
|
||||
name="username"
|
||||
ref={register({ required: 'Username is required' })}
|
||||
/>
|
||||
</Forms.Field>
|
||||
<Forms.Field
|
||||
invalid={!!errors.password}
|
||||
error={!!errors.password && errors.password.message}
|
||||
label="Password"
|
||||
>
|
||||
</Field>
|
||||
<Field invalid={!!errors.password} error={!!errors.password && errors.password.message} label="Password">
|
||||
<Input
|
||||
size="md"
|
||||
type="password"
|
||||
@ -113,12 +105,12 @@ const SingupInvitedPageUnconnected: FC<DispatchProps & ConnectedProps> = ({ code
|
||||
name="password"
|
||||
ref={register({ required: 'Password is required' })}
|
||||
/>
|
||||
</Forms.Field>
|
||||
</Field>
|
||||
|
||||
<Button type="submit">Sign Up</Button>
|
||||
</>
|
||||
)}
|
||||
</Forms.Form>
|
||||
</Form>
|
||||
</Page.Contents>
|
||||
</Page>
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user