commit
9208e76e2c
|
@ -12,6 +12,10 @@
|
|||
1. [#1992](https://github.com/influxdata/chronograf/pull/1992): Add .csv download button to data explorer
|
||||
|
||||
### UI Improvements
|
||||
1. [#2002](https://github.com/influxdata/chronograf/pull/2002): Require a second click when deleting a dashboard cell
|
||||
1. [#2002](https://github.com/influxdata/chronograf/pull/2002): Sort database list in Schema Explorer alphabetically
|
||||
1. [#2002](https://github.com/influxdata/chronograf/pull/2002): Improve usability of dashboard cell context menus
|
||||
1. [#2002](https://github.com/influxdata/chronograf/pull/2002): Move dashboard cell renaming UI into Cell Editor Overlay
|
||||
|
||||
## v1.3.8.1 [unreleased]
|
||||
### Bug Fixes
|
||||
|
|
|
@ -179,6 +179,10 @@ class CellEditorOverlay extends Component {
|
|||
})
|
||||
}
|
||||
|
||||
handleCellRename = newName => {
|
||||
this.setState({cellWorkingName: newName})
|
||||
}
|
||||
|
||||
handleSetScale = scale => () => {
|
||||
const {axes} = this.state
|
||||
|
||||
|
@ -263,6 +267,7 @@ class CellEditorOverlay extends Component {
|
|||
autoRefresh={autoRefresh}
|
||||
queryConfigs={queriesWorkingDraft}
|
||||
editQueryStatus={editQueryStatus}
|
||||
onCellRename={this.handleCellRename}
|
||||
/>
|
||||
<CEOBottom>
|
||||
<OverlayControls
|
||||
|
|
|
@ -10,11 +10,8 @@ const Dashboard = ({
|
|||
onZoom,
|
||||
dashboard,
|
||||
onAddCell,
|
||||
onEditCell,
|
||||
timeRange,
|
||||
autoRefresh,
|
||||
onRenameCell,
|
||||
onUpdateCell,
|
||||
onDeleteCell,
|
||||
synchronizer,
|
||||
onPositionChange,
|
||||
|
@ -24,7 +21,6 @@ const Dashboard = ({
|
|||
onSummonOverlayTechnologies,
|
||||
onSelectTemplate,
|
||||
showTemplateControlBar,
|
||||
onCancelEditCell,
|
||||
}) => {
|
||||
const cells = dashboard.cells.map(cell => {
|
||||
const dashboardCell = {...cell}
|
||||
|
@ -58,7 +54,6 @@ const Dashboard = ({
|
|||
/>}
|
||||
{cells.length
|
||||
? <LayoutRenderer
|
||||
onCancelEditCell={onCancelEditCell}
|
||||
templates={templatesIncludingDashTime}
|
||||
isEditable={true}
|
||||
cells={cells}
|
||||
|
@ -66,9 +61,6 @@ const Dashboard = ({
|
|||
autoRefresh={autoRefresh}
|
||||
source={source}
|
||||
onPositionChange={onPositionChange}
|
||||
onEditCell={onEditCell}
|
||||
onRenameCell={onRenameCell}
|
||||
onUpdateCell={onUpdateCell}
|
||||
onDeleteCell={onDeleteCell}
|
||||
onSummonOverlayTechnologies={onSummonOverlayTechnologies}
|
||||
synchronizer={synchronizer}
|
||||
|
@ -112,9 +104,6 @@ Dashboard.propTypes = {
|
|||
inPresentationMode: bool,
|
||||
onAddCell: func,
|
||||
onPositionChange: func,
|
||||
onEditCell: func,
|
||||
onRenameCell: func,
|
||||
onUpdateCell: func,
|
||||
onDeleteCell: func,
|
||||
onSummonOverlayTechnologies: func,
|
||||
synchronizer: func,
|
||||
|
@ -128,7 +117,6 @@ Dashboard.propTypes = {
|
|||
onOpenTemplateManager: func.isRequired,
|
||||
onSelectTemplate: func.isRequired,
|
||||
showTemplateControlBar: bool,
|
||||
onCancelEditCell: func,
|
||||
onZoom: func,
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import React, {PropTypes} from 'react'
|
||||
import RefreshingGraph from 'shared/components/RefreshingGraph'
|
||||
import buildQueries from 'utils/buildQueriesForGraphs'
|
||||
import VisualizationName from 'src/dashboards/components/VisualizationName'
|
||||
|
||||
const DashVisualization = (
|
||||
{
|
||||
|
@ -10,17 +11,14 @@ const DashVisualization = (
|
|||
templates,
|
||||
timeRange,
|
||||
autoRefresh,
|
||||
onCellRename,
|
||||
queryConfigs,
|
||||
editQueryStatus,
|
||||
},
|
||||
{source: {links: {proxy}}}
|
||||
) =>
|
||||
<div className="graph">
|
||||
<div className="graph-heading">
|
||||
<div className="graph-title">
|
||||
{name}
|
||||
</div>
|
||||
</div>
|
||||
<VisualizationName defaultName={name} onCellRename={onCellRename} />
|
||||
<div className="graph-container">
|
||||
<RefreshingGraph
|
||||
axes={axes}
|
||||
|
@ -56,6 +54,7 @@ DashVisualization.propTypes = {
|
|||
bounds: arrayOf(string),
|
||||
}),
|
||||
}),
|
||||
onCellRename: func,
|
||||
}
|
||||
|
||||
DashVisualization.contextTypes = {
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
import React, {Component, PropTypes} from 'react'
|
||||
|
||||
class VisualizationName extends Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
|
||||
this.state = {
|
||||
reset: false,
|
||||
}
|
||||
}
|
||||
|
||||
handleInputBlur = reset => e => {
|
||||
this.props.onCellRename(reset ? this.props.defaultName : e.target.value)
|
||||
this.setState({reset: false})
|
||||
}
|
||||
|
||||
handleKeyDown = e => {
|
||||
if (e.key === 'Enter') {
|
||||
this.inputRef.blur()
|
||||
}
|
||||
if (e.key === 'Escape') {
|
||||
this.inputRef.value = this.props.defaultName
|
||||
this.setState({reset: true}, () => this.inputRef.blur())
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const {defaultName} = this.props
|
||||
const {reset} = this.state
|
||||
|
||||
return (
|
||||
<div className="graph-heading">
|
||||
<input
|
||||
type="text"
|
||||
className="form-control input-md"
|
||||
defaultValue={defaultName}
|
||||
onBlur={this.handleInputBlur(reset)}
|
||||
onKeyDown={this.handleKeyDown}
|
||||
placeholder="Name this Cell..."
|
||||
ref={r => (this.inputRef = r)}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const {string, func} = PropTypes
|
||||
|
||||
VisualizationName.propTypes = {
|
||||
defaultName: string.isRequired,
|
||||
onCellRename: func,
|
||||
}
|
||||
|
||||
export default VisualizationName
|
|
@ -17,7 +17,7 @@ export const NEW_DEFAULT_DASHBOARD_CELL = {
|
|||
y: 0,
|
||||
w: 4,
|
||||
h: 4,
|
||||
name: 'Name This Graph',
|
||||
name: 'Untitled Cell',
|
||||
type: 'line',
|
||||
queries: [],
|
||||
}
|
||||
|
|
|
@ -110,18 +110,6 @@ class DashboardPage extends Component {
|
|||
this.props.dashboardActions.putDashboard(newDashboard)
|
||||
}
|
||||
|
||||
// Places cell into editing mode.
|
||||
handleEditDashboardCell = (x, y, isEditing) => {
|
||||
return () => {
|
||||
this.props.dashboardActions.editDashboardCell(
|
||||
this.getActiveDashboard(),
|
||||
x,
|
||||
y,
|
||||
!isEditing
|
||||
) /* eslint-disable no-negated-condition */
|
||||
}
|
||||
}
|
||||
|
||||
handleUpdateDashboardCell = newCell => {
|
||||
return () => {
|
||||
this.props.dashboardActions.updateDashboardCell(
|
||||
|
@ -187,13 +175,6 @@ class DashboardPage extends Component {
|
|||
this.props.templateControlBarVisibilityToggled()
|
||||
}
|
||||
|
||||
handleCancelEditCell = cellID => {
|
||||
this.props.dashboardActions.cancelEditCell(
|
||||
this.getActiveDashboard().id,
|
||||
cellID
|
||||
)
|
||||
}
|
||||
|
||||
handleZoomedTimeRange = (zoomedLower, zoomedUpper) => {
|
||||
this.setState({zoomedTimeRange: {zoomedLower, zoomedUpper}})
|
||||
}
|
||||
|
@ -350,12 +331,9 @@ class DashboardPage extends Component {
|
|||
onAddCell={this.handleAddCell}
|
||||
synchronizer={this.synchronizer}
|
||||
inPresentationMode={inPresentationMode}
|
||||
onEditCell={this.handleEditDashboardCell}
|
||||
onPositionChange={this.handleUpdatePosition}
|
||||
onSelectTemplate={this.handleSelectTemplate}
|
||||
onCancelEditCell={this.handleCancelEditCell}
|
||||
onDeleteCell={this.handleDeleteDashboardCell}
|
||||
onUpdateCell={this.handleUpdateDashboardCell}
|
||||
showTemplateControlBar={showTemplateControlBar}
|
||||
onOpenTemplateManager={this.handleOpenTemplateManager}
|
||||
templatesIncludingDashTime={templatesIncludingDashTime}
|
||||
|
|
|
@ -1,46 +0,0 @@
|
|||
import React, {PropTypes} from 'react'
|
||||
import classnames from 'classnames'
|
||||
import OnClickOutside from 'react-onclickoutside'
|
||||
|
||||
const ContextMenu = OnClickOutside(
|
||||
({isOpen, toggleMenu, onEdit, onRename, onDelete, cell}) =>
|
||||
<div
|
||||
className={classnames('dash-graph--options', {
|
||||
'dash-graph--options-show': isOpen,
|
||||
})}
|
||||
onClick={toggleMenu}
|
||||
>
|
||||
<button className="btn btn-info btn-xs">
|
||||
<span className="icon caret-down" />
|
||||
</button>
|
||||
<ul className="dash-graph--options-menu">
|
||||
<li onClick={onEdit(cell)}>Edit</li>
|
||||
<li onClick={onRename(cell.x, cell.y, cell.isEditing)}>Rename</li>
|
||||
<li onClick={onDelete(cell)}>Delete</li>
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
|
||||
const ContextMenuContainer = props => {
|
||||
if (!props.isEditable) {
|
||||
return null
|
||||
}
|
||||
|
||||
return <ContextMenu {...props} />
|
||||
}
|
||||
|
||||
const {bool, func, shape} = PropTypes
|
||||
|
||||
ContextMenuContainer.propTypes = {
|
||||
isOpen: bool,
|
||||
toggleMenu: func,
|
||||
onEdit: func,
|
||||
onRename: func,
|
||||
onDelete: func,
|
||||
cell: shape(),
|
||||
isEditable: bool,
|
||||
}
|
||||
|
||||
ContextMenu.propTypes = ContextMenuContainer.propTypes
|
||||
|
||||
export default ContextMenuContainer
|
|
@ -64,13 +64,17 @@ const DatabaseList = React.createClass({
|
|||
|
||||
render() {
|
||||
const {query, onChooseNamespace} = this.props
|
||||
const {namespaces} = this.state
|
||||
const sortedNamespaces = namespaces.length
|
||||
? _.sortBy(namespaces, n => n.database.toLowerCase())
|
||||
: namespaces
|
||||
|
||||
return (
|
||||
<div className="query-builder--column query-builder--column-db">
|
||||
<div className="query-builder--heading">Databases</div>
|
||||
<div className="query-builder--list">
|
||||
<FancyScrollbar>
|
||||
{this.state.namespaces.map(namespace => {
|
||||
{sortedNamespaces.map(namespace => {
|
||||
const {database, retentionPolicy} = namespace
|
||||
const isActive =
|
||||
database === query.database &&
|
||||
|
|
|
@ -1,41 +1,27 @@
|
|||
import React, {Component, PropTypes} from 'react'
|
||||
import _ from 'lodash'
|
||||
|
||||
import NameableGraphHeader from 'shared/components/NameableGraphHeader'
|
||||
import ContextMenu from 'shared/components/ContextMenu'
|
||||
import LayoutCellMenu from 'shared/components/LayoutCellMenu'
|
||||
import LayoutCellHeader from 'shared/components/LayoutCellHeader'
|
||||
|
||||
class NameableGraph extends Component {
|
||||
class LayoutCell extends Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
this.state = {
|
||||
isMenuOpen: false,
|
||||
cellName: props.cell.name,
|
||||
isDeleting: false,
|
||||
}
|
||||
}
|
||||
|
||||
toggleMenu = () => {
|
||||
this.setState({
|
||||
isMenuOpen: !this.state.isMenuOpen,
|
||||
})
|
||||
}
|
||||
|
||||
handleRenameCell = e => {
|
||||
const cellName = e.target.value
|
||||
this.setState({cellName})
|
||||
}
|
||||
|
||||
handleCancelEdit = cellID => {
|
||||
const {cell, onCancelEditCell} = this.props
|
||||
this.setState({cellName: cell.name})
|
||||
onCancelEditCell(cellID)
|
||||
}
|
||||
|
||||
closeMenu = () => {
|
||||
this.setState({
|
||||
isMenuOpen: false,
|
||||
isDeleting: false,
|
||||
})
|
||||
}
|
||||
|
||||
handleDeleteClick = () => {
|
||||
this.setState({isDeleting: true})
|
||||
}
|
||||
|
||||
handleDeleteCell = cell => () => {
|
||||
this.props.onDeleteCell(cell)
|
||||
}
|
||||
|
@ -45,31 +31,27 @@ class NameableGraph extends Component {
|
|||
}
|
||||
|
||||
render() {
|
||||
const {cell, children, isEditable, onEditCell, onUpdateCell} = this.props
|
||||
const {cell, children, isEditable} = this.props
|
||||
|
||||
const {cellName, isMenuOpen} = this.state
|
||||
const {isDeleting} = this.state
|
||||
const queries = _.get(cell, ['queries'], [])
|
||||
|
||||
return (
|
||||
<div className="dash-graph">
|
||||
<NameableGraphHeader
|
||||
cell={cell}
|
||||
cellName={cellName}
|
||||
isEditable={isEditable}
|
||||
onUpdateCell={onUpdateCell}
|
||||
onRenameCell={this.handleRenameCell}
|
||||
onCancelEditCell={this.handleCancelEdit}
|
||||
/>
|
||||
<ContextMenu
|
||||
<LayoutCellMenu
|
||||
cell={cell}
|
||||
onDeleteClick={this.handleDeleteClick}
|
||||
onDelete={this.handleDeleteCell}
|
||||
onRename={!cell.isEditing && isEditable ? onEditCell : () => {}}
|
||||
toggleMenu={this.toggleMenu}
|
||||
isOpen={isMenuOpen}
|
||||
isDeleting={isDeleting}
|
||||
isEditable={isEditable}
|
||||
handleClickOutside={this.closeMenu}
|
||||
onEdit={this.handleSummonOverlay}
|
||||
/>
|
||||
<LayoutCellHeader
|
||||
cellName={cell.name}
|
||||
queries={queries}
|
||||
isEditable={isEditable}
|
||||
/>
|
||||
<div className="dash-graph--container">
|
||||
{queries.length
|
||||
? children
|
||||
|
@ -89,7 +71,7 @@ class NameableGraph extends Component {
|
|||
|
||||
const {array, bool, func, node, number, shape, string} = PropTypes
|
||||
|
||||
NameableGraph.propTypes = {
|
||||
LayoutCell.propTypes = {
|
||||
cell: shape({
|
||||
name: string.isRequired,
|
||||
isEditing: bool,
|
||||
|
@ -98,13 +80,10 @@ NameableGraph.propTypes = {
|
|||
queries: array,
|
||||
}).isRequired,
|
||||
children: node.isRequired,
|
||||
onEditCell: func,
|
||||
onRenameCell: func,
|
||||
onUpdateCell: func,
|
||||
onDeleteCell: func,
|
||||
onSummonOverlayTechnologies: func,
|
||||
isEditable: bool,
|
||||
onCancelEditCell: func,
|
||||
}
|
||||
|
||||
export default NameableGraph
|
||||
export default LayoutCell
|
|
@ -0,0 +1,41 @@
|
|||
import React, {PropTypes} from 'react'
|
||||
import classnames from 'classnames'
|
||||
|
||||
import CustomTimeIndicator from 'shared/components/CustomTimeIndicator'
|
||||
|
||||
import {NEW_DEFAULT_DASHBOARD_CELL} from 'src/dashboards/constants/index'
|
||||
|
||||
const LayoutCellHeader = ({queries, isEditable, cellName}) => {
|
||||
const cellNameIsDefault = cellName === NEW_DEFAULT_DASHBOARD_CELL.name
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classnames('dash-graph--heading', {
|
||||
'dash-graph--heading-draggable': isEditable,
|
||||
})}
|
||||
>
|
||||
<span
|
||||
className={
|
||||
cellNameIsDefault
|
||||
? 'dash-graph--name dash-graph--name__default'
|
||||
: 'dash-graph--name'
|
||||
}
|
||||
>
|
||||
{cellName}
|
||||
{queries && queries.length
|
||||
? <CustomTimeIndicator queries={queries} />
|
||||
: null}
|
||||
</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const {array, bool, string} = PropTypes
|
||||
|
||||
LayoutCellHeader.propTypes = {
|
||||
queries: array,
|
||||
isEditable: bool,
|
||||
cellName: string,
|
||||
}
|
||||
|
||||
export default LayoutCellHeader
|
|
@ -0,0 +1,53 @@
|
|||
import React, {PropTypes} from 'react'
|
||||
import OnClickOutside from 'react-onclickoutside'
|
||||
|
||||
const LayoutCellMenu = OnClickOutside(
|
||||
({isDeleting, onEdit, onDeleteClick, onDelete, cell}) =>
|
||||
<div
|
||||
className={
|
||||
isDeleting
|
||||
? 'dash-graph-context dash-graph-context__deleting'
|
||||
: 'dash-graph-context'
|
||||
}
|
||||
>
|
||||
<div className="dash-graph-context--button" onClick={onEdit(cell)}>
|
||||
<span className="icon pencil" />
|
||||
</div>
|
||||
{isDeleting
|
||||
? <div className="dash-graph-context--button active">
|
||||
<span className="icon trash" />
|
||||
<div
|
||||
className="dash-graph-context--confirm"
|
||||
onClick={onDelete(cell)}
|
||||
>
|
||||
Confirm
|
||||
</div>
|
||||
</div>
|
||||
: <div className="dash-graph-context--button" onClick={onDeleteClick}>
|
||||
<span className="icon trash" />
|
||||
</div>}
|
||||
</div>
|
||||
)
|
||||
|
||||
const LayoutCellMenuContainer = props => {
|
||||
if (!props.isEditable) {
|
||||
return null
|
||||
}
|
||||
|
||||
return <LayoutCellMenu {...props} />
|
||||
}
|
||||
|
||||
const {bool, func, shape} = PropTypes
|
||||
|
||||
LayoutCellMenuContainer.propTypes = {
|
||||
isDeleting: bool,
|
||||
onEdit: func,
|
||||
onDelete: func,
|
||||
onDeleteClick: func,
|
||||
cell: shape(),
|
||||
isEditable: bool,
|
||||
}
|
||||
|
||||
LayoutCellMenu.propTypes = LayoutCellMenuContainer.propTypes
|
||||
|
||||
export default LayoutCellMenuContainer
|
|
@ -2,7 +2,7 @@ import React, {Component, PropTypes} from 'react'
|
|||
|
||||
import ReactGridLayout, {WidthProvider} from 'react-grid-layout'
|
||||
|
||||
import NameableGraph from 'shared/components/NameableGraph'
|
||||
import LayoutCell from 'shared/components/LayoutCell'
|
||||
import RefreshingGraph from 'shared/components/RefreshingGraph'
|
||||
import AlertsApp from 'src/alerts/containers/AlertsApp'
|
||||
import NewsFeed from 'src/status/components/NewsFeed'
|
||||
|
@ -139,8 +139,6 @@ class LayoutRenderer extends Component {
|
|||
cells,
|
||||
onEditCell,
|
||||
onCancelEditCell,
|
||||
onRenameCell,
|
||||
onUpdateCell,
|
||||
onDeleteCell,
|
||||
onSummonOverlayTechnologies,
|
||||
timeRange,
|
||||
|
@ -156,12 +154,10 @@ class LayoutRenderer extends Component {
|
|||
|
||||
return (
|
||||
<div key={cell.i}>
|
||||
<NameableGraph
|
||||
<LayoutCell
|
||||
onCancelEditCell={onCancelEditCell}
|
||||
isEditable={isEditable}
|
||||
onEditCell={onEditCell}
|
||||
onRenameCell={onRenameCell}
|
||||
onUpdateCell={onUpdateCell}
|
||||
onDeleteCell={onDeleteCell}
|
||||
onSummonOverlayTechnologies={onSummonOverlayTechnologies}
|
||||
cell={cell}
|
||||
|
@ -179,7 +175,7 @@ class LayoutRenderer extends Component {
|
|||
axes={axes}
|
||||
onZoom={onZoom}
|
||||
/>}
|
||||
</NameableGraph>
|
||||
</LayoutCell>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
|
@ -297,8 +293,6 @@ LayoutRenderer.propTypes = {
|
|||
}).isRequired,
|
||||
onPositionChange: func,
|
||||
onEditCell: func,
|
||||
onRenameCell: func,
|
||||
onUpdateCell: func,
|
||||
onDeleteCell: func,
|
||||
onSummonOverlayTechnologies: func,
|
||||
synchronizer: func,
|
||||
|
|
|
@ -1,85 +0,0 @@
|
|||
import React, {PropTypes} from 'react'
|
||||
import classnames from 'classnames'
|
||||
|
||||
import CustomTimeIndicator from 'shared/components/CustomTimeIndicator'
|
||||
|
||||
const NameableGraphHeader = ({
|
||||
onCancelEditCell,
|
||||
isEditable,
|
||||
onRenameCell,
|
||||
onUpdateCell,
|
||||
cell,
|
||||
cellName,
|
||||
cell: {i, name, queries},
|
||||
}) => {
|
||||
const isInputVisible = isEditable && cell.isEditing
|
||||
const className = classnames('dash-graph--heading', {
|
||||
'dash-graph--heading-draggable': isEditable,
|
||||
})
|
||||
const onKeyUp = evt => {
|
||||
if (evt.key === 'Enter') {
|
||||
onUpdateCell({...cell, name: cellName})()
|
||||
}
|
||||
|
||||
if (evt.key === 'Escape') {
|
||||
onCancelEditCell(i)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={className}>
|
||||
{isInputVisible
|
||||
? <GraphNameInput
|
||||
value={cellName}
|
||||
onChange={onRenameCell}
|
||||
onBlur={onUpdateCell({...cell, name: cellName})}
|
||||
onKeyUp={onKeyUp}
|
||||
/>
|
||||
: <GraphName name={name} queries={queries} />}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const {arrayOf, bool, func, string, shape} = PropTypes
|
||||
|
||||
NameableGraphHeader.propTypes = {
|
||||
cell: shape(),
|
||||
cellName: string,
|
||||
onRenameCell: func,
|
||||
onUpdateCell: func,
|
||||
isEditable: bool,
|
||||
onCancelEditCell: func,
|
||||
}
|
||||
|
||||
const GraphName = ({name, queries}) =>
|
||||
<span className="dash-graph--name">
|
||||
{name}
|
||||
{queries && queries.length
|
||||
? <CustomTimeIndicator queries={queries} />
|
||||
: null}
|
||||
</span>
|
||||
|
||||
GraphName.propTypes = {
|
||||
name: string,
|
||||
queries: arrayOf(shape()),
|
||||
}
|
||||
|
||||
const GraphNameInput = ({value, onKeyUp, onChange, onBlur}) =>
|
||||
<input
|
||||
className="form-control input-sm dash-graph--name-edit"
|
||||
type="text"
|
||||
value={value}
|
||||
autoFocus={true}
|
||||
onChange={onChange}
|
||||
onBlur={onBlur}
|
||||
onKeyUp={onKeyUp}
|
||||
/>
|
||||
|
||||
GraphNameInput.propTypes = {
|
||||
value: string,
|
||||
onKeyUp: func,
|
||||
onChange: func,
|
||||
onBlur: func,
|
||||
}
|
||||
|
||||
export default NameableGraphHeader
|
|
@ -132,7 +132,6 @@ $dash-graph-options-arrow: 8px;
|
|||
background-color: $g5-pepper;
|
||||
}
|
||||
}
|
||||
.dash-graph--name-edit,
|
||||
.dash-graph--name {
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
|
@ -142,25 +141,22 @@ $dash-graph-options-arrow: 8px;
|
|||
white-space: nowrap;
|
||||
}
|
||||
.dash-graph--name {
|
||||
position: relative;
|
||||
height: $dash-graph-heading;
|
||||
line-height: $dash-graph-heading;
|
||||
width: calc(100% - 30px);
|
||||
padding-left: 16px;
|
||||
width: calc(100% - 53px);
|
||||
padding-left: 10px;
|
||||
transition:
|
||||
color 0.25s ease,
|
||||
background-color 0.25s ease,
|
||||
border-color 0.25s ease;
|
||||
}
|
||||
input.form-control.dash-graph--name-edit {
|
||||
margin-left: 8px;
|
||||
padding: 0 6px;
|
||||
width: calc(100% - 42px);
|
||||
height: 26px !important;
|
||||
line-height: (26px - 4px) !important;
|
||||
position: relative;
|
||||
top: -1px; // Fix for slight offset
|
||||
.dash-graph--name.dash-graph--name__default {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.dash-graph--custom-time {
|
||||
font-style: normal;
|
||||
font-family: $code-font;
|
||||
color: $c-pool;
|
||||
background-color: $g2-kevlar;
|
||||
|
@ -171,111 +167,93 @@ input.form-control.dash-graph--name-edit {
|
|||
padding: 0 7px;
|
||||
position: absolute;
|
||||
top: 3px;
|
||||
right: 30px;
|
||||
}
|
||||
.presentation-mode .dash-graph--custom-time {
|
||||
right: 2px;
|
||||
}
|
||||
.dash-graph--options {
|
||||
width: $dash-graph-heading;
|
||||
|
||||
.dash-graph-context {
|
||||
z-index: 2;
|
||||
position: absolute;
|
||||
right: 0px;
|
||||
top: 0px;
|
||||
text-align: center;
|
||||
top: 0;
|
||||
right: 3px;
|
||||
height: 30px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
.dash-graph-context--button {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border-radius: 3px;
|
||||
font-size: 12px;
|
||||
position: relative;
|
||||
color: $g11-sidewalk;
|
||||
transition:
|
||||
color 0.25s ease,
|
||||
background-color 0.25s ease;
|
||||
|
||||
> .btn {
|
||||
background-color: transparent !important;
|
||||
padding: 0;
|
||||
margin: 4px 0;
|
||||
height: $dash-graph-heading-context;
|
||||
width: $dash-graph-heading-context;
|
||||
line-height: $dash-graph-heading-context;
|
||||
transition:
|
||||
background-color 0.25s ease,
|
||||
color 0.25s ease !important;
|
||||
&:hover,
|
||||
&.active {
|
||||
cursor: pointer;
|
||||
color: $g20-white;
|
||||
background-color: $g5-pepper;
|
||||
}
|
||||
&:first-child {margin-right: 2px;}
|
||||
|
||||
&:hover {
|
||||
background-color: $g5-pepper !important;
|
||||
color: $g20-white;
|
||||
}
|
||||
> .icon {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%,-50%);
|
||||
}
|
||||
}
|
||||
|
||||
.presentation-mode .dash-graph--options {
|
||||
display: none;
|
||||
visibility: hidden;
|
||||
}
|
||||
.dash-graph--options-menu {
|
||||
.dash-graph-context--confirm {
|
||||
z-index: 3;
|
||||
position: absolute;
|
||||
top: ($dash-graph-heading + $dash-graph-options-arrow);
|
||||
top: calc(100% + 8px);
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
display: block;
|
||||
z-index: 11;
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
width: 90px;
|
||||
visibility: hidden;
|
||||
transition-property: all;
|
||||
width: 58px;
|
||||
height: 24px;
|
||||
border-radius: 3px;
|
||||
text-align: center;
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
line-height: 24px;
|
||||
background-color: $c-curacao;
|
||||
color: $g20-white;
|
||||
transition: background-color 0.25s ease;
|
||||
|
||||
> li {
|
||||
@include no-user-select;
|
||||
position: relative;
|
||||
&:before {
|
||||
position: absolute;
|
||||
content: '';
|
||||
border: 6px solid transparent;
|
||||
border-bottom-color: $c-curacao;
|
||||
left: 50%;
|
||||
top: 0;
|
||||
transform: translate(-50%,-100%);
|
||||
transition: border-color 0.25s ease;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: $c-dreamsicle;
|
||||
cursor: pointer;
|
||||
}
|
||||
&:hover:before {
|
||||
border-bottom-color: $c-dreamsicle;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Presentation Mode */
|
||||
.presentation-mode {
|
||||
.dash-graph-context {
|
||||
display: none;
|
||||
}
|
||||
.dash-graph--name {
|
||||
width: 100%;
|
||||
height: 28px;
|
||||
line-height: 28px;
|
||||
background-color: $g5-pepper;
|
||||
padding: 0 11px;
|
||||
margin: 0;
|
||||
text-align: left;
|
||||
color: $g15-platinum;
|
||||
opacity: 0;
|
||||
transition:
|
||||
opacity 0.25s ease,
|
||||
color 0.25s ease,
|
||||
background-color 0.25s ease;
|
||||
|
||||
&:first-child {
|
||||
border-radius: $radius $radius 0 0;
|
||||
|
||||
&:before {
|
||||
content: '';
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-width: $dash-graph-options-arrow;
|
||||
border-style: solid;
|
||||
border-color: transparent transparent $g5-pepper transparent;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
top: -($dash-graph-options-arrow * 2);
|
||||
}
|
||||
}
|
||||
&:last-child {
|
||||
border-radius: 0 0 $radius $radius;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
background-color: $g7-graphite;
|
||||
color: $g20-white;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Menu Open State */
|
||||
.dash-graph--options.dash-graph--options-show {
|
||||
> .btn {
|
||||
color: $g20-white;
|
||||
background-color: $g5-pepper !important;
|
||||
}
|
||||
.dash-graph--options-menu { visibility: visible; }
|
||||
.dash-graph--options-menu > li { opacity: 1; }
|
||||
}
|
||||
|
||||
|
||||
|
||||
.graph-panel__refreshing {
|
||||
position: absolute;
|
||||
top: -18px !important;
|
||||
|
|
Loading…
Reference in New Issue