[ILM] Reposition form toggles (#85143)
* merged toggleable field and described form component and moved toggle to left * moved all toggles to left, renamed DescribedFormField -> DescribedFormRow and added new ToggleFieldWithDescribedFormRow component * added new prop fieldNotices to render callouts in correct position on the left
This commit is contained in:
parent
213b934386
commit
fac1f1204d
11 changed files with 179 additions and 128 deletions
|
@ -1,33 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React, { FunctionComponent } from 'react';
|
||||
import { EuiDescribedFormGroup, EuiDescribedFormGroupProps } from '@elastic/eui';
|
||||
|
||||
import { ToggleableField, Props as ToggleableFieldProps } from './toggleable_field';
|
||||
|
||||
type Props = EuiDescribedFormGroupProps & {
|
||||
children: (() => JSX.Element) | JSX.Element | JSX.Element[] | undefined;
|
||||
switchProps?: Omit<ToggleableFieldProps, 'children'>;
|
||||
};
|
||||
|
||||
export const DescribedFormField: FunctionComponent<Props> = ({
|
||||
children,
|
||||
switchProps,
|
||||
...restDescribedFormProps
|
||||
}) => {
|
||||
return (
|
||||
<EuiDescribedFormGroup {...restDescribedFormProps}>
|
||||
{switchProps ? (
|
||||
<ToggleableField {...switchProps}>{children}</ToggleableField>
|
||||
) : typeof children === 'function' ? (
|
||||
children()
|
||||
) : (
|
||||
children
|
||||
)}
|
||||
</EuiDescribedFormGroup>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React, { FunctionComponent, useState } from 'react';
|
||||
import {
|
||||
EuiDescribedFormGroup,
|
||||
EuiDescribedFormGroupProps,
|
||||
EuiSwitchProps,
|
||||
EuiSwitch,
|
||||
EuiSpacer,
|
||||
} from '@elastic/eui';
|
||||
|
||||
export interface SwitchProps
|
||||
extends Omit<EuiSwitchProps, 'children' | 'checked' | 'value' | 'onChange'> {
|
||||
/**
|
||||
* use initialValue to specify an uncontrolled component
|
||||
*/
|
||||
initialValue?: boolean;
|
||||
|
||||
/**
|
||||
* checked and onChange together specify a controlled component
|
||||
*/
|
||||
checked?: boolean;
|
||||
onChange?: (nextValue: boolean) => void;
|
||||
}
|
||||
|
||||
export type Props = EuiDescribedFormGroupProps & {
|
||||
children: (() => JSX.Element) | JSX.Element | JSX.Element[] | undefined;
|
||||
|
||||
switchProps?: SwitchProps;
|
||||
|
||||
/**
|
||||
* Use this prop to pass down components that should be rendered below the toggle like
|
||||
* warnings or notices.
|
||||
*/
|
||||
fieldNotices?: React.ReactNode;
|
||||
};
|
||||
|
||||
export const DescribedFormRow: FunctionComponent<Props> = ({
|
||||
children,
|
||||
switchProps,
|
||||
description,
|
||||
fieldNotices,
|
||||
...restDescribedFormProps
|
||||
}) => {
|
||||
if (
|
||||
switchProps &&
|
||||
!(typeof switchProps.checked === 'boolean' || typeof switchProps.initialValue === 'boolean')
|
||||
) {
|
||||
throw new Error('Must specify controlled, uncontrolled component. See SwitchProps interface!');
|
||||
}
|
||||
const [uncontrolledIsContentVisible, setUncontrolledIsContentVisible] = useState<boolean>(
|
||||
() => switchProps?.initialValue ?? false
|
||||
);
|
||||
const isContentVisible = Boolean(switchProps?.checked ?? uncontrolledIsContentVisible);
|
||||
|
||||
const renderToggle = () => {
|
||||
if (!switchProps) {
|
||||
return null;
|
||||
}
|
||||
const { onChange, checked, initialValue, ...restSwitchProps } = switchProps;
|
||||
|
||||
return (
|
||||
<EuiSwitch
|
||||
{...restSwitchProps}
|
||||
checked={isContentVisible}
|
||||
onChange={(e) => {
|
||||
const nextValue = e.target.checked;
|
||||
setUncontrolledIsContentVisible(nextValue);
|
||||
if (onChange) {
|
||||
onChange(nextValue);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
return (
|
||||
<EuiDescribedFormGroup
|
||||
{...restDescribedFormProps}
|
||||
description={
|
||||
<>
|
||||
{description}
|
||||
<EuiSpacer size="m" />
|
||||
{renderToggle()}
|
||||
{fieldNotices}
|
||||
</>
|
||||
}
|
||||
>
|
||||
{isContentVisible ? (typeof children === 'function' ? children() : children) : null}
|
||||
</EuiDescribedFormGroup>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,9 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
export { DescribedFormRow } from './described_form_row';
|
||||
|
||||
export { ToggleFieldWithDescribedFormRow } from './toggle_field_with_described_form_row';
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
import React, { FunctionComponent } from 'react';
|
||||
|
||||
import { UseField } from '../../../../../shared_imports';
|
||||
|
||||
import {
|
||||
DescribedFormRow,
|
||||
Props as DescribedFormRowProps,
|
||||
SwitchProps,
|
||||
} from './described_form_row';
|
||||
|
||||
type Props = Omit<DescribedFormRowProps, 'switchProps'> & {
|
||||
switchProps: Omit<SwitchProps, 'label'> & { path: string };
|
||||
};
|
||||
|
||||
export const ToggleFieldWithDescribedFormRow: FunctionComponent<Props> = ({
|
||||
switchProps,
|
||||
...passThroughProps
|
||||
}) => (
|
||||
<UseField<boolean> path={switchProps.path}>
|
||||
{(field) => {
|
||||
return (
|
||||
<DescribedFormRow
|
||||
{...passThroughProps}
|
||||
switchProps={{
|
||||
...switchProps,
|
||||
label: field.label,
|
||||
checked: field.value,
|
||||
onChange: field.setValue,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
</UseField>
|
||||
);
|
|
@ -9,7 +9,7 @@ export { ErrableFormRow } from './form_errors';
|
|||
export { LearnMoreLink } from './learn_more_link';
|
||||
export { OptionalLabel } from './optional_label';
|
||||
export { PolicyJsonFlyout } from './policy_json_flyout';
|
||||
export { DescribedFormField } from './described_form_field';
|
||||
export { DescribedFormRow, ToggleFieldWithDescribedFormRow } from './described_form_row';
|
||||
export { FieldLoadingError } from './field_loading_error';
|
||||
|
||||
export * from './phases';
|
||||
|
|
|
@ -18,7 +18,12 @@ import { useFormData, UseField, ToggleField, NumericField } from '../../../../..
|
|||
import { useEditPolicyContext } from '../../../edit_policy_context';
|
||||
import { useConfigurationIssues } from '../../../form';
|
||||
|
||||
import { LearnMoreLink, ActiveBadge, DescribedFormField } from '../../';
|
||||
import {
|
||||
LearnMoreLink,
|
||||
ActiveBadge,
|
||||
DescribedFormRow,
|
||||
ToggleFieldWithDescribedFormRow,
|
||||
} from '../../';
|
||||
|
||||
import {
|
||||
MinAgeInputField,
|
||||
|
@ -115,7 +120,7 @@ export const ColdPhase: FunctionComponent = () => {
|
|||
{
|
||||
/* Replicas section */
|
||||
showReplicasField && (
|
||||
<DescribedFormField
|
||||
<DescribedFormRow
|
||||
title={
|
||||
<h3>
|
||||
{i18n.translate('xpack.indexLifecycleMgmt.coldPhase.replicasTitle', {
|
||||
|
@ -153,13 +158,13 @@ export const ColdPhase: FunctionComponent = () => {
|
|||
},
|
||||
}}
|
||||
/>
|
||||
</DescribedFormField>
|
||||
</DescribedFormRow>
|
||||
)
|
||||
}
|
||||
|
||||
{/* Freeze section */}
|
||||
{!isUsingSearchableSnapshotInHotPhase && (
|
||||
<EuiDescribedFormGroup
|
||||
<ToggleFieldWithDescribedFormRow
|
||||
title={
|
||||
<h3>
|
||||
<FormattedMessage
|
||||
|
@ -179,17 +184,13 @@ export const ColdPhase: FunctionComponent = () => {
|
|||
}
|
||||
fullWidth
|
||||
titleSize="xs"
|
||||
switchProps={{
|
||||
'data-test-subj': 'freezeSwitch',
|
||||
path: '_meta.cold.freezeEnabled',
|
||||
}}
|
||||
>
|
||||
<UseField
|
||||
path="_meta.cold.freezeEnabled"
|
||||
component={ToggleField}
|
||||
componentProps={{
|
||||
euiFieldProps: {
|
||||
'data-test-subj': 'freezeSwitch',
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</EuiDescribedFormGroup>
|
||||
<div />
|
||||
</ToggleFieldWithDescribedFormRow>
|
||||
)}
|
||||
{/* Data tier allocation section */}
|
||||
<DataTierAllocationField
|
||||
|
|
|
@ -20,13 +20,7 @@ import {
|
|||
|
||||
import { Phases } from '../../../../../../../common/types';
|
||||
|
||||
import {
|
||||
useFormData,
|
||||
UseField,
|
||||
SelectField,
|
||||
ToggleField,
|
||||
NumericField,
|
||||
} from '../../../../../../shared_imports';
|
||||
import { useFormData, UseField, SelectField, NumericField } from '../../../../../../shared_imports';
|
||||
|
||||
import { i18nTexts } from '../../../i18n_texts';
|
||||
|
||||
|
@ -36,7 +30,7 @@ import { useEditPolicyContext } from '../../../edit_policy_context';
|
|||
|
||||
import { ROLLOVER_FORM_PATHS } from '../../../constants';
|
||||
|
||||
import { LearnMoreLink, ActiveBadge, DescribedFormField } from '../../';
|
||||
import { LearnMoreLink, ActiveBadge, ToggleFieldWithDescribedFormRow } from '../../';
|
||||
|
||||
import {
|
||||
ForcemergeField,
|
||||
|
@ -95,7 +89,7 @@ export const HotPhase: FunctionComponent = () => {
|
|||
})}
|
||||
paddingSize="m"
|
||||
>
|
||||
<DescribedFormField
|
||||
<ToggleFieldWithDescribedFormRow
|
||||
title={
|
||||
<h3>
|
||||
{i18n.translate('xpack.indexLifecycleMgmt.hotPhase.rolloverFieldTitle', {
|
||||
|
@ -123,19 +117,12 @@ export const HotPhase: FunctionComponent = () => {
|
|||
</p>
|
||||
</EuiTextColor>
|
||||
}
|
||||
switchProps={{
|
||||
path: '_meta.hot.useRollover',
|
||||
'data-test-subj': 'rolloverSwitch',
|
||||
}}
|
||||
fullWidth
|
||||
>
|
||||
<UseField<boolean>
|
||||
key="_meta.hot.useRollover"
|
||||
path="_meta.hot.useRollover"
|
||||
component={ToggleField}
|
||||
componentProps={{
|
||||
fullWidth: false,
|
||||
euiFieldProps: {
|
||||
'data-test-subj': 'rolloverSwitch',
|
||||
},
|
||||
}}
|
||||
/>
|
||||
{isRolloverEnabled && (
|
||||
<>
|
||||
<EuiSpacer size="m" />
|
||||
|
@ -246,7 +233,7 @@ export const HotPhase: FunctionComponent = () => {
|
|||
</EuiFlexGroup>
|
||||
</>
|
||||
)}
|
||||
</DescribedFormField>
|
||||
</ToggleFieldWithDescribedFormRow>
|
||||
{license.canUseSearchableSnapshot() && <SearchableSnapshotField phase="hot" />}
|
||||
{isRolloverEnabled && !isUsingSearchableSnapshotInHotPhase && (
|
||||
<ForcemergeField phase="hot" />
|
||||
|
|
|
@ -14,7 +14,7 @@ import { i18nTexts } from '../../../i18n_texts';
|
|||
|
||||
import { useEditPolicyContext } from '../../../edit_policy_context';
|
||||
|
||||
import { LearnMoreLink, DescribedFormField } from '../../';
|
||||
import { LearnMoreLink, DescribedFormRow } from '../../';
|
||||
|
||||
interface Props {
|
||||
phase: 'hot' | 'warm';
|
||||
|
@ -28,7 +28,7 @@ export const ForcemergeField: React.FunctionComponent<Props> = ({ phase }) => {
|
|||
}, [policy, phase]);
|
||||
|
||||
return (
|
||||
<DescribedFormField
|
||||
<DescribedFormRow
|
||||
title={
|
||||
<h3>
|
||||
<FormattedMessage
|
||||
|
@ -82,6 +82,6 @@ export const ForcemergeField: React.FunctionComponent<Props> = ({ phase }) => {
|
|||
}}
|
||||
/>
|
||||
</div>
|
||||
</DescribedFormField>
|
||||
</DescribedFormRow>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -29,7 +29,7 @@ import { useConfigurationIssues } from '../../../../form';
|
|||
|
||||
import { i18nTexts } from '../../../../i18n_texts';
|
||||
|
||||
import { FieldLoadingError, DescribedFormField, LearnMoreLink } from '../../../index';
|
||||
import { FieldLoadingError, DescribedFormRow, LearnMoreLink } from '../../../index';
|
||||
|
||||
import { SearchableSnapshotDataProvider } from './searchable_snapshot_data_provider';
|
||||
|
||||
|
@ -297,7 +297,7 @@ export const SearchableSnapshotField: FunctionComponent<Props> = ({ phase }) =>
|
|||
};
|
||||
|
||||
return (
|
||||
<DescribedFormField
|
||||
<DescribedFormRow
|
||||
data-test-subj={`searchableSnapshotField-${phase}`}
|
||||
switchProps={{
|
||||
checked: isFieldToggleChecked,
|
||||
|
@ -327,12 +327,12 @@ export const SearchableSnapshotField: FunctionComponent<Props> = ({ phase }) =>
|
|||
}}
|
||||
/>
|
||||
</EuiTextColor>
|
||||
{renderInfoCallout()}
|
||||
</>
|
||||
}
|
||||
fieldNotices={renderInfoCallout()}
|
||||
fullWidth
|
||||
>
|
||||
{isDisabled ? <div /> : renderField}
|
||||
</DescribedFormField>
|
||||
</DescribedFormRow>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -25,7 +25,7 @@ import { Phases } from '../../../../../../../common/types';
|
|||
import { useEditPolicyContext } from '../../../edit_policy_context';
|
||||
import { useConfigurationIssues } from '../../../form';
|
||||
|
||||
import { LearnMoreLink, ActiveBadge, DescribedFormField } from '../../';
|
||||
import { LearnMoreLink, ActiveBadge, DescribedFormRow } from '../../';
|
||||
|
||||
import {
|
||||
useRolloverPath,
|
||||
|
@ -141,7 +141,7 @@ export const WarmPhase: FunctionComponent = () => {
|
|||
)}
|
||||
paddingSize="m"
|
||||
>
|
||||
<DescribedFormField
|
||||
<DescribedFormRow
|
||||
title={
|
||||
<h3>
|
||||
{i18n.translate('xpack.indexLifecycleMgmt.warmPhase.replicasTitle', {
|
||||
|
@ -177,9 +177,9 @@ export const WarmPhase: FunctionComponent = () => {
|
|||
},
|
||||
}}
|
||||
/>
|
||||
</DescribedFormField>
|
||||
</DescribedFormRow>
|
||||
{!isUsingSearchableSnapshotInHotPhase && (
|
||||
<DescribedFormField
|
||||
<DescribedFormRow
|
||||
title={
|
||||
<h3>
|
||||
<FormattedMessage
|
||||
|
@ -225,7 +225,7 @@ export const WarmPhase: FunctionComponent = () => {
|
|||
</EuiFlexGroup>
|
||||
<EuiSpacer />
|
||||
</div>
|
||||
</DescribedFormField>
|
||||
</DescribedFormRow>
|
||||
)}
|
||||
|
||||
{!isUsingSearchableSnapshotInHotPhase && <ForcemergeField phase="warm" />}
|
||||
|
|
|
@ -1,47 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React, { FunctionComponent, useState } from 'react';
|
||||
import { EuiSpacer, EuiSwitch, EuiSwitchProps } from '@elastic/eui';
|
||||
|
||||
export interface Props extends Omit<EuiSwitchProps, 'checked' | 'onChange'> {
|
||||
children: (() => JSX.Element) | JSX.Element | JSX.Element[] | undefined;
|
||||
checked?: boolean;
|
||||
initialValue?: boolean;
|
||||
onChange?: (nextValue: boolean) => void;
|
||||
}
|
||||
|
||||
export const ToggleableField: FunctionComponent<Props> = ({
|
||||
initialValue,
|
||||
checked,
|
||||
onChange,
|
||||
children,
|
||||
...restProps
|
||||
}) => {
|
||||
const [uncontrolledIsContentVisible, setUncontrolledIsContentVisible] = useState<boolean>(
|
||||
initialValue ?? false
|
||||
);
|
||||
|
||||
const isContentVisible = Boolean(checked ?? uncontrolledIsContentVisible);
|
||||
|
||||
return (
|
||||
<>
|
||||
<EuiSwitch
|
||||
{...restProps}
|
||||
checked={isContentVisible}
|
||||
onChange={(e) => {
|
||||
const nextValue = e.target.checked;
|
||||
setUncontrolledIsContentVisible(nextValue);
|
||||
if (onChange) {
|
||||
onChange(nextValue);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<EuiSpacer size="m" />
|
||||
{isContentVisible ? (typeof children === 'function' ? children() : children) : null}
|
||||
</>
|
||||
);
|
||||
};
|
Loading…
Reference in a new issue