phobos_checkpoint_ui 1.0.0.rc1 → 1.0.0.rc2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1 -1
  3. data/frontend/src/actions/event-details.js +5 -7
  4. data/frontend/src/actions/event-retry.js +7 -9
  5. data/frontend/src/actions/events-search.js +5 -7
  6. data/frontend/src/actions/failures/details.js +5 -7
  7. data/frontend/src/actions/failures/details.spec.js +1 -1
  8. data/frontend/src/actions/failures/retry.js +34 -17
  9. data/frontend/src/actions/failures/retry.spec.js +52 -5
  10. data/frontend/src/actions/failures/search/index.js +5 -8
  11. data/frontend/src/actions/failures/search/index.spec.js +2 -2
  12. data/frontend/src/actions/index.js +3 -1
  13. data/frontend/src/components/empty-event/empty-event.scss +6 -0
  14. data/frontend/src/components/event/card-style.js +29 -0
  15. data/frontend/src/components/event/event.scss +12 -0
  16. data/frontend/src/components/event/index.js +12 -21
  17. data/frontend/src/components/event/index.spec.js +3 -2
  18. data/frontend/src/components/event-overview-dialog/index.js +1 -1
  19. data/frontend/src/components/event-retry-dialog/index.js +9 -1
  20. data/frontend/src/components/failure/empty/empty-failure.scss +6 -0
  21. data/frontend/src/components/failure/empty/index.js +20 -0
  22. data/frontend/src/components/failure/empty/index.spec.js +38 -0
  23. data/frontend/src/components/failure/index.js +11 -20
  24. data/frontend/src/components/failure/index.scss +15 -0
  25. data/frontend/src/components/failure/index.spec.js +19 -14
  26. data/frontend/src/components/{failures-list → failure/list}/failures-list.scss +1 -1
  27. data/frontend/src/components/{failures-list → failure/list}/index.spec.js +15 -11
  28. data/frontend/src/components/failure/overview-dialog/index.js +4 -4
  29. data/frontend/src/components/failure/retry-dialog/index.js +14 -9
  30. data/frontend/src/components/flash-message/flash-message.scss +0 -1
  31. data/frontend/src/components/header/header.scss +5 -0
  32. data/frontend/src/components/header/index.js +62 -22
  33. data/frontend/src/reducers/event-details.js +9 -8
  34. data/frontend/src/reducers/event-details.spec.js +12 -2
  35. data/frontend/src/reducers/failures/details/index.js +9 -8
  36. data/frontend/src/reducers/failures/details/index.spec.js +12 -2
  37. data/frontend/src/reducers/failures/index.js +6 -4
  38. data/frontend/src/reducers/failures/index.spec.js +5 -5
  39. data/frontend/src/reducers/xhr-status.js +4 -0
  40. data/frontend/src/reducers/xhr-status.spec.js +20 -0
  41. data/frontend/src/views/events/search/index.scss +0 -7
  42. data/frontend/src/views/failures/details/index.js +2 -2
  43. data/frontend/src/views/failures/search/index.js +5 -5
  44. data/frontend/src/views/failures/search/index.scss +1 -8
  45. data/frontend/src/views/failures/search/index.spec.js +4 -4
  46. data/frontend/src/views/layout.js +2 -2
  47. data/lib/phobos_checkpoint_ui/version.rb +1 -1
  48. metadata +12 -12
  49. data/frontend/src/components/event/style.js +0 -16
  50. data/frontend/src/components/failure/error-message.js +0 -19
  51. data/frontend/src/components/failure/error-message.scss +0 -8
  52. data/frontend/src/components/failure/event.scss +0 -3
  53. data/frontend/src/components/failure/loading.js +0 -16
  54. data/frontend/src/components/failure/style.js +0 -16
  55. /data/frontend/src/components/{failures-list → failure/list}/index.js +0 -0
  56. /data/frontend/src/components/failure/overview-dialog/{event-overview-dialog.scss → failure-overview-dialog.scss} +0 -0
