From 5be36c8fa1056f776cef09f1d89a38cb35a9bb43 Mon Sep 17 00:00:00 2001 From: Bartosz Wojciechowski Date: Tue, 19 Nov 2019 11:16:24 +0100 Subject: [PATCH 1/4] Added Rejected column --- src/Project.js | 13 +++++++++++++ src/Settings.js | 24 ++++++++++++++++++++++++ 2 files changed, 37 insertions(+) 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/Settings.js b/src/Settings.js index 1ca2b4f..986eaf9 100644 --- a/src/Settings.js +++ b/src/Settings.js @@ -7,6 +7,7 @@ const Settings = () => { ); const [slim, setSlim] = useLocalStorage('slim'); + const [rejected, setRejected] = useLocalStorage('rejected'); return (
@@ -60,6 +61,29 @@ const Settings = () => {

+ +
+
+ +
+ +
+

Rejected state column

+

+ Enable this setting to have Rejected state column. +
+ Current state: {rejected ? 'enabled' : 'disabled'} +

+
+
+ ); }; From cac92542aeb52d93ff8f6b7b5ec4bad03a507e55 Mon Sep 17 00:00:00 2001 From: Bartosz Wojciechowski Date: Tue, 19 Nov 2019 16:25:45 +0100 Subject: [PATCH 2/4] Added Blockers to cards [Finishes #169836792] --- src/ProjectContainer.js | 29 ++++++++++++++++++++++++++++- src/Story.js | 5 ++--- src/StoryBlockers.js | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+), 4 deletions(-) create mode 100644 src/StoryBlockers.js 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/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/StoryBlockers.js b/src/StoryBlockers.js new file mode 100644 index 0000000..10a8af2 --- /dev/null +++ b/src/StoryBlockers.js @@ -0,0 +1,35 @@ +import React from 'react'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { faBan } from '@fortawesome/free-solid-svg-icons'; + +function StoryBlockers({ blockers }) { + if (blockers && blockers.length) { + return ( +
+
+ + Blockers: + + + +
+ ); + } else { + return null; + } +} + +export { StoryBlockers }; From 56ad4e023e05077e854bd062ecbd849e647e89af Mon Sep 17 00:00:00 2001 From: Bartosz Wojciechowski Date: Wed, 20 Nov 2019 20:00:25 +0100 Subject: [PATCH 3/4] Fixed tests and lints --- src/Settings.js | 1 - src/Story.test.js | 20 ++------ src/StoryBlockers.js | 2 +- .../ProjectContainer.test.js.snap | 50 +++++++++++++++---- 4 files changed, 45 insertions(+), 28 deletions(-) diff --git a/src/Settings.js b/src/Settings.js index 986eaf9..8197e03 100644 --- a/src/Settings.js +++ b/src/Settings.js @@ -83,7 +83,6 @@ const Settings = () => {

- ); }; diff --git a/src/Story.test.js b/src/Story.test.js index 09064fb..70898bf 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 rnender 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 index 10a8af2..9b6e177 100644 --- a/src/StoryBlockers.js +++ b/src/StoryBlockers.js @@ -5,7 +5,7 @@ import { faBan } from '@fortawesome/free-solid-svg-icons'; function StoryBlockers({ blockers }) { if (blockers && blockers.length) { return ( -
+

Blockers: 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 - From 5a0c4e80d3c6d57cc00b0b9235318fb9384e2999 Mon Sep 17 00:00:00 2001 From: Bartosz Wojciechowski Date: Thu, 21 Nov 2019 12:42:54 +0100 Subject: [PATCH 4/4] - reduce nested conditional block in StoryBlockers - removed unnecessary conditions check - fixed test typo - fixed option variable names --- src/Settings.js | 10 +++++---- src/Story.test.js | 2 +- src/StoryBlockers.js | 50 +++++++++++++++++++++----------------------- 3 files changed, 31 insertions(+), 31 deletions(-) diff --git a/src/Settings.js b/src/Settings.js index 8197e03..8205642 100644 --- a/src/Settings.js +++ b/src/Settings.js @@ -7,7 +7,9 @@ const Settings = () => { ); const [slim, setSlim] = useLocalStorage('slim'); - const [rejected, setRejected] = useLocalStorage('rejected'); + const [showRejectedColumn, setShowRejectedColumn] = useLocalStorage( + 'rejected' + ); return (
@@ -67,8 +69,8 @@ const Settings = () => { @@ -79,7 +81,7 @@ const Settings = () => {

Enable this setting to have Rejected state column.
- Current state: {rejected ? 'enabled' : 'disabled'} + Current state: {showRejectedColumn ? 'enabled' : 'disabled'}

diff --git a/src/Story.test.js b/src/Story.test.js index 70898bf..a80c8af 100644 --- a/src/Story.test.js +++ b/src/Story.test.js @@ -151,7 +151,7 @@ describe('Story', () => { expect(queryByTestId('story-blockers')).toBeInTheDocument(); }); - it('does not rnender blockers if no blockers', () => { + it('does not render blockers if no blockers', () => { const { queryByTestId } = renderSubject({ blockers: [] }); diff --git a/src/StoryBlockers.js b/src/StoryBlockers.js index 9b6e177..67b1973 100644 --- a/src/StoryBlockers.js +++ b/src/StoryBlockers.js @@ -3,33 +3,31 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faBan } from '@fortawesome/free-solid-svg-icons'; function StoryBlockers({ blockers }) { - if (blockers && blockers.length) { - return ( -
-
- - Blockers: - + if (!blockers.length) return null; - -
- ); - } else { - return null; - } + return ( +
+
+ + Blockers: + + + +
+ ); } export { StoryBlockers };