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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1 -1
- data/frontend/src/actions/event-details.js +5 -7
- data/frontend/src/actions/event-retry.js +7 -9
- data/frontend/src/actions/events-search.js +5 -7
- data/frontend/src/actions/failures/details.js +5 -7
- data/frontend/src/actions/failures/details.spec.js +1 -1
- data/frontend/src/actions/failures/retry.js +34 -17
- data/frontend/src/actions/failures/retry.spec.js +52 -5
- data/frontend/src/actions/failures/search/index.js +5 -8
- data/frontend/src/actions/failures/search/index.spec.js +2 -2
- data/frontend/src/actions/index.js +3 -1
- data/frontend/src/components/empty-event/empty-event.scss +6 -0
- data/frontend/src/components/event/card-style.js +29 -0
- data/frontend/src/components/event/event.scss +12 -0
- data/frontend/src/components/event/index.js +12 -21
- data/frontend/src/components/event/index.spec.js +3 -2
- data/frontend/src/components/event-overview-dialog/index.js +1 -1
- data/frontend/src/components/event-retry-dialog/index.js +9 -1
- data/frontend/src/components/failure/empty/empty-failure.scss +6 -0
- data/frontend/src/components/failure/empty/index.js +20 -0
- data/frontend/src/components/failure/empty/index.spec.js +38 -0
- data/frontend/src/components/failure/index.js +11 -20
- data/frontend/src/components/failure/index.scss +15 -0
- data/frontend/src/components/failure/index.spec.js +19 -14
- data/frontend/src/components/{failures-list → failure/list}/failures-list.scss +1 -1
- data/frontend/src/components/{failures-list → failure/list}/index.spec.js +15 -11
- data/frontend/src/components/failure/overview-dialog/index.js +4 -4
- data/frontend/src/components/failure/retry-dialog/index.js +14 -9
- data/frontend/src/components/flash-message/flash-message.scss +0 -1
- data/frontend/src/components/header/header.scss +5 -0
- data/frontend/src/components/header/index.js +62 -22
- data/frontend/src/reducers/event-details.js +9 -8
- data/frontend/src/reducers/event-details.spec.js +12 -2
- data/frontend/src/reducers/failures/details/index.js +9 -8
- data/frontend/src/reducers/failures/details/index.spec.js +12 -2
- data/frontend/src/reducers/failures/index.js +6 -4
- data/frontend/src/reducers/failures/index.spec.js +5 -5
- data/frontend/src/reducers/xhr-status.js +4 -0
- data/frontend/src/reducers/xhr-status.spec.js +20 -0
- data/frontend/src/views/events/search/index.scss +0 -7
- data/frontend/src/views/failures/details/index.js +2 -2
- data/frontend/src/views/failures/search/index.js +5 -5
- data/frontend/src/views/failures/search/index.scss +1 -8
- data/frontend/src/views/failures/search/index.spec.js +4 -4
- data/frontend/src/views/layout.js +2 -2
- data/lib/phobos_checkpoint_ui/version.rb +1 -1
- metadata +12 -12
- data/frontend/src/components/event/style.js +0 -16
- data/frontend/src/components/failure/error-message.js +0 -19
- data/frontend/src/components/failure/error-message.scss +0 -8
- data/frontend/src/components/failure/event.scss +0 -3
- data/frontend/src/components/failure/loading.js +0 -16
- data/frontend/src/components/failure/style.js +0 -16
- /data/frontend/src/components/{failures-list → failure/list}/index.js +0 -0
- /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:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: eb5df88871389fe9876fae517e7ea256819fc778
|
4
|
+
data.tar.gz: 51534f08782de450550e91019322e2be8bf26681
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
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
|
-
|
35
|
-
|
36
|
-
|
37
|
-
.
|
38
|
-
|
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
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
.
|
49
|
-
|
50
|
-
|
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
|
-
|
57
|
-
|
58
|
-
|
59
|
-
.
|
60
|
-
|
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
|
-
|
35
|
-
|
36
|
-
|
37
|
-
.
|
38
|
-
|
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/
|
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
|
26
|
+
failure
|
25
27
|
})
|
26
28
|
|
27
29
|
const receiveFailureRetry = (failure, data) => ({
|
28
30
|
type: RECEIVE_FAILURE_RETRY,
|
29
|
-
|
30
|
-
|
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
|
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
|
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
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
.
|
49
|
-
|
50
|
-
|
51
|
-
|
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(
|
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
|
-
|
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
|
-
|
94
|
-
|
95
|
-
|
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:
|
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
|
-
|
58
|
-
|
59
|
-
|
60
|
-
.
|
61
|
-
|
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,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,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
|
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={
|
44
|
+
style={cardStyle.card}
|
50
45
|
onClick={() => this.showOverview()}>
|
51
46
|
<CardHeader
|
52
47
|
className='event-header'
|
53
|
-
|
54
|
-
|
55
|
-
title={
|
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={
|
59
|
-
title={this.
|
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
|
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(
|
55
|
+
expect(component.text()).toMatch(formatTime(props.event.event_time))
|
55
56
|
})
|
56
57
|
|
57
58
|
it('displays topic', () => {
|
@@ -32,7 +32,7 @@ class RetryDialog extends Component {
|
|
32
32
|
return (
|
33
33
|
<Dialog
|
34
34
|
modal={!!this.props.isRetryingEvent}
|
35
|
-
title=
|
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,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
|
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={
|
49
|
+
style={cardStyle.card}
|
55
50
|
onClick={() => this.showOverview()}>
|
56
51
|
<CardHeader
|
57
52
|
className='failure-header'
|
58
|
-
|
59
|
-
|
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={
|
64
|
-
title={this.
|
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, {
|