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.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -0
  3. data/assets/index-b24a670cc064e5a7b78d-0.css +2 -0
  4. data/assets/index-b24a670cc064e5a7b78d-0.css.map +1 -0
  5. data/assets/{index-b2f95711135c455435c3-1.css → index-b24a670cc064e5a7b78d-1.css} +1 -1
  6. data/assets/{index-b2f95711135c455435c3-1.css.map → index-b24a670cc064e5a7b78d-1.css.map} +1 -1
  7. data/assets/{index-b2f95711135c455435c3.js → index-b24a670cc064e5a7b78d.js} +29 -29
  8. data/assets/index-b24a670cc064e5a7b78d.js.map +1 -0
  9. data/assets/index.html +2 -2
  10. data/frontend/src/actions/dashboard/failure-count/index.js +38 -0
  11. data/frontend/src/actions/dashboard/failure-count/index.spec.js +70 -0
  12. data/frontend/src/actions/index.js +4 -0
  13. data/frontend/src/api.js +1 -0
  14. data/frontend/src/components/badge/badge.scss +13 -0
  15. data/frontend/src/components/badge/index.js +85 -0
  16. data/frontend/src/components/badge/index.spec.js +64 -0
  17. data/frontend/src/components/header/index.js +8 -0
  18. data/frontend/src/components/search-input/index.js +3 -2
  19. data/frontend/src/reducers/dashboard/index.js +15 -0
  20. data/frontend/src/reducers/dashboard/index.spec.js +16 -0
  21. data/frontend/src/reducers/events-filters.js +4 -1
  22. data/frontend/src/reducers/index.js +2 -0
  23. data/frontend/src/reducers/index.spec.js +3 -0
  24. data/frontend/src/reducers/xhr-status.js +23 -1
  25. data/frontend/src/reducers/xhr-status.spec.js +31 -1
  26. data/frontend/src/routes.js +3 -1
  27. data/frontend/src/views/dashboard/index.js +68 -0
  28. data/frontend/src/views/dashboard/index.scss +5 -0
  29. data/frontend/src/views/events/search/index.js +7 -2
  30. data/frontend/src/views/events/search/index.scss +0 -7
  31. data/frontend/src/views/failures/search/index.js +7 -2
  32. data/frontend/src/views/failures/search/index.scss +0 -7
  33. data/frontend/src/views/style.js +43 -0
  34. data/lib/phobos_checkpoint_ui/version.rb +1 -1
  35. data/phobos_checkpoint_ui.gemspec +1 -1
  36. metadata +20 -10
  37. data/assets/index-b2f95711135c455435c3-0.css +0 -2
  38. data/assets/index-b2f95711135c455435c3-0.css.map +0 -1
  39. 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
- <div className='search-input'>
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
- </div>
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 { SEARCH_INPUT_CHANGE_FILTER_TYPE, SEARCH_INPUT_CHANGE_FILTER_VALUE } from 'actions'
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 }
@@ -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='/events' />
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)
@@ -0,0 +1,5 @@
1
+ .dashboard {
2
+ font-size: 30px;
3
+ color: #333;
4
+ min-height: 720px;
5
+ }
@@ -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
- <div className='events-search'>
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
- </div>
91
+ </Paper>
87
92
  )
88
93
  }
89
94
 
@@ -1,11 +1,4 @@
1
1
  .events-search {
2
- max-width: 1020px;
3
- min-height: 100%;
4
-
5
- background-color: #e4e4e4;
6
- margin: 0 auto;
7
- padding: 20px 0;
8
-
9
2
  .page-loader {
10
3
  text-align: center;
11
4
  padding: 50px 0;
@@ -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
- <div className='failures-search'>
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
- </div>
99
+ </Paper>
95
100
  )
96
101
  }
97
102
 
@@ -1,11 +1,4 @@
1
1
  .failures-search {
2
- max-width: 1020px;
3
- min-height: 100%;
4
-
5
- background-color: #e4e4e4;
6
- margin: 0 auto;
7
- padding: 20px 0;
8
-
9
2
  .page-loader {
10
3
  text-align: center;
11
4
  padding: 50px 0;
@@ -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
+ }
@@ -1,3 +1,3 @@
1
1
  module PhobosCheckpointUI
2
- VERSION = '1.1.0'
2
+ VERSION = '1.2.0'
3
3
  end
@@ -50,5 +50,5 @@ Gem::Specification.new do |spec|
50
50
 
51
51
  spec.add_dependency 'rake'
52
52
  spec.add_dependency 'sinatra'
53
- spec.add_dependency 'phobos_db_checkpoint', '~> 2.0'
53
+ spec.add_dependency 'phobos_db_checkpoint', '~> 2.4'
54
54
  end