NameableGraph Dropdown now contains an active Delete button (#1058)

* Dropdown now contains an active Delete button

* Prefer `filter` over `findIndex` => `slice`
pull/1061/head
lukevmorris 2017-03-24 13:24:11 -07:00 committed by Jared Scheib
parent 01ec21b483
commit 148140effa
7 changed files with 66 additions and 5 deletions

View File

@ -3,6 +3,7 @@ import {
updateDashboard as updateDashboardAJAX, updateDashboard as updateDashboardAJAX,
updateDashboardCell as updateDashboardCellAJAX, updateDashboardCell as updateDashboardCellAJAX,
addDashboardCell as addDashboardCellAJAX, addDashboardCell as addDashboardCellAJAX,
deleteDashboardCell as deleteDashboardCellAJAX,
} from 'src/dashboards/apis' } from 'src/dashboards/apis'
import {NEW_DEFAULT_DASHBOARD_CELL} from 'src/dashboards/constants' import {NEW_DEFAULT_DASHBOARD_CELL} from 'src/dashboards/constants'
@ -86,6 +87,13 @@ export const renameDashboardCell = (x, y, name) => ({
}, },
}) })
export const deleteDashboardCell = (cell) => ({
type: 'DELETE_DASHBOARD_CELL',
payload: {
cell,
},
})
// Async Action Creators // Async Action Creators
export const getDashboards = (dashboardID) => (dispatch) => { export const getDashboards = (dashboardID) => (dispatch) => {
@ -117,3 +125,13 @@ export const addDashboardCellAsync = (dashboard) => async (dispatch) => {
throw error throw error
} }
} }
export const deleteDashboardCellAsync = (cell) => async (dispatch) => {
try {
await deleteDashboardCellAJAX(cell)
dispatch(deleteDashboardCell(cell))
} catch (error) {
console.error(error)
throw error
}
}

View File

@ -48,3 +48,15 @@ export const addDashboardCell = async (dashboard, cell) => {
throw error throw error
} }
} }
export const deleteDashboardCell = async (cell) => {
try {
return await AJAX({
method: 'DELETE',
url: cell.links.self,
})
} catch (error) {
console.error(error)
throw error
}
}

View File

