diff --git a/src/Project.js b/src/Project.js
index 7a3e053..fae9435 100644
--- a/src/Project.js
+++ b/src/Project.js
@@ -26,6 +26,7 @@ const Project = ({
}) => {
const [splitFinalColumns] = useLocalStorage('splitColumns');
const [slim, setSlim] = useLocalStorage('slim');
+ const [rejected] = useLocalStorage('rejected');
const keyMap = useMemo(
() => ({
@@ -115,6 +116,18 @@ const Project = ({
slim={slim}
/>
)}
+ {rejected && (
+
+ )}
diff --git a/src/ProjectContainer.js b/src/ProjectContainer.js
index f049675..655895a 100644
--- a/src/ProjectContainer.js
+++ b/src/ProjectContainer.js
@@ -38,10 +38,37 @@ function reducer(state, action) {
case 'FETCH_BLOCKERS_SUCCESS': {
const storiesWithBlockers = { ...state.stories };
+ const matchStoryId = str =>
+ (str && str.match(/([0-9]){9}$/)[0]) || 'Unknown';
+
+ const getStoryBlockers = blockers => {
+ return blockers
+ .map(b => {
+ const storyId = matchStoryId(b.description);
+ const scopedStory = storiesWithBlockers[storyId];
+ return scopedStory
+ ? {
+ id: scopedStory.id,
+ url: scopedStory.url,
+ name: scopedStory.name,
+ resolved: b.resolved
+ }
+ : {
+ id: storyId,
+ url: `https://www.pivotaltracker.com/story/show/${storyId}`,
+ name: '[Out of current iteration blocker]',
+ resolved: b.resolved
+ };
+ })
+ .filter(b => !b.resolved);
+ };
+
payload.forEach(story => {
if (story.blockers.length > 0) {
if (storiesWithBlockers[story.id]) {
- storiesWithBlockers[story.id].blockers = story.blockers;
+ storiesWithBlockers[story.id].blockers = getStoryBlockers(
+ story.blockers
+ );
} else {
console.warn(
'Recieved blockers for unknow story, with id',
diff --git a/src/Settings.js b/src/Settings.js
index 1ca2b4f..8205642 100644
--- a/src/Settings.js
+++ b/src/Settings.js
@@ -7,6 +7,9 @@ const Settings = () => {
);
const [slim, setSlim] = useLocalStorage('slim');
+ const [showRejectedColumn, setShowRejectedColumn] = useLocalStorage(
+ 'rejected'
+ );
return (
@@ -60,6 +63,28 @@ const Settings = () => {
+
+
+
+
+
+
+
+
Rejected state column
+
+ Enable this setting to have Rejected state column.
+
+ Current state: {showRejectedColumn ? 'enabled' : 'disabled'}
+
+
+
);
};
diff --git a/src/Story.js b/src/Story.js
index c270adb..01c9a0e 100644
--- a/src/Story.js
+++ b/src/Story.js
@@ -1,7 +1,6 @@
import React from 'react';
import { Owners } from './Owners';
import {
- BlockedTag,
BugTag,
ChoreTag,
EstimateTag,
@@ -10,6 +9,7 @@ import {
SlimTag
} from './Tags';
import { hasUnresolvedBlockers } from './FilterContainer';
+import { StoryBlockers } from './StoryBlockers';
const renderTypeTag = type => {
switch (type) {
@@ -84,10 +84,9 @@ function Story({
-
-
)}
+
);
diff --git a/src/Story.test.js b/src/Story.test.js
index 09064fb..a80c8af 100644
--- a/src/Story.test.js
+++ b/src/Story.test.js
@@ -142,31 +142,21 @@ describe('Story', () => {
expect(within(getByTestId('owners')).getByText('WT')).toBeInTheDocument();
});
- describe('blocked tag', () => {
- it('renders visible blocked tag if blocked', () => {
+ describe('story blockers', () => {
+ it('renders blockers if blocked', () => {
const { queryByTestId } = renderSubject({
blockers: [{ resolved: false }]
});
- expect(queryByTestId('blocked-tag')).toBeVisible();
+ expect(queryByTestId('story-blockers')).toBeInTheDocument();
});
- it('renders invisible blocked tag if not blocked', () => {
- const { queryByTestId } = renderSubject({
- blockers: [{ resolved: true }]
- });
-
- expect(queryByTestId('blocked-tag')).toBeInTheDocument();
- expect(queryByTestId('blocked-tag')).not.toBeVisible();
- });
-
- it('renders invisible blocked tag if no blockers', () => {
+ it('does not render blockers if no blockers', () => {
const { queryByTestId } = renderSubject({
blockers: []
});
- expect(queryByTestId('blocked-tag')).toBeInTheDocument();
- expect(queryByTestId('blocked-tag')).not.toBeVisible();
+ expect(queryByTestId('story-blockers')).not.toBeInTheDocument();
});
});
diff --git a/src/StoryBlockers.js b/src/StoryBlockers.js
new file mode 100644
index 0000000..67b1973
--- /dev/null
+++ b/src/StoryBlockers.js
@@ -0,0 +1,33 @@
+import React from 'react';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { faBan } from '@fortawesome/free-solid-svg-icons';
+
+function StoryBlockers({ blockers }) {
+ if (!blockers.length) return null;
+
+ return (
+
+ );
+}
+
+export { StoryBlockers };
diff --git a/src/__snapshots__/ProjectContainer.test.js.snap b/src/__snapshots__/ProjectContainer.test.js.snap
index 7f6b87e..c4deb0e 100644
--- a/src/__snapshots__/ProjectContainer.test.js.snap
+++ b/src/__snapshots__/ProjectContainer.test.js.snap
@@ -146,13 +146,48 @@ exports[`ProjectContainer renders fetched and normalized data 1`] = `
+
+
+
- Blocked
+
+ Blockers:
+
@@ -245,13 +280,6 @@ exports[`ProjectContainer renders fetched and normalized data 1`] = `
-
- Blocked
-