Skip to content

Commit d20387d

Browse files
committed
fix(Add laneDraggable and cardDraggable props to override draggable prop to disable DnD for lane or
#98
1 parent 7a324e2 commit d20387d

4 files changed

Lines changed: 119 additions & 86 deletions

File tree

README.md

Lines changed: 89 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ Pluggable components to add a trello-like kanban board to your application
55
[![Build Status](https://travis-ci.org/rcdexta/react-trello.svg?branch=master)](https://travis-ci.org/rcdexta/react-trello)
66
[![npm version](https://badge.fury.io/js/react-trello.svg)](https://badge.fury.io/js/react-trello)
77

8-
[Demo]( https://rcdexta.github.io/react-trello/)
8+
[Demo](https://rcdexta.github.io/react-trello/)
99

1010
## Features
1111

@@ -21,7 +21,7 @@ Pluggable components to add a trello-like kanban board to your application
2121

2222
## Getting Started
2323

24-
Install using npm or yarn
24+
Install using npm or yarn
2525

2626
```bash
2727
$ npm install --save react-trello
@@ -46,7 +46,7 @@ const data = {
4646
label: '2/2',
4747
cards: [
4848
{id: 'Card1', title: 'Write Blog', description: 'Can AI make memes', label: '30 mins'},
49-
{id: 'Card2', title: 'Pay Rent', description: 'Transfer via NEFT', label: '5 mins', metadata: {sha: 'be312a1'}}
49+
{id: 'Card2', title: 'Pay Rent', description: 'Transfer via NEFT', label: '5 mins', metadata: {sha: 'be312a1'}}
5050
]
5151
},
5252
{
@@ -66,9 +66,9 @@ import React from 'react'
6666
import Board from 'react-trello'
6767

6868
export default class App extends React.Component {
69-
render() {
70-
return <Board data={data} />
71-
}
69+
render() {
70+
return <Board data={data} />
71+
}
7272
}
7373
```
7474

@@ -82,31 +82,33 @@ Also refer to the sample project that uses react-trello as illustration: https:/
8282

8383
This is the container component that encapsulates the lanes and cards
8484

85-
| Name | Type | Description |
86-
| ------------------- | -------- | ------------------------------------------------------------ |
87-
| draggable | boolean | Makes all cards in the lanes draggable. Default: false |
88-
| collapsibleLanes | boolean | Make the lanes with cards collapsible. Default: false |
89-
| editable | boolean | Makes the entire board editable. Allow cards to be added or deleted Default: false |
90-
| handleDragStart | function | Callback function triggered when card drag is started: `handleDragStart(cardId, laneId)` |
91-
| handleDragEnd | function | Callback function triggered when card drag ends: `handleDragEnd(cardId, sourceLaneId, targetLaneId, position)` |
92-
| handleLaneDragStart | function | Callback function triggered when lane drag is started: `handleLaneDragStart(laneId)` |
93-
| handleLaneDragEnd | function | Callback function triggered when lane drag ends: `handleLaneDragEnd(laneId, newPosition)` |
94-
| onLaneScroll | function | Called when a lane is scrolled to the end: `onLaneScroll(requestedPage, laneId)` |
95-
| onCardClick | function | Called when a card is clicked: `onCardClick(cardId, metadata, laneId) ` |
96-
| onCardAdd | function | Called when a new card is added: `onCardAdd(card, laneId) ` |
97-
| addCardLink | node | Pass custom element to replace the `Add Card` link at the end of the lane (when board is editable) |
98-
| newCardTemplate | node | Pass a custom new card template to add new cards to a lane (when board is editable) |
99-
| hideCardDeleteIcon | boolean | Disable showing the delete icon to the top right corner of the card (when board is editable) |
100-
| onCardDelete | function | Called when a card is deleted: `onCardDelete(cardId, laneId) ` |
101-
| onLaneClick | function | Called when a lane is clicked: `onLaneClick(laneId) `. Card clicks are not propagated to lane click event |
102-
| laneSortFunction | function | Used to specify the logic to sort cards on a lane: `laneSortFunction(card1, card2)` |
85+
| Name | Type | Description |
86+
| ------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------ |
87+
| draggable | boolean | Makes all cards and lanes draggable. Default: false |
88+
| laneDraggable | boolean | Set to false to disable lane dragging. Default: true |
89+
| cardDraggable | boolean | Set to false to disable card dragging. Default: true |
90+
| collapsibleLanes | boolean | Make the lanes with cards collapsible. Default: false |
91+
| editable | boolean | Makes the entire board editable. Allow cards to be added or deleted Default: false |
92+
| handleDragStart | function | Callback function triggered when card drag is started: `handleDragStart(cardId, laneId)` |
93+
| handleDragEnd | function | Callback function triggered when card drag ends: `handleDragEnd(cardId, sourceLaneId, targetLaneId, position)` |
94+
| handleLaneDragStart | function | Callback function triggered when lane drag is started: `handleLaneDragStart(laneId)` |
95+
| handleLaneDragEnd | function | Callback function triggered when lane drag ends: `handleLaneDragEnd(laneId, newPosition)` |
96+
| onLaneScroll | function | Called when a lane is scrolled to the end: `onLaneScroll(requestedPage, laneId)` |
97+
| onCardClick | function | Called when a card is clicked: `onCardClick(cardId, metadata, laneId)` |
98+
| onCardAdd | function | Called when a new card is added: `onCardAdd(card, laneId)` |
99+
| addCardLink | node | Pass custom element to replace the `Add Card` link at the end of the lane (when board is editable) |
100+
| newCardTemplate | node | Pass a custom new card template to add new cards to a lane (when board is editable) |
101+
| hideCardDeleteIcon | boolean | Disable showing the delete icon to the top right corner of the card (when board is editable) |
102+
| onCardDelete | function | Called when a card is deleted: `onCardDelete(cardId, laneId)` |
103+
| onLaneClick | function | Called when a lane is clicked: `onLaneClick(laneId)`. Card clicks are not propagated to lane click event |
104+
| laneSortFunction | function | Used to specify the logic to sort cards on a lane: `laneSortFunction(card1, card2)` |
103105
| eventBusHandle | function | This is a special function that providers a publishHook to pass new events to the board. See details in Publish Events section |
104-
| onDataChange | function | Called everytime the data changes due to user interaction or event bus: `onDataChange(newData)` |
105-
| style | object | Pass css style props to board container |
106-
| customCardLayout | function | Boolean to indicate a custom card template will be specified. Add the card component as child to Board |
107-
| customLaneHeader | element | Pass custom lane header as react component to modify appearance |
108-
| data | object | Actual board data in the form of json |
109-
| tagStyle | object | If cards have tags, use this prop to modify their style |
106+
| onDataChange | function | Called everytime the data changes due to user interaction or event bus: `onDataChange(newData)` |
107+
| style | object | Pass css style props to board container |
108+
| customCardLayout | function | Boolean to indicate a custom card template will be specified. Add the card component as child to Board |
109+
| customLaneHeader | element | Pass custom lane header as react component to modify appearance |
110+
| data | object | Actual board data in the form of json |
111+
| tagStyle | object | If cards have tags, use this prop to modify their style |
110112

111113
Refer to `stories` folder for examples on many more options for customization.
112114

@@ -143,7 +145,7 @@ You can completely customize the look-and-feel of each card in any lane by passi
143145

144146
```javascript
145147
<Board data={data} customCardLayout>
146-
<CustomCard />
148+
<CustomCard />
147149
</Board>
148150
```
149151

@@ -156,18 +158,24 @@ const CustomCard = props => {
156158
return (
157159
<div>
158160
<header
159-
style={{borderBottom: '1px solid #eee', paddingBottom: 6, marginBottom: 10,
160-
display: 'flex', flexDirection: 'row', justifyContent: 'space-between',
161-
color: props.cardColor
162-
}}
163-
>
164-
<div style={{ fontSize: 14, fontWeight: 'bold' }}>{props.name}</div>
165-
<div style={{ fontSize: 11 }}>{props.dueOn}</div>
161+
style={{
162+
borderBottom: '1px solid #eee',
163+
paddingBottom: 6,
164+
marginBottom: 10,
165+
display: 'flex',
166+
flexDirection: 'row',
167+
justifyContent: 'space-between',
168+
color: props.cardColor
169+
}}>
170+
<div style={{fontSize: 14, fontWeight: 'bold'}}>{props.name}</div>
171+
<div style={{fontSize: 11}}>{props.dueOn}</div>
166172
</header>
167-
<div style={{ fontSize: 12, color: '#BD3B36' }}>
168-
<div style={{ color: '#4C4C4C', fontWeight: 'bold' }}>{props.subTitle}</div>
169-
<div style={{ padding: '5px 0px' }}><i>{props.body}</i></div>
170-
<div style={{ marginTop: 10, textAlign: 'center', color: props.cardColor, fontSize: 15, fontWeight: 'bold' }}>
173+
<div style={{fontSize: 12, color: '#BD3B36'}}>
174+
<div style={{color: '#4C4C4C', fontWeight: 'bold'}}>{props.subTitle}</div>
175+
<div style={{padding: '5px 0px'}}>
176+
<i>{props.body}</i>
177+
</div>
178+
<div style={{marginTop: 10, textAlign: 'center', color: props.cardColor, fontSize: 15, fontWeight: 'bold'}}>
171179
{props.escalationText}
172180
</div>
173181
</div>
@@ -176,35 +184,35 @@ const CustomCard = props => {
176184
}
177185

178186
const data = {
179-
lanes: [
180-
{
181-
id: 'lane1',
182-
title: 'Planned Tasks',
183-
cards: [
184-
{
185-
id: 'Card1',
186-
name: 'John Smith',
187-
dueOn: 'due in a day',
188-
subTitle: 'SMS received at 12:13pm today',
189-
body: 'Thanks. Please schedule me for an estimate on Monday.',
190-
escalationText: 'Escalated to OPS-ESCALATIONS!',
191-
cardColor: '#BD3B36',
192-
cardStyle: { borderRadius: 6, boxShadow: '0 0 6px 1px #BD3B36', marginBottom: 15 }
193-
},
194-
{
195-
id: 'Card2',
196-
name: 'Card Weathers',
197-
dueOn: 'due now',
198-
subTitle: 'Email received at 1:14pm',
199-
body: 'Is the estimate free, and can someone call me soon?',
200-
escalationText: 'Escalated to Admin',
201-
cardColor: '#E08521',
202-
cardStyle: { borderRadius: 6, boxShadow: '0 0 6px 1px #E08521', marginBottom: 15 }
203-
}
204-
]
205-
}
206-
]
207-
}
187+
lanes: [
188+
{
189+
id: 'lane1',
190+
title: 'Planned Tasks',
191+
cards: [
192+
{
193+
id: 'Card1',
194+
name: 'John Smith',
195+
dueOn: 'due in a day',
196+
subTitle: 'SMS received at 12:13pm today',
197+
body: 'Thanks. Please schedule me for an estimate on Monday.',
198+
escalationText: 'Escalated to OPS-ESCALATIONS!',
199+
cardColor: '#BD3B36',
200+
cardStyle: {borderRadius: 6, boxShadow: '0 0 6px 1px #BD3B36', marginBottom: 15}
201+
},
202+
{
203+
id: 'Card2',
204+
name: 'Card Weathers',
205+
dueOn: 'due now',
206+
subTitle: 'Email received at 1:14pm',
207+
body: 'Is the estimate free, and can someone call me soon?',
208+
escalationText: 'Escalated to Admin',
209+
cardColor: '#E08521',
210+
cardStyle: {borderRadius: 6, boxShadow: '0 0 6px 1px #E08521', marginBottom: 15}
211+
}
212+
]
213+
}
214+
]
215+
}
208216
```
209217

210218
## Editable Board
@@ -231,18 +239,19 @@ yarn run storybook
231239

232240
### Scripts
233241

234-
1. `npm run lint` : Lint all js files
235-
2. `npm run lintfix` : fix linting errors of all js files
236-
3. `npm run semantic-release` : make a release. Leave it for CI to do.
237-
4. `npm run storybook`: Start developing by using storybook
238-
5. `npm run test` : Run tests. tests file should be written as `*.test.js` and using ES2015
239-
6. `npm run test:watch` : Watch tests while writing
240-
7. `npm run test:cover` : Show coverage report of your tests
241-
8. `npm run test:report` : Report test coverage to codecov.io. Leave this for CI
242-
9. `npm run build`: transpile all ES6 component files into ES5(commonjs) and put it in `dist` directory
242+
1. `npm run lint` : Lint all js files
243+
2. `npm run lintfix` : fix linting errors of all js files
244+
3. `npm run semantic-release` : make a release. Leave it for CI to do.
245+
4. `npm run storybook`: Start developing by using storybook
246+
5. `npm run test` : Run tests. tests file should be written as `*.test.js` and using ES2015
247+
6. `npm run test:watch` : Watch tests while writing
248+
7. `npm run test:cover` : Show coverage report of your tests
249+
8. `npm run test:report` : Report test coverage to codecov.io. Leave this for CI
250+
9. `npm run build`: transpile all ES6 component files into ES5(commonjs) and put it in `dist` directory
243251
10. `npm run docs`: create static build of storybook in `docs` directory that can be used for github pages
244252

245253
Learn how to write stories [here](https://getstorybook.io/docs/basics/writing-stories)
246254

247255
### License
256+
248257
MIT

src/components/BoardContainer.js

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ class BoardContainer extends Component {
7878
}
7979

8080
render() {
81-
const {reducerData, draggable, style, ...otherProps} = this.props
81+
const {reducerData, draggable, laneDraggable, style, ...otherProps} = this.props
8282
// Stick to whitelisting attributes to segregate board and lane props
8383
const passthroughProps = pick(this.props, [
8484
'onLaneScroll',
@@ -89,6 +89,7 @@ class BoardContainer extends Component {
8989
'addCardLink',
9090
'laneSortFunction',
9191
'draggable',
92+
'cardDraggable',
9293
'collapsibleLanes',
9394
'editable',
9495
'hideCardDeleteIcon',
@@ -123,7 +124,11 @@ class BoardContainer extends Component {
123124
{...passthroughProps}
124125
/>
125126
)
126-
return draggable ? <Draggable key={lane.id}>{laneToRender}</Draggable> : <span key={lane.id}>{laneToRender}</span>
127+
return draggable && laneDraggable ? (
128+
<Draggable key={lane.id}>{laneToRender}</Draggable>
129+
) : (
130+
<span key={lane.id}>{laneToRender}</span>
131+
)
127132
})}
128133
</Container>
129134
</BoardDiv>
@@ -156,7 +161,9 @@ BoardContainer.propTypes = {
156161
newCardTemplate: PropTypes.node,
157162
customLaneHeader: PropTypes.element,
158163
style: PropTypes.object,
159-
tagStyle: PropTypes.object
164+
tagStyle: PropTypes.object,
165+
laneDraggable: PropTypes.bool,
166+
cardDraggable: PropTypes.bool
160167
}
161168

162169
BoardContainer.defaultProps = {
@@ -168,7 +175,9 @@ BoardContainer.defaultProps = {
168175
editable: false,
169176
hideCardDeleteIcon: false,
170177
draggable: false,
171-
collapsibleLanes: false
178+
collapsibleLanes: false,
179+
laneDraggable: true,
180+
cardDraggable: true
172181
}
173182

174183
const mapStateToProps = state => {

src/components/Lane.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ class Lane extends Component {
150150
tagStyle,
151151
cardStyle,
152152
draggable,
153+
cardDraggable,
153154
cards,
154155
id
155156
} = this.props
@@ -174,7 +175,7 @@ class Lane extends Component {
174175
{...card}
175176
/>
176177
)
177-
return draggable ? <Draggable key={card.id}>{cardToRender}</Draggable> : <span key={card.id}>{cardToRender}</span>
178+
return draggable && cardDraggable ? <Draggable key={card.id}>{cardToRender}</Draggable> : <span key={card.id}>{cardToRender}</span>
178179
})
179180

180181
return (
@@ -269,7 +270,8 @@ Lane.propTypes = {
269270
onLaneClick: PropTypes.func,
270271
newCardTemplate: PropTypes.node,
271272
addCardLink: PropTypes.node,
272-
editable: PropTypes.bool
273+
editable: PropTypes.bool,
274+
cardDraggable: PropTypes.bool
273275
}
274276

275277
Lane.defaultProps = {

stories/RestrictedLanes.story.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,16 @@ storiesOf('Drag-n-Drop', module).add(
1717
)
1818
})
1919
)
20+
21+
storiesOf('Drag-n-Drop', module).add(
22+
'Drag Cards not Lanes',
23+
withInfo('Use props to disable dragging lanes but enable card dragging')(() => {
24+
return (
25+
<Board
26+
data={data}
27+
draggable
28+
laneDraggable={false}
29+
/>
30+
)
31+
})
32+
)

0 commit comments

Comments
 (0)