Refactor dashboard naming flow and associated UI
parent
1fe6d76f7e
commit
2c3ab050d7
|
@ -1,49 +1,44 @@
|
|||
import React, {PropTypes} from 'react'
|
||||
import classnames from 'classnames'
|
||||
import _ from 'lodash'
|
||||
|
||||
import AutoRefreshDropdown from 'shared/components/AutoRefreshDropdown'
|
||||
import TimeRangeDropdown from 'shared/components/TimeRangeDropdown'
|
||||
import SourceIndicator from 'shared/components/SourceIndicator'
|
||||
import GraphTips from 'shared/components/GraphTips'
|
||||
import DashboardHeaderEdit from 'src/dashboards/components/DashboardHeaderEdit'
|
||||
|
||||
const DashboardHeader = ({
|
||||
onSave,
|
||||
children,
|
||||
buttonText,
|
||||
dashboard,
|
||||
timeRange: {upper, lower},
|
||||
zoomedTimeRange: {zoomedLower, zoomedUpper},
|
||||
autoRefresh,
|
||||
onCancel,
|
||||
isEditMode,
|
||||
isHidden,
|
||||
dashboard,
|
||||
onAddCell,
|
||||
autoRefresh,
|
||||
dashboardName,
|
||||
onEditDashboard,
|
||||
onManualRefresh,
|
||||
handleChooseTimeRange,
|
||||
handleChooseAutoRefresh,
|
||||
onManualRefresh,
|
||||
handleClickPresentationButton,
|
||||
onAddCell,
|
||||
onEditDashboard,
|
||||
onToggleTempVarControls,
|
||||
showTemplateControlBar,
|
||||
timeRange: {upper, lower},
|
||||
handleClickPresentationButton,
|
||||
zoomedTimeRange: {zoomedLower, zoomedUpper},
|
||||
}) =>
|
||||
isHidden
|
||||
? null
|
||||
: <div className="page-header full-width">
|
||||
<div className="page-header__container">
|
||||
<div className="page-header__left">
|
||||
{buttonText &&
|
||||
<div className="dropdown page-header-dropdown">
|
||||
<button
|
||||
className="dropdown-toggle"
|
||||
type="button"
|
||||
data-toggle="dropdown"
|
||||
>
|
||||
<span>
|
||||
{buttonText}
|
||||
</span>
|
||||
<span className="caret" />
|
||||
</button>
|
||||
<ul className="dropdown-menu">
|
||||
{children}
|
||||
</ul>
|
||||
</div>}
|
||||
<div
|
||||
className={
|
||||
dashboard
|
||||
? 'page-header__left page-header__dash-editable'
|
||||
: 'page-header__left'
|
||||
}
|
||||
>
|
||||
{children.length > 1
|
||||
? <div className="dropdown dashboard-switcher">
|
||||
<button
|
||||
|
@ -60,6 +55,17 @@ const DashboardHeader = ({
|
|||
</ul>
|
||||
</div>
|
||||
: null}
|
||||
{dashboard
|
||||
? <DashboardHeaderEdit
|
||||
onSave={onSave}
|
||||
onCancel={onCancel}
|
||||
dashboardName={dashboardName}
|
||||
onEditDashboard={onEditDashboard}
|
||||
isEditMode={isEditMode}
|
||||
/>
|
||||
: <h1 className="page-header__title">
|
||||
{dashboardName}
|
||||
</h1>}
|
||||
</div>
|
||||
<div className="page-header__right">
|
||||
<GraphTips />
|
||||
|
@ -70,15 +76,6 @@ const DashboardHeader = ({
|
|||
Add Cell
|
||||
</button>
|
||||
: null}
|
||||
{dashboard
|
||||
? <button
|
||||
className="btn btn-default btn-sm"
|
||||
onClick={onEditDashboard}
|
||||
>
|
||||
<span className="icon pencil" />
|
||||
Rename
|
||||
</button>
|
||||
: null}
|
||||
{dashboard
|
||||
? <div
|
||||
className={classnames('btn btn-default btn-sm', {
|
||||
|
@ -123,7 +120,8 @@ DashboardHeader.defaultProps = {
|
|||
|
||||
DashboardHeader.propTypes = {
|
||||
children: array,
|
||||
buttonText: string,
|
||||
dashboardName: string.isRequired,
|
||||
onEditDashboard: func.isRequired,
|
||||
dashboard: shape({}),
|
||||
timeRange: shape({
|
||||
lower: string,
|
||||
|
@ -131,15 +129,17 @@ DashboardHeader.propTypes = {
|
|||
}).isRequired,
|
||||
autoRefresh: number.isRequired,
|
||||
isHidden: bool.isRequired,
|
||||
isEditMode: bool,
|
||||
handleChooseTimeRange: func.isRequired,
|
||||
handleChooseAutoRefresh: func.isRequired,
|
||||
onManualRefresh: func.isRequired,
|
||||
handleClickPresentationButton: func.isRequired,
|
||||
onAddCell: func,
|
||||
onEditDashboard: func,
|
||||
onToggleTempVarControls: func,
|
||||
showTemplateControlBar: bool,
|
||||
zoomedTimeRange: shape({}),
|
||||
onCancel: func.isRequired,
|
||||
onSave: func.isRequired,
|
||||
}
|
||||
|
||||
export default DashboardHeader
|
||||
|
|
|
@ -1,70 +1,76 @@
|
|||
import React, {PropTypes, Component} from 'react'
|
||||
import ConfirmButtons from 'shared/components/ConfirmButtons'
|
||||
import {
|
||||
DASHBOARD_NAME_MAX_LENGTH,
|
||||
NEW_DASHBOARD,
|
||||
} from 'src/dashboards/constants/index'
|
||||
|
||||
class DashboardEditHeader extends Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
|
||||
const {dashboard: {name}} = props
|
||||
this.state = {
|
||||
name,
|
||||
reset: false,
|
||||
}
|
||||
}
|
||||
|
||||
handleChange = e => {
|
||||
this.setState({name: e.target.value})
|
||||
}
|
||||
handleInputBlur = e => {
|
||||
const {onSave, onCancel} = this.props
|
||||
const {reset} = this.state
|
||||
|
||||
handleFormSubmit = e => {
|
||||
e.preventDefault()
|
||||
const name = e.target.name.value
|
||||
this.props.onSave(name)
|
||||
}
|
||||
|
||||
handleKeyUp = e => {
|
||||
const {onCancel} = this.props
|
||||
if (e.key === 'Escape') {
|
||||
if (reset) {
|
||||
onCancel()
|
||||
} else {
|
||||
const newName = e.target.value || NEW_DASHBOARD.name
|
||||
onSave(newName)
|
||||
}
|
||||
this.setState({reset: false})
|
||||
}
|
||||
|
||||
handleKeyDown = e => {
|
||||
if (e.key === 'Enter') {
|
||||
this.inputRef.blur()
|
||||
}
|
||||
if (e.key === 'Escape') {
|
||||
this.inputRef.value = this.props.dashboardName
|
||||
this.setState({reset: true}, () => this.inputRef.blur())
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const {onSave, onCancel} = this.props
|
||||
const {name} = this.state
|
||||
const {onEditDashboard, isEditMode, dashboardName} = this.props
|
||||
|
||||
return (
|
||||
<div className="page-header full-width">
|
||||
<div className="page-header__container">
|
||||
<form
|
||||
className="page-header__left"
|
||||
style={{flex: '1 0 0%'}}
|
||||
onSubmit={this.handleFormSubmit}
|
||||
>
|
||||
<input
|
||||
className="page-header--editing"
|
||||
name="name"
|
||||
value={name}
|
||||
placeholder="Name this Dashboard"
|
||||
onKeyUp={this.handleKeyUp}
|
||||
<div className="dashboard-title">
|
||||
{isEditMode
|
||||
? <input
|
||||
maxLength={DASHBOARD_NAME_MAX_LENGTH}
|
||||
type="text"
|
||||
className="dashboard-title--input form-control"
|
||||
defaultValue={dashboardName}
|
||||
autoComplete="off"
|
||||
autoFocus={true}
|
||||
spellCheck={false}
|
||||
autoComplete="off"
|
||||
onChange={this.handleChange}
|
||||
onBlur={this.handleInputBlur}
|
||||
onKeyDown={this.handleKeyDown}
|
||||
placeholder="Name this Dashboard"
|
||||
ref={r => (this.inputRef = r)}
|
||||
/>
|
||||
</form>
|
||||
<ConfirmButtons item={name} onConfirm={onSave} onCancel={onCancel} />
|
||||
</div>
|
||||
: <h1 onClick={onEditDashboard}>
|
||||
{dashboardName}
|
||||
</h1>}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const {shape, func} = PropTypes
|
||||
const {bool, func, string} = PropTypes
|
||||
|
||||
DashboardEditHeader.propTypes = {
|
||||
dashboard: shape({}),
|
||||
onCancel: func.isRequired,
|
||||
dashboardName: string.isRequired,
|
||||
onSave: func.isRequired,
|
||||
onCancel: func.isRequired,
|
||||
isEditMode: bool,
|
||||
onEditDashboard: func.isRequired,
|
||||
}
|
||||
|
||||
export default DashboardEditHeader
|
||||
|
|
|
@ -109,3 +109,5 @@ export const TOOLTIP_CONTENT = {
|
|||
|
||||
export const TYPE_QUERY_CONFIG = 'queryConfig'
|
||||
export const TYPE_IFQL = 'ifql'
|
||||
|
||||
export const DASHBOARD_NAME_MAX_LENGTH = 50
|
||||
|
|
|
@ -8,7 +8,6 @@ import Dygraph from 'src/external/dygraph'
|
|||
import OverlayTechnologies from 'shared/components/OverlayTechnologies'
|
||||
import CellEditorOverlay from 'src/dashboards/components/CellEditorOverlay'
|
||||
import DashboardHeader from 'src/dashboards/components/DashboardHeader'
|
||||
import DashboardHeaderEdit from 'src/dashboards/components/DashboardHeaderEdit'
|
||||
import Dashboard from 'src/dashboards/components/Dashboard'
|
||||
import TemplateVariableManager from 'src/dashboards/components/template_variables/Manager'
|
||||
import ManualRefresh from 'src/shared/components/ManualRefresh'
|
||||
|
@ -309,40 +308,36 @@ class DashboardPage extends Component {
|
|||
editQueryStatus={dashboardActions.editCellQueryStatus}
|
||||
/>
|
||||
: null}
|
||||
{isEditMode
|
||||
? <DashboardHeaderEdit
|
||||
dashboard={dashboard}
|
||||
onSave={this.handleRenameDashboard}
|
||||
onCancel={this.handleCancelEditDashboard}
|
||||
/>
|
||||
: <DashboardHeader
|
||||
source={source}
|
||||
sourceID={sourceID}
|
||||
dashboard={dashboard}
|
||||
timeRange={timeRange}
|
||||
zoomedTimeRange={zoomedTimeRange}
|
||||
autoRefresh={autoRefresh}
|
||||
isHidden={inPresentationMode}
|
||||
onAddCell={this.handleAddCell}
|
||||
onEditDashboard={this.handleEditDashboard}
|
||||
buttonText={dashboard ? dashboard.name : ''}
|
||||
showTemplateControlBar={showTemplateControlBar}
|
||||
handleChooseAutoRefresh={handleChooseAutoRefresh}
|
||||
onManualRefresh={onManualRefresh}
|
||||
handleChooseTimeRange={this.handleChooseTimeRange}
|
||||
onToggleTempVarControls={this.handleToggleTempVarControls}
|
||||
handleClickPresentationButton={handleClickPresentationButton}
|
||||
>
|
||||
{dashboards
|
||||
? dashboards.map((d, i) =>
|
||||
<li className="dropdown-item" key={i}>
|
||||
<Link to={`/sources/${sourceID}/dashboards/${d.id}`}>
|
||||
{d.name}
|
||||
</Link>
|
||||
</li>
|
||||
)
|
||||
: null}
|
||||
</DashboardHeader>}
|
||||
<DashboardHeader
|
||||
source={source}
|
||||
sourceID={sourceID}
|
||||
dashboard={dashboard}
|
||||
timeRange={timeRange}
|
||||
isEditMode={isEditMode}
|
||||
autoRefresh={autoRefresh}
|
||||
isHidden={inPresentationMode}
|
||||
onAddCell={this.handleAddCell}
|
||||
zoomedTimeRange={zoomedTimeRange}
|
||||
onSave={this.handleRenameDashboard}
|
||||
onCancel={this.handleCancelEditDashboard}
|
||||
onEditDashboard={this.handleEditDashboard}
|
||||
dashboardName={dashboard ? dashboard.name : ''}
|
||||
showTemplateControlBar={showTemplateControlBar}
|
||||
handleChooseAutoRefresh={handleChooseAutoRefresh}
|
||||
handleChooseTimeRange={this.handleChooseTimeRange}
|
||||
onToggleTempVarControls={this.handleToggleTempVarControls}
|
||||
handleClickPresentationButton={handleClickPresentationButton}
|
||||
>
|
||||
{dashboards
|
||||
? dashboards.map((d, i) =>
|
||||
<li className="dropdown-item" key={i}>
|
||||
<Link to={`/sources/${sourceID}/dashboards/${d.id}`}>
|
||||
{d.name}
|
||||
</Link>
|
||||
</li>
|
||||
)
|
||||
: null}
|
||||
</DashboardHeader>
|
||||
{dashboard
|
||||
? <Dashboard
|
||||
source={source}
|
||||
|
|
|
@ -182,7 +182,7 @@ class HostPage extends Component {
|
|||
<div className="page">
|
||||
<DashboardHeader
|
||||
source={source}
|
||||
buttonText={hostID}
|
||||
dashboardName={hostID}
|
||||
timeRange={timeRange}
|
||||
autoRefresh={autoRefresh}
|
||||
isHidden={inPresentationMode}
|
||||
|
|
|
@ -340,8 +340,48 @@ $tick-script-overlay-margin: 30px;
|
|||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
.dropdown.dashboard-switcher {
|
||||
margin-right: 4px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
.dropdown.dashboard-switcher .btn.dropdown-toggle {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
/*
|
||||
Dashboard Name Editing
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
.page-header__left.page-header__dash-editable,
|
||||
.dashboard-title,
|
||||
.dashboard-title input[type="text"].form-control.dashboard-title--input {
|
||||
flex: 1 0 0;
|
||||
}
|
||||
.dashboard-title {
|
||||
display: flex;
|
||||
|
||||
input[type="text"].form-control.dashboard-title--input,
|
||||
input[type="text"].form-control.dashboard-title--input:focus {
|
||||
border: 0;
|
||||
border-radius: 0;
|
||||
padding: 0;
|
||||
font-size: $page-header-size;
|
||||
font-weight: $page-header-weight;
|
||||
color: $c-pool;
|
||||
box-shadow: none;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 0;
|
||||
letter-spacing: 0;
|
||||
text-transform: none;
|
||||
font-size: $page-header-size;
|
||||
font-weight: $page-header-weight;
|
||||
transition: color 0.25s ease;
|
||||
|
||||
&:hover {
|
||||
cursor: text;
|
||||
color: $c-pool;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue