mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
A11y/Dashboard: Fix misc. fastpass issues (#40296)
* A11y/Dashboard: Fix misc. fastpass issues See #39429
This commit is contained in:
parent
0ac81e9e47
commit
c443f244a0
@ -14,7 +14,7 @@ export const smokeTestScenario = {
|
|||||||
e2e.components.DataSource.TestData.QueryTab.scenarioSelectContainer()
|
e2e.components.DataSource.TestData.QueryTab.scenarioSelectContainer()
|
||||||
.should('be.visible')
|
.should('be.visible')
|
||||||
.within(() => {
|
.within(() => {
|
||||||
e2e.components.Select.input().should('be.visible').click();
|
e2e().get('input[id*="scenario-input-"]').should('be.visible').click();
|
||||||
});
|
});
|
||||||
|
|
||||||
cy.contains('CSV Metric Values').scrollIntoView().should('be.visible').click();
|
cy.contains('CSV Metric Values').scrollIntoView().should('be.visible').click();
|
||||||
|
@ -14,7 +14,7 @@ e2e.scenario({
|
|||||||
e2e.components.DataSource.TestData.QueryTab.scenarioSelectContainer()
|
e2e.components.DataSource.TestData.QueryTab.scenarioSelectContainer()
|
||||||
.should('be.visible')
|
.should('be.visible')
|
||||||
.within(() => {
|
.within(() => {
|
||||||
e2e.components.Select.input().should('be.visible').click();
|
e2e().get('input[id*="scenario-input-"]').should('be.visible').click();
|
||||||
});
|
});
|
||||||
|
|
||||||
cy.contains('CSV Metric Values').scrollIntoView().should('be.visible').click();
|
cy.contains('CSV Metric Values').scrollIntoView().should('be.visible').click();
|
||||||
|
@ -50,7 +50,7 @@ e2e.scenario({
|
|||||||
e2e.components.DataSource.TestData.QueryTab.scenarioSelectContainer()
|
e2e.components.DataSource.TestData.QueryTab.scenarioSelectContainer()
|
||||||
.should('be.visible')
|
.should('be.visible')
|
||||||
.within(() => {
|
.within(() => {
|
||||||
e2e.components.Select.input().eq(0).should('be.visible').click();
|
e2e().get('input[id*="scenario-input-"]').eq(0).should('be.visible').click();
|
||||||
});
|
});
|
||||||
|
|
||||||
cy.contains('CSV Metric Values').scrollIntoView().should('be.visible').eq(0).click();
|
cy.contains('CSV Metric Values').scrollIntoView().should('be.visible').eq(0).click();
|
||||||
|
@ -39,6 +39,7 @@ export interface SliderFieldConfigSettings {
|
|||||||
min: number;
|
min: number;
|
||||||
max: number;
|
max: number;
|
||||||
step?: number;
|
step?: number;
|
||||||
|
ariaLabelForHandle?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DataLinksFieldConfigSettings {}
|
export interface DataLinksFieldConfigSettings {}
|
||||||
|
@ -19,6 +19,7 @@ export interface StandardEditorProps<TValue = any, TSettings = any, TOptions = a
|
|||||||
onChange: (value?: TValue) => void;
|
onChange: (value?: TValue) => void;
|
||||||
item: StandardEditorsRegistryItem<TValue, TSettings>;
|
item: StandardEditorsRegistryItem<TValue, TSettings>;
|
||||||
context: StandardEditorContext<TOptions, TState>;
|
context: StandardEditorContext<TOptions, TState>;
|
||||||
|
id?: string;
|
||||||
}
|
}
|
||||||
export interface StandardEditorsRegistryItem<TValue = any, TSettings = any> extends RegistryItem {
|
export interface StandardEditorsRegistryItem<TValue = any, TSettings = any> extends RegistryItem {
|
||||||
editor: ComponentType<StandardEditorProps<TValue, TSettings>>;
|
editor: ComponentType<StandardEditorProps<TValue, TSettings>>;
|
||||||
|
@ -17,6 +17,8 @@ export interface Props extends ButtonHTMLAttributes<HTMLButtonElement> {
|
|||||||
tooltip?: string;
|
tooltip?: string;
|
||||||
/** For image icons */
|
/** For image icons */
|
||||||
imgSrc?: string;
|
imgSrc?: string;
|
||||||
|
/** Alt text for imgSrc */
|
||||||
|
imgAlt?: string;
|
||||||
/** if true or false will show angle-down/up */
|
/** if true or false will show angle-down/up */
|
||||||
isOpen?: boolean;
|
isOpen?: boolean;
|
||||||
/** Controls flex-grow: 1 */
|
/** Controls flex-grow: 1 */
|
||||||
@ -39,6 +41,7 @@ export const ToolbarButton = forwardRef<HTMLButtonElement, Props>(
|
|||||||
className,
|
className,
|
||||||
children,
|
children,
|
||||||
imgSrc,
|
imgSrc,
|
||||||
|
imgAlt,
|
||||||
fullWidth,
|
fullWidth,
|
||||||
isOpen,
|
isOpen,
|
||||||
narrow,
|
narrow,
|
||||||
@ -72,12 +75,12 @@ export const ToolbarButton = forwardRef<HTMLButtonElement, Props>(
|
|||||||
<button
|
<button
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={buttonStyles}
|
className={buttonStyles}
|
||||||
aria-label={getButttonAriaLabel(ariaLabel, tooltip)}
|
aria-label={getButtonAriaLabel(ariaLabel, tooltip)}
|
||||||
aria-expanded={isOpen}
|
aria-expanded={isOpen}
|
||||||
{...rest}
|
{...rest}
|
||||||
>
|
>
|
||||||
{renderIcon(icon)}
|
{renderIcon(icon)}
|
||||||
{imgSrc && <img className={styles.img} src={imgSrc} />}
|
{imgSrc && <img className={styles.img} src={imgSrc} alt={imgAlt ?? ''} />}
|
||||||
{children && !iconOnly && <div className={contentStyles}>{children}</div>}
|
{children && !iconOnly && <div className={contentStyles}>{children}</div>}
|
||||||
{isOpen === false && <Icon name="angle-down" />}
|
{isOpen === false && <Icon name="angle-down" />}
|
||||||
{isOpen === true && <Icon name="angle-up" />}
|
{isOpen === true && <Icon name="angle-up" />}
|
||||||
@ -94,7 +97,7 @@ export const ToolbarButton = forwardRef<HTMLButtonElement, Props>(
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
function getButttonAriaLabel(ariaLabel: string | undefined, tooltip: string | undefined) {
|
function getButtonAriaLabel(ariaLabel: string | undefined, tooltip: string | undefined) {
|
||||||
return ariaLabel ? ariaLabel : tooltip ? selectors.components.PageToolbar.item(tooltip) : undefined;
|
return ariaLabel ? ariaLabel : tooltip ? selectors.components.PageToolbar.item(tooltip) : undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ export const FieldColorEditor: React.FC<FieldConfigEditorProps<FieldColor | unde
|
|||||||
value,
|
value,
|
||||||
onChange,
|
onChange,
|
||||||
item,
|
item,
|
||||||
|
id,
|
||||||
}) => {
|
}) => {
|
||||||
const theme = useTheme2();
|
const theme = useTheme2();
|
||||||
const styles = useStyles2(getStyles);
|
const styles = useStyles2(getStyles);
|
||||||
@ -81,6 +82,7 @@ export const FieldColorEditor: React.FC<FieldConfigEditorProps<FieldColor | unde
|
|||||||
value={mode}
|
value={mode}
|
||||||
onChange={onModeChange}
|
onChange={onModeChange}
|
||||||
className={styles.select}
|
className={styles.select}
|
||||||
|
inputId={id}
|
||||||
/>
|
/>
|
||||||
<ColorValueEditor value={value?.fixedColor} onChange={onColorChange} />
|
<ColorValueEditor value={value?.fixedColor} onChange={onColorChange} />
|
||||||
</div>
|
</div>
|
||||||
@ -97,7 +99,14 @@ export const FieldColorEditor: React.FC<FieldConfigEditorProps<FieldColor | unde
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div style={{ marginBottom: theme.spacing(2) }}>
|
<div style={{ marginBottom: theme.spacing(2) }}>
|
||||||
<Select menuShouldPortal minMenuHeight={200} options={options} value={mode} onChange={onModeChange} />
|
<Select
|
||||||
|
menuShouldPortal
|
||||||
|
minMenuHeight={200}
|
||||||
|
options={options}
|
||||||
|
value={mode}
|
||||||
|
onChange={onModeChange}
|
||||||
|
inputId={id}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<Field label="Color series by">
|
<Field label="Color series by">
|
||||||
<RadioButtonGroup value={value?.seriesBy ?? 'last'} options={seriesModes} onChange={onSeriesModeChange} />
|
<RadioButtonGroup value={value?.seriesBy ?? 'last'} options={seriesModes} onChange={onSeriesModeChange} />
|
||||||
@ -106,7 +115,9 @@ export const FieldColorEditor: React.FC<FieldConfigEditorProps<FieldColor | unde
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return <Select menuShouldPortal minMenuHeight={200} options={options} value={mode} onChange={onModeChange} />;
|
return (
|
||||||
|
<Select menuShouldPortal minMenuHeight={200} options={options} value={mode} onChange={onModeChange} inputId={id} />
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
interface ModeProps {
|
interface ModeProps {
|
||||||
|
@ -17,6 +17,7 @@ export const SliderValueEditor: React.FC<FieldConfigEditorProps<number, SliderFi
|
|||||||
max={settings?.max || 100}
|
max={settings?.max || 100}
|
||||||
step={settings?.step}
|
step={settings?.step}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
|
ariaLabelForHandle={settings?.ariaLabelForHandle}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -6,6 +6,7 @@ export const StatsPickerEditor: React.FC<FieldConfigEditorProps<string[], StatsP
|
|||||||
value,
|
value,
|
||||||
onChange,
|
onChange,
|
||||||
item,
|
item,
|
||||||
|
id,
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<StatsPicker
|
<StatsPicker
|
||||||
@ -13,6 +14,7 @@ export const StatsPickerEditor: React.FC<FieldConfigEditorProps<string[], StatsP
|
|||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
allowMultiple={!!item.settings?.allowMultiple}
|
allowMultiple={!!item.settings?.allowMultiple}
|
||||||
defaultStat={item.settings?.defaultStat}
|
defaultStat={item.settings?.defaultStat}
|
||||||
|
inputId={id}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -19,6 +19,7 @@ export const Slider: FunctionComponent<SliderProps> = ({
|
|||||||
reverse,
|
reverse,
|
||||||
step,
|
step,
|
||||||
value,
|
value,
|
||||||
|
ariaLabelForHandle,
|
||||||
}) => {
|
}) => {
|
||||||
const isHorizontal = orientation === 'horizontal';
|
const isHorizontal = orientation === 'horizontal';
|
||||||
const theme = useTheme2();
|
const theme = useTheme2();
|
||||||
@ -79,6 +80,7 @@ export const Slider: FunctionComponent<SliderProps> = ({
|
|||||||
onAfterChange={onAfterChange}
|
onAfterChange={onAfterChange}
|
||||||
vertical={!isHorizontal}
|
vertical={!isHorizontal}
|
||||||
reverse={reverse}
|
reverse={reverse}
|
||||||
|
ariaLabelForHandle={ariaLabelForHandle}
|
||||||
/>
|
/>
|
||||||
{/* Uses text input so that the number spinners are not shown */}
|
{/* Uses text input so that the number spinners are not shown */}
|
||||||
<Input
|
<Input
|
||||||
|
@ -12,6 +12,7 @@ export interface SliderProps {
|
|||||||
formatTooltipResult?: (value: number) => number;
|
formatTooltipResult?: (value: number) => number;
|
||||||
onChange?: (value: number) => void;
|
onChange?: (value: number) => void;
|
||||||
onAfterChange?: (value?: number) => void;
|
onAfterChange?: (value?: number) => void;
|
||||||
|
ariaLabelForHandle?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface RangeSliderProps {
|
export interface RangeSliderProps {
|
||||||
|
@ -15,6 +15,7 @@ export interface Props {
|
|||||||
className?: string;
|
className?: string;
|
||||||
width?: number;
|
width?: number;
|
||||||
menuPlacement?: 'auto' | 'bottom' | 'top';
|
menuPlacement?: 'auto' | 'bottom' | 'top';
|
||||||
|
inputId?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class StatsPicker extends PureComponent<Props> {
|
export class StatsPicker extends PureComponent<Props> {
|
||||||
@ -63,7 +64,7 @@ export class StatsPicker extends PureComponent<Props> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { stats, allowMultiple, defaultStat, placeholder, className, menuPlacement, width } = this.props;
|
const { stats, allowMultiple, defaultStat, placeholder, className, menuPlacement, width, inputId } = this.props;
|
||||||
|
|
||||||
const select = fieldReducers.selectOptions(stats);
|
const select = fieldReducers.selectOptions(stats);
|
||||||
return (
|
return (
|
||||||
@ -79,6 +80,7 @@ export class StatsPicker extends PureComponent<Props> {
|
|||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
onChange={this.onSelectionChange}
|
onChange={this.onSelectionChange}
|
||||||
menuPlacement={menuPlacement}
|
menuPlacement={menuPlacement}
|
||||||
|
inputId={inputId}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -151,11 +151,13 @@ export class ThresholdsEditor extends PureComponent<Props, State> {
|
|||||||
renderInput(threshold: ThresholdWithKey, styles: ThresholdStyles, idx: number) {
|
renderInput(threshold: ThresholdWithKey, styles: ThresholdStyles, idx: number) {
|
||||||
const isPercent = this.props.thresholds.mode === ThresholdsMode.Percentage;
|
const isPercent = this.props.thresholds.mode === ThresholdsMode.Percentage;
|
||||||
|
|
||||||
|
const ariaLabel = `Threshold ${idx + 1}`;
|
||||||
if (!isFinite(threshold.value)) {
|
if (!isFinite(threshold.value)) {
|
||||||
return (
|
return (
|
||||||
<Input
|
<Input
|
||||||
type="text"
|
type="text"
|
||||||
value={'Base'}
|
value={'Base'}
|
||||||
|
aria-label={ariaLabel}
|
||||||
disabled
|
disabled
|
||||||
prefix={
|
prefix={
|
||||||
<div className={styles.colorPicker}>
|
<div className={styles.colorPicker}>
|
||||||
@ -177,6 +179,7 @@ export class ThresholdsEditor extends PureComponent<Props, State> {
|
|||||||
key={isPercent.toString()}
|
key={isPercent.toString()}
|
||||||
onChange={(event: ChangeEvent<HTMLInputElement>) => this.onChangeThresholdValue(event, threshold)}
|
onChange={(event: ChangeEvent<HTMLInputElement>) => this.onChangeThresholdValue(event, threshold)}
|
||||||
value={threshold.value}
|
value={threshold.value}
|
||||||
|
aria-label={ariaLabel}
|
||||||
ref={idx === 0 ? this.latestThresholdInputRef : null}
|
ref={idx === 0 ? this.latestThresholdInputRef : null}
|
||||||
onBlur={this.onBlur}
|
onBlur={this.onBlur}
|
||||||
prefix={
|
prefix={
|
||||||
|
@ -225,7 +225,7 @@ const AddPanelWidgetHandle: React.FC<AddPanelWidgetHandleProps> = ({ children, o
|
|||||||
)}
|
)}
|
||||||
{children && <span>{children}</span>}
|
{children && <span>{children}</span>}
|
||||||
<div className="flex-grow-1" />
|
<div className="flex-grow-1" />
|
||||||
<IconButton name="times" onClick={onCancel} surface="header" />
|
<IconButton aria-label="Close 'Add Panel' widget" name="times" onClick={onCancel} surface="header" />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -83,9 +83,7 @@ export const OptionsPaneCategory: FC<OptionsPaneCategoryProps> = React.memo(
|
|||||||
<div className={cx(styles.toggle, 'editor-options-group-toggle')}>
|
<div className={cx(styles.toggle, 'editor-options-group-toggle')}>
|
||||||
<Icon name={isExpanded ? 'angle-down' : 'angle-right'} />
|
<Icon name={isExpanded ? 'angle-down' : 'angle-right'} />
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.title} role="heading">
|
<h6 className={styles.title}>{renderTitle(isExpanded)}</h6>
|
||||||
{renderTitle(isExpanded)}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
{isExpanded && <div className={bodyStyles}>{children}</div>}
|
{isExpanded && <div className={bodyStyles}>{children}</div>}
|
||||||
</div>
|
</div>
|
||||||
@ -108,6 +106,10 @@ const getStyles = (theme: GrafanaTheme2) => {
|
|||||||
title: css`
|
title: css`
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
line-height: 1.5;
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: ${theme.typography.fontWeightMedium};
|
||||||
|
margin: 0;
|
||||||
`,
|
`,
|
||||||
header: css`
|
header: css`
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -39,6 +39,7 @@ export function getPanelFrameCategory(props: OptionPaneRenderProps): OptionsPane
|
|||||||
render: function renderDescription() {
|
render: function renderDescription() {
|
||||||
return (
|
return (
|
||||||
<TextArea
|
<TextArea
|
||||||
|
id="description-text-area"
|
||||||
defaultValue={panel.description}
|
defaultValue={panel.description}
|
||||||
onBlur={(e) => onPanelConfigChange('description', e.currentTarget.value)}
|
onBlur={(e) => onPanelConfigChange('description', e.currentTarget.value)}
|
||||||
/>
|
/>
|
||||||
@ -96,6 +97,7 @@ export function getPanelFrameCategory(props: OptionPaneRenderProps): OptionsPane
|
|||||||
render: function renderRepeatOptions() {
|
render: function renderRepeatOptions() {
|
||||||
return (
|
return (
|
||||||
<RepeatRowSelect
|
<RepeatRowSelect
|
||||||
|
id="repeat-by-variable-select"
|
||||||
repeat={panel.repeat}
|
repeat={panel.repeat}
|
||||||
onChange={(value?: string | null) => {
|
onChange={(value?: string | null) => {
|
||||||
onPanelConfigChange('repeat', value);
|
onPanelConfigChange('repeat', value);
|
||||||
|
@ -98,7 +98,7 @@ export function getVizualizationOptions(props: OptionPaneRenderProps): OptionsPa
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
return <Editor value={value} onChange={onChange} item={fieldOption} context={context} />;
|
return <Editor value={value} onChange={onChange} item={fieldOption} context={context} id={fieldOption.id} />;
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
@ -161,6 +161,7 @@ export function fillOptionsPaneItems(
|
|||||||
}}
|
}}
|
||||||
item={pluginOption}
|
item={pluginOption}
|
||||||
context={context}
|
context={context}
|
||||||
|
id={pluginOption.id}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -7,11 +7,12 @@ import { getVariables } from '../../../variables/state/selectors';
|
|||||||
import { StoreState } from '../../../../types';
|
import { StoreState } from '../../../../types';
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
|
id?: string;
|
||||||
repeat?: string | null;
|
repeat?: string | null;
|
||||||
onChange: (name: string | null) => void;
|
onChange: (name: string | null) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const RepeatRowSelect: FC<Props> = ({ repeat, onChange }) => {
|
export const RepeatRowSelect: FC<Props> = ({ repeat, onChange, id }) => {
|
||||||
const variables = useSelector((state: StoreState) => getVariables(state));
|
const variables = useSelector((state: StoreState) => getVariables(state));
|
||||||
|
|
||||||
const variableOptions = useMemo(() => {
|
const variableOptions = useMemo(() => {
|
||||||
@ -36,5 +37,5 @@ export const RepeatRowSelect: FC<Props> = ({ repeat, onChange }) => {
|
|||||||
|
|
||||||
const onSelectChange = useCallback((option: SelectableValue<string | null>) => onChange(option.value!), [onChange]);
|
const onSelectChange = useCallback((option: SelectableValue<string | null>) => onChange(option.value!), [onChange]);
|
||||||
|
|
||||||
return <Select menuShouldPortal value={repeat} onChange={onSelectChange} options={variableOptions} />;
|
return <Select inputId={id} menuShouldPortal value={repeat} onChange={onSelectChange} options={variableOptions} />;
|
||||||
};
|
};
|
||||||
|
@ -114,6 +114,7 @@ export class ShareLink extends PureComponent<Props, State> {
|
|||||||
|
|
||||||
<Field label="Link URL">
|
<Field label="Link URL">
|
||||||
<Input
|
<Input
|
||||||
|
id="link-url-input"
|
||||||
value={shareUrl}
|
value={shareUrl}
|
||||||
readOnly
|
readOnly
|
||||||
addonAfter={
|
addonAfter={
|
||||||
|
@ -41,7 +41,7 @@ export const PanelTypeCard: React.FC<Props> = ({
|
|||||||
onClick={disabled ? undefined : onClick}
|
onClick={disabled ? undefined : onClick}
|
||||||
title={isCurrent ? 'Click again to close this section' : plugin.name}
|
title={isCurrent ? 'Click again to close this section' : plugin.name}
|
||||||
>
|
>
|
||||||
<img className={styles.img} src={plugin.info.logos.small} alt={`${plugin.name} logo`} />
|
<img className={styles.img} src={plugin.info.logos.small} alt="" />
|
||||||
|
|
||||||
<div className={styles.itemContent}>
|
<div className={styles.itemContent}>
|
||||||
<div className={styles.name}>{title}</div>
|
<div className={styles.name}>{title}</div>
|
||||||
|
@ -203,7 +203,9 @@ export class QueryGroup extends PureComponent<Props, State> {
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className={styles.dataSourceRow}>
|
<div className={styles.dataSourceRow}>
|
||||||
<InlineFormLabel width={'auto'}>Data source</InlineFormLabel>
|
<InlineFormLabel htmlFor="data-source-picker" width={'auto'}>
|
||||||
|
Data source
|
||||||
|
</InlineFormLabel>
|
||||||
<div className={styles.dataSourceRowItem}>
|
<div className={styles.dataSourceRowItem}>
|
||||||
<DataSourcePicker
|
<DataSourcePicker
|
||||||
onChange={this.onChangeDataSource}
|
onChange={this.onChangeDataSource}
|
||||||
|
@ -175,6 +175,7 @@ export const QueryEditor = ({ query, datasource, onChange, onRunQuery }: Props)
|
|||||||
value={options.find((item) => item.value === query.scenarioId)}
|
value={options.find((item) => item.value === query.scenarioId)}
|
||||||
onChange={onScenarioChange}
|
onChange={onScenarioChange}
|
||||||
width={32}
|
width={32}
|
||||||
|
inputId={`scenario-input-${query.refId}`}
|
||||||
/>
|
/>
|
||||||
</InlineField>
|
</InlineField>
|
||||||
{currentScenario?.stringInput && (
|
{currentScenario?.stringInput && (
|
||||||
|
@ -16,9 +16,10 @@
|
|||||||
></gf-form-switch>
|
></gf-form-switch>
|
||||||
|
|
||||||
<div class="gf-form" ng-if="ctrl.panel.lines">
|
<div class="gf-form" ng-if="ctrl.panel.lines">
|
||||||
<label class="gf-form-label width-8">Line width</label>
|
<label class="gf-form-label width-8" for="linewidth-select-input">Line width</label>
|
||||||
<div class="gf-form-select-wrapper max-width-5">
|
<div class="gf-form-select-wrapper max-width-5">
|
||||||
<select
|
<select
|
||||||
|
id="linewidth-select-input"
|
||||||
class="gf-form-input"
|
class="gf-form-input"
|
||||||
ng-model="ctrl.panel.linewidth"
|
ng-model="ctrl.panel.linewidth"
|
||||||
ng-options="f for f in [0,1,2,3,4,5,6,7,8,9,10]"
|
ng-options="f for f in [0,1,2,3,4,5,6,7,8,9,10]"
|
||||||
@ -37,9 +38,10 @@
|
|||||||
></gf-form-switch>
|
></gf-form-switch>
|
||||||
|
|
||||||
<div class="gf-form" ng-if="ctrl.panel.lines">
|
<div class="gf-form" ng-if="ctrl.panel.lines">
|
||||||
<label class="gf-form-label width-8">Area fill</label>
|
<label class="gf-form-label width-8" for="fill-select-input">Area fill</label>
|
||||||
<div class="gf-form-select-wrapper max-width-5">
|
<div class="gf-form-select-wrapper max-width-5">
|
||||||
<select
|
<select
|
||||||
|
id="fill-select-input"
|
||||||
class="gf-form-input"
|
class="gf-form-input"
|
||||||
ng-model="ctrl.panel.fill"
|
ng-model="ctrl.panel.fill"
|
||||||
ng-options="f for f in [0,1,2,3,4,5,6,7,8,9,10]"
|
ng-options="f for f in [0,1,2,3,4,5,6,7,8,9,10]"
|
||||||
@ -69,9 +71,10 @@
|
|||||||
></gf-form-switch>
|
></gf-form-switch>
|
||||||
|
|
||||||
<div class="gf-form" ng-if="ctrl.panel.points">
|
<div class="gf-form" ng-if="ctrl.panel.points">
|
||||||
<label class="gf-form-label width-8">Point Radius</label>
|
<label class="gf-form-label width-8" for="pointradius-select-input">Point Radius</label>
|
||||||
<div class="gf-form-select-wrapper max-width-5">
|
<div class="gf-form-select-wrapper max-width-5">
|
||||||
<select
|
<select
|
||||||
|
id="pointradius-select-input"
|
||||||
class="gf-form-input"
|
class="gf-form-input"
|
||||||
ng-model="ctrl.panel.pointradius"
|
ng-model="ctrl.panel.pointradius"
|
||||||
ng-options="f for f in [0.5,1,2,3,4,5,6,7,8,9,10]"
|
ng-options="f for f in [0.5,1,2,3,4,5,6,7,8,9,10]"
|
||||||
@ -87,7 +90,6 @@
|
|||||||
checked="ctrl.panel.options.alertThreshold"
|
checked="ctrl.panel.options.alertThreshold"
|
||||||
on-change="ctrl.render()"
|
on-change="ctrl.render()"
|
||||||
></gf-form-switch>
|
></gf-form-switch>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="gf-form-group">
|
<div class="gf-form-group">
|
||||||
@ -110,9 +112,10 @@
|
|||||||
>
|
>
|
||||||
</gf-form-switch>
|
</gf-form-switch>
|
||||||
<div class="gf-form">
|
<div class="gf-form">
|
||||||
<label class="gf-form-label width-7">Null value</label>
|
<label class="gf-form-label width-7" for="null-value-select-input">Null value</label>
|
||||||
<div class="gf-form-select-wrapper">
|
<div class="gf-form-select-wrapper">
|
||||||
<select
|
<select
|
||||||
|
id="null-value-select-input"
|
||||||
class="gf-form-input max-width-9"
|
class="gf-form-input max-width-9"
|
||||||
ng-model="ctrl.panel.nullPointMode"
|
ng-model="ctrl.panel.nullPointMode"
|
||||||
ng-options="f for f in ['connected', 'null', 'null as zero']"
|
ng-options="f for f in ['connected', 'null', 'null as zero']"
|
||||||
@ -125,9 +128,10 @@
|
|||||||
<div class="gf-form-group">
|
<div class="gf-form-group">
|
||||||
<h5 class="section-heading">Hover tooltip</h5>
|
<h5 class="section-heading">Hover tooltip</h5>
|
||||||
<div class="gf-form">
|
<div class="gf-form">
|
||||||
<label class="gf-form-label width-9">Mode</label>
|
<label class="gf-form-label width-9" for="tooltip-mode-select-input">Mode</label>
|
||||||
<div class="gf-form-select-wrapper max-width-8">
|
<div class="gf-form-select-wrapper max-width-8">
|
||||||
<select
|
<select
|
||||||
|
id="tooltip-mode-select-input"
|
||||||
class="gf-form-input"
|
class="gf-form-input"
|
||||||
ng-model="ctrl.panel.tooltip.shared"
|
ng-model="ctrl.panel.tooltip.shared"
|
||||||
ng-options="f.value as f.text for f in [{text: 'All series', value: true}, {text: 'Single', value: false}]"
|
ng-options="f.value as f.text for f in [{text: 'All series', value: true}, {text: 'Single', value: false}]"
|
||||||
@ -136,9 +140,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="gf-form">
|
<div class="gf-form">
|
||||||
<label class="gf-form-label width-9">Sort order</label>
|
<label class="gf-form-label width-9" for="tooltip-sort-select-input">Sort order</label>
|
||||||
<div class="gf-form-select-wrapper max-width-8">
|
<div class="gf-form-select-wrapper max-width-8">
|
||||||
<select
|
<select
|
||||||
|
id="tooltip-sort-select-input"
|
||||||
class="gf-form-input"
|
class="gf-form-input"
|
||||||
ng-model="ctrl.panel.tooltip.sort"
|
ng-model="ctrl.panel.tooltip.sort"
|
||||||
ng-options="f.value as f.text for f in [{text: 'None', value: 0}, {text: 'Increasing', value: 1}, {text: 'Decreasing', value: 2}]"
|
ng-options="f.value as f.text for f in [{text: 'None', value: 0}, {text: 'Increasing', value: 1}, {text: 'Decreasing', value: 2}]"
|
||||||
|
@ -5,7 +5,7 @@ import { Select } from '@grafana/ui';
|
|||||||
|
|
||||||
export const ThresholdsStyleEditor: React.FC<
|
export const ThresholdsStyleEditor: React.FC<
|
||||||
FieldOverrideEditorProps<SelectableValue<{ mode: GraphTresholdsStyleMode }>, any>
|
FieldOverrideEditorProps<SelectableValue<{ mode: GraphTresholdsStyleMode }>, any>
|
||||||
> = ({ item, value, onChange }) => {
|
> = ({ item, value, onChange, id }) => {
|
||||||
const onChangeCb = useCallback(
|
const onChangeCb = useCallback(
|
||||||
(v: SelectableValue<GraphTresholdsStyleMode>) => {
|
(v: SelectableValue<GraphTresholdsStyleMode>) => {
|
||||||
onChange({
|
onChange({
|
||||||
@ -14,5 +14,7 @@ export const ThresholdsStyleEditor: React.FC<
|
|||||||
},
|
},
|
||||||
[onChange]
|
[onChange]
|
||||||
);
|
);
|
||||||
return <Select menuShouldPortal value={value.mode} options={item.settings.options} onChange={onChangeCb} />;
|
return (
|
||||||
|
<Select inputId={id} menuShouldPortal value={value.mode} options={item.settings.options} onChange={onChangeCb} />
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
@ -95,6 +95,7 @@ export function getGraphFieldConfig(cfg: GraphFieldConfig): SetFieldConfigOption
|
|||||||
min: 0,
|
min: 0,
|
||||||
max: 10,
|
max: 10,
|
||||||
step: 1,
|
step: 1,
|
||||||
|
ariaLabelForHandle: 'Line width',
|
||||||
},
|
},
|
||||||
showIf: (c) => c.drawStyle !== GraphDrawStyle.Points,
|
showIf: (c) => c.drawStyle !== GraphDrawStyle.Points,
|
||||||
})
|
})
|
||||||
@ -107,6 +108,7 @@ export function getGraphFieldConfig(cfg: GraphFieldConfig): SetFieldConfigOption
|
|||||||
min: 0,
|
min: 0,
|
||||||
max: 100,
|
max: 100,
|
||||||
step: 1,
|
step: 1,
|
||||||
|
ariaLabelForHandle: 'Fill opacity',
|
||||||
},
|
},
|
||||||
showIf: (c) => c.drawStyle !== GraphDrawStyle.Points,
|
showIf: (c) => c.drawStyle !== GraphDrawStyle.Points,
|
||||||
})
|
})
|
||||||
@ -173,6 +175,7 @@ export function getGraphFieldConfig(cfg: GraphFieldConfig): SetFieldConfigOption
|
|||||||
min: 1,
|
min: 1,
|
||||||
max: 40,
|
max: 40,
|
||||||
step: 1,
|
step: 1,
|
||||||
|
ariaLabelForHandle: 'Point size',
|
||||||
},
|
},
|
||||||
showIf: (c) => c.showPoints !== VisibilityMode.Never || c.drawStyle === GraphDrawStyle.Points,
|
showIf: (c) => c.showPoints !== VisibilityMode.Never || c.drawStyle === GraphDrawStyle.Points,
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user