mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Merge pull request #12665 from grafana/9863-animated-delete-button
built a component for delete button in tables
This commit is contained in:
@@ -5,7 +5,7 @@ import PageHeader from 'app/core/components/PageHeader/PageHeader';
|
|||||||
import { NavStore } from 'app/stores/NavStore/NavStore';
|
import { NavStore } from 'app/stores/NavStore/NavStore';
|
||||||
import { TeamsStore, ITeam } from 'app/stores/TeamsStore/TeamsStore';
|
import { TeamsStore, ITeam } from 'app/stores/TeamsStore/TeamsStore';
|
||||||
import { BackendSrv } from 'app/core/services/backend_srv';
|
import { BackendSrv } from 'app/core/services/backend_srv';
|
||||||
import appEvents from 'app/core/app_events';
|
import DeleteButton from 'app/core/components/DeleteButton/DeleteButton';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
nav: typeof NavStore.Type;
|
nav: typeof NavStore.Type;
|
||||||
@@ -28,18 +28,6 @@ export class TeamList extends React.Component<Props, any> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
deleteTeam(team: ITeam) {
|
deleteTeam(team: ITeam) {
|
||||||
appEvents.emit('confirm-modal', {
|
|
||||||
title: 'Delete',
|
|
||||||
text: 'Are you sure you want to delete Team ' + team.name + '?',
|
|
||||||
yesText: 'Delete',
|
|
||||||
icon: 'fa-warning',
|
|
||||||
onConfirm: () => {
|
|
||||||
this.deleteTeamConfirmed(team);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
deleteTeamConfirmed(team) {
|
|
||||||
this.props.backendSrv.delete('/api/teams/' + team.id).then(this.fetchTeams.bind(this));
|
this.props.backendSrv.delete('/api/teams/' + team.id).then(this.fetchTeams.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,9 +55,7 @@ export class TeamList extends React.Component<Props, any> {
|
|||||||
<a href={teamUrl}>{team.memberCount}</a>
|
<a href={teamUrl}>{team.memberCount}</a>
|
||||||
</td>
|
</td>
|
||||||
<td className="text-right">
|
<td className="text-right">
|
||||||
<a onClick={() => this.deleteTeam(team)} className="btn btn-danger btn-small">
|
<DeleteButton onConfirmDelete={() => this.deleteTeam(team)} />
|
||||||
<i className="fa fa-remove" />
|
|
||||||
</a>
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
);
|
);
|
||||||
@@ -102,7 +88,7 @@ export class TeamList extends React.Component<Props, any> {
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="admin-list-table">
|
<div className="admin-list-table tr-overflow">
|
||||||
<table className="filter-table filter-table--hover form-inline">
|
<table className="filter-table filter-table--hover form-inline">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import DeleteButton from './DeleteButton';
|
||||||
|
import { shallow } from 'enzyme';
|
||||||
|
|
||||||
|
describe('DeleteButton', () => {
|
||||||
|
let wrapper;
|
||||||
|
let deleted;
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
deleted = false;
|
||||||
|
|
||||||
|
function deleteItem() {
|
||||||
|
deleted = true;
|
||||||
|
}
|
||||||
|
wrapper = shallow(<DeleteButton onConfirmDelete={() => deleteItem()} />);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should show confirm delete when clicked', () => {
|
||||||
|
expect(wrapper.state().showConfirm).toBe(false);
|
||||||
|
wrapper.find('.delete-button').simulate('click');
|
||||||
|
expect(wrapper.state().showConfirm).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should hide confirm delete when clicked', () => {
|
||||||
|
wrapper.find('.delete-button').simulate('click');
|
||||||
|
expect(wrapper.state().showConfirm).toBe(true);
|
||||||
|
wrapper
|
||||||
|
.find('.confirm-delete')
|
||||||
|
.find('.btn')
|
||||||
|
.at(0)
|
||||||
|
.simulate('click');
|
||||||
|
expect(wrapper.state().showConfirm).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should show confirm delete when clicked', () => {
|
||||||
|
expect(deleted).toBe(false);
|
||||||
|
wrapper
|
||||||
|
.find('.confirm-delete')
|
||||||
|
.find('.btn')
|
||||||
|
.at(1)
|
||||||
|
.simulate('click');
|
||||||
|
expect(deleted).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
66
public/app/core/components/DeleteButton/DeleteButton.tsx
Normal file
66
public/app/core/components/DeleteButton/DeleteButton.tsx
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
import React, { PureComponent } from 'react';
|
||||||
|
|
||||||
|
export interface DeleteButtonProps {
|
||||||
|
onConfirmDelete();
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DeleteButtonStates {
|
||||||
|
showConfirm: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class DeleteButton extends PureComponent<DeleteButtonProps, DeleteButtonStates> {
|
||||||
|
state: DeleteButtonStates = {
|
||||||
|
showConfirm: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
onClickDelete = event => {
|
||||||
|
if (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
showConfirm: true,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
onClickCancel = event => {
|
||||||
|
if (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
this.setState({
|
||||||
|
showConfirm: false,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const onClickConfirm = this.props.onConfirmDelete;
|
||||||
|
let showConfirm;
|
||||||
|
let showDeleteButton;
|
||||||
|
|
||||||
|
if (this.state.showConfirm) {
|
||||||
|
showConfirm = 'show';
|
||||||
|
showDeleteButton = 'hide';
|
||||||
|
} else {
|
||||||
|
showConfirm = 'hide';
|
||||||
|
showDeleteButton = 'show';
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<span className="delete-button-container">
|
||||||
|
<a className={'delete-button ' + showDeleteButton + ' btn btn-danger btn-small'} onClick={this.onClickDelete}>
|
||||||
|
<i className="fa fa-remove" />
|
||||||
|
</a>
|
||||||
|
<span className="confirm-delete-container">
|
||||||
|
<span className={'confirm-delete ' + showConfirm}>
|
||||||
|
<a className="btn btn-small" onClick={this.onClickCancel}>
|
||||||
|
Cancel
|
||||||
|
</a>
|
||||||
|
<a className="btn btn-danger btn-small" onClick={onClickConfirm}>
|
||||||
|
Confirm Delete
|
||||||
|
</a>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -93,6 +93,7 @@
|
|||||||
@import 'components/form_select_box';
|
@import 'components/form_select_box';
|
||||||
@import 'components/user-picker';
|
@import 'components/user-picker';
|
||||||
@import 'components/description-picker';
|
@import 'components/description-picker';
|
||||||
|
@import 'components/delete_button';
|
||||||
|
|
||||||
// PAGES
|
// PAGES
|
||||||
@import 'pages/login';
|
@import 'pages/login';
|
||||||
|
|||||||
50
public/sass/components/_delete_button.scss
Normal file
50
public/sass/components/_delete_button.scss
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
// sets a fixed width so that the rest of the table
|
||||||
|
// isn't affected by the animation
|
||||||
|
.delete-button-container {
|
||||||
|
width: 24px;
|
||||||
|
direction: rtl;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
//this container is used to make sure confirm-delete isn't
|
||||||
|
//shown outside of table
|
||||||
|
.confirm-delete-container {
|
||||||
|
overflow: hidden;
|
||||||
|
width: 145px;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.delete-button {
|
||||||
|
position: absolute;
|
||||||
|
|
||||||
|
&.show {
|
||||||
|
opacity: 1;
|
||||||
|
transition: opacity 0.1s ease;
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.hide {
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 0.1s ease;
|
||||||
|
z-index: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.confirm-delete {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
|
||||||
|
&.show {
|
||||||
|
opacity: 1;
|
||||||
|
transition: opacity 0.08s ease-out, transform 0.1s ease-out;
|
||||||
|
transform: translateX(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.hide {
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 0.12s ease-in, transform 0.14s ease-in;
|
||||||
|
transform: translateX(100px);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user