mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Chore: Enable eslint-plugin-react partial rules (#29428)
* Chore: Enable eslint react/display-name Enable react/display-name and fixed the corresponding linting issue part of: #29201 * Chore: Enable eslint react/no-deprecated Enable react/no-deprecated and add the UNSAFE_ prefix for deprected methods part of: #29201 * Chore: Enable eslint react/no-find-dom-node Enable react/no-find-dom-node rule and use ref instead part of: #29201 * Test: Update TeamGroupSync test snapshot Since we added the displayName for ToolTip compontent and tag name is changed. * Fix: Fixed ClickOutsideWrapper render The props.children might contains numbers of nodes which make cloneElement failed. Change to simply use a div to wrapper the children and assign the ref to div for this feature * Style: Use shorthand method definition style for inline component * Fix: Rebase master and fix linting Rebase from master branch and fix new displayName linting warning
This commit is contained in:
parent
ccac8d2294
commit
546f569e0c
@ -16,11 +16,8 @@
|
||||
"react-hooks/exhaustive-deps": "off",
|
||||
"react/prop-types": "off",
|
||||
"react/no-unescaped-entities": "off",
|
||||
"react/display-name": "off",
|
||||
"react/no-deprecated": "off",
|
||||
"react/no-unknown-property": "off",
|
||||
"react/no-children-prop": "off",
|
||||
"react/no-find-dom-node": "off",
|
||||
"react/no-render-return-value": "off",
|
||||
"no-only-tests/no-only-tests": "error"
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { PureComponent } from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import React, { PureComponent, createRef } from 'react';
|
||||
|
||||
export interface Props {
|
||||
/**
|
||||
@ -28,6 +27,7 @@ export class ClickOutsideWrapper extends PureComponent<Props, State> {
|
||||
parent: window,
|
||||
useCapture: false,
|
||||
};
|
||||
myRef = createRef<HTMLDivElement>();
|
||||
state = {
|
||||
hasEventListener: false,
|
||||
};
|
||||
@ -48,7 +48,7 @@ export class ClickOutsideWrapper extends PureComponent<Props, State> {
|
||||
}
|
||||
|
||||
onOutsideClick = (event: any) => {
|
||||
const domNode = ReactDOM.findDOMNode(this) as Element;
|
||||
const domNode = this.myRef.current;
|
||||
|
||||
if (!domNode || !domNode.contains(event.target)) {
|
||||
this.props.onClick();
|
||||
@ -56,6 +56,6 @@ export class ClickOutsideWrapper extends PureComponent<Props, State> {
|
||||
};
|
||||
|
||||
render() {
|
||||
return this.props.children;
|
||||
return <div ref={this.myRef}>{this.props.children}</div>;
|
||||
}
|
||||
}
|
||||
|
@ -19,20 +19,22 @@ export const SeriesColorPickerPopover: FunctionComponent<SeriesColorPickerPopove
|
||||
customPickers={{
|
||||
yaxis: {
|
||||
name: 'Y-Axis',
|
||||
tabComponent: () => (
|
||||
<Switch
|
||||
key="yaxisSwitch"
|
||||
label="Use right y-axis"
|
||||
className="ColorPicker__axisSwitch"
|
||||
labelClass="ColorPicker__axisSwitchLabel"
|
||||
checked={yaxis === 2}
|
||||
onChange={() => {
|
||||
if (onToggleAxis) {
|
||||
onToggleAxis();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
),
|
||||
tabComponent() {
|
||||
return (
|
||||
<Switch
|
||||
key="yaxisSwitch"
|
||||
label="Use right y-axis"
|
||||
className="ColorPicker__axisSwitch"
|
||||
labelClass="ColorPicker__axisSwitchLabel"
|
||||
checked={yaxis === 2}
|
||||
onChange={() => {
|
||||
if (onToggleAxis) {
|
||||
onToggleAxis();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
);
|
||||
},
|
||||
},
|
||||
}}
|
||||
/>
|
||||
|
@ -13,6 +13,7 @@ export interface SpectrumPaletteProps extends Themeable {
|
||||
onChange: (color: string) => void;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line react/display-name
|
||||
const renderPointer = (theme: GrafanaTheme) => (props: SpectrumPalettePointerProps) => (
|
||||
<SpectrumPalettePointer {...props} theme={theme} />
|
||||
);
|
||||
|
@ -191,6 +191,7 @@ const ContextMenuItemComponent: React.FC<ContextMenuItemProps> = React.memo(
|
||||
);
|
||||
}
|
||||
);
|
||||
ContextMenuItemComponent.displayName = 'ContextMenuItemComponent';
|
||||
|
||||
interface ContextMenuGroupProps {
|
||||
group: ContextMenuGroup;
|
||||
|
@ -11,6 +11,7 @@ interface ButtonComponentProps {
|
||||
iconClass?: string;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line react/display-name
|
||||
const ButtonComponent = (buttonProps: ButtonComponentProps) => (props: any) => {
|
||||
const { label, className, iconClass } = buttonProps;
|
||||
|
||||
|
@ -28,6 +28,7 @@ export const FeatureInfoBox = React.memo(
|
||||
return <InfoBox branded title={titleEl} urlTitle="Read documentation" {...otherProps} />;
|
||||
})
|
||||
);
|
||||
FeatureInfoBox.displayName = 'FeatureInfoBox';
|
||||
|
||||
const getFeatureInfoBoxStyles = stylesFactory((theme: GrafanaTheme) => {
|
||||
return {
|
||||
|
@ -55,6 +55,7 @@ export const InfoBox = React.memo(
|
||||
}
|
||||
)
|
||||
);
|
||||
InfoBox.displayName = 'InfoBox';
|
||||
|
||||
const getInfoBoxStyles = stylesFactory((theme: GrafanaTheme, severity: AlertVariant) => ({
|
||||
wrapper: css`
|
||||
|
@ -15,6 +15,7 @@ export const FieldNameByRegexMatcherEditor = memo<MatcherUIProps<string>>(props
|
||||
|
||||
return <Input placeholder="Enter regular expression" defaultValue={options} onBlur={onBlur} />;
|
||||
});
|
||||
FieldNameByRegexMatcherEditor.displayName = 'FieldNameByRegexMatcherEditor';
|
||||
|
||||
export const fieldNameByRegexMatcherItem: FieldMatcherUIRegistryItem<string> = {
|
||||
id: FieldMatcherID.byRegexp,
|
||||
|
@ -21,6 +21,7 @@ export const FieldNameMatcherEditor = memo<MatcherUIProps<string>>(props => {
|
||||
const selectedOption = selectOptions.find(v => v.value === options);
|
||||
return <Select value={selectedOption} options={selectOptions} onChange={onChange} />;
|
||||
});
|
||||
FieldNameMatcherEditor.displayName = 'FieldNameMatcherEditor';
|
||||
|
||||
export const fieldNameMatcherItem: FieldMatcherUIRegistryItem<string> = {
|
||||
id: FieldMatcherID.byName,
|
||||
|
@ -18,6 +18,7 @@ export const FieldTypeMatcherEditor = memo<MatcherUIProps<string>>(props => {
|
||||
const selectedOption = selectOptions.find(v => v.value === options);
|
||||
return <Select value={selectedOption} options={selectOptions} onChange={onChange} />;
|
||||
});
|
||||
FieldTypeMatcherEditor.displayName = 'FieldTypeMatcherEditor';
|
||||
|
||||
const allTypes: Array<SelectableValue<FieldType>> = [
|
||||
{ value: FieldType.number, label: 'Numeric' },
|
||||
|
@ -26,6 +26,8 @@ export const FieldsByFrameRefIdMatcher = memo<MatcherUIProps<string>>(props => {
|
||||
return <Select value={selectedOption} options={selectOptions} onChange={onChange} />;
|
||||
});
|
||||
|
||||
FieldsByFrameRefIdMatcher.displayName = 'FieldsByFrameRefIdMatcher';
|
||||
|
||||
/**
|
||||
* Registry item for UI to configure "fields by frame refId"-matcher.
|
||||
* @public
|
||||
|
@ -36,7 +36,9 @@ export const FieldColorEditor: React.FC<FieldConfigEditorProps<FieldColor | unde
|
||||
description: mode.description,
|
||||
isContinuous: mode.isContinuous,
|
||||
isByValue: mode.isByValue,
|
||||
component: () => <FieldColorModeViz mode={mode} theme={theme} />,
|
||||
component() {
|
||||
return <FieldColorModeViz mode={mode} theme={theme} />;
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
|
@ -54,6 +54,7 @@ const SelectButton = React.forwardRef<HTMLButtonElement, SelectButtonProps>(
|
||||
);
|
||||
}
|
||||
);
|
||||
SelectButton.displayName = 'SelectButton';
|
||||
|
||||
export function ButtonSelect<T>({
|
||||
placeholder,
|
||||
@ -75,6 +76,7 @@ export function ButtonSelect<T>({
|
||||
return (
|
||||
<SelectBase
|
||||
{...selectProps}
|
||||
// eslint-disable-next-line react/display-name
|
||||
renderControl={React.forwardRef<any, CustomControlProps<T>>(({ onBlur, onClick, value, isOpen }, ref) => {
|
||||
return (
|
||||
<SelectButton {...buttonProps} ref={ref} onBlur={onBlur} onClick={onClick} isOpen={isOpen}>
|
||||
|
@ -237,26 +237,28 @@ export function SelectBase<T>({
|
||||
MenuList: SelectMenu,
|
||||
Group: SelectOptionGroup,
|
||||
ValueContainer,
|
||||
Placeholder: (props: any) => (
|
||||
<div
|
||||
{...props.innerProps}
|
||||
className={cx(
|
||||
css(props.getStyles('placeholder', props)),
|
||||
css`
|
||||
display: inline-block;
|
||||
color: ${theme.colors.formInputPlaceholderText};
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
box-sizing: border-box;
|
||||
line-height: 1;
|
||||
`
|
||||
)}
|
||||
>
|
||||
{props.children}
|
||||
</div>
|
||||
),
|
||||
IndicatorsContainer: (props: any) => {
|
||||
Placeholder(props: any) {
|
||||
return (
|
||||
<div
|
||||
{...props.innerProps}
|
||||
className={cx(
|
||||
css(props.getStyles('placeholder', props)),
|
||||
css`
|
||||
display: inline-block;
|
||||
color: ${theme.colors.formInputPlaceholderText};
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
box-sizing: border-box;
|
||||
line-height: 1;
|
||||
`
|
||||
)}
|
||||
>
|
||||
{props.children}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
IndicatorsContainer(props: any) {
|
||||
const { selectProps } = props;
|
||||
const { value, showAllSelectedWhenOpen, maxVisibleValues, menuIsOpen } = selectProps;
|
||||
|
||||
@ -278,10 +280,12 @@ export function SelectBase<T>({
|
||||
|
||||
return <IndicatorsContainer {...props} />;
|
||||
},
|
||||
IndicatorSeparator: () => <></>,
|
||||
IndicatorSeparator() {
|
||||
return <></>;
|
||||
},
|
||||
Control: CustomControl,
|
||||
Option: SelectMenuOptions,
|
||||
ClearIndicator: (props: any) => {
|
||||
ClearIndicator(props: any) {
|
||||
const { clearValue } = props;
|
||||
return (
|
||||
<Icon
|
||||
@ -294,20 +298,22 @@ export function SelectBase<T>({
|
||||
/>
|
||||
);
|
||||
},
|
||||
LoadingIndicator: (props: any) => {
|
||||
LoadingIndicator(props: any) {
|
||||
return <Spinner inline={true} />;
|
||||
},
|
||||
LoadingMessage: (props: any) => {
|
||||
LoadingMessage(props: any) {
|
||||
return <div className={styles.loadingMessage}>{loadingMessage}</div>;
|
||||
},
|
||||
NoOptionsMessage: (props: any) => {
|
||||
NoOptionsMessage(props: any) {
|
||||
return (
|
||||
<div className={styles.loadingMessage} aria-label="No options provided">
|
||||
{noOptionsMessage}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
DropdownIndicator: (props: any) => <DropdownIndicator isOpen={props.selectProps.menuIsOpen} />,
|
||||
DropdownIndicator(props: any) {
|
||||
return <DropdownIndicator isOpen={props.selectProps.menuIsOpen} />;
|
||||
},
|
||||
SingleValue: SingleValue,
|
||||
MultiValueContainer: MultiValueContainer,
|
||||
MultiValueRemove: MultiValueRemove,
|
||||
|
@ -65,3 +65,5 @@ export const SelectMenuOptions = React.forwardRef<HTMLDivElement, React.PropsWit
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
SelectMenuOptions.displayName = 'SelectMenuOptions';
|
||||
|
@ -40,3 +40,5 @@ export const TabsBar = React.forwardRef<HTMLDivElement, Props>(({ children, clas
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
TabsBar.displayName = 'TabsBar';
|
||||
|
@ -40,6 +40,8 @@ export const Tag = forwardRef<HTMLElement, Props>(({ name, onClick, className, c
|
||||
);
|
||||
});
|
||||
|
||||
Tag.displayName = 'Tag';
|
||||
|
||||
const getTagStyles = (theme: GrafanaTheme, name: string, colorIndex?: number) => {
|
||||
let colors;
|
||||
if (colorIndex === undefined) {
|
||||
|
@ -21,6 +21,8 @@ export const TagList: FC<Props> = memo(({ tags, onClick, className }) => {
|
||||
);
|
||||
});
|
||||
|
||||
TagList.displayName = 'TagList';
|
||||
|
||||
const getStyles = () => {
|
||||
return {
|
||||
wrapper: css`
|
||||
|
@ -210,6 +210,8 @@ export const TimePickerButtonLabel = memo<LabelProps>(({ hideText, value, timeZo
|
||||
);
|
||||
});
|
||||
|
||||
TimePickerButtonLabel.displayName = 'TimePickerButtonLabel';
|
||||
|
||||
const formattedRange = (value: TimeRange, timeZone?: TimeZone) => {
|
||||
const adjustedTimeRange = {
|
||||
to: dateMath.isMathString(value.raw.to) ? value.raw.to : value.to,
|
||||
|
@ -231,6 +231,8 @@ export const TimePickerCalendar = memo<Props>(props => {
|
||||
);
|
||||
});
|
||||
|
||||
TimePickerCalendar.displayName = 'TimePickerCalendar';
|
||||
|
||||
const Header = memo<Props>(({ onClose }) => {
|
||||
const theme = useTheme();
|
||||
const styles = getHeaderStyles(theme);
|
||||
@ -243,6 +245,8 @@ const Header = memo<Props>(({ onClose }) => {
|
||||
);
|
||||
});
|
||||
|
||||
Header.displayName = 'Header';
|
||||
|
||||
const Body = memo<Props>(({ onChange, from, to, timeZone }) => {
|
||||
const value = inputToValue(from, to);
|
||||
const theme = useTheme();
|
||||
@ -265,6 +269,8 @@ const Body = memo<Props>(({ onChange, from, to, timeZone }) => {
|
||||
);
|
||||
});
|
||||
|
||||
Body.displayName = 'Body';
|
||||
|
||||
const Footer = memo<Props>(({ onClose, onApply }) => {
|
||||
const theme = useTheme();
|
||||
const styles = getFooterStyles(theme);
|
||||
@ -281,6 +287,8 @@ const Footer = memo<Props>(({ onClose, onApply }) => {
|
||||
);
|
||||
});
|
||||
|
||||
Footer.displayName = 'Footer';
|
||||
|
||||
export function inputToValue(from: DateTime, to: DateTime, invalidDateDefault: Date = new Date()): Date[] {
|
||||
const fromAsDate = from.toDate();
|
||||
const toAsDate = to.toDate();
|
||||
|
@ -307,3 +307,5 @@ function mapToHistoryOptions(ranges?: TimeRange[], timeZone?: TimeZone): TimeOpt
|
||||
}
|
||||
return ranges.slice(ranges.length - 4).map(range => mapRangeToTimeOption(range, timeZone));
|
||||
}
|
||||
|
||||
EmptyRecentList.displayName = 'EmptyRecentList';
|
||||
|
@ -19,3 +19,5 @@ export const TimePickerTitle = memo<PropsWithChildren<{}>>(({ children }) => {
|
||||
|
||||
return <span className={styles.text}>{children}</span>;
|
||||
});
|
||||
|
||||
TimePickerTitle.displayName = 'TimePickerTitle';
|
||||
|
@ -53,3 +53,5 @@ export const TimeRangeOption = memo<Props>(({ value, onSelect, selected = false
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
TimeRangeOption.displayName = 'TimeRangeOption';
|
||||
|
@ -53,3 +53,5 @@ export const Tooltip: FC<TooltipProps> = React.memo(({ children, theme, ...contr
|
||||
</PopoverController>
|
||||
);
|
||||
});
|
||||
|
||||
Tooltip.displayName = 'Tooltip';
|
||||
|
@ -189,7 +189,7 @@ export function SuggestionsPlugin({
|
||||
},
|
||||
},
|
||||
|
||||
renderEditor: (props, editor, next) => {
|
||||
renderEditor(props, editor, next) {
|
||||
if (editor.value.selection.isExpanded) {
|
||||
return next();
|
||||
}
|
||||
|
@ -259,7 +259,9 @@ export const getStandardOptionEditors = () => {
|
||||
id: 'boolean',
|
||||
name: 'Boolean',
|
||||
description: 'Allows boolean values input',
|
||||
editor: props => <Switch {...props} onChange={e => props.onChange(e.currentTarget.checked)} />,
|
||||
editor(props) {
|
||||
return <Switch {...props} onChange={e => props.onChange(e.currentTarget.checked)} />;
|
||||
},
|
||||
};
|
||||
|
||||
const select: StandardEditorsRegistryItem<any> = {
|
||||
@ -273,7 +275,9 @@ export const getStandardOptionEditors = () => {
|
||||
id: 'radio',
|
||||
name: 'Radio',
|
||||
description: 'Allows option selection',
|
||||
editor: props => <RadioButtonGroup {...props} options={props.item.settings?.options} />,
|
||||
editor(props) {
|
||||
return <RadioButtonGroup {...props} options={props.item.settings?.options} />;
|
||||
},
|
||||
};
|
||||
|
||||
const unit: StandardEditorsRegistryItem<string> = {
|
||||
@ -301,7 +305,9 @@ export const getStandardOptionEditors = () => {
|
||||
id: 'color',
|
||||
name: 'Color',
|
||||
description: 'Allows color selection',
|
||||
editor: props => <ColorValueEditor value={props.value} onChange={props.onChange} />,
|
||||
editor(props) {
|
||||
return <ColorValueEditor value={props.value} onChange={props.onChange} />;
|
||||
},
|
||||
};
|
||||
|
||||
const fieldColor: StandardEditorsRegistryItem<FieldColor> = {
|
||||
|
@ -32,6 +32,7 @@ export const renderComponentWithTheme = (component: React.ComponentType<any>, pr
|
||||
);
|
||||
};
|
||||
|
||||
// eslint-disable-next-line react/display-name
|
||||
export const withTheme = (handleSassThemeChange: SassThemeChangeHandler) => (story: RenderFunction) => (
|
||||
<ThemeableStory handleSassThemeChange={handleSassThemeChange}>{story()}</ThemeableStory>
|
||||
);
|
||||
|
@ -68,7 +68,7 @@ export default class SpanGraph extends React.PureComponent<SpanGraphProps, SpanG
|
||||
};
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps: SpanGraphProps) {
|
||||
UNSAFE_componentWillReceiveProps(nextProps: SpanGraphProps) {
|
||||
const { trace } = nextProps;
|
||||
if (this.props.trace !== trace) {
|
||||
this.setState({
|
||||
|
@ -164,7 +164,7 @@ export const HEADER_ITEMS = [
|
||||
{
|
||||
key: 'timestamp',
|
||||
label: 'Trace Start',
|
||||
renderer: (trace: Trace, styles?: ReturnType<typeof getStyles>) => {
|
||||
renderer(trace: Trace, styles?: ReturnType<typeof getStyles>) {
|
||||
const dateStr = formatDatetime(trace.startTime);
|
||||
const match = dateStr.match(/^(.+)(:\d\d\.\d+)$/);
|
||||
return match ? (
|
||||
|
@ -71,7 +71,9 @@ describe(ReferencesButton, () => {
|
||||
// here
|
||||
const menuInstance = shallow(
|
||||
shallow(dropdown.first().props().overlay).prop('children')({
|
||||
Menu: ({ children }) => <div>{children}</div>,
|
||||
Menu({ children }) {
|
||||
return <div>{children}</div>;
|
||||
},
|
||||
})
|
||||
);
|
||||
const submenuItems = menuInstance.find(UIMenuItem);
|
||||
|
@ -112,7 +112,13 @@ describe('<KeyValuesTable>', () => {
|
||||
const overlay = shallow(dropdown.prop('overlay'));
|
||||
// We have some wrappers here that dynamically inject specific component so we need to traverse a bit
|
||||
// here
|
||||
const menu = shallow(overlay.prop('children')({ Menu: ({ children }) => <div>{children}</div> }));
|
||||
const menu = shallow(
|
||||
overlay.prop('children')({
|
||||
Menu({ children }) {
|
||||
return <div>{children}</div>;
|
||||
},
|
||||
})
|
||||
);
|
||||
const anchors = menu.find(LinkValue);
|
||||
expect(anchors).toHaveLength(2);
|
||||
const firstAnchor = anchors.first();
|
||||
|
@ -194,7 +194,7 @@ export default class TimelineViewingLayer extends React.PureComponent<TimelineVi
|
||||
this._root = undefined;
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps: TimelineViewingLayerProps) {
|
||||
UNSAFE_componentWillReceiveProps(nextProps: TimelineViewingLayerProps) {
|
||||
const { boundsInvalidator } = this.props;
|
||||
if (boundsInvalidator !== nextProps.boundsInvalidator) {
|
||||
this._draggerReframe.resetBounds();
|
||||
|
@ -189,7 +189,7 @@ export class UnthemedVirtualizedTraceView extends React.Component<VirtualizedTra
|
||||
return false;
|
||||
}
|
||||
|
||||
componentWillUpdate(nextProps: VirtualizedTraceViewProps) {
|
||||
UNSAFE_componentWillUpdate(nextProps: VirtualizedTraceViewProps) {
|
||||
const { childrenHiddenIDs, detailStates, registerAccessors, trace, currentViewRangeTime } = this.props;
|
||||
const {
|
||||
currentViewRangeTime: nextViewRangeTime,
|
||||
|
@ -84,3 +84,5 @@ export const Footer: FC = React.memo(() => {
|
||||
</footer>
|
||||
);
|
||||
});
|
||||
|
||||
Footer.displayName = 'Footer';
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
|
||||
export default () => (
|
||||
const PermissionsInfo = () => (
|
||||
<div>
|
||||
<h5>What are Permissions?</h5>
|
||||
<p>
|
||||
@ -9,3 +9,5 @@ export default () => (
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
|
||||
export default PermissionsInfo;
|
||||
|
@ -79,7 +79,7 @@ export const TagFilter: FC<Props> = ({
|
||||
MultiValueLabel: (): any => {
|
||||
return null; // We want the whole tag to be clickable so we use MultiValueRemove instead
|
||||
},
|
||||
MultiValueRemove: (props: any) => {
|
||||
MultiValueRemove(props: any) {
|
||||
const { data } = props;
|
||||
|
||||
return (
|
||||
|
@ -7,7 +7,7 @@ import { convertToType } from './utils';
|
||||
export function basicMatcherEditor<T = any>(
|
||||
config: ValueMatcherEditorConfig
|
||||
): React.FC<ValueMatcherUIProps<BasicValueMatcherOptions<T>>> {
|
||||
return ({ options, onChange, field }) => {
|
||||
return function render({ options, onChange, field }) {
|
||||
const { validator, converter = convertToType } = config;
|
||||
const { value } = options;
|
||||
const [isInvalid, setInvalid] = useState(!validator(value));
|
||||
|
@ -73,7 +73,7 @@ export class UserProvider extends PureComponent<Props, State> {
|
||||
},
|
||||
};
|
||||
|
||||
componentWillMount() {
|
||||
UNSAFE_componentWillMount() {
|
||||
if (this.props.userId) {
|
||||
this.loadUser();
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import { store } from '../../store/store';
|
||||
export function connectWithStore(WrappedComponent: any, ...args: any[]) {
|
||||
const ConnectedWrappedComponent = (connect as any)(...args)(WrappedComponent);
|
||||
|
||||
// eslint-disable-next-line react/display-name
|
||||
return (props: any) => {
|
||||
return <ConnectedWrappedComponent {...props} store={store} />;
|
||||
};
|
||||
@ -12,6 +13,8 @@ export function connectWithStore(WrappedComponent: any, ...args: any[]) {
|
||||
|
||||
export function connectWithProvider(WrappedComponent: any, ...args: any[]) {
|
||||
const ConnectedWrappedComponent = (connect as any)(...args)(WrappedComponent);
|
||||
|
||||
// eslint-disable-next-line react/display-name
|
||||
return (props: any) => {
|
||||
return (
|
||||
<Provider store={store}>
|
||||
|
@ -30,6 +30,7 @@ export const DynamicConfigValueEditor: React.FC<DynamicConfigValueEditorProps> =
|
||||
}
|
||||
let editor;
|
||||
|
||||
// eslint-disable-next-line react/display-name
|
||||
const renderLabel = (includeDescription = true, includeCounter = false) => (isExpanded = false) => (
|
||||
<HorizontalGroup justify="space-between">
|
||||
<Label description={includeDescription ? item.description : undefined}>
|
||||
|
@ -87,6 +87,9 @@ export const VisualizationTabUnconnected = React.forwardRef<HTMLInputElement, Pr
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
VisualizationTabUnconnected.displayName = 'VisualizationTabUnconnected';
|
||||
|
||||
const getStyles = stylesFactory((theme: GrafanaTheme) => {
|
||||
return {
|
||||
icon: css`
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
|
||||
export default function({ value }: any) {
|
||||
export default function JSONViewer({ value }: any) {
|
||||
return (
|
||||
<div>
|
||||
<pre>{JSON.stringify(value, undefined, 2)}</pre>
|
||||
|
@ -54,3 +54,5 @@ export const ResponsiveButton = forwardRef<HTMLButtonElement, Props>((props, ref
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
ResponsiveButton.displayName = 'ResponsiveButton';
|
||||
|
@ -18,18 +18,24 @@ export const UIElements: Elements = {
|
||||
Dropdown: (() => null as any) as any,
|
||||
Menu: (() => null as any) as any,
|
||||
MenuItem: (() => null as any) as any,
|
||||
Button: ({ onClick, children, className }: ButtonProps) => (
|
||||
<Button variant={'secondary'} onClick={onClick} className={className}>
|
||||
{children}
|
||||
</Button>
|
||||
),
|
||||
Button({ onClick, children, className }: ButtonProps) {
|
||||
return (
|
||||
<Button variant={'secondary'} onClick={onClick} className={className}>
|
||||
{children}
|
||||
</Button>
|
||||
);
|
||||
},
|
||||
Divider,
|
||||
Input: props => <Input {...props} />,
|
||||
InputGroup: ({ children, className, style }) => (
|
||||
<span className={className} style={style}>
|
||||
{children}
|
||||
</span>
|
||||
),
|
||||
Input(props) {
|
||||
return <Input {...props} />;
|
||||
},
|
||||
InputGroup({ children, className, style }) {
|
||||
return (
|
||||
<span className={className} style={style}>
|
||||
{children}
|
||||
</span>
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
const getStyles = stylesFactory((theme: GrafanaTheme) => {
|
||||
|
@ -28,7 +28,9 @@ type Mock = jest.Mock;
|
||||
jest.mock('react-virtualized-auto-sizer', () => {
|
||||
return {
|
||||
__esModule: true,
|
||||
default: (props: any) => <div>{props.children({ width: 1000 })}</div>,
|
||||
default(props: any) {
|
||||
return <div>{props.children({ width: 1000 })}</div>;
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
@ -273,11 +275,13 @@ function makeDatasourceSetup({ name = 'loki', id = 1 }: { name?: string; id?: nu
|
||||
},
|
||||
api: {
|
||||
components: {
|
||||
QueryEditor: (props: QueryEditorProps<LokiDatasource, LokiQuery>) => (
|
||||
<div>
|
||||
{name} Editor input: {props.query.expr}
|
||||
</div>
|
||||
),
|
||||
QueryEditor(props: QueryEditorProps<LokiDatasource, LokiQuery>) {
|
||||
return (
|
||||
<div>
|
||||
{name} Editor input: {props.query.expr}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
},
|
||||
name: name,
|
||||
query: jest.fn(),
|
||||
|
@ -41,6 +41,7 @@ export const DashboardListPage: FC<Props> = memo(({ navModel, uid, url }) => {
|
||||
</Page>
|
||||
);
|
||||
});
|
||||
DashboardListPage.displayName = 'DashboardListPage';
|
||||
|
||||
const mapStateToProps: MapStateToProps<Props, {}, StoreState> = state => {
|
||||
return {
|
||||
|
@ -57,6 +57,7 @@ export const DashboardSearch: FC<Props> = memo(({ onCloseSearch, params, updateL
|
||||
</div>
|
||||
);
|
||||
});
|
||||
DashboardSearch.displayName = 'DashboardSearch';
|
||||
|
||||
export default connectWithRouteParams(DashboardSearch);
|
||||
|
||||
|
@ -28,3 +28,5 @@ const getStyles = stylesFactory(() => ({
|
||||
}
|
||||
`,
|
||||
}));
|
||||
|
||||
SearchCheckbox.displayName = 'SearchCheckbox';
|
||||
|
@ -40,6 +40,8 @@ export const SearchWrapper: FC<Props> = memo(({ search, folder, updateLocation }
|
||||
return isOpen ? <DashboardSearch onCloseSearch={closeSearch} folder={folder} /> : null;
|
||||
});
|
||||
|
||||
SearchWrapper.displayName = 'SearchWrapper';
|
||||
|
||||
const mapStateToProps: MapStateToProps<{}, OwnProps, StoreState> = (state: StoreState) => {
|
||||
const { search, folder } = getLocationQuery(state.location);
|
||||
return { search, folder };
|
||||
|
@ -10,7 +10,7 @@ exports[`Render should render component 1`] = `
|
||||
>
|
||||
External group sync
|
||||
</h3>
|
||||
<Memo()
|
||||
<Tooltip
|
||||
content="Sync LDAP or OAuth groups with your Grafana teams."
|
||||
placement="auto"
|
||||
>
|
||||
@ -18,7 +18,7 @@ exports[`Render should render component 1`] = `
|
||||
className="icon--has-hover page-sub-heading-icon"
|
||||
name="question-circle"
|
||||
/>
|
||||
</Memo()>
|
||||
</Tooltip>
|
||||
<div
|
||||
className="page-action-bar__spacer"
|
||||
/>
|
||||
@ -92,7 +92,7 @@ exports[`Render should render groups table 1`] = `
|
||||
>
|
||||
External group sync
|
||||
</h3>
|
||||
<Memo()
|
||||
<Tooltip
|
||||
content="Sync LDAP or OAuth groups with your Grafana teams."
|
||||
placement="auto"
|
||||
>
|
||||
@ -100,7 +100,7 @@ exports[`Render should render groups table 1`] = `
|
||||
className="icon--has-hover page-sub-heading-icon"
|
||||
name="question-circle"
|
||||
/>
|
||||
</Memo()>
|
||||
</Tooltip>
|
||||
<div
|
||||
className="page-action-bar__spacer"
|
||||
/>
|
||||
|
@ -16,7 +16,9 @@ const props: Props = {
|
||||
} as any,
|
||||
crossSeriesReducer: '',
|
||||
groupBys: [],
|
||||
children: renderProps => <div />,
|
||||
children(renderProps) {
|
||||
return <div />;
|
||||
},
|
||||
templateVariableOptions: [],
|
||||
};
|
||||
|
||||
|
@ -42,8 +42,8 @@ const DefaultTarget: State = {
|
||||
export class AnnotationQueryEditor extends React.Component<Props, State> {
|
||||
state: State = DefaultTarget;
|
||||
|
||||
async UNSAFE_componentWillMount() {
|
||||
// Unfortunately, migrations like this need to go componentWillMount. As soon as there's
|
||||
async UNSAFE_UNSAFE_componentWillMount() {
|
||||
// Unfortunately, migrations like this need to go UNSAFE_componentWillMount. As soon as there's
|
||||
// migration hook for this module.ts, we can do the migrations there instead.
|
||||
const { target, datasource } = this.props;
|
||||
if (!target.projectName) {
|
||||
|
@ -18,10 +18,10 @@ interface State {
|
||||
export class QueryEditor extends PureComponent<Props, State> {
|
||||
state: State = { lastQueryError: '' };
|
||||
|
||||
async UNSAFE_componentWillMount() {
|
||||
async UNSAFE_UNSAFE_componentWillMount() {
|
||||
const { datasource, query } = this.props;
|
||||
|
||||
// Unfortunately, migrations like this need to go componentWillMount. As soon as there's
|
||||
// Unfortunately, migrations like this need to go UNSAFE_componentWillMount. As soon as there's
|
||||
// migration hook for this module.ts, we can do the migrations there instead.
|
||||
if (!this.props.query.hasOwnProperty('metricQuery')) {
|
||||
const { hide, refId, datasource, key, queryType, maxLines, metric, ...metricQuery } = this.props.query as any;
|
||||
|
@ -13,9 +13,9 @@ const FunctionDescription = React.lazy(async () => {
|
||||
// @ts-ignore
|
||||
const { default: rst2html } = await import(/* webpackChunkName: "rst2html" */ 'rst2html');
|
||||
return {
|
||||
default: (props: { description?: string }) => (
|
||||
<div dangerouslySetInnerHTML={{ __html: rst2html(props.description ?? '') }} />
|
||||
),
|
||||
default(props: { description?: string }) {
|
||||
return <div dangerouslySetInnerHTML={{ __html: rst2html(props.description ?? '') }} />;
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
|
@ -8,7 +8,7 @@ const CHEAT_SHEET_ITEMS = [
|
||||
},
|
||||
];
|
||||
|
||||
export default (props: any) => (
|
||||
const InfluxCheatSheet = (props: any) => (
|
||||
<div>
|
||||
<h2>InfluxDB Cheat Sheet</h2>
|
||||
{CHEAT_SHEET_ITEMS.map(item => (
|
||||
@ -19,3 +19,5 @@ export default (props: any) => (
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
|
||||
export default InfluxCheatSheet;
|
||||
|
@ -25,7 +25,7 @@ const CHEAT_SHEET_ITEMS = [
|
||||
},
|
||||
];
|
||||
|
||||
export default (props: ExploreStartPageProps) => (
|
||||
const PromCheatSheet = (props: ExploreStartPageProps) => (
|
||||
<div>
|
||||
<h2>PromQL Cheat Sheet</h2>
|
||||
{CHEAT_SHEET_ITEMS.map((item, index) => (
|
||||
@ -44,3 +44,5 @@ export default (props: ExploreStartPageProps) => (
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
|
||||
export default PromCheatSheet;
|
||||
|
@ -60,7 +60,7 @@ export const plugin = new PanelPlugin<AnnoOptions>(AnnoListPanel)
|
||||
path: 'tags',
|
||||
name: 'Tags',
|
||||
description: '',
|
||||
editor: props => {
|
||||
editor(props) {
|
||||
return <TagsInput tags={props.value} onChange={props.onChange} />;
|
||||
},
|
||||
})
|
||||
|
@ -44,7 +44,7 @@ export const plugin = new PanelPlugin<DashListOptions>(DashList)
|
||||
name: 'Folder',
|
||||
id: 'folderId',
|
||||
defaultValue: null,
|
||||
editor: props => {
|
||||
editor: function RenderFolderPicker(props) {
|
||||
return <FolderPicker initialTitle="All" enableReset={true} onChange={({ id }) => props.onChange(id)} />;
|
||||
},
|
||||
})
|
||||
@ -54,7 +54,7 @@ export const plugin = new PanelPlugin<DashListOptions>(DashList)
|
||||
name: 'Tags',
|
||||
description: '',
|
||||
defaultValue: [],
|
||||
editor: props => {
|
||||
editor(props) {
|
||||
return <TagsInput tags={props.value} onChange={props.onChange} />;
|
||||
},
|
||||
});
|
||||
|
@ -22,6 +22,7 @@ export function WrapInProvider(store: any, Component: any, props: any) {
|
||||
}
|
||||
|
||||
export const provideModalsContext = (component: any) => {
|
||||
// eslint-disable-next-line react/display-name
|
||||
return (props: any) => (
|
||||
<ModalsProvider>
|
||||
<>
|
||||
|
Loading…
Reference in New Issue
Block a user