phobos_checkpoint_ui 1.1.0 → 1.2.0
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 +4 -0
- data/assets/index-b24a670cc064e5a7b78d-0.css +2 -0
- data/assets/index-b24a670cc064e5a7b78d-0.css.map +1 -0
- data/assets/{index-b2f95711135c455435c3-1.css → index-b24a670cc064e5a7b78d-1.css} +1 -1
- data/assets/{index-b2f95711135c455435c3-1.css.map → index-b24a670cc064e5a7b78d-1.css.map} +1 -1
- data/assets/{index-b2f95711135c455435c3.js → index-b24a670cc064e5a7b78d.js} +29 -29
- data/assets/index-b24a670cc064e5a7b78d.js.map +1 -0
- data/assets/index.html +2 -2
- data/frontend/src/actions/dashboard/failure-count/index.js +38 -0
- data/frontend/src/actions/dashboard/failure-count/index.spec.js +70 -0
- data/frontend/src/actions/index.js +4 -0
- data/frontend/src/api.js +1 -0
- data/frontend/src/components/badge/badge.scss +13 -0
- data/frontend/src/components/badge/index.js +85 -0
- data/frontend/src/components/badge/index.spec.js +64 -0
- data/frontend/src/components/header/index.js +8 -0
- data/frontend/src/components/search-input/index.js +3 -2
- data/frontend/src/reducers/dashboard/index.js +15 -0
- data/frontend/src/reducers/dashboard/index.spec.js +16 -0
- data/frontend/src/reducers/events-filters.js +4 -1
- data/frontend/src/reducers/index.js +2 -0
- data/frontend/src/reducers/index.spec.js +3 -0
- data/frontend/src/reducers/xhr-status.js +23 -1
- data/frontend/src/reducers/xhr-status.spec.js +31 -1
- data/frontend/src/routes.js +3 -1
- data/frontend/src/views/dashboard/index.js +68 -0
- data/frontend/src/views/dashboard/index.scss +5 -0
- data/frontend/src/views/events/search/index.js +7 -2
- data/frontend/src/views/events/search/index.scss +0 -7
- data/frontend/src/views/failures/search/index.js +7 -2
- data/frontend/src/views/failures/search/index.scss +0 -7
- data/frontend/src/views/style.js +43 -0
- data/lib/phobos_checkpoint_ui/version.rb +1 -1
- data/phobos_checkpoint_ui.gemspec +1 -1
- metadata +20 -10
- data/assets/index-b2f95711135c455435c3-0.css +0 -2
- data/assets/index-b2f95711135c455435c3-0.css.map +0 -1
- data/assets/index-b2f95711135c455435c3.js.map +0 -1
@@ -6,6 +6,7 @@ import {
|
|
6
6
|
changeSearchInputFilterValue
|
7
7
|
} from 'actions/search-input-filter'
|
8
8
|
|
9
|
+
import Paper from 'material-ui/Paper'
|
9
10
|
import SelectField from 'material-ui/SelectField'
|
10
11
|
import MenuItem from 'material-ui/MenuItem'
|
11
12
|
import TextField from 'material-ui/TextField'
|
@@ -38,7 +39,7 @@ export class SearchInput extends Component {
|
|
38
39
|
|
39
40
|
render () {
|
40
41
|
return (
|
41
|
-
<
|
42
|
+
<Paper className='search-input'>
|
42
43
|
<SelectField
|
43
44
|
style={{width: '140px'}}
|
44
45
|
value={this.props.filterType || DEFAULT_FILTER_TYPE}
|
@@ -64,7 +65,7 @@ export class SearchInput extends Component {
|
|
64
65
|
onClick={() => this.search()}
|
65
66
|
style={{height: '50px', marginLeft: '20px'}}
|
66
67
|
icon={this.getButtonIcon()} />
|
67
|
-
</
|
68
|
+
</Paper>
|
68
69
|
)
|
69
70
|
}
|
70
71
|
|
@@ -0,0 +1,15 @@
|
|
1
|
+
import {
|
2
|
+
RECEIVE_FAILURE_COUNT
|
3
|
+
} from 'actions'
|
4
|
+
|
5
|
+
export default (state = {}, action) => {
|
6
|
+
switch (action.type) {
|
7
|
+
case RECEIVE_FAILURE_COUNT:
|
8
|
+
return {...state,
|
9
|
+
failureCount: action.data.count
|
10
|
+
}
|
11
|
+
|
12
|
+
default:
|
13
|
+
return state
|
14
|
+
}
|
15
|
+
}
|
@@ -0,0 +1,16 @@
|
|
1
|
+
import {
|
2
|
+
RECEIVE_FAILURE_COUNT
|
3
|
+
} from 'actions'
|
4
|
+
|
5
|
+
import reducer from 'reducers/dashboard'
|
6
|
+
|
7
|
+
describe('reducers/dashboard', () => {
|
8
|
+
describe('for RECEIVE_FAILURE_COUNT', () => {
|
9
|
+
it('sets overviewVisible for the specific event to true', () => {
|
10
|
+
const currentState = {}
|
11
|
+
const action = { type: RECEIVE_FAILURE_COUNT, data: { count: 8 } }
|
12
|
+
const expectedState = { failureCount: 8 }
|
13
|
+
expect(reducer(currentState, action)).toEqual(expectedState)
|
14
|
+
})
|
15
|
+
})
|
16
|
+
})
|
@@ -1,4 +1,7 @@
|
|
1
|
-
import {
|
1
|
+
import {
|
2
|
+
SEARCH_INPUT_CHANGE_FILTER_TYPE,
|
3
|
+
SEARCH_INPUT_CHANGE_FILTER_VALUE
|
4
|
+
} from 'actions'
|
2
5
|
|
3
6
|
export const DEFAULT_FILTER_TYPE = 'entity_id'
|
4
7
|
const initialState = { type: DEFAULT_FILTER_TYPE }
|
@@ -2,6 +2,7 @@ import { combineReducers } from 'redux'
|
|
2
2
|
import { routerReducer } from 'react-router-redux'
|
3
3
|
|
4
4
|
import events from 'reducers/events'
|
5
|
+
import dashboard from 'reducers/dashboard'
|
5
6
|
import failures from 'reducers/failures'
|
6
7
|
import eventDetails from 'reducers/event-details'
|
7
8
|
import failureDetails from 'reducers/failures/details'
|
@@ -10,6 +11,7 @@ import xhrStatus from 'reducers/xhr-status'
|
|
10
11
|
import flashMessages from 'reducers/flash-messages'
|
11
12
|
|
12
13
|
export default combineReducers({
|
14
|
+
dashboard,
|
13
15
|
xhrStatus,
|
14
16
|
flashMessages,
|
15
17
|
eventsFilters,
|
@@ -3,11 +3,14 @@ import reducer from 'reducers'
|
|
3
3
|
describe('reducers', () => {
|
4
4
|
it('without actions returns the initial state', () => {
|
5
5
|
expect(reducer(undefined, {})).toEqual({
|
6
|
+
dashboard: {},
|
6
7
|
xhrStatus: {
|
7
8
|
isFetchingEvents: false,
|
8
9
|
isRetryingEvent: false,
|
9
10
|
isRetryingFailure: false,
|
10
11
|
isDeletingFailure: false,
|
12
|
+
isFetchingFailureCount: false,
|
13
|
+
fetchFailureCountFailed: false,
|
11
14
|
isFetchingEventDetails: false,
|
12
15
|
currentEventsOffset: 0,
|
13
16
|
lastEventsLoadSize: 0
|
@@ -19,15 +19,20 @@ import {
|
|
19
19
|
RECEIVE_EVENT_RETRY,
|
20
20
|
REQUEST_EVENT_RETRY_FAILED,
|
21
21
|
REQUEST_EVENT_DETAILS,
|
22
|
-
RECEIVE_EVENT_DETAILS
|
22
|
+
RECEIVE_EVENT_DETAILS,
|
23
|
+
REQUEST_FAILURE_COUNT,
|
24
|
+
RECEIVE_FAILURE_COUNT,
|
25
|
+
REQUEST_FAILURE_COUNT_FAILED
|
23
26
|
} from 'actions'
|
24
27
|
|
25
28
|
const initialState = {
|
26
29
|
isFetchingEvents: false,
|
30
|
+
isFetchingFailureCount: false,
|
27
31
|
isRetryingEvent: false,
|
28
32
|
isRetryingFailure: false,
|
29
33
|
isDeletingFailure: false,
|
30
34
|
isFetchingEventDetails: false,
|
35
|
+
fetchFailureCountFailed: false,
|
31
36
|
currentEventsOffset: 0,
|
32
37
|
lastEventsLoadSize: 0
|
33
38
|
}
|
@@ -114,6 +119,23 @@ export default (state = initialState, action) => {
|
|
114
119
|
isFetchingEventDetails: false
|
115
120
|
}
|
116
121
|
|
122
|
+
case REQUEST_FAILURE_COUNT:
|
123
|
+
return {...state,
|
124
|
+
isFetchingFailureCount: true
|
125
|
+
}
|
126
|
+
|
127
|
+
case RECEIVE_FAILURE_COUNT:
|
128
|
+
return {...state,
|
129
|
+
isFetchingFailureCount: false,
|
130
|
+
fetchFailureCountFailed: false
|
131
|
+
}
|
132
|
+
|
133
|
+
case REQUEST_FAILURE_COUNT_FAILED:
|
134
|
+
return {...state,
|
135
|
+
isFetchingFailureCount: false,
|
136
|
+
fetchFailureCountFailed: true
|
137
|
+
}
|
138
|
+
|
117
139
|
default:
|
118
140
|
return state
|
119
141
|
}
|
@@ -17,7 +17,10 @@ import {
|
|
17
17
|
REQUEST_FAILURE_DELETE_FAILED,
|
18
18
|
REQUEST_EVENT_RETRY,
|
19
19
|
RECEIVE_EVENT_RETRY,
|
20
|
-
REQUEST_EVENT_RETRY_FAILED
|
20
|
+
REQUEST_EVENT_RETRY_FAILED,
|
21
|
+
REQUEST_FAILURE_COUNT,
|
22
|
+
RECEIVE_FAILURE_COUNT,
|
23
|
+
REQUEST_FAILURE_COUNT_FAILED
|
21
24
|
} from 'actions'
|
22
25
|
|
23
26
|
import reducer from 'reducers/xhr-status'
|
@@ -194,6 +197,33 @@ describe('reducers/xhr-status', () => {
|
|
194
197
|
})
|
195
198
|
})
|
196
199
|
|
200
|
+
describe('for REQUEST_FAILURE_COUNT', () => {
|
201
|
+
it('enables isFetchingFailureCount', () => {
|
202
|
+
const currentState = { isFetchingFailureCount: false }
|
203
|
+
const action = { type: REQUEST_FAILURE_COUNT }
|
204
|
+
const expectedState = { isFetchingFailureCount: true }
|
205
|
+
expect(reducer(currentState, action)).toEqual(expectedState)
|
206
|
+
})
|
207
|
+
})
|
208
|
+
|
209
|
+
describe('for RECEIVE_FAILURE_COUNT', () => {
|
210
|
+
it('disables isFetchingFailureCount', () => {
|
211
|
+
const currentState = { isFetchingFailureCount: true, fetchFailureCountFailed: true }
|
212
|
+
const action = { type: RECEIVE_FAILURE_COUNT }
|
213
|
+
const expectedState = { isFetchingFailureCount: false, fetchFailureCountFailed: false }
|
214
|
+
expect(reducer(currentState, action)).toEqual(expectedState)
|
215
|
+
})
|
216
|
+
})
|
217
|
+
|
218
|
+
describe('for REQUEST_FAILURE_COUNT_FAILED', () => {
|
219
|
+
it('disables isFetchingFailureCount', () => {
|
220
|
+
const currentState = { isFetchingFailureCount: true, fetchFailureCountFailed: false }
|
221
|
+
const action = { type: REQUEST_FAILURE_COUNT_FAILED }
|
222
|
+
const expectedState = { isFetchingFailureCount: false, fetchFailureCountFailed: true }
|
223
|
+
expect(reducer(currentState, action)).toEqual(expectedState)
|
224
|
+
})
|
225
|
+
})
|
226
|
+
|
197
227
|
describe('for default', () => {
|
198
228
|
it('returns the currentState', () => {
|
199
229
|
const currentState = { current: true }
|
data/frontend/src/routes.js
CHANGED
@@ -8,13 +8,15 @@ import EventsSearch from 'views/events/search'
|
|
8
8
|
import EventDetails from 'views/events/details'
|
9
9
|
import FailuresSearch from 'views/failures/search'
|
10
10
|
import FailureDetails from 'views/failures/details'
|
11
|
+
import Dashboard from 'views/dashboard'
|
11
12
|
|
12
13
|
export const history = syncHistoryWithStore(browserHistory, store)
|
13
14
|
|
14
15
|
export default (
|
15
16
|
<Router history={history}>
|
16
17
|
<Route path='/' component={Layout}>
|
17
|
-
<IndexRedirect to='/
|
18
|
+
<IndexRedirect to='/dashboard' />
|
19
|
+
<Route path='/dashboard' component={Dashboard} />
|
18
20
|
<Route path='/events' component={EventsSearch} />
|
19
21
|
<Route path='/events/:id' component={EventDetails} />
|
20
22
|
<Route path='/failures' component={FailuresSearch} />
|
@@ -0,0 +1,68 @@
|
|
1
|
+
import React, { Component, PropTypes } from 'react'
|
2
|
+
import { connect } from 'react-redux'
|
3
|
+
|
4
|
+
import Badge from 'components/badge'
|
5
|
+
import Paper from 'material-ui/Paper'
|
6
|
+
import { fetchFailureCount } from 'actions/dashboard/failure-count'
|
7
|
+
import { style } from 'views/style'
|
8
|
+
|
9
|
+
export class Dashboard extends Component {
|
10
|
+
static get propTypes () {
|
11
|
+
return {
|
12
|
+
fetchFailureCount: PropTypes.func.isRequired,
|
13
|
+
|
14
|
+
xhrStatus: PropTypes.shape({
|
15
|
+
isFetchingFailureCount: PropTypes.bool
|
16
|
+
})
|
17
|
+
}
|
18
|
+
}
|
19
|
+
|
20
|
+
componentDidMount () {
|
21
|
+
this.props.fetchFailureCount()
|
22
|
+
|
23
|
+
this.intervalId = setInterval(() => {
|
24
|
+
this.props.fetchFailureCount()
|
25
|
+
}, 10000)
|
26
|
+
}
|
27
|
+
|
28
|
+
componentWillUnmount () {
|
29
|
+
clearInterval(this.intervalId)
|
30
|
+
}
|
31
|
+
|
32
|
+
render () {
|
33
|
+
return (
|
34
|
+
<Paper zDepth={3} className='dashboard' style={style.view}>
|
35
|
+
<div style={style.title}>
|
36
|
+
Dashboard
|
37
|
+
</div>
|
38
|
+
<div style={style.body}>
|
39
|
+
<div style={style.row}>
|
40
|
+
<div style={style.heading}>
|
41
|
+
There are
|
42
|
+
</div>
|
43
|
+
{
|
44
|
+
<Badge
|
45
|
+
classCondition={this.props.dashboard.failureCount === 0}
|
46
|
+
text={this.props.dashboard.failureCount}
|
47
|
+
failed={this.props.xhrStatus.fetchFailureCountFailed}
|
48
|
+
loading={this.isLoadingFirstPage()} />
|
49
|
+
}
|
50
|
+
<div style={style.altHeading}>
|
51
|
+
failures
|
52
|
+
</div>
|
53
|
+
</div>
|
54
|
+
</div>
|
55
|
+
</Paper>
|
56
|
+
)
|
57
|
+
}
|
58
|
+
|
59
|
+
isLoadingFirstPage () {
|
60
|
+
return this.props.dashboard.failureCount === null && this.props.xhrStatus.isFetchingFailureCount
|
61
|
+
}
|
62
|
+
}
|
63
|
+
|
64
|
+
export default connect(
|
65
|
+
(state) => state, {
|
66
|
+
fetchFailureCount
|
67
|
+
}
|
68
|
+
)(Dashboard)
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import React, { Component, PropTypes } from 'react'
|
2
2
|
import { connect } from 'react-redux'
|
3
3
|
|
4
|
+
import Paper from 'material-ui/Paper'
|
4
5
|
import LoadMore from 'components/load-more'
|
5
6
|
import EmptyEvent from 'components/empty-event'
|
6
7
|
import EventsList from 'components/events-list'
|
@@ -10,6 +11,7 @@ import CircularProgress from 'material-ui/CircularProgress'
|
|
10
11
|
import { fetchSearchResults, loadMoreSearchResults, triggerSearch } from 'actions/events-search'
|
11
12
|
import { changeSearchInputFilterType, changeSearchInputFilterValue } from 'actions/search-input-filter'
|
12
13
|
import { showEventOverview } from 'actions/event-overview'
|
14
|
+
import { style } from 'views/style'
|
13
15
|
|
14
16
|
export class EventsSearch extends Component {
|
15
17
|
static get propTypes () {
|
@@ -68,7 +70,10 @@ export class EventsSearch extends Component {
|
|
68
70
|
const { type, value } = this.props.eventsFilters
|
69
71
|
|
70
72
|
return (
|
71
|
-
<
|
73
|
+
<Paper zDepth={3} className='events-search' style={style.view}>
|
74
|
+
<div style={style.title}>
|
75
|
+
Event search
|
76
|
+
</div>
|
72
77
|
<SearchInput triggerSearch={this.props.triggerSearch} filterType={type} filterValue={value}/>
|
73
78
|
<div>
|
74
79
|
<EventsList events={events} />
|
@@ -83,7 +88,7 @@ export class EventsSearch extends Component {
|
|
83
88
|
<CircularProgress />
|
84
89
|
</div>
|
85
90
|
}
|
86
|
-
</
|
91
|
+
</Paper>
|
87
92
|
)
|
88
93
|
}
|
89
94
|
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import React, { Component, PropTypes } from 'react'
|
2
2
|
import { connect } from 'react-redux'
|
3
3
|
|
4
|
+
import Paper from 'material-ui/Paper'
|
4
5
|
import LoadMore from 'components/load-more'
|
5
6
|
import EmptyFailure from 'components/failure/empty'
|
6
7
|
import FailuresList from 'components/failure/list'
|
@@ -10,6 +11,7 @@ import CircularProgress from 'material-ui/CircularProgress'
|
|
10
11
|
import { fetchSearchResults, loadMoreSearchResults, triggerSearch } from 'actions/failures/search'
|
11
12
|
import { changeSearchInputFilterType, changeSearchInputFilterValue } from 'actions/search-input-filter'
|
12
13
|
import { showEventOverview } from 'actions/event-overview'
|
14
|
+
import { style } from 'views/style'
|
13
15
|
|
14
16
|
export class FailuresSearch extends Component {
|
15
17
|
static get propTypes () {
|
@@ -76,7 +78,10 @@ export class FailuresSearch extends Component {
|
|
76
78
|
const { type, value } = this.props.eventsFilters
|
77
79
|
|
78
80
|
return (
|
79
|
-
<
|
81
|
+
<Paper zDepth={3} className='failures-search' style={style.view}>
|
82
|
+
<div style={style.title}>
|
83
|
+
Failure search
|
84
|
+
</div>
|
80
85
|
<SearchInput triggerSearch={this.props.triggerSearch} filterType={type} filterValue={value}/>
|
81
86
|
<div>
|
82
87
|
<FailuresList failures={failures} />
|
@@ -91,7 +96,7 @@ export class FailuresSearch extends Component {
|
|
91
96
|
<CircularProgress />
|
92
97
|
</div>
|
93
98
|
}
|
94
|
-
</
|
99
|
+
</Paper>
|
95
100
|
)
|
96
101
|
}
|
97
102
|
|
@@ -0,0 +1,43 @@
|
|
1
|
+
import {
|
2
|
+
grey200,
|
3
|
+
grey50,
|
4
|
+
blueGrey300
|
5
|
+
} from 'material-ui/styles/colors'
|
6
|
+
|
7
|
+
export const style = {
|
8
|
+
view: {
|
9
|
+
maxWidth: '1020px',
|
10
|
+
minHeigh: '100%',
|
11
|
+
backgroundColor: grey200,
|
12
|
+
margin: '0 auto'
|
13
|
+
},
|
14
|
+
title: {
|
15
|
+
padding: '20px 20px',
|
16
|
+
color: grey50,
|
17
|
+
backgroundColor: blueGrey300,
|
18
|
+
fontSize: '20px',
|
19
|
+
fontWeight: 'lighter',
|
20
|
+
fontFamily: 'Roboto',
|
21
|
+
marginBottom: '20px'
|
22
|
+
},
|
23
|
+
body: {
|
24
|
+
display: 'flex',
|
25
|
+
padding: '0 20px',
|
26
|
+
justifyContent: 'center'
|
27
|
+
},
|
28
|
+
row: {
|
29
|
+
display: 'flex',
|
30
|
+
alignItems: 'flex-start'
|
31
|
+
},
|
32
|
+
heading: {
|
33
|
+
fontSize: '24px',
|
34
|
+
fontWeight: 'lighter',
|
35
|
+
fontFamily: 'Roboto'
|
36
|
+
},
|
37
|
+
altHeading: {
|
38
|
+
fontSize: '24px',
|
39
|
+
fontWeight: 'lighter',
|
40
|
+
fontFamily: 'Roboto',
|
41
|
+
alignSelf: 'flex-end'
|
42
|
+
}
|
43
|
+
}
|