diff --git a/CHANGELOG.md b/CHANGELOG.md index 02944a941..547d6ab34 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,14 +2,15 @@ ### Bug Fixes 1. [#1708](https://github.com/influxdata/chronograf/pull/1708): Fix z-index issue in dashboard cell context menu -1. [#1752](https://github.com/influxdata/chronograf/pull/1752): Clarify BoltPath server flag help text by making example the default path + +1. [#1703](https://github.com/influxdata/chronograf/pull/1703): Fix cell name cancel not reverting to original name ### Features 1. [#1717](https://github.com/influxdata/chronograf/pull/1717): View server generated TICKscripts -1. [#1681](https://github.com/influxdata/chronograf/pull/1681): Add the ability to select Custom Time Ranges in the Hostpages, Data Explorer, and Dashboards. +1. [#1681](https://github.com/influxdata/chronograf/pull/1681): Add the ability to select Custom Time Ranges in the Hostpages, Data Explorer, and Dashboards +1. [#1752](https://github.com/influxdata/chronograf/pull/1752): Clarify BoltPath server flag help text by making example the default path 1. [#1738](https://github.com/influxdata/chronograf/pull/1738): Add shared secret JWT authorization to InfluxDB - ### UI Improvements 1. [#1707](https://github.com/influxdata/chronograf/pull/1707): Polish alerts table in status page to wrap text less diff --git a/ui/spec/dashboards/reducers/uiSpec.js b/ui/spec/dashboards/reducers/uiSpec.js index 9fc364ff0..537e851eb 100644 --- a/ui/spec/dashboards/reducers/uiSpec.js +++ b/ui/spec/dashboards/reducers/uiSpec.js @@ -11,6 +11,7 @@ import { renameDashboardCell, syncDashboardCell, templateVariableSelected, + cancelEditCell, } from 'src/dashboards/actions' let state @@ -62,6 +63,13 @@ const c1 = { isEditing: false, name: 'Gigawatts', } + +const editingCell = { + i: 1, + isEditing: true, + name: 'Edit me', +} + const cells = [c1] const tempVar = { ...d1.templates[0], @@ -180,4 +188,17 @@ describe('DataExplorer.Reducers.UI', () => { expect(actual.dashboards[0].templates[0].values[1].selected).to.equal(false) expect(actual.dashboards[0].templates[0].values[2].selected).to.equal(true) }) + + it('can cancel cell editing', () => { + const dash = _.cloneDeep(d1) + dash.cells = [editingCell] + + const actual = reducer( + {dashboards: [dash]}, + cancelEditCell(dash.id, editingCell.i) + ) + + expect(actual.dashboards[0].cells[0].isEditing).to.equal(false) + expect(actual.dashboards[0].cells[0].name).to.equal(editingCell.name) + }) }) diff --git a/ui/src/dashboards/actions/index.js b/ui/src/dashboards/actions/index.js index 71f9c3ba2..205d017cb 100644 --- a/ui/src/dashboards/actions/index.js +++ b/ui/src/dashboards/actions/index.js @@ -91,6 +91,14 @@ export const editDashboardCell = (dashboard, x, y, isEditing) => ({ }, }) +export const cancelEditCell = (dashboardID, cellID) => ({ + type: 'CANCEL_EDIT_CELL', + payload: { + dashboardID, + cellID, + }, +}) + export const renameDashboardCell = (dashboard, x, y, name) => ({ type: 'RENAME_DASHBOARD_CELL', payload: { diff --git a/ui/src/dashboards/components/Dashboard.js b/ui/src/dashboards/components/Dashboard.js index 0afd0e5f8..95b5065b3 100644 --- a/ui/src/dashboards/components/Dashboard.js +++ b/ui/src/dashboards/components/Dashboard.js @@ -23,6 +23,7 @@ const Dashboard = ({ onSummonOverlayTechnologies, onSelectTemplate, showTemplateControlBar, + onCancelEditCell, }) => { const cells = dashboard.cells.map(cell => { const dashboardCell = {...cell} @@ -56,6 +57,7 @@ const Dashboard = ({ />} {cells.length ? { - this.props.dashboardActions.renameDashboardCell( - this.getActiveDashboard(), - x, - y, - evt.target.value - ) - } - } - handleUpdateDashboardCell(newCell) { return () => { - this.props.dashboardActions.editDashboardCell( + this.props.dashboardActions.updateDashboardCell( this.getActiveDashboard(), - newCell.x, - newCell.y, - false + newCell ) - this.props.dashboardActions.putDashboard(this.getActiveDashboard()) } } @@ -238,6 +223,13 @@ class DashboardPage extends Component { this.props.templateControlBarVisibilityToggled() } + handleCancelEditCell(cellID) { + this.props.dashboardActions.cancelEditCell( + this.getActiveDashboard().id, + cellID + ) + } + getActiveDashboard() { const {params: {dashboardID}, dashboards} = this.props return dashboards.find(d => d.id === +dashboardID) @@ -363,13 +355,13 @@ class DashboardPage extends Component { showTemplateControlBar={showTemplateControlBar} > {dashboards - ? dashboards.map((d, i) => + ? dashboards.map((d, i) => (
  • {d.name}
  • - ) + )) : null} } {dashboard @@ -384,13 +376,13 @@ class DashboardPage extends Component { onEditCell={this.handleEditDashboardCell} onPositionChange={this.handleUpdatePosition} onDeleteCell={this.handleDeleteDashboardCell} - onRenameCell={this.handleRenameDashboardCell} onUpdateCell={this.handleUpdateDashboardCell} onOpenTemplateManager={this.handleOpenTemplateManager} templatesIncludingDashTime={templatesIncludingDashTime} onSummonOverlayTechnologies={this.handleSummonOverlayTechnologies} onSelectTemplate={this.handleSelectTemplate} showTemplateControlBar={showTemplateControlBar} + onCancelEditCell={::this.handleCancelEditCell} /> : null} @@ -420,7 +412,7 @@ DashboardPage.propTypes = { setTimeRange: func.isRequired, addDashboardCellAsync: func.isRequired, editDashboardCell: func.isRequired, - renameDashboardCell: func.isRequired, + cancelEditCell: func.isRequired, }).isRequired, dashboards: arrayOf( shape({ diff --git a/ui/src/dashboards/reducers/ui.js b/ui/src/dashboards/reducers/ui.js index 7ec655787..1cfaaf870 100644 --- a/ui/src/dashboards/reducers/ui.js +++ b/ui/src/dashboards/reducers/ui.js @@ -132,6 +132,24 @@ export default function ui(state = initialState, action) { return {...state, ...newState} } + case 'CANCEL_EDIT_CELL': { + const {dashboardID, cellID} = action.payload + + const dashboards = state.dashboards.map( + d => + (d.id === dashboardID + ? { + ...d, + cells: d.cells.map( + c => (c.i === cellID ? {...c, isEditing: false} : c) + ), + } + : d) + ) + + return {...state, dashboards} + } + case 'SYNC_DASHBOARD_CELL': { const {cell, dashboard} = action.payload diff --git a/ui/src/shared/components/CustomTimeRangeDropdown.js b/ui/src/shared/components/CustomTimeRangeDropdown.js index baa2b4dc3..e2cef14e2 100644 --- a/ui/src/shared/components/CustomTimeRangeDropdown.js +++ b/ui/src/shared/components/CustomTimeRangeDropdown.js @@ -44,9 +44,7 @@ class CustomTimeRangeDropdown extends Component { onClick={this.handleToggleDropdown} > - {`${moment(lower).format( - 'MMM Do HH:mm' - )} — ${moment(upper).format('MMM Do HH:mm')}`} + {`${moment(lower).format('MMM Do HH:mm')} — ${moment(upper).format('MMM Do HH:mm')}`} {cell.isWidget @@ -215,7 +215,7 @@ class LayoutRenderer extends Component { PAGE_HEADER_HEIGHT - PAGE_CONTAINER_MARGIN - PAGE_CONTAINER_MARGIN) / - STATUS_PAGE_ROW_COUNT + STATUS_PAGE_ROW_COUNT : DASHBOARD_LAYOUT_ROW_HEIGHT } @@ -298,10 +298,10 @@ LayoutRenderer.propTypes = { onUpdateCell: func, onDeleteCell: func, onSummonOverlayTechnologies: func, - shouldNotBeEditable: bool, synchronizer: func, isStatusPage: bool, isEditable: bool, + onCancelEditCell: func, } export default LayoutRenderer diff --git a/ui/src/shared/components/NameableGraph.js b/ui/src/shared/components/NameableGraph.js index d07e8db05..9a76a6ce7 100644 --- a/ui/src/shared/components/NameableGraph.js +++ b/ui/src/shared/components/NameableGraph.js @@ -8,10 +8,8 @@ class NameableGraph extends Component { super(props) this.state = { isMenuOpen: false, + cellName: props.cell.name, } - - this.toggleMenu = ::this.toggleMenu - this.closeMenu = ::this.closeMenu } toggleMenu() { @@ -20,6 +18,17 @@ class NameableGraph extends Component { }) } + 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, @@ -30,7 +39,6 @@ class NameableGraph extends Component { const { cell, onEditCell, - onRenameCell, onUpdateCell, onDeleteCell, onSummonOverlayTechnologies, @@ -38,23 +46,26 @@ class NameableGraph extends Component { children, } = this.props + const {cellName, isMenuOpen} = this.state + return (
    {}} - toggleMenu={this.toggleMenu} - isOpen={this.state.isMenuOpen} + toggleMenu={::this.toggleMenu} + isOpen={isMenuOpen} isEditable={isEditable} - handleClickOutside={this.closeMenu} + handleClickOutside={::this.closeMenu} onEdit={onSummonOverlayTechnologies} />
    @@ -81,8 +92,8 @@ NameableGraph.propTypes = { onUpdateCell: func, onDeleteCell: func, onSummonOverlayTechnologies: func, - shouldNotBeEditable: bool, isEditable: bool, + onCancelEditCell: func, } export default NameableGraph diff --git a/ui/src/shared/components/NameableGraphHeader.js b/ui/src/shared/components/NameableGraphHeader.js index 2613cc579..e3ae35cbd 100644 --- a/ui/src/shared/components/NameableGraphHeader.js +++ b/ui/src/shared/components/NameableGraphHeader.js @@ -4,12 +4,13 @@ import classnames from 'classnames' import CustomTimeIndicator from 'shared/components/CustomTimeIndicator' const NameableGraphHeader = ({ + onCancelEditCell, isEditable, - onEditCell, onRenameCell, onUpdateCell, cell, - cell: {x, y, name, queries}, + cellName, + cell: {i, name, queries}, }) => { const isInputVisible = isEditable && cell.isEditing const className = classnames('dash-graph--heading', { @@ -17,10 +18,11 @@ const NameableGraphHeader = ({ }) const onKeyUp = evt => { if (evt.key === 'Enter') { - onUpdateCell(cell)() + onUpdateCell({...cell, name: cellName})() } + if (evt.key === 'Escape') { - onEditCell(x, y, true)() + onCancelEditCell(i) } } @@ -28,9 +30,9 @@ const NameableGraphHeader = ({
    {isInputVisible ? : } @@ -42,26 +44,28 @@ const {arrayOf, bool, func, string, shape} = PropTypes NameableGraphHeader.propTypes = { cell: shape(), - onEditCell: func, + cellName: string, onRenameCell: func, onUpdateCell: func, isEditable: bool, + onCancelEditCell: func, } -const GraphName = ({name, queries}) => +const GraphName = ({name, queries}) => ( {name} {queries && queries.length ? : null} +) GraphName.propTypes = { name: string, queries: arrayOf(shape()), } -const GraphNameInput = ({value, onKeyUp, onChange, onBlur}) => +const GraphNameInput = ({value, onKeyUp, onChange, onBlur}) => ( onBlur={onBlur} onKeyUp={onKeyUp} /> +) GraphNameInput.propTypes = { value: string,