@@ -0,0 +1,15 @@
1
+ .failure {
2
+ cursor: pointer;
3
+
4
+ .failure-header {
5
+ display: flex;
6
+ justify-content: space-between;
7
+ }
8
+
9
+ .failure-icon {
10
+ order: 2;
11
+ width: 35px !important;
12
+ height: 35px !important;
13
+ margin-right: 0 !important;
14
+ }
15
+ }
@@ -1,7 +1,8 @@
1
1
  import React from 'react'
2
2
  import jasmineEnzyme from 'jasmine-enzyme'
3
3
  import { mount } from 'enzyme'
4
- import { Event, formatEventTime } from 'components/event'
4
+ import { Failure } from 'components/failure'
5
+ import { formatTime } from 'components/event/card-style'
5
6
  import getMuiTheme from 'material-ui/styles/getMuiTheme'
6
7
  import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider'
7
8
  import { Provider } from 'react-redux'
@@ -14,12 +15,12 @@ const mockStore = configureMockStore(middlewares)
14
15
  const mountComponent = (store, props) => mount(
15
16
  <Provider store={store}>
16
17
  <MuiThemeProvider muiTheme={getMuiTheme()}>
17
- <Event {...props} />
18
+ <Failure {...props} />
18
19
  </MuiThemeProvider>
19
20
  </Provider>
20
21
  )
21
22
 
