Style dashboard renamer
parent
3097b3ca83
commit
c7980563df
|
@ -22,7 +22,7 @@ interface Props {
|
|||
placeholder?: string
|
||||
onChange?: (e: ChangeEvent<HTMLInputElement>) => void
|
||||
onBlur?: (e?: ChangeEvent<HTMLInputElement>) => void
|
||||
onFocus?: () => void
|
||||
onFocus?: (e?: ChangeEvent<HTMLInputElement>) => void
|
||||
onKeyPress?: (e: KeyboardEvent<HTMLInputElement>) => void
|
||||
onKeyUp?: (e: KeyboardEvent<HTMLInputElement>) => void
|
||||
onKeyDown?: (e: KeyboardEvent<HTMLInputElement>) => void
|
||||
|
@ -36,6 +36,7 @@ interface Props {
|
|||
titleText?: string
|
||||
disabledTitleText?: string
|
||||
customClass?: string
|
||||
maxLength?: number
|
||||
}
|
||||
|
||||
class Input extends Component<Props> {
|
||||
|
@ -65,6 +66,7 @@ class Input extends Component<Props> {
|
|||
onKeyPress,
|
||||
onKeyUp,
|
||||
onKeyDown,
|
||||
maxLength,
|
||||
} = this.props
|
||||
|
||||
return (
|
||||
|
@ -84,6 +86,7 @@ class Input extends Component<Props> {
|
|||
onKeyDown={onKeyDown}
|
||||
className="input-field"
|
||||
disabled={status === ComponentStatus.Disabled}
|
||||
maxLength={maxLength}
|
||||
/>
|
||||
{this.icon}
|
||||
{this.statusIndicator}
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
// Libraries
|
||||
import React, {Component} from 'react'
|
||||
|
||||
// Components
|
||||
import {PageHeader} from 'src/page_layout'
|
||||
import AutoRefreshDropdown from 'src/shared/components/AutoRefreshDropdown'
|
||||
import TimeRangeDropdown from 'src/shared/components/TimeRangeDropdown'
|
||||
import GraphTips from 'src/shared/components/graph_tips/GraphTips'
|
||||
import RenameDashboard from 'src/dashboards/components/rename_dashboard/RenameDashboard'
|
||||
import DashboardSwitcher from 'src/dashboards/components/DashboardSwitcher'
|
||||
import {Button, ButtonShape, ComponentColor, IconFont} from 'src/clockface'
|
||||
|
||||
// Types
|
||||
import * as AppActions from 'src/types/actions/app'
|
||||
import * as QueriesModels from 'src/types/queries'
|
||||
import {Dashboard, DashboardSwitcherLinks} from 'src/types/v2/dashboards'
|
||||
|
@ -37,24 +40,6 @@ class DashboardHeader extends Component<Props> {
|
|||
}
|
||||
|
||||
public render() {
|
||||
return (
|
||||
<PageHeader fullWidth={true}>
|
||||
<PageHeader.Left>{this.renderPageTitle}</PageHeader.Left>
|
||||
<PageHeader.Right>{this.optionsComponents}</PageHeader.Right>
|
||||
</PageHeader>
|
||||
)
|
||||
}
|
||||
|
||||
private get renderPageTitle(): JSX.Element {
|
||||
return (
|
||||
<>
|
||||
{this.dashboardSwitcher}
|
||||
{this.dashboardTitle}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
private get optionsComponents(): JSX.Element {
|
||||
const {
|
||||
handleChooseAutoRefresh,
|
||||
onManualRefresh,
|
||||
|
@ -65,29 +50,32 @@ class DashboardHeader extends Component<Props> {
|
|||
} = this.props
|
||||
|
||||
return (
|
||||
<>
|
||||
<GraphTips />
|
||||
{this.addCellButton}
|
||||
<AutoRefreshDropdown
|
||||
onChoose={handleChooseAutoRefresh}
|
||||
onManualRefresh={onManualRefresh}
|
||||
selected={autoRefresh}
|
||||
iconName="refresh"
|
||||
/>
|
||||
<TimeRangeDropdown
|
||||
onChooseTimeRange={handleChooseTimeRange}
|
||||
selected={{
|
||||
upper: zoomedUpper || upper,
|
||||
lower: zoomedLower || lower,
|
||||
}}
|
||||
/>
|
||||
<button
|
||||
className="btn btn-default btn-sm btn-square"
|
||||
onClick={this.handleClickPresentationButton}
|
||||
>
|
||||
<span className="icon expand-a" />
|
||||
</button>
|
||||
</>
|
||||
<PageHeader fullWidth={true}>
|
||||
<PageHeader.Left>{this.dashboardTitle}</PageHeader.Left>
|
||||
<PageHeader.Right>
|
||||
<GraphTips />
|
||||
{this.addCellButton}
|
||||
<AutoRefreshDropdown
|
||||
onChoose={handleChooseAutoRefresh}
|
||||
onManualRefresh={onManualRefresh}
|
||||
selected={autoRefresh}
|
||||
iconName="refresh"
|
||||
/>
|
||||
<TimeRangeDropdown
|
||||
onChooseTimeRange={handleChooseTimeRange}
|
||||
selected={{
|
||||
upper: zoomedUpper || upper,
|
||||
lower: zoomedLower || lower,
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
icon={IconFont.ExpandA}
|
||||
titleText="Enter Presentation Mode"
|
||||
shape={ButtonShape.Square}
|
||||
onClick={this.handleClickPresentationButton}
|
||||
/>
|
||||
</PageHeader.Right>
|
||||
</PageHeader>
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -100,22 +88,17 @@ class DashboardHeader extends Component<Props> {
|
|||
|
||||
if (dashboard) {
|
||||
return (
|
||||
<button className="btn btn-primary btn-sm" onClick={onAddCell}>
|
||||
<span className="icon plus" />
|
||||
Add Cell
|
||||
</button>
|
||||
<Button
|
||||
shape={ButtonShape.Square}
|
||||
icon={IconFont.AddCell}
|
||||
color={ComponentColor.Primary}
|
||||
onClick={onAddCell}
|
||||
titleText="Add cell to dashboard"
|
||||
/>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private get dashboardSwitcher(): JSX.Element {
|
||||
const {dashboardLinks} = this.props
|
||||
|
||||
if (dashboardLinks.links.length > 1) {
|
||||
return <DashboardSwitcher dashboardLinks={dashboardLinks} />
|
||||
}
|
||||
}
|
||||
|
||||
private get dashboardTitle(): JSX.Element {
|
||||
const {dashboard, activeDashboard, onRenameDashboard} = this.props
|
||||
|
||||
|
|
|
@ -3,39 +3,38 @@
|
|||
------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
$rename-dash-title-padding: 7px;
|
||||
$rename-dash-title-padding: 8px;
|
||||
|
||||
.rename-dashboard {
|
||||
height: $form-sm-height;
|
||||
min-width: 0;
|
||||
width: 100%;;
|
||||
width: 100%;
|
||||
}
|
||||
.dashboard-switcher + .rename-dashboard {
|
||||
width: calc(100% - 38px);
|
||||
|
||||
.rename-dashboard--title,
|
||||
.rename-dashboard--input {
|
||||
position: relative;
|
||||
width: calc(100% + #{$rename-dash-title-padding});
|
||||
left: -$rename-dash-title-padding;
|
||||
height: $form-sm-height;
|
||||
border: $ix-border solid transparent;
|
||||
padding: 0 $form-sm-height 0 $rename-dash-title-padding;
|
||||
border-radius: $radius;
|
||||
font-size: $page-title-size;
|
||||
font-weight: $page-title-weight;
|
||||
font-family: $ix-text-font;
|
||||
word-spacing: 0.3em;
|
||||
}
|
||||
|
||||
.rename-dashboard--title {
|
||||
width: 100%;
|
||||
position: relative;
|
||||
padding: 0 $form-sm-height 0 $rename-dash-title-padding;
|
||||
border: $ix-border solid $g0-obsidian;
|
||||
height: $form-sm-height;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
border-radius: $radius;
|
||||
@include no-user-select();
|
||||
color: $g17-whisper;
|
||||
transition:
|
||||
color 0.25s ease,
|
||||
background-color 0.25s ease,
|
||||
border-color 0.25s ease;
|
||||
text-transform: none;
|
||||
letter-spacing: 0;
|
||||
line-height: $form-sm-height - $ix-border;
|
||||
margin: 0;
|
||||
font-size: $page-header-size;
|
||||
font-weight: $page-header-weight;
|
||||
transition: color 0.25s ease, background-color 0.25s ease, border-color 0.25s ease;
|
||||
line-height: $form-sm-height - ($ix-border * 2);
|
||||
|
||||
.icon {
|
||||
position: absolute;
|
||||
|
@ -60,8 +59,11 @@ $rename-dash-title-padding: 7px;
|
|||
}
|
||||
}
|
||||
|
||||
input.form-control.input-sm.rename-dashboard--input {
|
||||
padding: 0 $rename-dash-title-padding;
|
||||
font-size: $page-header-size;
|
||||
font-weight: $page-header-weight;
|
||||
.rename-dashboard--input {
|
||||
color: $g20-white;
|
||||
background-color: $g2-kevlar;
|
||||
|
||||
&:focus {
|
||||
border-color: $c-pool;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
import React, {Component, KeyboardEvent} from 'react'
|
||||
// Libraries
|
||||
import React, {Component, KeyboardEvent, ChangeEvent} from 'react'
|
||||
|
||||
// Constants
|
||||
import {DASHBOARD_NAME_MAX_LENGTH} from 'src/dashboards/constants/index'
|
||||
|
||||
// Decorators
|
||||
import {ErrorHandling} from 'src/shared/decorators/errors'
|
||||
import {
|
||||
DASHBOARD_NAME_MAX_LENGTH,
|
||||
DEFAULT_DASHBOARD_NAME,
|
||||
} from 'src/dashboards/constants/index'
|
||||
|
||||
interface Props {
|
||||
onRename: (name: string) => void
|
||||
|
@ -12,18 +14,17 @@ interface Props {
|
|||
|
||||
interface State {
|
||||
isEditing: boolean
|
||||
reset: boolean
|
||||
workingName: string
|
||||
}
|
||||
|
||||
@ErrorHandling
|
||||
class RenameDashboard extends Component<Props, State> {
|
||||
private inputRef: HTMLInputElement
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props)
|
||||
|
||||
this.state = {
|
||||
isEditing: false,
|
||||
reset: false,
|
||||
workingName: props.name,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -49,22 +50,21 @@ class RenameDashboard extends Component<Props, State> {
|
|||
}
|
||||
|
||||
private get input(): JSX.Element {
|
||||
const {name} = this.props
|
||||
const {workingName} = this.state
|
||||
|
||||
return (
|
||||
<input
|
||||
maxLength={DASHBOARD_NAME_MAX_LENGTH}
|
||||
type="text"
|
||||
className="rename-dashboard--input form-control input-sm"
|
||||
defaultValue={name}
|
||||
autoComplete="off"
|
||||
value={workingName}
|
||||
autoFocus={true}
|
||||
spellCheck={false}
|
||||
onBlur={this.handleInputBlur}
|
||||
onKeyDown={this.handleKeyDown}
|
||||
onFocus={this.handleFocus}
|
||||
placeholder="Name this Dashboard"
|
||||
ref={r => (this.inputRef = r)}
|
||||
onFocus={this.handleInputFocus}
|
||||
onBlur={this.handleInputBlur(false)}
|
||||
onChange={this.handleInputChange}
|
||||
onKeyDown={this.handleKeyDown}
|
||||
className="rename-dashboard--input"
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
@ -73,31 +73,34 @@ class RenameDashboard extends Component<Props, State> {
|
|||
this.setState({isEditing: true})
|
||||
}
|
||||
|
||||
private handleInputBlur = e => {
|
||||
private handleInputChange = (e: ChangeEvent<HTMLInputElement>): void => {
|
||||
this.setState({workingName: e.target.value})
|
||||
}
|
||||
|
||||
private handleInputBlur = (reset: boolean) => (): void => {
|
||||
const {onRename} = this.props
|
||||
const {reset} = this.state
|
||||
|
||||
if (reset) {
|
||||
this.setState({isEditing: false})
|
||||
onRename(this.props.name)
|
||||
} else {
|
||||
const newName = e.target.value || DEFAULT_DASHBOARD_NAME
|
||||
onRename(newName)
|
||||
onRename(this.state.workingName)
|
||||
}
|
||||
this.setState({isEditing: false, reset: false})
|
||||
|
||||
this.setState({isEditing: false})
|
||||
}
|
||||
|
||||
private handleKeyDown = (e: KeyboardEvent<HTMLInputElement>): void => {
|
||||
if (e.key === 'Enter') {
|
||||
this.inputRef.blur()
|
||||
this.handleInputBlur(false)()
|
||||
}
|
||||
|
||||
if (e.key === 'Escape') {
|
||||
this.inputRef.value = this.props.name
|
||||
this.setState({reset: true}, () => this.inputRef.blur())
|
||||
this.handleInputBlur(true)()
|
||||
}
|
||||
}
|
||||
|
||||
private handleFocus = (e): void => {
|
||||
e.target.select()
|
||||
private handleInputFocus = (e: ChangeEvent<HTMLInputElement>): void => {
|
||||
e.currentTarget.select()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue