Skip to content

Commit 5b5654a

Browse files
committed
ChildTasks: add bread crumbs to easily access parent tasks
This adds parent task bread crumbs to both the task show view and the focus view. **Notes** - Because `ParentTaskBreadCrumbs` is a recursive component (container -> component -> container -> component) they needed to be co-located in the same file. Having two files that each import the other was throwing an error for me. The component was coming in `undefined`. - Enzyme doesn't yet have support for "fragments", which were introduced in React 16, otherwise I'd have avoided the outer `span` in `ParentTaskBreadCrumbs` and just returned an array. I tried the hack mentioned in the linked thread, but it didn't work for me. enzymejs/enzyme#1213
1 parent 309abb1 commit 5b5654a

File tree

4 files changed

+64
-0
lines changed

4 files changed

+64
-0
lines changed

app/javascript/src/task/components/show_view.js

+2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import PropTypes from 'prop-types';
22
import React from 'react';
33

44
import NewTaskForm from 'src/task/containers/new_task_form';
5+
import ParentTaskBreadCrumbs from 'src/task/containers/parent_task_bread_crumbs';
56
import SubTasksTable from 'src/task/components/sub_tasks_table';
67
import ToEnglish from 'src/_helpers/to_english';
78

@@ -63,6 +64,7 @@ class TaskShowView extends React.Component {
6364

6465
return (
6566
<section>
67+
<ParentTaskBreadCrumbs taskId={task.parentTaskId} />
6668
<h2>{task.title}</h2>
6769
<div>{repeatString(task)}</div>
6870
<div>{estimateString(task)}</div>

app/javascript/src/task/components/task_display.js

+4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import PropTypes from 'prop-types';
22
import React from 'react';
33

44
import MainButtons from 'src/task/components/main_buttons';
5+
import ParentTaskBreadCrumbs from 'src/task/containers/parent_task_bread_crumbs';
56
import TaskTitle from 'src/task/components/task_title';
67
import TagButtonsContainer from 'src/tag/containers/buttons';
78
import EditTaskForm from 'src/task/components/edit_task_form';
@@ -10,6 +11,9 @@ function TaskDisplay(props) {
1011
return (
1112
<div>
1213
<TagButtonsContainer currentTagIds={props.task && props.task.tagIds} />
14+
<div className='row'>
15+
<ParentTaskBreadCrumbs taskId={props.task.parentTaskId} />
16+
</div>
1317
<TaskTitle
1418
task={props.task}
1519
deleteTask={props.deleteTask}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import PropTypes from 'prop-types';
2+
import React from 'react';
3+
import {connect} from 'react-redux';
4+
5+
import TaskLink from 'src/task/components/link';
6+
7+
// The component is in the same file as the container due to circular references
8+
// ParentTaskBreadCrumbs renders ParentTaskBreadCrumbsContainer and vice versa
9+
// otherwise imports get funky
10+
function ParentTaskBreadCrumbs({task}) {
11+
if (!task) { return null; }
12+
13+
// span wrapper rather than array fragments due to lack of enzyme support
14+
// https://github.com/airbnb/enzyme/issues/1213
15+
// hack didn't work
16+
return (
17+
<span>
18+
<ParentTaskBreadCrumbsContainer taskId={task.parentTaskId} />
19+
<span>{' > '}<TaskLink task={task} /></span>
20+
</span>
21+
);
22+
}
23+
24+
ParentTaskBreadCrumbs.propTypes = {task: PropTypes.object};
25+
26+
function mapStateToProps(state, ownProps) {
27+
return {task: state.task.byId[ownProps.taskId]};
28+
}
29+
30+
const ParentTaskBreadCrumbsContainer = connect(mapStateToProps)(ParentTaskBreadCrumbs);
31+
32+
export {ParentTaskBreadCrumbs};
33+
export default ParentTaskBreadCrumbsContainer;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import React from 'react';
2+
import {shallow} from 'enzyme';
3+
4+
import {ParentTaskBreadCrumbs} from 'src/task/containers/parent_task_bread_crumbs';
5+
6+
it('renders nothing when there is no task', () => {
7+
const component = shallow(<ParentTaskBreadCrumbs />);
8+
9+
expect(component.type()).toBeNull();
10+
});
11+
12+
it('renders a link to the task when present', () => {
13+
const task = {};
14+
const component = shallow(<ParentTaskBreadCrumbs task={task} />);
15+
16+
expect(component.find('TaskLink')).toHaveProp('task', task);
17+
});
18+
19+
it('renders a parent task link recursively when tree goes deeper', () => {
20+
const task = {title: 'some parent', parentTaskId: 5};
21+
const component = shallow(<ParentTaskBreadCrumbs task={task} />);
22+
const container = component.find('Connect(ParentTaskBreadCrumbs)');
23+
24+
expect(container).toHaveProp('taskId', 5);
25+
});

0 commit comments

Comments
 (0)