22
- describe('<Event />', () => {
23
+ describe('<Failure />', () => {
23
24
  let props, component, store, onShowOverview
24
25
 
25
26
  beforeEach(() => {
@@ -34,7 +35,7 @@ describe('<Event />', () => {
34
35
 
35
36
  props = {
36
37
  onShowOverview: onShowOverview,
37
- event: {
38
+ failure: {
38
39
  id: 1,
39
40
  topic: 'phobos.test',
40
41
  group_id: 'phobos-checkpoint-consumer',
@@ -43,7 +44,11 @@ describe('<Event />', () => {
43
44
  event_type: 'order-placed',
44
45
  event_version: 'v1',
45
46
  checksum: '188773471ec0f898fd81d272760a027f',
46
- payload: { data: { name: 'phobos' } }
47
+ payload: { data: { name: 'phobos' } },
48
+ metadata: { meta: { version: 'foo' } },
49
+ error_class: 'FooError',
50
+ error_message: 'Expected "foo" to equal "bar"',
51
+ error_backtrace: ['Line 1: foo', 'Line 2: baz']
47
52
  }
48
53
  }
49
54
 
@@ -51,7 +56,7 @@ describe('<Event />', () => {
51
56
  })
52
57
 
53
58
  it('displays event_time formatted', () => {
54
- expect(component.text()).toMatch(formatEventTime(props.event.event_time))
59
+ expect(component.text()).toMatch(formatTime(props.failure.event_time))
55
60
  })
56
61
 
57
62
  it('displays topic', () => {
@@ -63,27 +68,27 @@ describe('<Event />', () => {
63
68
  })
64
69
 
65
70
  describe('when clicked', () => {
66
- it('calls onShowOverview with the event', () => {
67
- component.find('.event').simulate('click')
68
- expect(onShowOverview).toHaveBeenCalledWith(props.event)
71
+ it('calls onShowOverview with the failure', () => {
72
+ component.find('.failure').simulate('click')
73
+ expect(onShowOverview).toHaveBeenCalledWith(props.failure)
69
74
  })
70
75
  })
71
76
 
72
- describe('when event has overviewVisible=true', () => {
77
+ describe('when failure has overviewVisible=true', () => {
73
78
  let dialog
74
79
  beforeEach(() => {
75
- Object.assign(props.event, { overviewVisible: true })
80
+ Object.assign(props.failure, { overviewVisible: true })
76
81
  component = mountComponent(store, props)
77
- const dialogs = document.getElementsByClassName('event-overview-dialog')
82
+ const dialogs = document.getElementsByClassName('failure-overview-dialog')
78
83
  dialog = dialogs[dialogs.length - 1]
79
84
  })
80
85
 
81
- it('opens the event overview dialog', () => {
86
+ it('opens the failure overview dialog', () => {
82
87
  expect(dialog).not.toBe(null)
83
88
  })
84
89
 
85
90
  it('displays event_id', () => {
86
- expect(dialog.innerText).toMatch(`#${props.event.id}`)
91
+ expect(dialog.innerText).toMatch(`#${props.failure.id}`)
87
92
  })
88
93
  })
89
94
  })
@@ -42,7 +42,7 @@
42
42
  }
43
43
  }
44
44
 
45
- & > .event {
45
+ & > .failure {
46
46
  margin: 10px 10px;
47
47
  }
48
48
  }
@@ -1,7 +1,7 @@
1
1
  import React from 'react'
2
2
  import jasmineEnzyme from 'jasmine-enzyme'
3
3
  import { mount } from 'enzyme'
4
- import EventsList from 'components/events-list'
4
+ import FailuresList from 'components/failure/list'
5
5
  import getMuiTheme from 'material-ui/styles/getMuiTheme'
6
6
  import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider'
7
7
  import { Provider } from 'react-redux'
@@ -14,13 +14,13 @@ const mockStore = configureMockStore(middlewares)
14
14
  const mountComponent = (store, props) => mount(
15
15
  <Provider store={store}>
16
16
  <MuiThemeProvider muiTheme={getMuiTheme()}>
17
- <EventsList {...props} />
17
+ <FailuresList {...props} />
18
18
  </MuiThemeProvider>
19
19
  </Provider>
20
20
  )
21
21
 
22
- describe('<EventsList />', () => {
23
- let store, props, component, event
22
+ describe('<FailuresList />', () => {
23
+ let store, props, component, failure
24
24
 
25
25
  beforeEach(() => {
26
26
  jasmineEnzyme()
@@ -31,7 +31,7 @@ describe('<EventsList />', () => {
31
31
  }
32
32
  })
33
33
 
34
- event = {
34
+ failure = {
35
35
  id: 1,
36
36
  topic: 'phobos.test',
37
37
  group_id: 'phobos-checkpoint-consumer',
@@ -40,20 +40,24 @@ describe('<EventsList />', () => {
40
40
  event_type: 'order-placed',
41
41
  event_version: 'v1',
42
42
  checksum: '188773471ec0f898fd81d272760a027f',
43
- payload: { data: { name: 'phobos' } }
43
+ payload: { data: { name: 'phobos' } },
44
+ metadata: { meta: { version: 'foo' } },
45
+ error_class: 'FooError',
46
+ error_message: 'Expected "foo" to equal "bar"',
47
+ error_backtrace: ['Line 1: foo', 'Line 2: baz']
44
48
  }
45
49
 
46
50
  props = {
47
- events: [
48
- event,
49
- Object.assign({}, event, { id: 2 })
51
+ failures: [
52
+ failure,
53
+ Object.assign({}, failure, { id: 2 })
50
54
  ]
51
55
  }
52
56
 
53
57
  component = mountComponent(store, props)
54
58
  })
55
59
 
56
- it('renders the list of events', () => {
57
- expect(component.find('.event').length).toEqual(2)
60
+ it('renders the list of failures', () => {
61
+ expect(component.find('.failure').length).toEqual(2)
58
62
  })
59
63
  })
@@ -9,7 +9,7 @@ import Dialog from 'material-ui/Dialog'
9
9
  import RaisedButton from 'material-ui/RaisedButton'
10
10
  import FailureOverview from 'components/failure/overview'
11
11
 
12
- class OverviewDialog extends Component {
12
+ class FailureOverviewDialog extends Component {
13
13
  static get propTypes () {
14
14
  return {
15
15
  onHideOverview: PropTypes.func,
@@ -46,7 +46,7 @@ class OverviewDialog extends Component {
46
46
  <Dialog
47
47
  modal={false}
48
48
  autoScrollBodyContent
49
- className='failures/overview-dialog'
49
+ className='failure-overview-dialog'
50
50
  title={this.dialogTitle()}
51
51
  open={!!this.props.failure.overviewVisible}
52
52
  onRequestClose={() => this.hideOverview()}
@@ -54,7 +54,7 @@ class OverviewDialog extends Component {
54
54
  bodyStyle={{maxWidth: '1024px'}}
55
55
  actions={[
56
56
  <RaisedButton
57
- secondary
57
+ primary
58
58
  label='Retry'
59
59
  onClick={() => this.showRetry()}/>
60
60
  ]}>
@@ -87,4 +87,4 @@ export default connect(
87
87
  onHideOverview: hideFailureOverview,
88
88
  onShowRetry: showFailureRetry
89
89
  }
90
- )(OverviewDialog)
90
+ )(FailureOverviewDialog)
@@ -1,7 +1,6 @@
1
1
  import React, { Component, PropTypes } from 'react'
2
2
  import { connect } from 'react-redux'
3
3
 
4
- import ErrorMessage from 'components/event/error-message'
5
4
  import Loading from 'components/event/loading'
6
5
 
7
6
  import { hideFailureRetry, performFailureRetry } from 'actions/failures/retry'
@@ -24,7 +23,7 @@ class FailureRetryDialog extends Component {
24
23
 
25
24
  static get defaultProps () {
26
25
  return {
27
- event: {}
26
+ failure: {}
28
27
  }
29
28
  }
30
29
 
@@ -32,7 +31,7 @@ class FailureRetryDialog extends Component {
32
31
  return (
33
32
  <Dialog
34
33
  modal={!!this.props.isRetryingEvent}
35
- title='Are you sure?'
34
+ title={this.renderTitle()}
36
35
  open={!!this.props.failure.retryVisible}
37
36
  bodyStyle={{maxWidth: '300px'}}
38
37
  contentStyle={{maxWidth: '300px'}}
@@ -41,16 +40,23 @@ class FailureRetryDialog extends Component {
41
40
  <RaisedButton
42
41
  primary
43
42
  label='Retry'
43
+ disabled={this.props.isRetryingEvent}
44
44
  onClick={() => this.performRetry()}/>
45
45
  ]}>
46
46
  <div style={{textAlign: 'center'}}>
47
47
  <Loading visible={this.props.isRetryingEvent}/>
48
- <ErrorMessage message={this.props.failure.error}/>
49
48
  </div>
50
49
  </Dialog>
51
50
  )
52
51
  }
53
52
 
53
+ renderTitle () {
54
+ if (this.props.isRetryingEvent) {
55
+ return 'Retrying failure...'
56
+ }
57
+ return 'Are you sure?'
58
+ }
59
+
54
60
  hide () {
55
61
  this.props.onHideRetry(this.props.failure)
56
62
  }
@@ -60,11 +66,10 @@ class FailureRetryDialog extends Component {
60
66
  }
61
67
  }
62
68
 
63
- const mapStateToProps = (state, ownProps) => (
64
- Object.assign({
65
- isRetryingEvent: state.xhrStatus.isRetryingEvent
66
- }, ownProps)
67
- )
69
+ const mapStateToProps = (state, ownProps) => ({
70
+ ...ownProps,
71
+ isRetryingEvent: state.xhrStatus.isRetryingEvent
72
+ })
68
73
 
69
74
  export default connect(mapStateToProps, {
70
75
  onHideRetry: hideFailureRetry,
@@ -13,7 +13,6 @@
13
13
  color: #fff;
14
14
  font-family: 'Roboto';
15
15
  font-size: 20px;
16
- max-width: 95%;
17
16
 
18
17
  .close {
19
18
  transition: all ease-in-out 200ms;
@@ -1,4 +1,9 @@
1
1
  .header {
2
+ display: flex;
3
+ justify-content: space-between;
4
+ }
5
+
6
+ .header--title {
2
7
  display: inline-flex;
3
8
  align-items: center;
4
9
  text-decoration: none;
@@ -5,27 +5,53 @@ import AppBar from 'material-ui/AppBar'
5
5
  import Chip from 'material-ui/Chip'
6
6
  import { Link } from 'react-router'
7
7
 
8
- import IconButton from 'material-ui/IconButton'
9
- import IconMenu from 'material-ui/IconMenu'
8
+ import Menu from 'material-ui/Menu'
10
9
  import MenuItem from 'material-ui/MenuItem'
11
- import MoreVertIcon from 'material-ui/svg-icons/navigation/more-vert'
12
- import ContentSend from 'material-ui/svg-icons/content/send'
13
- import ActionAssignment from 'material-ui/svg-icons/action/assignment'
10
+ import EventsIcon from 'material-ui/svg-icons/communication/call-received'
11
+ import FailuresIcon from 'material-ui/svg-icons/communication/call-missed'
12
+ import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider'
13
+ import getMuiTheme from 'material-ui/styles/getMuiTheme'
14
+ import {
15
+ blueGrey800,
16
+ cyan500,
17
+ grey100,
18
+ grey500,
19
+ yellowA100
20
+ } from 'material-ui/styles/colors'
14
21
  import { navigateTo } from 'actions/navigation'
15
22
 
16
23
  const DEFAULT_TITLE = 'Phobos Checkpoint'
24
+ const muiTheme = getMuiTheme({
25
+ palette: {
26
+ accent1Color: cyan500
27
+ },
28
+ ripple: {
29
+ color: grey100
30
+ }
31
+ })
17
32
 
18
33
  const style = {
19
34
  bar: {
20
- backgroundColor: '#302e3a'
35
+ backgroundColor: blueGrey800
21
36
  },
22
37
  title: {
23
- color: '#fff',
24
38
  fontFamily: 'Roboto',
25
39
  fontWeight: 'lighter'
26
40
  },
27
41
  envLabel: {
28
- marginLeft: 30
42
+ marginLeft: 20,
43
+ backgroundColor: yellowA100
44
+ },
45
+ innerTitle: {
46
+ marginLeft: 10
47
+ },
48
+ menuInner: {
49
+ display: 'flex'
50
+ },
51
+ menuItem: {
52
+ color: grey500,
53
+ fontFamily: 'Roboto',
54
+ fontWeight: 'lighter'
29
55
  }
30
56
  }
31
57
 
@@ -37,15 +63,6 @@ export class Header extends Component {
37
63
  showMenuIconButton={false}
38
64
  style={style.bar}
39
65
  titleStyle={style.title}
40
- iconElementRight={
41
- <IconMenu
42
- iconButtonElement={<IconButton><MoreVertIcon /></IconButton>}
43
- targetOrigin={{horizontal: 'right', vertical: 'top'}}
44
- anchorOrigin={{horizontal: 'right', vertical: 'top'}}>
45
- <MenuItem primaryText='Events' leftIcon={<ContentSend />} onTouchTap={() => this.props.navigateTo('/events')} />
46
- <MenuItem primaryText='Errors' leftIcon={<ActionAssignment />} onTouchTap={() => this.props.navigateTo('/failures')} />
47
- </IconMenu>
48
- }
49
66
  />
50
67
  )
51
68
  }
@@ -53,11 +70,34 @@ export class Header extends Component {
53
70
  logo () {
54
71
  const { title, logo, env_label } = configs()
55
72
  return (
56
- <Link className='header' to='/'>
57
- {logo && <img className='logo' src={logo} />}
58
- <span className='title'>{title || DEFAULT_TITLE}</span>
59
- <Chip className='env-label' style={style.envLabel}>{env_label}</Chip>
60
- </Link>
73
+ <MuiThemeProvider muiTheme={muiTheme}>
74
+ <div className='header'>
75
+ <Link className='header--title' to='/'>
76
+ {logo && <img className='logo' src={logo} />}
77
+ <span className='title' style={style.innerTitle}>{title || DEFAULT_TITLE}</span>
78
+ <Chip className='env-label' style={style.envLabel}>{env_label}</Chip>
79
+ </Link>
80
+ <Menu
81
+ disableAutoFocus
82
+ value={this.props.routing.locationBeforeTransitions.pathname}
83
+ listStyle={style.menuInner}>
84
+ <MenuItem
85
+ value='/events'
86
+ style={style.menuItem}
87
+ primaryText='Events'
88
+ leftIcon={<EventsIcon />}
89
+ onTouchTap={() => this.props.navigateTo('/events')}
90
+ />
91
+ <MenuItem
92
+ value='/failures'
93
+ style={style.menuItem}
94
+ primaryText='Failures'
95
+ leftIcon={<FailuresIcon />}
96
+ onTouchTap={() => this.props.navigateTo('/failures')}
97
+ />
98
+ </Menu>
99
+ </div>
100
+ </MuiThemeProvider>
61
101
  )
62
102
  }
63
103
  }
@@ -2,23 +2,21 @@ import {
2
2
  EVENT_SHOW_RETRY,
3
3
  EVENT_HIDE_RETRY,
4
4
  EVENT_HIDE_OVERVIEW,
5
- RECEIVE_EVENT_DETAILS
5
+ RECEIVE_EVENT_DETAILS,
6
+ REQUEST_EVENT_RETRY_FAILED
6
7
  } from 'actions'
7
8
 
8
- function patchEvent (state, action, params) {
9
- if (state.id === action.event.id) {
10
- return Object.assign(state, params)
11
- }
12
- return state
9
+ function patchEvent (state, params) {
10
+ return {...state, ...params}
13
11
  }
14
12
 
15
13
  export default (state = {}, action) => {
16
14
  switch (action.type) {
17
15
  case EVENT_SHOW_RETRY:
18
- return patchEvent(state, action, { retryVisible: true })
16
+ return patchEvent(state, { retryVisible: true })
19
17
 
20
18
  case EVENT_HIDE_RETRY:
21
- return patchEvent(state, action, { retryVisible: false })
19
+ return patchEvent(state, { retryVisible: false, error: null })
22
20
 
23
21
  case EVENT_HIDE_OVERVIEW:
24
22
  return {}
@@ -26,6 +24,9 @@ export default (state = {}, action) => {
26
24
  case RECEIVE_EVENT_DETAILS:
27
25
  return action.event
28
26
 
27
+ case REQUEST_EVENT_RETRY_FAILED:
28
+ return patchEvent(state, { error: action.error })
29
+
29
30
  default:
30
31
  return state
31
32
  }
@@ -2,7 +2,8 @@ import {
2
2
  EVENT_SHOW_RETRY,
3
3
  EVENT_HIDE_RETRY,
4
4
  EVENT_HIDE_OVERVIEW,
5
- RECEIVE_EVENT_DETAILS
5
+ RECEIVE_EVENT_DETAILS,
6
+ REQUEST_EVENT_RETRY_FAILED
6
7
  } from 'actions'
7
8
 
8
9
  import reducer from 'reducers/event-details'
@@ -21,7 +22,7 @@ describe('reducers/events-details', () => {
21
22
  it('sets retryVisible to false', () => {
22
23
  const currentState = { id: 1 }
23
24
  const action = { type: EVENT_HIDE_RETRY, event: { id: 1 } }
24
- const expectedState = { id: 1, retryVisible: false }
25
+ const expectedState = { id: 1, retryVisible: false, error: null }
25
26
  expect(reducer(currentState, action)).toEqual(expectedState)
26
27
  })
27
28
  })
@@ -44,6 +45,15 @@ describe('reducers/events-details', () => {
44
45
  })
45
46
  })
46
47
 
48
+ describe('for REQUEST_EVENT_RETRY_FAILED', () => {
49
+ it('replaces the state', () => {
50
+ const currentState = { id: 1 }
51
+ const action = { type: REQUEST_EVENT_RETRY_FAILED, error: 'an error', event: { id: 2 } }
52
+ const expectedState = { id: 1, error: 'an error' }
53
+ expect(reducer(currentState, action)).toEqual(expectedState)
54
+ })
55
+ })
56
+
47
57
  describe('for default', () => {
48
58
  it('returns the currentState', () => {
49
59
  const currentState = { current: true }
@@ -2,23 +2,21 @@ import {
2
2
  FAILURE_SHOW_RETRY,
3
3
  FAILURE_HIDE_RETRY,
4
4
  FAILURE_HIDE_OVERVIEW,
5
- RECEIVE_FAILURE_DETAILS
5
+ RECEIVE_FAILURE_DETAILS,
6
+ REQUEST_EVENT_RETRY_FAILED
6
7
  } from 'actions'
7
8
 
8
- function patchFailure (state, action, params) {
9
- if (state.id === action.failure.id) {
10
- return Object.assign(state, params)
11
- }
12
- return state
9
+ function patchFailure (state, params) {
10
+ return { ...state, ...params }
13
11
  }
14
12
 
15
13
  export default (state = {}, action) => {
16
14
  switch (action.type) {
17
15
  case FAILURE_SHOW_RETRY:
18
- return patchFailure(state, action, { retryVisible: true })
16
+ return patchFailure(state, { retryVisible: true })
19
17
 
20
18
  case FAILURE_HIDE_RETRY:
21
- return patchFailure(state, action, { retryVisible: false })
19
+ return patchFailure(state, { retryVisible: false, error: null })
22
20
 
23
21
  case FAILURE_HIDE_OVERVIEW:
24
22
  return {}
@@ -26,6 +24,9 @@ export default (state = {}, action) => {
26
24
  case RECEIVE_FAILURE_DETAILS:
27
25
  return action.failure
28
26
 
27
+ case REQUEST_EVENT_RETRY_FAILED:
28
+ return patchFailure(state, { error: action.error })
29
+
29
30
  default:
30
31
  return state
31
32
  }
@@ -2,7 +2,8 @@ import {
2
2
  FAILURE_SHOW_RETRY,
3
3
  FAILURE_HIDE_RETRY,
4
4
  FAILURE_HIDE_OVERVIEW,
5
- RECEIVE_FAILURE_DETAILS
5
+ RECEIVE_FAILURE_DETAILS,
6
+ REQUEST_EVENT_RETRY_FAILED
6
7
  } from 'actions'
7
8
 
8
9
  import reducer from 'reducers/failures/details'
@@ -21,7 +22,7 @@ describe('reducers/failures/details', () => {
21
22
  it('sets retryVisible to false', () => {
22
23
  const currentState = { id: 1 }
23
24
  const action = { type: FAILURE_HIDE_RETRY, failure: { id: 1 } }
24
- const expectedState = { id: 1, retryVisible: false }
25
+ const expectedState = { id: 1, retryVisible: false, error: null }
25
26
  expect(reducer(currentState, action)).toEqual(expectedState)
26
27
  })
27
28
  })
@@ -44,6 +45,15 @@ describe('reducers/failures/details', () => {
44
45
  })
45
46
  })
46
47
 
48
+ describe('for REQUEST_EVENT_RETRY_FAILED', () => {
49
+ it('replaces the state', () => {
50
+ const currentState = { id: 1 }
51
+ const action = { type: REQUEST_EVENT_RETRY_FAILED, error: 'an error', failure: { id: 2 } }
52
+ const expectedState = { id: 1, error: 'an error' }
53
+ expect(reducer(currentState, action)).toEqual(expectedState)
54
+ })
55
+ })
56
+
47
57
  describe('for default', () => {
48
58
  it('returns the currentState', () => {
49
59
  const currentState = { current: true }
@@ -5,13 +5,13 @@ import {
5
5
  FAILURE_SHOW_RETRY,
6
6
  FAILURE_HIDE_RETRY,
7
7
  RECEIVE_FAILURE_RETRY,
8
- REQUEST_FAILURE_RETRY_FAILED
8
+ DELETE_FAILURE
9
9
  } from 'actions'
10
10
 
11
11
  function patchFailure (state, action, params) {
12
12
  return state.map((failure) => {
13
13
  if (failure.id === action.failure.id) {
14
- return Object.assign({}, failure, params)
14
+ return { ...failure, ...params }
15
15
  }
16
16
  return failure
17
17
  })
@@ -39,8 +39,10 @@ export default (state = [], action) => {
39
39
  case RECEIVE_FAILURE_RETRY:
40
40
  return patchFailure(state, action, { acknowledged: action.acknowledged, error: null })
41
41
 
42
- case REQUEST_FAILURE_RETRY_FAILED:
43
- return patchFailure(state, action, { error: action.error })
42
+ case DELETE_FAILURE:
43
+ return state.filter((failure) => {
44
+ return failure.id !== action.failure.id
45
+ })
44
46
 
45
47
  default:
46
48
  return state
@@ -5,7 +5,7 @@ import {
5
5
  FAILURE_SHOW_RETRY,
6
6
  FAILURE_HIDE_RETRY,
7
7
  RECEIVE_FAILURE_RETRY,
8
- REQUEST_FAILURE_RETRY_FAILED
8
+ DELETE_FAILURE
9
9
  } from 'actions'
10
10
 
11
11
  import reducer from 'reducers/failures'
@@ -76,11 +76,11 @@ describe('reducers/failures', () => {
76
76
  })
77
77
  })
78
78
 
79
- describe('for REQUEST_FAILURE_RETRY_FAILED', () => {
80
- it('sets error for a specific', () => {
79
+ describe('for DELETE_FAILURE', () => {
80
+ it('removes the given failure from state', () => {
81
81
  const currentState = [{ id: 1 }, { id: 2 }, { id: 3 }]
82
- const action = { type: REQUEST_FAILURE_RETRY_FAILED, failure: { id: 2 }, error: 'some error' }
83
- const expectedState = [{ id: 1 }, { id: 2, error: 'some error' }, { id: 3 }]
82
+ const action = { type: DELETE_FAILURE, failure: { id: 2 } }
83
+ const expectedState = [{ id: 1 }, { id: 3 }]
84
84
  expect(reducer(currentState, action)).toEqual(expectedState)
85
85
  })
86
86
  })
@@ -9,6 +9,8 @@ import {
9
9
  REQUEST_FAILURES_SEARCH_RESULTS_FAILED,
10
10
  LOAD_MORE_FAILURES_SEARCH_RESULTS,
11
11
  TRIGGER_FAILURES_SEARCH,
12
+ REQUEST_FAILURE_RETRY,
13
+ REQUEST_FAILURE_RETRY_FAILED,
12
14
  REQUEST_EVENT_RETRY,
13
15
  RECEIVE_EVENT_RETRY,
14
16
  REQUEST_EVENT_RETRY_FAILED,
@@ -63,12 +65,14 @@ export default (state = initialState, action) => {
63
65
  currentEventsOffset: action.offset
64
66
  })
65
67
 
68
+ case REQUEST_FAILURE_RETRY:
66
69
  case REQUEST_EVENT_RETRY:
67
70
  return Object.assign({}, state, {
68
71
  isRetryingEvent: true
69
72
  })
70
73
 
71
74
  case RECEIVE_EVENT_RETRY:
75
+ case REQUEST_FAILURE_RETRY_FAILED:
72
76
  case REQUEST_EVENT_RETRY_FAILED:
73
77
  return Object.assign({}, state, {
74
78
  isRetryingEvent: false