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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c06ac3b49f17bb1a0cfd0b99c381cbf472ea99c2
4
- data.tar.gz: 6a20e89e24e36288a4448c6e05d560613c7440b6
3
+ metadata.gz: eb5df88871389fe9876fae517e7ea256819fc778
4
+ data.tar.gz: 51534f08782de450550e91019322e2be8bf26681
5
5
  SHA512:
6
- metadata.gz: 9c9ff42eee60f0ec01a4ce14b24f3f9903444a91a41a6bd140aae7eef2d427817275f2300ed768fa8b08bc2c5a04a4a9270681697d4116c991a3f86b04f1085a
7
- data.tar.gz: 11524361e949b14a83a0404c6161581d08b0342b8628ea162e4a7432c660f32337077cb0c56e4e6e670c9b2aed9592bb7246bf4348c36aa7228a3b5c2e73a55f
6
+ metadata.gz: 5c9ffd04210a079c88c49096d0dd45fb8828b04c3d54a3203af1334c63c185aee87c8a73efeecffd4d288a1874c57a75132f461a6ee0dda8864c7e4a3ab2a97d
7
+ data.tar.gz: 9e1865a07414149eeaaf201b2b3def89a217669ba8469f9d749db4cbb1d648e73c18badabfa5a420b19c6d019ff2af3387cf17129bdee6046a4594066d42f901
data/CHANGELOG.md CHANGED
@@ -4,7 +4,7 @@ All notable changes to this project will be documented in this file.
4
4
  The format is based on [Keep a Changelog](http://keepachangelog.com/)
5
5
  and this project adheres to [Semantic Versioning](http://semver.org/).
6
6
 
7
- ## 1.0.0.rc1 (2017-03-01)
7
+ ## 1.0.0.rc2 (2017-03-01)
8
8
 
9
9
  - [feature] Add GUI interacting with PhobosDBCheckpoint failures
10
10
 
@@ -31,12 +31,10 @@ export const fetchEventDetails = (event) => (dispatch, getState) => {
31
31
  .then((response) => dispatch(receiveEventDetails(response.data)))
32
32
  .catch((response) => {
33
33
  const error = parseResponseError(response)
34
- return Promise
35
- .resolve()
36
- .then(() => dispatch(requestEventDetailsFailed(event, error.message)))
37
- .then(() => dispatch(addFlashMessage({
38
- type: 'error',
39
- text: error.message
40
- })))
34
+ dispatch(requestEventDetailsFailed(event, error.message))
35
+ dispatch(addFlashMessage({
36
+ type: 'error',
37
+ text: error.message
38
+ }))
41
39
  })
42
40
  }
@@ -41,15 +41,13 @@ export const performEventRetry = (event) => (dispatch, getState) => {
41
41
  return API.Event
42
42
  .retry({id: event.id})
43
43
  .then((response) => {
44
- return Promise
45
- .resolve()
46
- .then(() => dispatch(receiveEventRetry(event, response.data)))
47
- .then(() => dispatch(hideEventRetry(event)))
48
- .then(() => dispatch(addFlashMessage({
49
- type: 'success',
50
- text: `Event retried with success. Acknowledged: ${response.data.acknowledged}`,
51
- autoClose: true
52
- })))
44
+ dispatch(receiveEventRetry(event, response.data))
45
+ dispatch(hideEventRetry(event))
46
+ dispatch(addFlashMessage({
47
+ type: 'success',
48
+ text: `Event retried with success. Acknowledged: ${response.data.acknowledged}`,
49
+ autoClose: true
50
+ }))
53
51
  })
54
52
  .catch((response) => {
55
53
  const error = parseResponseError(response)
@@ -53,13 +53,11 @@ export const fetchSearchResults = () => (dispatch, getState) => {
53
53
  })
54
54
  .catch((response) => {
55
55
  const error = parseResponseError(response)
56
- return Promise
57
- .resolve()
58
- .then(() => dispatch(requestSearchResultsFailed(query, error.message)))
59
- .then(() => dispatch(addFlashMessage({
60
- type: 'error',
61
- text: `Events search failed. "${error.message}"`
62
- })))
56
+ dispatch(requestSearchResultsFailed(query, error.message))
57
+ dispatch(addFlashMessage({
58
+ type: 'error',
59
+ text: `Events search failed. "${error.message}"`
60
+ }))
63
61
  })
64
62
  }
65
63
 
@@ -31,12 +31,10 @@ export const fetchFailureDetails = (failure) => (dispatch, getState) => {
31
31
  .then((response) => dispatch(receiveFailureDetails(response.data)))
32
32
  .catch((response) => {
33
33
  const error = parseResponseError(response)
34
- return Promise
35
- .resolve()
36
- .then(() => dispatch(requestFailureDetailsFailed(failure, error.message)))
37
- .then(() => dispatch(addFlashMessage({
38
- type: 'error',
39
- text: error.message
40
- })))
34
+ dispatch(requestFailureDetailsFailed(failure, error.message))
35
+ dispatch(addFlashMessage({
36
+ type: 'error',
37
+ text: error.message
38
+ }))
41
39
  })
42
40
  }
@@ -19,7 +19,7 @@ beforeEach(() => {
19
19
  Mappersmith.Env.Fixture.clear()
20
20
  })
21
21
 
22
- describe('actions/failure-details', () => {
22
+ describe('actions/failures/details', () => {
23
23
  describe('#fetchFailureDetails', () => {
24
24
  describe('when it succeeds', () => {
25
25
  let failure, store
@@ -6,7 +6,9 @@ import {
6
6
  FAILURE_HIDE_RETRY,
7
7
  REQUEST_FAILURE_RETRY,
8
8
  RECEIVE_FAILURE_RETRY,
9
- REQUEST_FAILURE_RETRY_FAILED
9
+ REQUEST_FAILURE_RETRY_FAILED,
10
+ FAILURE_HIDE_OVERVIEW,
11
+ DELETE_FAILURE
10
12
  } from 'actions'
11
13
 
12
14
  export const showFailureRetry = (failure) => ({
@@ -21,19 +23,28 @@ export const hideFailureRetry = (failure) => ({
21
23
 
22
24
  const requestFailureRetry = (failure) => ({
23
25
  type: REQUEST_FAILURE_RETRY,
24
- failure: failure
26
+ failure
25
27
  })
26
28
 
27
29
  const receiveFailureRetry = (failure, data) => ({
28
30
  type: RECEIVE_FAILURE_RETRY,
29
- failure: failure,
30
- acknowledged: data.acknowledged
31
+ acknowledged: data.acknowledged,
32
+ failure
33
+ })
34
+
35
+ const hideFailureOverview = (failure) => ({
36
+ type: FAILURE_HIDE_OVERVIEW,
37
+ failure
31
38
  })
32
39
 
33
- const requestFailureRetryFailed = (failure, error) => ({
40
+ const deleteFailure = (failure) => ({
41
+ type: DELETE_FAILURE,
42
+ failure
43
+ })
44
+
45
+ const requestFailureRetryFailed = (failure) => ({
34
46
  type: REQUEST_FAILURE_RETRY_FAILED,
35
- failure: failure,
36
- error
47
+ failure
37
48
  })
38
49
 
39
50
  export const performFailureRetry = (failure) => (dispatch, getState) => {
@@ -41,18 +52,24 @@ export const performFailureRetry = (failure) => (dispatch, getState) => {
41
52
  return API.Failure
42
53
  .retry({id: failure.id})
43
54
  .then((response) => {
44
- return Promise
45
- .resolve()
46
- .then(() => dispatch(receiveFailureRetry(failure, response.data)))
47
- .then(() => dispatch(hideFailureRetry(failure)))
48
- .then(() => dispatch(addFlashMessage({
49
- type: 'success',
50
- text: `Failure retried with success. Acknowledged: ${response.data.acknowledged}`,
51
- autoClose: true
52
- })))
55
+ dispatch(receiveFailureRetry(failure, response.data))
56
+ dispatch(hideFailureRetry(failure))
57
+ dispatch(addFlashMessage({
58
+ type: 'success',
59
+ text: `Failure retried with success. Acknowledged: ${response.data.acknowledged}`,
60
+ autoClose: true
61
+ }))
62
+ dispatch(hideFailureOverview(failure))
63
+ dispatch(deleteFailure(failure))
53
64
  })
54
65
  .catch((response) => {
55
66
  const error = parseResponseError(response)
56
- dispatch(requestFailureRetryFailed(failure, error.message))
67
+ dispatch(hideFailureRetry(failure))
68
+ dispatch(addFlashMessage({
69
+ type: 'error',
70
+ text: `Failure retried with error: ${error.message}`,
71
+ autoClose: false
72
+ }))
73
+ dispatch(requestFailureRetryFailed(failure))
57
74
  })
58
75
  }
@@ -12,8 +12,10 @@ import {
12
12
  FAILURE_HIDE_RETRY,
13
13
  REQUEST_FAILURE_RETRY,
14
14
  RECEIVE_FAILURE_RETRY,
15
+ REQUEST_FAILURE_RETRY_FAILED,
15
16
  ADD_FLASH_MESSAGE,
16
- REQUEST_FAILURE_RETRY_FAILED
17
+ FAILURE_HIDE_OVERVIEW,
18
+ DELETE_FAILURE
17
19
  } from 'actions'
18
20
 
19
21
  import {
@@ -87,12 +89,32 @@ describe('actions/failures/retry', () => {
87
89
  })
88
90
  .catch((e) => done.fail(`test failed with promise error: ${e.message}`))
89
91
  })
92
+
93
+ it('creates an action to hide the failure overview', (done) => {
94
+ store.dispatch(performFailureRetry(failure)).then(() => {
95
+ const actions = store.getActions()
96
+ expect(actions[4]).toEqual({ type: FAILURE_HIDE_OVERVIEW, failure: failure })
97
+ done()
98
+ })
99
+ .catch((e) => done.fail(`test failed with promise error: ${e.message}`))
100
+ })
101
+
102
+ it('creates an action to delete the failure from state', (done) => {
103
+ store.dispatch(performFailureRetry(failure)).then(() => {
104
+ const actions = store.getActions()
105
+ expect(actions[5]).toEqual({ type: DELETE_FAILURE, failure: failure })
106
+ done()
107
+ })
108
+ .catch((e) => done.fail(`test failed with promise error: ${e.message}`))
109
+ })
90
110
  })
91
111
 
92
112
  describe('when it fails', () => {
93
- it('creates REQUEST and REQUEST_FAILED actions', (done) => {
94
- const failure = { id: 1 }
95
- const store = mockStore({})
113
+ let store, failure
114
+
115
+ beforeEach(() => {
116
+ failure = { id: 1 }
117
+ store = mockStore({})
96
118
  Mappersmith.Env.Fixture
97
119
  .define('post')
98
120
  .matching({ url: `/api/v1/failures/${failure.id}/retry` })
@@ -103,11 +125,36 @@ describe('actions/failures/retry', () => {
103
125
  message: 'some error'
104
126
  })
105
127
  })
128
+ })
106
129
 
130
+ it('creates REQUEST and REQUEST_FAILED actions', (done) => {
107
131
  store.dispatch(performFailureRetry(failure)).then(() => {
108
132
  const actions = store.getActions()
109
133
  expect(actions[0]).toEqual({ type: REQUEST_FAILURE_RETRY, failure })
110
- expect(actions[1]).toEqual({ type: REQUEST_FAILURE_RETRY_FAILED, failure, error: 'some error' })
134
+ expect(actions[1]).toEqual({ type: FAILURE_HIDE_RETRY, failure })
135
+ done()
136
+ })
137
+ .catch((e) => done.fail(`test failed with promise error: ${e.message}`))
138
+ })
139
+
140
+ it('creates an action to add an error flash message', (done) => {
141
+ store.dispatch(performFailureRetry(failure)).then(() => {
142
+ const actions = store.getActions()
143
+ expect(actions[2]).toEqual({ type: ADD_FLASH_MESSAGE, message: {
144
+ id: jasmine.any(String),
145
+ type: 'error',
146
+ text: 'Failure retried with error: some error',
147
+ autoClose: false
148
+ }})
149
+ done()
150
+ })
151
+ .catch((e) => done.fail(`test failed with promise error: ${e.message}`))
152
+ })
153
+
154
+ it('creates an action to clear the loading status', (done) => {
155
+ store.dispatch(performFailureRetry(failure)).then(() => {
156
+ const actions = store.getActions()
157
+ expect(actions[3]).toEqual({ type: REQUEST_FAILURE_RETRY_FAILED, failure })
111
158
  done()
112
159
  })
113
160
  .catch((e) => done.fail(`test failed with promise error: ${e.message}`))
@@ -1,4 +1,3 @@
1
-
2
1
  import API, { EVENTS_SEARCH_LIMIT, parseResponseError } from 'api'
3
2
  import { addFlashMessage } from 'actions/flash-messages'
4
3
  import { history } from 'routes'
@@ -54,13 +53,11 @@ export const fetchSearchResults = () => (dispatch, getState) => {
54
53
  })
55
54
  .catch((response) => {
56
55
  const error = parseResponseError(response)
57
- return Promise
58
- .resolve()
59
- .then(() => dispatch(requestSearchResultsFailed(query, error.message)))
60
- .then(() => dispatch(addFlashMessage({
61
- type: 'error',
62
- text: `Failures search failed. "${error.message}"`
63
- })))
56
+ dispatch(requestSearchResultsFailed(query, error.message))
57
+ dispatch(addFlashMessage({
58
+ type: 'error',
59
+ text: `Failures search failed. "${error.message}"`
60
+ }))
64
61
  })
65
62
  }
66
63
 
@@ -145,14 +145,14 @@ describe('actions/failures/search', () => {
145
145
  let failure, initialState, store
146
146
  beforeEach(() => {
147
147
  initialState = {
148
- eventsFilters: {},
148
+ eventsFilters: { type: 'event_type', value: 'new' },
149
149
  xhrStatus: { currentEventsOffset: 0 }
150
150
  }
151
151
  store = mockStore(initialState)
152
152
  failure = { id: 1 }
153
153
  Mappersmith.Env.Fixture
154
154
  .define('get')
155
- .matching({ url: `/api/v1/failures?limit=${EVENTS_SEARCH_LIMIT}&offset=0` })
155
+ .matching({ url: `/api/v1/failures?limit=${EVENTS_SEARCH_LIMIT}&event_type=new&offset=0` })
156
156
  .response([failure])
157
157
  })
158
158
 
@@ -13,8 +13,8 @@ export const REQUEST_EVENT_RETRY_FAILED = 'REQUEST_EVENT_RETRY_FAILED'
13
13
  export const FAILURE_SHOW_RETRY = 'FAILURE_SHOW_RETRY'
14
14
  export const FAILURE_HIDE_RETRY = 'FAILURE_HIDE_RETRY'
15
15
  export const REQUEST_FAILURE_RETRY = 'REQUEST_FAILURE_RETRY'
16
- export const RECEIVE_FAILURE_RETRY = 'RECEIVE_FAILURE_RETRY'
17
16
  export const REQUEST_FAILURE_RETRY_FAILED = 'REQUEST_FAILURE_RETRY_FAILED'
17
+ export const RECEIVE_FAILURE_RETRY = 'RECEIVE_FAILURE_RETRY'
18
18
 
19
19
  export const SEARCH_INPUT_CHANGE_FILTER_TYPE = 'SEARCH_INPUT_CHANGE_FILTER_TYPE'
20
20
  export const SEARCH_INPUT_CHANGE_FILTER_VALUE = 'SEARCH_INPUT_CHANGE_FILTER_VALUE'
@@ -41,3 +41,5 @@ export const REQUEST_EVENT_DETAILS_FAILED = 'REQUEST_EVENT_DETAILS_FAILED'
41
41
  export const REQUEST_FAILURE_DETAILS = 'REQUEST_FAILURE_DETAILS'
42
42
  export const RECEIVE_FAILURE_DETAILS = 'RECEIVE_FAILURE_DETAILS'
43
43
  export const REQUEST_FAILURE_DETAILS_FAILED = 'REQUEST_FAILURE_DETAILS_FAILED'
44
+
45
+ export const DELETE_FAILURE = 'DELETE_FAILURE'
@@ -0,0 +1,6 @@
1
+ .empty-event {
2
+ margin: 50px 15px 0;
3
+ font-size: 30px;
4
+ font-weight: lighter;
5
+ font-family: Roboto;
6
+ }
@@ -0,0 +1,29 @@
1
+ import moment from 'moment'
2
+ const TIME_FORMAT = 'h:mm:ss a'
3
+ const EMPTY_TYPE = '<no type>'
4
+
5
+ export function formatTime (time) {
6
+ if (!time) return null
7
+ const timeDate = new Date(time)
8
+ return moment(timeDate).format(TIME_FORMAT)
9
+ }
10
+
11
+ export function formattedEventType (eventType) {
12
+ return eventType || EMPTY_TYPE
13
+ }
14
+
15
+ export default {
16
+ card: {
17
+ width: '490px',
18
+ overflow: 'hidden'
19
+ },
20
+ cardHeader: {
21
+ title: {
22
+ fontWeight: 'lighter'
23
+ }
24
+ },
25
+ cardTitle: {
26
+ fontSize: '38px',
27
+ fontWeight: 'lighter'
28
+ }
29
+ }
@@ -1,3 +1,15 @@
1
1
  .event {
2
2
  cursor: pointer;
3
+
4
+ .event-header {
5
+ display: flex;
6
+ justify-content: space-between;
7
+ }
8
+
9
+ .event-icon {
10
+ order: 2;
11
+ width: 35px !important;
12
+ height: 35px !important;
13
+ margin-right: 0 !important;
14
+ }
3
15
  }
@@ -1,22 +1,17 @@
1
1
  import React, { Component, PropTypes } from 'react'
2
2
  import { connect } from 'react-redux'
3
- import moment from 'moment'
4
3
 
5
4
  import { showEventOverview } from 'actions/event-overview'
6
- import style from 'components/event/style'
5
+ import cardStyle, {
6
+ formatTime,
7
+ formattedEventType
8
+ } from 'components/event/card-style'
7
9
 
8
10
  import {Card, CardHeader, CardTitle} from 'material-ui/Card'
11
+ import EventsIcon from 'material-ui/svg-icons/communication/call-received'
9
12
  import EventOverviewDialog from 'components/event-overview-dialog'
10
13
  import EventRetryDialog from 'components/event-retry-dialog'
11
-
12
- const EVENT_TIME_FORMAT = 'h:mm:ss a'
13
- const EMPTY_EVENT_TYPE = '<no type>'
14
-
15
- export function formatEventTime (eventTime) {
16
- if (!eventTime) return null
17
- const eventTimeDate = new Date(eventTime)
18
- return moment(eventTimeDate).format(EVENT_TIME_FORMAT)
19
- }
14
+ import { green200 } from 'material-ui/styles/colors'
20
15
 
21
16
  export class Event extends Component {
22
17
  static get propTypes () {
@@ -46,17 +41,17 @@ export class Event extends Component {
46
41
  return (
47
42
  <Card
48
43
  className='event'
49
- style={style.card}
44
+ style={cardStyle.card}
50
45
  onClick={() => this.showOverview()}>
51
46
  <CardHeader
52
47
  className='event-header'
53
- titleStyle={style.cardHeader.title}
54
- subtitleStyle={style.cardHeader.subtitle}
55
- title={formatEventTime(this.props.event.event_time)}
48
+ avatar={<EventsIcon className='event-icon' color={green200} />}
49
+ titleStyle={cardStyle.cardHeader.title}
50
+ title={formatTime(this.props.event.event_time)}
56
51
  subtitle={this.props.event.topic}/>
57
52
  <CardTitle
58
- titleStyle={style.cardTitle}
59
- title={this.formatedEventType()}/>
53
+ titleStyle={cardStyle.cardTitle}
54
+ title={formattedEventType(this.props.event.event_type)}/>
60
55
  <EventOverviewDialog event={this.props.event} />
61
56
  <EventRetryDialog event={this.props.event} />
62
57
  </Card>
@@ -66,10 +61,6 @@ export class Event extends Component {
66
61
  showOverview () {
67
62
  this.props.onShowOverview(this.props.event)
68
63
  }
69
-
70
- formatedEventType () {
71
- return this.props.event.event_type || EMPTY_EVENT_TYPE
72
- }
73
64
  }
74
65
 
75
66
  export default connect((state, ownProps) => ownProps, {
@@ -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 { Event } from 'components/event'
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'
@@ -51,7 +52,7 @@ describe('<Event />', () => {
51
52
  })
52
53
 
53
54
  it('displays event_time formatted', () => {
54
- expect(component.text()).toMatch(formatEventTime(props.event.event_time))
55
+ expect(component.text()).toMatch(formatTime(props.event.event_time))
55
56
  })
56
57
 
57
58
  it('displays topic', () => {
@@ -49,7 +49,7 @@ class OverviewDialog extends Component {
49
49
  bodyStyle={{maxWidth: '1024px'}}
50
50
  actions={[
51
51
  <RaisedButton
52
- secondary
52
+ primary
53
53
  label='Retry'
54
54
  onClick={() => this.showRetry()}/>
55
55
  ]}>
@@ -32,7 +32,7 @@ class RetryDialog extends Component {
32
32
  return (
33
33
  <Dialog
34
34
  modal={!!this.props.isRetryingEvent}
35
- title='Are you sure?'
35
+ title={this.renderTitle()}
36
36
  open={!!this.props.event.retryVisible}
37
37
  bodyStyle={{maxWidth: '300px'}}
38
38
  contentStyle={{maxWidth: '300px'}}
@@ -41,6 +41,7 @@ class RetryDialog extends Component {
41
41
  <RaisedButton
42
42
  primary
43
43
  label='Retry'
44
+ disabled={this.props.isRetryingEvent}
44
45
  onClick={() => this.performRetry()}/>
45
46
  ]}>
46
47
  <div style={{textAlign: 'center'}}>
@@ -51,6 +52,13 @@ class RetryDialog extends Component {
51
52
  )
52
53
  }
53
54
 
55
+ renderTitle () {
56
+ if (this.props.isRetryingEvent) {
57
+ return 'Retrying event...'
58
+ }
59
+ return 'Are you sure?'
60
+ }
61
+
54
62
  hide () {
55
63
  this.props.onHideRetry(this.props.event)
56
64
  }
@@ -0,0 +1,6 @@
1
+ .empty-failure {
2
+ margin: 50px 15px 0;
3
+ font-size: 30px;
4
+ font-weight: lighter;
5
+ font-family: Roboto;
6
+ }
@@ -0,0 +1,20 @@
1
+ import React, { Component, PropTypes } from 'react'
2
+
3
+ export default class EmptyFailure extends Component {
4
+ static get propTypes () {
5
+ return {
6
+ failures: PropTypes.array.isRequired,
7
+ isFetchingEvents: PropTypes.bool.isRequired
8
+ }
9
+ }
10
+
11
+ render () {
12
+ return (
13
+ this.props.failures.length === 0 &&
14
+ !this.props.isFetchingEvents &&
15
+ <div className='empty-failure'>
16
+ No failures found
17
+ </div>
18
+ )
19
+ }
20
+ }
@@ -0,0 +1,38 @@
1
+ import React from 'react'
2
+ import jasmineEnzyme from 'jasmine-enzyme'
3
+ import { shallow } from 'enzyme'
4
+
5
+ import EmptyFailure from 'components/failure/empty'
6
+
7
+ describe('<EmptyFailure />', () => {
8
+ let props, wrapper
9
+
10
+ beforeEach(() => {
11
+ jasmineEnzyme()
12
+ props = {
13
+ failures: [{ id: 1 }, { id: 2 }],
14
+ isFetchingEvents: false
15
+ }
16
+ wrapper = shallow(<EmptyFailure {...props} />)
17
+ })
18
+
19
+ describe('with events', () => {
20
+ it('does not render <EmptyFailure />', () => {
21
+ expect(wrapper.find('.empty-failure').length).toEqual(0)
22
+ })
23
+ })
24
+
25
+ describe('without events', () => {
26
+ beforeEach(() => {
27
+ props = {
28
+ ...props,
29
+ failures: []
30
+ }
31
+ wrapper = shallow(<EmptyFailure {...props} />)
32
+ })
33
+
34
+ it('renders <EmptyFailure />', () => {
35
+ expect(wrapper.find('.empty-failure').length).toEqual(1)
36
+ })
37
+ })
38
+ })
@@ -1,22 +1,17 @@
1
1
  import React, { Component, PropTypes } from 'react'
2
2
  import { connect } from 'react-redux'
3
- import moment from 'moment'
4
3
 
5
4
  import { showFailureOverview } from 'actions/failures/overview'
6
- import style from 'components/event/style'
5
+ import cardStyle, {
6
+ formatTime,
7
+ formattedEventType
8
+ } from 'components/event/card-style'
7
9
 
8
10
  import { Card, CardHeader, CardTitle } from 'material-ui/Card'
11
+ import FailuresIcon from 'material-ui/svg-icons/communication/call-missed'
9
12
  import FailureOverviewDialog from 'components/failure/overview-dialog'
10
13
  import FailureRetryDialog from 'components/failure/retry-dialog'
11
-
12
- const TIME_FORMAT = 'h:mm:ss a'
13
- const EMPTY_TYPE = '<no type>'
14
-
15
- export function formatTime (time) {
16
- if (!time) return null
17
- const timeDate = new Date(time)
18
- return moment(timeDate).format(TIME_FORMAT)
19
- }
14
+ import { red500 } from 'material-ui/styles/colors'
20
15
 
21
16
  export class Failure extends Component {
22
17
  static get propTypes () {
@@ -51,17 +46,17 @@ export class Failure extends Component {
51
46
  return (
52
47
  <Card
53
48
  className='failure'
54
- style={style.card}
49
+ style={cardStyle.card}
55
50
  onClick={() => this.showOverview()}>
56
51
  <CardHeader
57
52
  className='failure-header'
58
- titleStyle={style.cardHeader.title}
59
- subtitleStyle={style.cardHeader.subtitle}
53
+ avatar={<FailuresIcon className='failure-icon' color={red500} />}
54
+ titleStyle={cardStyle.cardHeader.title}
60
55
  title={formatTime(this.props.failure.event_time)}
61
56
  subtitle={this.props.failure.topic}/>
62
57
  <CardTitle
63
- titleStyle={style.cardTitle}
64
- title={this.formattedEventType()}/>
58
+ titleStyle={cardStyle.cardTitle}
59
+ title={formattedEventType(this.props.failure.event_type)}/>
65
60
  <FailureOverviewDialog failure={this.props.failure} />
66
61
  <FailureRetryDialog failure={this.props.failure} />
67
62
  </Card>
@@ -71,10 +66,6 @@ export class Failure extends Component {
71
66
  showOverview () {
72
67
  this.props.onShowOverview(this.props.failure)
73
68
  }
74
-
75
- formattedEventType () {
76
- return this.props.failure.event_type || EMPTY_TYPE
77
- }
78
69
  }
79
70
 
80
71
  export default connect((state, ownProps) => ownProps, {