diff --git a/README.md b/README.md index 3bb61be8e..9f05feaad 100644 --- a/README.md +++ b/README.md @@ -78,6 +78,8 @@ This is the container component that encapsulates the lanes and cards | handleDragEnd | function | Callback function triggered when card drag ends: `handleDragEnd(cardId, sourceLaneId, targetLaneId)` | | onLaneScroll | function | Called when a lane is scrolled to the end: `onLaneScroll(requestedPage, laneId)` | | onCardClick | function | Called when a card is clicked: `onCardClick(cardId, metadata, laneId) ` | +| onCardAdd | function | Called when a new card is added: `onCardAdd(card, laneId) ` | +| onCardDelete | function | Called when a card is deleted: `onCardDelete(cardId, laneId) ` | | onLaneClick | function | Called when a lane is clicked: `onLaneClick(laneId) `. Card clicks are not propagated to lane click event | | laneSortFunction | function | Used to specify the logic to sort cards on a lane: `laneSortFunction(card1, card2)` | | eventBusHandle | function | This is a special function that providers a publishHook to pass new events to the board. See details in Publish Events section | diff --git a/package.json b/package.json index 995bbbad0..9c85d4a31 100644 --- a/package.json +++ b/package.json @@ -103,7 +103,8 @@ "redux": "^3.6.0", "redux-actions": "^1.2.2", "redux-logger": "^3.0.6", - "styled-components": "^2.1.1" + "styled-components": "^2.1.1", + "uuid": "^3.1.0" }, "peerDependencies": { "react": ">= 0.14.0 < 17.0.0-0", diff --git a/src/components/BoardContainer.js b/src/components/BoardContainer.js index 82f48d08c..cc28041d4 100644 --- a/src/components/BoardContainer.js +++ b/src/components/BoardContainer.js @@ -60,6 +60,8 @@ class BoardContainer extends Component { const passthroughProps = pick(this.props, [ 'onLaneScroll', 'onCardClick', + 'onCardDelete', + 'onCardAdd', 'onLaneClick', 'laneSortFunction', 'draggable', @@ -84,6 +86,8 @@ BoardContainer.propTypes = { eventBusHandle: PropTypes.func, onLaneScroll: PropTypes.func, onCardClick: PropTypes.func, + onCardDelete: PropTypes.func, + onCardAdd: PropTypes.func, onLaneClick: PropTypes.func, laneSortFunction: PropTypes.func, draggable: PropTypes.bool, diff --git a/src/components/Card.js b/src/components/Card.js index 019f3bd0f..2ed6be64d 100644 --- a/src/components/Card.js +++ b/src/components/Card.js @@ -1,51 +1,36 @@ -import React, {Component} from 'react'; -import PropTypes from 'prop-types'; -import { - CardHeader, CardRightContent, CardTitle, Detail, Footer, - MovableCardWrapper, -} from '../styles/Base'; -import {DragType} from '../helpers/DragType'; -import {DragSource, DropTarget} from 'react-dnd'; -import {findDOMNode} from 'react-dom'; -import Tag from './Tag'; -import flow from 'lodash/flow'; -import DeleteButton from './widgets/DeleteButton'; +import React, {Component} from 'react' +import PropTypes from 'prop-types' +import {CardHeader, CardRightContent, CardTitle, Detail, Footer, MovableCardWrapper} from '../styles/Base' +import {DragType} from '../helpers/DragType' +import {DragSource, DropTarget} from 'react-dnd' +import {findDOMNode} from 'react-dom' +import Tag from './Tag' +import flow from 'lodash/flow' +import DeleteButton from './widgets/DeleteButton' class Card extends Component { - - removeCard = () => { - const {id, laneId} = this.props - this.props.removeCard(laneId, id) + removeCard = e => { + const {id, laneId, removeCard, onDelete} = this.props + removeCard(laneId, id) + onDelete(id, laneId) + e.stopPropagation() } renderBody = () => { if (this.props.customCardLayout) { const {customCard, ...otherProps} = this.props const customCardWithProps = React.cloneElement(customCard, {...otherProps}) - return ( - - {customCardWithProps} - - ) + return {customCardWithProps} } else { const {title, description, label, tags} = this.props return ( - - {title} - - - {label} - + {title} + {label} - - {description} - - {tags && - } + {description} + {tags && } ) } @@ -60,7 +45,7 @@ class Card extends Component {
{this.renderBody()} - {editable && } + {editable && }
) @@ -140,7 +125,8 @@ const cardTarget = { Card.defaultProps = { cardStyle: {}, - customCardLayout: false + customCardLayout: false, + onDelete: () => {} } Card.propTypes = { @@ -149,6 +135,7 @@ Card.propTypes = { description: PropTypes.string, label: PropTypes.string, onClick: PropTypes.func, + onDelete: PropTypes.func, metadata: PropTypes.object, connectDragSource: PropTypes.func.isRequired, isDragging: PropTypes.bool.isRequired, diff --git a/src/components/Lane.js b/src/components/Lane.js index bec093c3e..4ffd5fd54 100644 --- a/src/components/Lane.js +++ b/src/components/Lane.js @@ -2,7 +2,7 @@ import React, {Component} from 'react' import Loader from './Loader' import PropTypes from 'prop-types' import Card from './Card' -import {Section, Header, Title, RightContent, DraggableList, Placeholder, AddCard} from '../styles/Base' +import {Section, Header, Title, RightContent, DraggableList, Placeholder, AddCardLink} from '../styles/Base' import {bindActionCreators} from 'redux' import {connect} from 'react-redux' import {DropTarget} from 'react-dnd' @@ -10,6 +10,7 @@ import update from 'immutability-helper' import {DragType} from '../helpers/DragType' import {findDOMNode} from 'react-dom' import NewCard from './NewCard' +import uuidv1 from 'uuid/v1' const laneActions = require('../actions/LaneActions') @@ -118,15 +119,19 @@ class Lane extends Component { this.setState({addCardMode: true}) } - hideEditableCard = () => { - this.setState({addCardMode: false}) - } - - addNewCard = (card) => { - this.hideEditableCard() - return this.props.actions.addCard({laneId: this.props.id, card: card}) + hideEditableCard = () => { + this.setState({addCardMode: false}) } + addNewCard = params => { + const laneId = this.props.id + const id = uuidv1() + this.hideEditableCard() + let card = {...params, id}; + this.props.actions.addCard({laneId, card}) + this.props.onCardAdd(card, laneId) + } + renderDragContainer = () => { const {connectDropTarget, laneSortFunction, editable, tagStyle, cardStyle, draggable} = this.props const {addCardMode} = this.state @@ -145,6 +150,7 @@ class Lane extends Component { moveCardAcrossLanes={this.moveCardAcrossLanes} removeCard={this.removeCard} onClick={e => this.handleCardClick(e, card)} + onDelete={this.props.onCardDelete} draggable={draggable} editable={editable} {...card} @@ -158,8 +164,8 @@ class Lane extends Component { return connectDropTarget(
{cardList} - {editable && !addCardMode && Add Card} - {addCardMode && } + {editable && !addCardMode && Add Card} + {addCardMode && }
) } @@ -208,14 +214,18 @@ Lane.propTypes = { droppable: PropTypes.bool, onLaneScroll: PropTypes.func, handleDragStart: PropTypes.func, - handleDragEnd: PropTypes.func + handleDragEnd: PropTypes.func, + onCardClick: PropTypes.func, + onCardDelete: PropTypes.func, + onCardAdd: PropTypes.func } Lane.defaultProps = { style: {}, titleStyle: {}, labelStyle: {}, - label: undefined + label: undefined, + onCardAdd: () => {} } const cardTarget = { diff --git a/src/styles/Base.js b/src/styles/Base.js index bd33291b9..3fa68f3a7 100644 --- a/src/styles/Base.js +++ b/src/styles/Base.js @@ -128,7 +128,7 @@ export const TagSpan = styled.span` font-size: 70%; ` -export const AddCard = styled.a` +export const AddCardLink = styled.a` border-radius: 0 0 3px 3px; color: #838c91; display: block; diff --git a/stories/EditableBoard.story.js b/stories/EditableBoard.story.js index 38daa2ac7..b41476b70 100644 --- a/stories/EditableBoard.story.js +++ b/stories/EditableBoard.story.js @@ -15,10 +15,23 @@ storiesOf('Editable Board', module).add( console.log(nextData) } + const handleCardDelete = (cardId, laneId) => { + console.log(`Card: ${cardId} deleted from lane: ${laneId}`) + } + + const handleCardAdd = (card, laneId) => { + console.log(`New card added to lane ${laneId}`) + console.dir(card) + } + return ( alert(`Card with id:${cardId} clicked. Card in lane: ${laneId}`)} editable /> )