phobos_checkpoint_ui 1.0.0.rc1 → 1.0.0.rc2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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