Skip to content

Commit

Permalink
feat(): Custom card templates
Browse files Browse the repository at this point in the history
Ability to add customised styling to card with props injected at runtime
  • Loading branch information
rcdexta committed Jul 11, 2017
1 parent c4865f8 commit dd1d023
Show file tree
Hide file tree
Showing 6 changed files with 197 additions and 116 deletions.
66 changes: 29 additions & 37 deletions src/components/BoardContainer.js
Original file line number Diff line number Diff line change
@@ -1,27 +1,25 @@
import React, { Component, PropTypes } from 'react'
import { BoardDiv } from '../styles/Base'
import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'
import { DragDropContext } from 'react-dnd'
import React, {Component, PropTypes} from 'react'
import {BoardDiv} from '../styles/Base'
import {bindActionCreators} from 'redux'
import {connect} from 'react-redux'
import {DragDropContext} from 'react-dnd'
import MultiBackend from 'react-dnd-multi-backend'
import update from 'immutability-helper'
import HTML5toTouch from 'react-dnd-multi-backend/lib/HTML5toTouch'
import Lane from './Lane'

const boardActions = require('../actions/BoardActions')
const laneActions = require('../actions/LaneActions')

class BoardContainer extends Component {
state = { data: this.props.data }

wireEventBus = () => {
let eventBus = {
publish: event => {
publish: (event) => {
switch (event.type) {
case 'ADD_CARD':
return this.props.actions.addCard({ laneId: event.laneId, card: event.card })
return this.props.actions.addCard({laneId: event.laneId, card: event.card})
case 'REMOVE_CARD':
return this.props.actions.removeCard({ laneId: event.laneId, cardId: event.cardId })
return this.props.actions.removeCard({laneId: event.laneId, cardId: event.cardId})
case 'REFRESH_BOARD':
return this.props.actions.loadBoard(event.data)
}
Expand All @@ -30,40 +28,33 @@ class BoardContainer extends Component {
this.props.eventBusHandle(eventBus)
}

componentWillMount() {
componentWillMount () {
this.props.actions.loadBoard(this.props.data)
if (this.props.eventBusHandle) {
this.wireEventBus()
}
}

componentWillReceiveProps(nextProps) {
if (nextProps.lanes) {
const newData = update(this.state.data, { lanes: { $set: nextProps.lanes } })

this.setState({ data: newData })
componentWillReceiveProps (nextProps) {
if (nextProps.data) {
this.props.onDataChange && this.props.onDataChange(nextProps.data)
}
}

render() {
const { data } = this.state
return (
<BoardDiv>
{data.lanes.map(lane => {
const { id, ...otherProps } = lane
const { tagStyle, draggable, handleDragStart, handleDragEnd, onCardClick, onLaneScroll, laneSortFunction } = this.props
return (
<Lane
key={`${id}`}
id={id}
{...otherProps}
{...{ tagStyle, draggable, handleDragStart, handleDragEnd, onCardClick, onLaneScroll, laneSortFunction }}
/>
)
render () {
const {data} = this.props
return <BoardDiv>
{
data.lanes.map((lane) => {
const {id, ...otherProps} = lane
const {tagStyle, draggable, handleDragStart, handleDragEnd, onCardClick, onLaneScroll, laneSortFunction, customCardLayout, cardStyle, children} = this.props
return <Lane key={`${id}`}
id={id}
{...otherProps}
{...{tagStyle, draggable, handleDragStart, handleDragEnd, onCardClick, onLaneScroll, laneSortFunction, customCardLayout, cardStyle, children}}
/>
})}
</BoardDiv>
)
</BoardDiv>
}
}

Expand All @@ -76,13 +67,14 @@ BoardContainer.propTypes = {
draggable: PropTypes.bool,
handleDragStart: PropTypes.func,
handleDragEnd: PropTypes.func,
onDataChange: PropTypes.func
onDataChange: PropTypes.func,
customCardLayout: PropTypes.bool
}

const mapStateToProps = state => {
return state.lanes ? { lanes: state.lanes } : {}
const mapStateToProps = (state) => {
return state.lanes ? {data: state} : {}
}

const mapDispatchToProps = dispatch => ({ actions: bindActionCreators({ ...boardActions, ...laneActions }, dispatch) })
const mapDispatchToProps = (dispatch) => ({actions: bindActionCreators({...boardActions, ...laneActions}, dispatch)})

export default connect(mapStateToProps, mapDispatchToProps)(DragDropContext(MultiBackend(HTML5toTouch))(BoardContainer))
58 changes: 39 additions & 19 deletions src/components/Card.js
Original file line number Diff line number Diff line change
@@ -1,30 +1,43 @@
import React, {Component, PropTypes} from 'react'
import {CardWrapper, CardHeader, CardTitle, CardRightContent, Detail, Footer} from '../styles/Base'
import {DragType} from '../helpers/DragType'
import {DragSource, DropTarget} from 'react-dnd'
import React, { Component, PropTypes } from 'react'
import { CardWrapper, CardHeader, CardTitle, CardRightContent, Detail, Footer } from '../styles/Base'
import { DragType } from '../helpers/DragType'
import { DragSource, DropTarget } from 'react-dnd'
var flow = require('lodash.flow')
import {findDOMNode} from 'react-dom'
import { findDOMNode } from 'react-dom'
import Tag from './Tag'

class Card extends Component {
renderBody = () => {
if (this.props.customCardLayout) {
const customCardWithProps = React.cloneElement(this.props.customCard, { ...this.props })
return <span>{customCardWithProps}</span>
} else {
const { title, description, label, tags } = this.props
return (
<span>
<CardHeader>
<CardTitle>{title}</CardTitle>
<CardRightContent>{label}</CardRightContent>
</CardHeader>
<Detail>{description}</Detail>
{tags &&
<Footer>
{tags.map(tag => <Tag key={tag.title} {...tag} tagStyle={this.props.tagStyle} />)}
</Footer>}
</span>
)
}
}

render () {
const {id, title, description, label, tags, connectDragSource, connectDropTarget, isDragging, ...otherProps} = this.props
const { id, connectDragSource, connectDropTarget, isDragging, cardStyle, ...otherProps } = this.props
const opacity = isDragging ? 0 : 1
const background = isDragging ? '#CCC' : '#E3E3E3'
return connectDragSource(
connectDropTarget(
<div style={{background: background}}>
<CardWrapper key={id} data-id={id} {...otherProps} style={{opacity: opacity}}>
<CardHeader>
<CardTitle>{title}</CardTitle>
<CardRightContent>{label}</CardRightContent>
</CardHeader>
<Detail>{description}</Detail>
{tags && <Footer>
{tags.map((tag) => <Tag key={tag.title} {...tag} tagStyle={this.props.tagStyle} />)}
</Footer>
}
<div style={{ background: background }}>
<CardWrapper key={id} data-id={id} {...otherProps} style={{ ...cardStyle, opacity: opacity }}>
{this.renderBody()}
</CardWrapper>
</div>
)
Expand Down Expand Up @@ -100,17 +113,24 @@ const cardTarget = {
}
}

Card.defaultProps = {
cardStyle: {},
customCardLayout: false
}

Card.propTypes = {
id: PropTypes.string.isRequired,
title: PropTypes.string.isRequired,
title: PropTypes.string,
description: PropTypes.string,
label: PropTypes.string,
onClick: PropTypes.func,
metadata: PropTypes.object,
connectDragSource: PropTypes.func.isRequired,
isDragging: PropTypes.bool.isRequired,
handleDragStart: React.PropTypes.func,
handleDragEnd: React.PropTypes.func
handleDragEnd: React.PropTypes.func,
customCardLayout: React.PropTypes.bool,
customCard: React.PropTypes.node
}

export default flow(
Expand Down
Loading

0 comments on commit dd1d023

Please sign in to comment.