Add a confirmation dialog for deleting a pod.

This commit is contained in:
Filip Barl
2019-02-25 16:41:15 +01:00
parent 6074655eb0
commit e66a3e08dc
5 changed files with 42 additions and 31 deletions

View File

@@ -1,5 +1,6 @@
import React from 'react';
import { connect } from 'react-redux';
import { isEmpty } from 'lodash';
import classNames from 'classnames';
import { trackAnalyticsEvent } from '../../utils/tracking-utils';
@@ -25,9 +26,11 @@ class NodeDetailsControlButton extends React.Component {
handleClick(ev) {
ev.preventDefault();
const { id, human } = this.props.control;
const { id, human, confirmation } = this.props.control;
trackAnalyticsEvent('scope.node.control.click', { id, title: human });
this.props.dispatch(doControl(this.props.nodeId, this.props.control));
if (isEmpty(confirmation) || window.confirm(confirmation)) { // eslint-disable-line no-alert
this.props.dispatch(doControl(this.props.nodeId, this.props.control));
}
}
}

View File

@@ -22,11 +22,14 @@ export default function NodeDetailsControls({
</div>
}
<span className="node-details-controls-buttons">
{sortBy(controls, 'rank').map(control => (<NodeDetailsControlButton
nodeId={nodeId}
control={control}
pending={pending}
key={control.id} />))}
{sortBy(controls, 'rank').map(control => (
<NodeDetailsControlButton
nodeId={nodeId}
control={control}
pending={pending}
key={control.id}
/>
))}
</span>
{controls && <span title="Applying..." className={spinnerClassName} />}
</div>

View File

@@ -538,10 +538,11 @@ func (r *Reporter) podTopology(services []Service, deployments []Deployment, dae
Rank: 0,
})
pods.Controls.AddControl(report.Control{
ID: DeletePod,
Human: "Delete",
Icon: "far fa-trash-alt",
Rank: 1,
ID: DeletePod,
Human: "Delete",
Icon: "far fa-trash-alt",
Confirmation: "Are you sure you want to delete this pod?",
Rank: 1,
})
for _, service := range services {
selectors = append(selectors, match(

View File

@@ -41,24 +41,26 @@ func (*ControlInstance) UnmarshalJSON(b []byte) error {
}
type wiredControlInstance struct {
ProbeID string `json:"probeId"`
NodeID string `json:"nodeId"`
ID string `json:"id"`
Human string `json:"human"`
Icon string `json:"icon"`
Rank int `json:"rank"`
ProbeID string `json:"probeId"`
NodeID string `json:"nodeId"`
ID string `json:"id"`
Human string `json:"human"`
Icon string `json:"icon"`
Confirmation string `json:"confirmation,omitempty"`
Rank int `json:"rank"`
}
// CodecEncodeSelf marshals this ControlInstance. It takes the basic Metric
// rendering, then adds some row-specific fields.
func (c *ControlInstance) CodecEncodeSelf(encoder *codec.Encoder) {
encoder.Encode(wiredControlInstance{
ProbeID: c.ProbeID,
NodeID: c.NodeID,
ID: c.Control.ID,
Human: c.Control.Human,
Icon: c.Control.Icon,
Rank: c.Control.Rank,
ProbeID: c.ProbeID,
NodeID: c.NodeID,
ID: c.Control.ID,
Human: c.Control.Human,
Icon: c.Control.Icon,
Confirmation: c.Control.Confirmation,
Rank: c.Control.Rank,
})
}
@@ -70,10 +72,11 @@ func (c *ControlInstance) CodecDecodeSelf(decoder *codec.Decoder) {
ProbeID: in.ProbeID,
NodeID: in.NodeID,
Control: report.Control{
ID: in.ID,
Human: in.Human,
Icon: in.Icon,
Rank: in.Rank,
ID: in.ID,
Human: in.Human,
Icon: in.Icon,
Confirmation: in.Confirmation,
Rank: in.Rank,
},
}
}

View File

@@ -12,10 +12,11 @@ type Controls map[string]Control
// A Control basically describes an RPC
type Control struct {
ID string `json:"id"`
Human string `json:"human"`
Icon string `json:"icon"` // from https://fortawesome.github.io/Font-Awesome/cheatsheet/ please
Rank int `json:"rank"`
ID string `json:"id"`
Human string `json:"human"`
Icon string `json:"icon"` // from https://fortawesome.github.io/Font-Awesome/cheatsheet/ please
Confirmation string `json:"confirmation,omitempty"`
Rank int `json:"rank"`
}
// Merge merges other with cs, returning a fresh Controls.