mirror of
https://github.com/grafana/grafana.git
synced 2024-12-26 00:41:20 -06:00
NewPanelEditor: minor UI twekas (#24042)
* Forward ref for tabs, use html props * Inspect: add inspect label to drawer title * Add tooltips to sidebar pane tabs, copy changes * Remove unused import * Place tooltips over tabs * Inspector: dont show transformations select if there is only one data frame * Review
This commit is contained in:
parent
4645167421
commit
7601e0bbd3
@ -31,7 +31,7 @@ e2e.scenario({
|
||||
.should('be.visible')
|
||||
.click();
|
||||
|
||||
e2e.components.Drawer.General.title(PANEL_UNDER_TEST)
|
||||
e2e.components.Drawer.General.title(`Inspect: ${PANEL_UNDER_TEST}`)
|
||||
.should('be.visible')
|
||||
.within(() => {
|
||||
e2e.components.Tab.title('Query').should('be.visible');
|
||||
@ -44,7 +44,7 @@ e2e.scenario({
|
||||
});
|
||||
|
||||
const expectDrawerTabsAndContent = () => {
|
||||
e2e.components.Drawer.General.title(PANEL_UNDER_TEST)
|
||||
e2e.components.Drawer.General.title(`Inspect: ${PANEL_UNDER_TEST}`)
|
||||
.should('be.visible')
|
||||
.within(() => {
|
||||
e2e.components.Tab.title('Data').should('be.visible');
|
||||
@ -87,7 +87,7 @@ const expectDrawerTabsAndContent = () => {
|
||||
const expectDrawerClose = () => {
|
||||
// close using close button
|
||||
e2e.components.Drawer.General.close().click();
|
||||
e2e.components.Drawer.General.title(PANEL_UNDER_TEST).should('not.be.visible');
|
||||
e2e.components.Drawer.General.title(`Inspect: ${PANEL_UNDER_TEST}`).should('not.be.visible');
|
||||
};
|
||||
|
||||
const expectDrawerExpandAndContract = (viewPortWidth: number) => {
|
||||
|
@ -314,7 +314,7 @@ export class PanelPlugin<TOptions = any, TFieldConfigOptions extends object = an
|
||||
|
||||
for (const customProp of builder.getRegistry().list()) {
|
||||
customProp.isCustom = true;
|
||||
customProp.category = ['Custom field options'].concat(customProp.category || []);
|
||||
customProp.category = ['Custom options'].concat(customProp.category || []);
|
||||
// need to do something to make the custom items not conflict with standard ones
|
||||
// problem is id (registry index) is used as property path
|
||||
// so sort of need a property path on the FieldPropertyEditorItem
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React, { FC } from 'react';
|
||||
import React, { HTMLProps } from 'react';
|
||||
import { css, cx } from 'emotion';
|
||||
import { GrafanaTheme } from '@grafana/data';
|
||||
import { selectors } from '@grafana/e2e-selectors';
|
||||
@ -8,7 +8,7 @@ import { IconName } from '../../types';
|
||||
import { stylesFactory, useTheme } from '../../themes';
|
||||
import { Counter } from './Counter';
|
||||
|
||||
export interface TabProps {
|
||||
export interface TabProps extends HTMLProps<HTMLLIElement> {
|
||||
label: string;
|
||||
active?: boolean;
|
||||
icon?: IconName;
|
||||
@ -16,6 +16,31 @@ export interface TabProps {
|
||||
counter?: number;
|
||||
}
|
||||
|
||||
export const Tab = React.forwardRef<HTMLLIElement, TabProps>(
|
||||
({ label, active, icon, onChangeTab, counter, className, ...otherProps }, ref) => {
|
||||
const theme = useTheme();
|
||||
const tabsStyles = getTabStyles(theme);
|
||||
|
||||
return (
|
||||
<li
|
||||
{...otherProps}
|
||||
className={cx(tabsStyles.tabItem, active && tabsStyles.activeStyle)}
|
||||
onClick={() => {
|
||||
if (!active) {
|
||||
onChangeTab();
|
||||
}
|
||||
}}
|
||||
aria-label={selectors.components.Tab.title(label)}
|
||||
ref={ref}
|
||||
>
|
||||
{icon && <Icon name={icon} />}
|
||||
{label}
|
||||
{typeof counter === 'number' && <Counter value={counter} />}
|
||||
</li>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
const getTabStyles = stylesFactory((theme: GrafanaTheme) => {
|
||||
const colors = theme.colors;
|
||||
|
||||
@ -47,6 +72,7 @@ const getTabStyles = stylesFactory((theme: GrafanaTheme) => {
|
||||
background: ${colors.bodyBg};
|
||||
color: ${colors.link};
|
||||
overflow: hidden;
|
||||
cursor: default;
|
||||
|
||||
&::before {
|
||||
display: block;
|
||||
@ -61,20 +87,3 @@ const getTabStyles = stylesFactory((theme: GrafanaTheme) => {
|
||||
`,
|
||||
};
|
||||
});
|
||||
|
||||
export const Tab: FC<TabProps> = ({ label, active, icon, onChangeTab, counter }) => {
|
||||
const theme = useTheme();
|
||||
const tabsStyles = getTabStyles(theme);
|
||||
|
||||
return (
|
||||
<li
|
||||
className={cx(tabsStyles.tabItem, active && tabsStyles.activeStyle)}
|
||||
onClick={onChangeTab}
|
||||
aria-label={selectors.components.Tab.title(label)}
|
||||
>
|
||||
{icon && <Icon name={icon} />}
|
||||
{label}
|
||||
{typeof counter === 'number' && <Counter value={counter} />}
|
||||
</li>
|
||||
);
|
||||
};
|
||||
|
@ -32,7 +32,7 @@ import { StatsPickerEditor } from '../components/OptionsUI/stats';
|
||||
* Returns collection of common field config properties definitions
|
||||
*/
|
||||
export const getStandardFieldConfigs = () => {
|
||||
const category = ['Standard field options'];
|
||||
const category = ['Standard options'];
|
||||
const title: FieldConfigPropertyItem<any, string, StringFieldConfigSettings> = {
|
||||
id: 'title',
|
||||
path: 'title',
|
||||
|
@ -84,7 +84,7 @@ export class InspectDataTab extends PureComponent<Props, State> {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { isLoading } = this.props;
|
||||
const { isLoading, data } = this.props;
|
||||
const { dataFrameIndex, transformId, transformationOptions } = this.state;
|
||||
const styles = getPanelInspectorStyles();
|
||||
|
||||
@ -112,9 +112,11 @@ export class InspectDataTab extends PureComponent<Props, State> {
|
||||
return (
|
||||
<div className={styles.dataTabContent} aria-label={selectors.components.PanelInspector.Data.content}>
|
||||
<div className={styles.toolbar}>
|
||||
<Field label="Transformer" className="flex-grow-1">
|
||||
<Select options={transformationOptions} value={transformId} onChange={this.onTransformationChange} />
|
||||
</Field>
|
||||
{data.length > 1 && (
|
||||
<Field label="Transformer" className="flex-grow-1">
|
||||
<Select options={transformationOptions} value={transformId} onChange={this.onTransformationChange} />
|
||||
</Field>
|
||||
)}
|
||||
{choices.length > 1 && (
|
||||
<Field label="Select result" className={cx(styles.toolbarItem, 'flex-grow-1')}>
|
||||
<Select options={choices} value={dataFrameIndex} onChange={this.onSelectedFrameChanged} />
|
||||
|
@ -311,7 +311,7 @@ export class PanelInspectorUnconnected extends PureComponent<Props, State> {
|
||||
|
||||
return (
|
||||
<Drawer
|
||||
title={panel.title || 'Panel inspect'}
|
||||
title={`Inspect: ${panel.title}` || 'Panel inspect'}
|
||||
subtitle={this.drawerSubtitle(tabs, activeTab)}
|
||||
width={drawerWidth}
|
||||
onClose={this.onClose}
|
||||
|
@ -17,6 +17,7 @@ export const getPanelInspectorStyles = stylesFactory(() => {
|
||||
flex-grow: 0;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
margin-bottom: ${config.theme.spacing.sm};
|
||||
`,
|
||||
toolbarItem: css`
|
||||
margin-left: ${config.theme.spacing.md};
|
||||
|
@ -203,6 +203,7 @@ export const TabsBarContent: React.FC<{
|
||||
counter={item.value === 'overrides' ? overridesCount : undefined}
|
||||
active={active.value === item.value}
|
||||
onChangeTab={() => setActiveTab(item.value)}
|
||||
title={item.tooltip}
|
||||
/>
|
||||
))}
|
||||
<div className="flex-grow-1" />
|
||||
@ -225,14 +226,17 @@ const tabSelections: Array<SelectableValue<string>> = [
|
||||
{
|
||||
label: 'Panel',
|
||||
value: 'options',
|
||||
tooltip: 'Configure panel display options',
|
||||
},
|
||||
{
|
||||
label: 'Fields',
|
||||
label: 'Field',
|
||||
value: 'defaults',
|
||||
tooltip: 'Configure field options',
|
||||
},
|
||||
{
|
||||
label: 'Overrides',
|
||||
value: 'overrides',
|
||||
tooltip: 'Configure field option overrides',
|
||||
},
|
||||
];
|
||||
|
||||
|
@ -48,7 +48,7 @@ export const PanelOptionsTab: FC<Props> = ({
|
||||
};
|
||||
// Fist common panel settings Title, description
|
||||
elements.push(
|
||||
<OptionsGroup title="Panel settings" id="Panel settings" key="Panel settings">
|
||||
<OptionsGroup title="Settings" id="Panel settings" key="Panel settings">
|
||||
<Field label="Panel title">
|
||||
<Input defaultValue={panel.title} onBlur={e => onPanelConfigChange('title', e.currentTarget.value)} />
|
||||
</Field>
|
||||
@ -65,7 +65,7 @@ export const PanelOptionsTab: FC<Props> = ({
|
||||
);
|
||||
|
||||
elements.push(
|
||||
<OptionsGroup title="Panel type" id="Panel type" key="Panel type" defaultToClosed onToggle={focusVisPickerInput}>
|
||||
<OptionsGroup title="Visualisation" id="Panel type" key="Panel type" defaultToClosed onToggle={focusVisPickerInput}>
|
||||
<VisualizationTab panel={panel} ref={visTabInputRef} />
|
||||
</OptionsGroup>
|
||||
);
|
||||
@ -73,7 +73,7 @@ export const PanelOptionsTab: FC<Props> = ({
|
||||
// Old legacy react editor
|
||||
if (plugin.editor && panel && !plugin.optionEditors) {
|
||||
elements.push(
|
||||
<OptionsGroup title="Display" id="legacy react editor" key="legacy react editor">
|
||||
<OptionsGroup title="Options" id="legacy react editor" key="legacy react editor">
|
||||
<plugin.editor data={data} options={panel.getOptions()} onOptionsChange={onPanelOptionsChanged} />
|
||||
</OptionsGroup>
|
||||
);
|
||||
@ -98,9 +98,7 @@ export const PanelOptionsTab: FC<Props> = ({
|
||||
|
||||
elements.push(
|
||||
<OptionsGroup
|
||||
renderTitle={isExpanded => (
|
||||
<>Panel links {!isExpanded && panelLinksCount > 0 && <Counter value={panelLinksCount} />}</>
|
||||
)}
|
||||
renderTitle={isExpanded => <>Links {!isExpanded && panelLinksCount > 0 && <Counter value={panelLinksCount} />}</>}
|
||||
id="panel links"
|
||||
key="panel links"
|
||||
defaultToClosed
|
||||
@ -115,7 +113,7 @@ export const PanelOptionsTab: FC<Props> = ({
|
||||
);
|
||||
|
||||
elements.push(
|
||||
<OptionsGroup title="Panel repeats" id="panel repeats" key="panel repeats" defaultToClosed>
|
||||
<OptionsGroup title="Repeat options" id="panel repeats" key="panel repeats" defaultToClosed>
|
||||
<Field
|
||||
label="Repeat by variable"
|
||||
description="Repeat this panel for each value in the selected variable.
|
||||
|
Loading…
Reference in New Issue
Block a user