@ -12,6 +12,7 @@ const Dashboard = ({
onEditCell, onEditCell,
onRenameCell, onRenameCell,
onUpdateCell, onUpdateCell,
onDeleteCell,
onSummonOverlayTechnologies, onSummonOverlayTechnologies,
source, source,
autoRefresh, autoRefresh,
@ -25,13 +26,13 @@ const Dashboard = ({
<div className={classnames({'page-contents': true, 'presentation-mode': inPresentationMode})}> <div className={classnames({'page-contents': true, 'presentation-mode': inPresentationMode})}>
<div className={classnames('container-fluid full-width dashboard', {'dashboard-edit': isEditMode})}> <div className={classnames('container-fluid full-width dashboard', {'dashboard-edit': isEditMode})}>
{isEditMode ? <Visualizations/> : null} {isEditMode ? <Visualizations/> : null}
{Dashboard.renderDashboard(dashboard, autoRefresh, timeRange, source, onPositionChange, onEditCell, onRenameCell, onUpdateCell, onSummonOverlayTechnologies)} {Dashboard.renderDashboard(dashboard, autoRefresh, timeRange, source, onPositionChange, onEditCell, onRenameCell, onUpdateCell, onDeleteCell, onSummonOverlayTechnologies)}
</div> </div>
</div> </div>
) )
} }
Dashboard.renderDashboard = (dashboard, autoRefresh, timeRange, source, onPositionChange, onEditCell, onRenameCell, onUpdateCell, onSummonOverlayTechnologies) => { Dashboard.renderDashboard = (dashboard, autoRefresh, timeRange, source, onPositionChange, onEditCell, onRenameCell, onUpdateCell, onDeleteCell, onSummonOverlayTechnologies) => {
const cells = dashboard.cells.map((cell, i) => { const cells = dashboard.cells.map((cell, i) => {
i = `${i}` i = `${i}`
const dashboardCell = {...cell, i} const dashboardCell = {...cell, i}
@ -58,6 +59,7 @@ Dashboard.renderDashboard = (dashboard, autoRefresh, timeRange, source, onPositi
onEditCell={onEditCell} onEditCell={onEditCell}
onRenameCell={onRenameCell} onRenameCell={onRenameCell}
onUpdateCell={onUpdateCell} onUpdateCell={onUpdateCell}
onDeleteCell={onDeleteCell}
onSummonOverlayTechnologies={onSummonOverlayTechnologies} onSummonOverlayTechnologies={onSummonOverlayTechnologies}
/> />
) )
@ -79,6 +81,7 @@ Dashboard.propTypes = {
onEditCell: func, onEditCell: func,
onRenameCell: func, onRenameCell: func,
onUpdateCell: func, onUpdateCell: func,
onDeleteCell: func,
onSummonOverlayTechnologies: func, onSummonOverlayTechnologies: func,
source: shape({ source: shape({
links: shape({ links: shape({

View File

@ -154,6 +154,10 @@ const DashboardPage = React.createClass({
} }
}, },
handleDeleteDashboardCell(cell) {
this.props.dashboardActions.deleteDashboardCellAsync(cell)
},
render() { render() {
const { const {
dashboards, dashboards,
@ -223,6 +227,7 @@ const DashboardPage = React.createClass({
onEditCell={this.handleEditDashboardCell} onEditCell={this.handleEditDashboardCell}
onRenameCell={this.handleRenameDashboardCell} onRenameCell={this.handleRenameDashboardCell}
onUpdateCell={this.handleUpdateDashboardCell} onUpdateCell={this.handleUpdateDashboardCell}
onDeleteCell={this.handleDeleteDashboardCell}
onSummonOverlayTechnologies={this.handleSummonOverlayTechnologies} onSummonOverlayTechnologies={this.handleSummonOverlayTechnologies}
/> />
</div> </div>

View File

@ -109,6 +109,23 @@ export default function ui(state = initialState, action) {
return {...state, ...newState} return {...state, ...newState}
} }
case 'DELETE_DASHBOARD_CELL': {
const {cell} = action.payload
const {dashboard} = state
const newCells = dashboard.cells.filter((c) => !(c.x === cell.x && c.y === cell.y))
const newDashboard = {
...dashboard,
cells: newCells,
}
const newState = {
dashboard: newDashboard,
dashboards: state.dashboards.map((d) => d.id === dashboard.id ? newDashboard : d),
}
return {...state, ...newState}
}
case 'SYNC_DASHBOARD_CELL': { case 'SYNC_DASHBOARD_CELL': {
const {cell} = action.payload const {cell} = action.payload
const {dashboard} = state const {dashboard} = state

View File

@ -50,6 +50,7 @@ export const LayoutRenderer = React.createClass({
onEditCell: func, onEditCell: func,
onRenameCell: func, onRenameCell: func,
onUpdateCell: func, onUpdateCell: func,
onDeleteCell: func,
onSummonOverlayTechnologies: func, onSummonOverlayTechnologies: func,
}, },
@ -86,7 +87,7 @@ export const LayoutRenderer = React.createClass({
}, },
generateVisualizations() { generateVisualizations() {
const {autoRefresh, source, cells, onEditCell, onRenameCell, onUpdateCell, onSummonOverlayTechnologies} = this.props; const {autoRefresh, source, cells, onEditCell, onRenameCell, onUpdateCell, onDeleteCell, onSummonOverlayTechnologies} = this.props;
return cells.map((cell) => { return cells.map((cell) => {
const qs = cell.queries.map((query) => { const qs = cell.queries.map((query) => {
@ -103,6 +104,7 @@ export const LayoutRenderer = React.createClass({
onEditCell={onEditCell} onEditCell={onEditCell}
onRenameCell={onRenameCell} onRenameCell={onRenameCell}
onUpdateCell={onUpdateCell} onUpdateCell={onUpdateCell}
onDeleteCell={onDeleteCell}
onSummonOverlayTechnologies={onSummonOverlayTechnologies} onSummonOverlayTechnologies={onSummonOverlayTechnologies}
cell={cell} cell={cell}
> >
@ -123,6 +125,7 @@ export const LayoutRenderer = React.createClass({
onEditCell={onEditCell} onEditCell={onEditCell}
onRenameCell={onRenameCell} onRenameCell={onRenameCell}
onUpdateCell={onUpdateCell} onUpdateCell={onUpdateCell}
onDeleteCell={onDeleteCell}
onSummonOverlayTechnologies={onSummonOverlayTechnologies} onSummonOverlayTechnologies={onSummonOverlayTechnologies}
cell={cell} cell={cell}
> >

View File

@ -23,6 +23,7 @@ const NameableGraph = React.createClass({
onEditCell: func, onEditCell: func,
onRenameCell: func, onRenameCell: func,
onUpdateCell: func, onUpdateCell: func,
onDeleteCell: func,
onSummonOverlayTechnologies: func, onSummonOverlayTechnologies: func,
}, },
@ -56,6 +57,7 @@ const NameableGraph = React.createClass({
onEditCell, onEditCell,
onRenameCell, onRenameCell,
onUpdateCell, onUpdateCell,
onDeleteCell,
onSummonOverlayTechnologies, onSummonOverlayTechnologies,
children, children,
} = this.props } = this.props
@ -96,7 +98,7 @@ const NameableGraph = React.createClass({
<div className="dash-graph"> <div className="dash-graph">
<div className="dash-graph--heading"> <div className="dash-graph--heading">
<div onClick={onClickHandler(x, y, isEditing)}>{nameOrField}</div> <div onClick={onClickHandler(x, y, isEditing)}>{nameOrField}</div>
<ContextMenu isOpen={this.state.isMenuOpen} toggleMenu={this.toggleMenu} onEdit={onSummonOverlayTechnologies} cell={cell} handleClickOutside={this.closeMenu}/> <ContextMenu isOpen={this.state.isMenuOpen} toggleMenu={this.toggleMenu} onEdit={onSummonOverlayTechnologies} onDelete={onDeleteCell} cell={cell} handleClickOutside={this.closeMenu}/>
</div> </div>
<div className="dash-graph--container"> <div className="dash-graph--container">
{children} {children}
@ -106,13 +108,14 @@ const NameableGraph = React.createClass({
}, },
}) })
const ContextMenu = OnClickOutside(({isOpen, toggleMenu, onEdit, cell}) => ( const ContextMenu = OnClickOutside(({isOpen, toggleMenu, onEdit, onDelete, cell}) => (
<div className={classnames("dash-graph--options", {"dash-graph--options-show": isOpen})} onClick={toggleMenu}> <div className={classnames("dash-graph--options", {"dash-graph--options-show": isOpen})} onClick={toggleMenu}>
<button className="btn btn-info btn-xs"> <button className="btn btn-info btn-xs">
<span className="icon caret-down"></span> <span className="icon caret-down"></span>
</button> </button>
<ul className="dash-graph--options-menu"> <ul className="dash-graph--options-menu">
<li onClick={() => onEdit(cell)}>Edit</li> <li onClick={() => onEdit(cell)}>Edit</li>
<li onClick={() => onDelete(cell)}>Delete</li>
</ul> </ul>
</div> </div>
)) ))