Commit 758d1386 by Torkel Ödegaard Committed by GitHub

DashboardSettings: Update to new form styles (#31022)

* DashboardSettings: Update to new form styles

* Improve header margin and fixing issue in permissions tab

* Updated

* Switch to radio

* Remove unused import
parent b8a52ed0
...@@ -37,6 +37,7 @@ const collapsableSectionStyles = (theme: GrafanaTheme) => { ...@@ -37,6 +37,7 @@ const collapsableSectionStyles = (theme: GrafanaTheme) => {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
font-size: ${theme.typography.size.lg}; font-size: ${theme.typography.size.lg};
line-height: ${theme.spacing.base * 5}px;
cursor: pointer; cursor: pointer;
`, `,
headerCollapsed: css` headerCollapsed: css`
......
...@@ -21,7 +21,7 @@ export interface FieldProps extends HTMLAttributes<HTMLDivElement> { ...@@ -21,7 +21,7 @@ export interface FieldProps extends HTMLAttributes<HTMLDivElement> {
/** Indicates if field is required */ /** Indicates if field is required */
required?: boolean; required?: boolean;
/** Error message to display */ /** Error message to display */
error?: string; error?: string | null;
/** Indicates horizontal layout of the field */ /** Indicates horizontal layout of the field */
horizontal?: boolean; horizontal?: boolean;
className?: string; className?: string;
......
...@@ -25,7 +25,7 @@ const getStyles = stylesFactory(({ theme, name }: { theme: GrafanaTheme; name: s ...@@ -25,7 +25,7 @@ const getStyles = stylesFactory(({ theme, name }: { theme: GrafanaTheme; name: s
white-space: nowrap; white-space: nowrap;
text-shadow: none; text-shadow: none;
font-weight: 500; font-weight: 500;
line-height: 14px; font-size: ${theme.typography.size.sm};
display: flex; display: flex;
align-items: center; align-items: center;
`, `,
...@@ -43,7 +43,7 @@ export const TagItem: FC<Props> = ({ name, onRemove }) => { ...@@ -43,7 +43,7 @@ export const TagItem: FC<Props> = ({ name, onRemove }) => {
return ( return (
<div className={styles.itemStyle}> <div className={styles.itemStyle}>
<span className={styles.nameStyle}>{name}</span> <span className={styles.nameStyle}>{name}</span>
<Icon name="times" onClick={() => onRemove(name)} /> <Icon className="pointer" name="times" onClick={() => onRemove(name)} />
</div> </div>
); );
}; };
...@@ -94,17 +94,15 @@ export class DashboardPermissionsUnconnected extends PureComponent<Props, State> ...@@ -94,17 +94,15 @@ export class DashboardPermissionsUnconnected extends PureComponent<Props, State>
<h5>You have changed folder, please save to view permissions.</h5> <h5>You have changed folder, please save to view permissions.</h5>
) : ( ) : (
<div> <div>
<div className="dashboard-settings__header"> <div className="page-action-bar">
<div className="page-action-bar"> <h3 className="page-sub-heading">Permissions</h3>
<h3 className="d-inline-block">Permissions</h3> <Tooltip placement="auto" content={<PermissionsInfo />}>
<Tooltip placement="auto" content={<PermissionsInfo />}> <Icon className="icon--has-hover page-sub-heading-icon" name="question-circle" />
<Icon className="icon--has-hover page-sub-heading-icon" name="question-circle" /> </Tooltip>
</Tooltip> <div className="page-action-bar__spacer" />
<div className="page-action-bar__spacer" /> <Button className="pull-right" onClick={this.onOpenAddPermissions} disabled={isAdding}>
<Button className="pull-right" onClick={this.onOpenAddPermissions} disabled={isAdding}> Add Permission
Add Permission </Button>
</Button>
</div>
</div> </div>
<SlideDown in={isAdding}> <SlideDown in={isAdding}>
<AddPermission onAddPermission={this.onAddPermission} onCancel={this.onCancelAddPermission} /> <AddPermission onAddPermission={this.onAddPermission} onCancel={this.onCancelAddPermission} />
......
import React, { FC, useCallback, useEffect, useMemo, useState } from 'react'; import React, { FC, useCallback, useEffect, useMemo, useState } from 'react';
import { Input, Tooltip, defaultIntervals } from '@grafana/ui'; import { Input, defaultIntervals, Field } from '@grafana/ui';
import { getTimeSrv } from '../../services/TimeSrv'; import { getTimeSrv } from '../../services/TimeSrv';
...@@ -56,16 +56,19 @@ export const AutoRefreshIntervals: FC<Props> = ({ ...@@ -56,16 +56,19 @@ export const AutoRefreshIntervals: FC<Props> = ({
); );
return ( return (
<div className="gf-form"> <Field
<label className="gf-form-label width-7">Auto-refresh</label> label="Auto refresh"
{invalidIntervalsMessage ? ( description="Define the auto refresh intervals that should be available in the auto refresh dropdown"
<Tooltip placement="right" content={invalidIntervalsMessage}> error={invalidIntervalsMessage}
<Input width={60} invalid value={intervalsString} onChange={onIntervalsChange} onBlur={onIntervalsBlur} /> invalid={!!invalidIntervalsMessage}
</Tooltip> >
) : ( <Input
<Input width={60} value={intervalsString} onChange={onIntervalsChange} onBlur={onIntervalsBlur} /> invalid={!!invalidIntervalsMessage}
)} value={intervalsString}
</div> onChange={onIntervalsChange}
onBlur={onIntervalsBlur}
/>
</Field>
); );
}; };
......
import React, { useState } from 'react'; import React, { useState } from 'react';
import { SelectableValue, TimeZone } from '@grafana/data'; import { SelectableValue, TimeZone } from '@grafana/data';
import { Select, InlineSwitch, TagsInput, InlineField, Input } from '@grafana/ui'; import { Select, TagsInput, Input, Field, CollapsableSection, RadioButtonGroup } from '@grafana/ui';
import { selectors } from '@grafana/e2e-selectors'; import { selectors } from '@grafana/e2e-selectors';
import { FolderPicker } from 'app/core/components/Select/FolderPicker'; import { FolderPicker } from 'app/core/components/Select/FolderPicker';
import { DashboardModel } from '../../state/DashboardModel'; import { DashboardModel } from '../../state/DashboardModel';
...@@ -57,41 +57,50 @@ export const GeneralSettings: React.FC<Props> = ({ dashboard }) => { ...@@ -57,41 +57,50 @@ export const GeneralSettings: React.FC<Props> = ({ dashboard }) => {
dashboard.tags = tags; dashboard.tags = tags;
}; };
const onEditableChange = (ev: React.FormEvent<HTMLInputElement>) => { const onEditableChange = (value: boolean) => {
dashboard.editable = ev.currentTarget.checked; dashboard.editable = value;
setRenderCounter(renderCounter + 1); setRenderCounter(renderCounter + 1);
}; };
const editableOptions = [
{ label: 'Editable', value: true },
{ label: 'Read-only', value: false },
];
return ( return (
<> <div style={{ maxWidth: '600px' }}>
<h3 className="dashboard-settings__header" aria-label={selectors.pages.Dashboard.Settings.General.title}> <h3 className="dashboard-settings__header" aria-label={selectors.pages.Dashboard.Settings.General.title}>
General General
</h3> </h3>
<div className="gf-form-group"> <div className="gf-form-group">
<InlineField label="Name" labelWidth={14}> <Field label="Name">
<Input name="title" onBlur={onBlur} defaultValue={dashboard.title} width={60} /> <Input name="title" onBlur={onBlur} defaultValue={dashboard.title} />
</InlineField> </Field>
<InlineField label="Description" labelWidth={14}> <Field label="Description">
<Input name="description" onBlur={onBlur} defaultValue={dashboard.description} width={60} /> <Input name="description" onBlur={onBlur} defaultValue={dashboard.description} />
</InlineField> </Field>
<InlineField label="Tags" tooltip="Press enter to add a tag" labelWidth={14}> <Field label="Tags" description="Press enter to add a tag">
<TagsInput tags={dashboard.tags} onChange={onTagsChange} /> <TagsInput tags={dashboard.tags} onChange={onTagsChange} />
</InlineField> </Field>
<FolderPicker <Field label="Folder">
initialTitle={dashboard.meta.folderTitle} <FolderPicker
initialFolderId={dashboard.meta.folderId} useNewForms={true}
onChange={onFolderChange} initialTitle={dashboard.meta.folderTitle}
enableCreateNew={true} initialFolderId={dashboard.meta.folderId}
dashboardId={dashboard.id} onChange={onFolderChange}
/> enableCreateNew={true}
<InlineField dashboardId={dashboard.id}
/>
</Field>
<Field
label="Editable" label="Editable"
tooltip="Uncheck, then save and reload to disable all dashboard editing" description="Set to read-only to disable all editing. Reload the dashboard for changes to take effect"
labelWidth={14}
> >
<InlineSwitch value={dashboard.editable} onChange={onEditableChange} /> <RadioButtonGroup value={dashboard.editable} options={editableOptions} onChange={onEditableChange} />
</InlineField> </Field>
</div> </div>
<TimePickerSettings <TimePickerSettings
onTimeZoneChange={onTimeZoneChange} onTimeZoneChange={onTimeZoneChange}
onRefreshIntervalChange={onRefreshIntervalChange} onRefreshIntervalChange={onRefreshIntervalChange}
...@@ -103,20 +112,23 @@ export const GeneralSettings: React.FC<Props> = ({ dashboard }) => { ...@@ -103,20 +112,23 @@ export const GeneralSettings: React.FC<Props> = ({ dashboard }) => {
timezone={dashboard.timezone} timezone={dashboard.timezone}
/> />
<h5 className="section-heading">Panel Options</h5> <CollapsableSection label="Panel options" isOpen={true}>
<div className="gf-form"> <Field
<InlineField label="Graph Tooltip" labelWidth={14}> label="Graph tooltip"
description="Controls tooltip and hover highlight behavior across different panels"
>
<Select <Select
onChange={onTooltipChange} onChange={onTooltipChange}
options={GRAPH_TOOLTIP_OPTIONS} options={GRAPH_TOOLTIP_OPTIONS}
width={40} width={40}
value={dashboard.graphTooltip} value={dashboard.graphTooltip}
/> />
</InlineField> </Field>
</div> </CollapsableSection>
<div className="gf-form-button-row"> <div className="gf-form-button-row">
{dashboard.meta.canSave && <DeleteDashboardButton dashboard={dashboard} />} {dashboard.meta.canSave && <DeleteDashboardButton dashboard={dashboard} />}
</div> </div>
</> </div>
); );
}; };
import React, { PureComponent } from 'react'; import React, { PureComponent } from 'react';
import { InlineField, Input, InlineSwitch, TimeZonePicker, Tooltip } from '@grafana/ui'; import { Input, TimeZonePicker, Field, Switch, CollapsableSection } from '@grafana/ui';
import { rangeUtil, TimeZone } from '@grafana/data'; import { rangeUtil, TimeZone } from '@grafana/data';
import isEmpty from 'lodash/isEmpty'; import isEmpty from 'lodash/isEmpty';
import { selectors } from '@grafana/e2e-selectors'; import { selectors } from '@grafana/e2e-selectors';
...@@ -52,45 +52,34 @@ export class TimePickerSettings extends PureComponent<Props, State> { ...@@ -52,45 +52,34 @@ export class TimePickerSettings extends PureComponent<Props, State> {
render() { render() {
return ( return (
<div className="editor-row"> <CollapsableSection label="Time options" isOpen={true}>
<h5 className="section-heading">Time Options</h5> <Field label="Timezone" aria-label={selectors.components.TimeZonePicker.container}>
<div className="gf-form-group"> <TimeZonePicker
<div className="gf-form" aria-label={selectors.components.TimeZonePicker.container}> includeInternal={true}
<label className="gf-form-label width-7">Timezone</label> value={this.props.timezone}
<TimeZonePicker onChange={this.onTimeZoneChange}
includeInternal={true} width={40}
value={this.props.timezone}
onChange={this.onTimeZoneChange}
width={40}
/>
</div>
<AutoRefreshIntervals
refreshIntervals={this.props.refreshIntervals}
onRefreshIntervalChange={this.props.onRefreshIntervalChange}
/> />
<div className="gf-form"> </Field>
<span className="gf-form-label width-7">Now delay now-</span> <AutoRefreshIntervals
<Tooltip refreshIntervals={this.props.refreshIntervals}
placement="right" onRefreshIntervalChange={this.props.onRefreshIntervalChange}
content={'Enter 1m to ignore the last minute (because it can contain incomplete metrics)'} />
> <Field
<Input label="Now delay now"
width={60} description="Enter 1m to ignore the last minute (because it can contain incomplete metrics)"
invalid={!this.state.isNowDelayValid} >
placeholder="0m" <Input
onChange={this.onNowDelayChange} invalid={!this.state.isNowDelayValid}
defaultValue={this.props.nowDelay} placeholder="0m"
/> onChange={this.onNowDelayChange}
</Tooltip> defaultValue={this.props.nowDelay}
</div> />
</Field>
<div className="gf-form"> <Field label="Hide time picker">
<InlineField labelWidth={14} label="Hide time picker"> <Switch value={!!this.props.timePickerHidden} onChange={this.onHideTimePickerChange} />
<InlineSwitch value={!!this.props.timePickerHidden} onChange={this.onHideTimePickerChange} /> </Field>
</InlineField> </CollapsableSection>
</div>
</div>
</div>
); );
} }
} }
...@@ -52,8 +52,7 @@ ...@@ -52,8 +52,7 @@
.dashboard-settings__header { .dashboard-settings__header {
font-size: $font-size-h3; font-size: $font-size-h3;
margin-bottom: $space-xl; margin-bottom: $space-md;
line-height: 36px;
} }
.dashboard-settings__subheader { .dashboard-settings__subheader {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment