phobos_checkpoint_ui 0.4.0 → 1.0.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -1
- data/frontend/.gitignore +4 -0
- data/frontend/src/actions/events-search.js +11 -11
- data/frontend/src/actions/events-search.spec.js +21 -21
- data/frontend/src/actions/failures/details.js +42 -0
- data/frontend/src/actions/failures/details.spec.js +71 -0
- data/frontend/src/actions/failures/overview.js +14 -0
- data/frontend/src/actions/failures/overview.spec.js +20 -0
- data/frontend/src/actions/failures/retry.js +58 -0
- data/frontend/src/actions/failures/retry.spec.js +117 -0
- data/frontend/src/actions/failures/search/index.js +76 -0
- data/frontend/src/actions/failures/search/index.spec.js +197 -0
- data/frontend/src/actions/index.js +24 -5
- data/frontend/src/actions/navigation/index.js +5 -0
- data/frontend/src/actions/navigation/index.spec.js +21 -0
- data/frontend/src/api.js +11 -0
- data/frontend/src/components/{event-overview/attribute.js → attribute/index.js} +0 -0
- data/frontend/src/components/empty-event/index.js +20 -0
- data/frontend/src/components/empty-event/index.spec.js +38 -0
- data/frontend/src/components/event-overview/index.js +1 -1
- data/frontend/src/components/event-retry-dialog/index.js +1 -1
- data/frontend/src/components/failure/error-message.js +19 -0
- data/frontend/src/components/failure/error-message.scss +8 -0
- data/frontend/src/components/failure/event.scss +3 -0
- data/frontend/src/components/failure/index.js +82 -0
- data/frontend/src/components/failure/index.spec.js +89 -0
- data/frontend/src/components/failure/loading.js +16 -0
- data/frontend/src/components/failure/overview/failure-overview.scss +28 -0
- data/frontend/src/components/failure/overview/index.js +60 -0
- data/frontend/src/components/failure/overview/index.spec.js +71 -0
- data/frontend/src/components/failure/overview-dialog/event-overview-dialog.scss +15 -0
- data/frontend/src/components/failure/overview-dialog/index.js +90 -0
- data/frontend/src/components/failure/retry-dialog/index.js +72 -0
- data/frontend/src/components/failure/style.js +16 -0
- data/frontend/src/components/failures-list/failures-list.scss +49 -0
- data/frontend/src/components/failures-list/index.js +62 -0
- data/frontend/src/components/failures-list/index.spec.js +59 -0
- data/frontend/src/components/header/index.js +36 -2
- data/frontend/src/components/load-more/index.js +22 -0
- data/frontend/src/components/load-more/index.spec.js +54 -0
- data/frontend/src/components/search-input/index.js +2 -5
- data/frontend/src/components/search-input/index.spec.js +6 -6
- data/frontend/src/reducers/events.js +2 -2
- data/frontend/src/reducers/events.spec.js +4 -4
- data/frontend/src/reducers/failures/details/index.js +32 -0
- data/frontend/src/reducers/failures/details/index.spec.js +54 -0
- data/frontend/src/reducers/failures/index.js +48 -0
- data/frontend/src/reducers/failures/index.spec.js +95 -0
- data/frontend/src/reducers/index.js +4 -1
- data/frontend/src/reducers/index.spec.js +2 -0
- data/frontend/src/reducers/xhr-status.js +25 -10
- data/frontend/src/reducers/xhr-status.spec.js +65 -15
- data/frontend/src/routes.js +6 -2
- data/frontend/src/store.js +7 -3
- data/frontend/src/views/{event-details.js → events/details/index.js} +0 -0
- data/frontend/src/views/{events-search.js → events/search/index.js} +37 -44
- data/frontend/src/views/{events-search.scss → events/search/index.scss} +0 -0
- data/frontend/src/views/{events-search.spec.js → events/search/index.spec.js} +35 -25
- data/frontend/src/views/failures/details/index.js +50 -0
- data/frontend/src/views/failures/search/index.js +113 -0
- data/frontend/src/views/failures/search/index.scss +24 -0
- data/frontend/src/views/failures/search/index.spec.js +106 -0
- data/lib/phobos_checkpoint_ui/version.rb +1 -1
- data/phobos_checkpoint_ui.gemspec +1 -1
- metadata +53 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c06ac3b49f17bb1a0cfd0b99c381cbf472ea99c2
|
4
|
+
data.tar.gz: 6a20e89e24e36288a4448c6e05d560613c7440b6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9c9ff42eee60f0ec01a4ce14b24f3f9903444a91a41a6bd140aae7eef2d427817275f2300ed768fa8b08bc2c5a04a4a9270681697d4116c991a3f86b04f1085a
|
7
|
+
data.tar.gz: 11524361e949b14a83a0404c6161581d08b0342b8628ea162e4a7432c660f32337077cb0c56e4e6e670c9b2aed9592bb7246bf4348c36aa7228a3b5c2e73a55f
|
data/CHANGELOG.md
CHANGED
@@ -4,13 +4,17 @@ 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)
|
8
|
+
|
9
|
+
- [feature] Add GUI interacting with PhobosDBCheckpoint failures
|
10
|
+
|
7
11
|
## 0.4.0 (2017-01-28)
|
8
12
|
|
9
13
|
- [enhancement] Add /ping endpoint
|
10
14
|
|
11
15
|
## 0.3.0 (2017-01-28)
|
12
16
|
|
13
|
-
- [bugfix] Gem should require
|
17
|
+
- [bugfix] Gem should require PhobosDBCheckpoint
|
14
18
|
|
15
19
|
## 0.2.0 (2016-10-10)
|
16
20
|
|
data/frontend/.gitignore
ADDED
@@ -3,34 +3,34 @@ import { addFlashMessage } from 'actions/flash-messages'
|
|
3
3
|
import { history } from 'routes'
|
4
4
|
|
5
5
|
import {
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
6
|
+
TRIGGER_EVENTS_SEARCH,
|
7
|
+
REQUEST_EVENTS_SEARCH_RESULTS,
|
8
|
+
RECEIVE_EVENTS_SEARCH_RESULTS,
|
9
|
+
REQUEST_EVENTS_SEARCH_RESULTS_FAILED,
|
10
|
+
LOAD_MORE_EVENTS_SEARCH_RESULTS
|
11
11
|
} from 'actions'
|
12
12
|
|
13
13
|
export const triggerSearch = () => (dispatch, getState) => {
|
14
14
|
const filters = getState().eventsFilters
|
15
15
|
return Promise
|
16
16
|
.resolve()
|
17
|
-
.then(() => history.push({ query: filters.value ? filters : {} }))
|
18
|
-
.then(() => dispatch({ type:
|
17
|
+
.then(() => history.push({ pathname: window.location.pathname, query: filters.value ? filters : {} }))
|
18
|
+
.then(() => dispatch({ type: TRIGGER_EVENTS_SEARCH }))
|
19
19
|
.then(() => dispatch(fetchSearchResults()))
|
20
20
|
}
|
21
21
|
|
22
22
|
const requestSearchResults = () => ({
|
23
|
-
type:
|
23
|
+
type: REQUEST_EVENTS_SEARCH_RESULTS
|
24
24
|
})
|
25
25
|
|
26
26
|
const receiveSearchResults = (data, offset) => ({
|
27
|
-
type:
|
27
|
+
type: RECEIVE_EVENTS_SEARCH_RESULTS,
|
28
28
|
events: data,
|
29
29
|
offset
|
30
30
|
})
|
31
31
|
|
32
32
|
const requestSearchResultsFailed = (query, error) => ({
|
33
|
-
type:
|
33
|
+
type: REQUEST_EVENTS_SEARCH_RESULTS_FAILED,
|
34
34
|
query,
|
35
35
|
error
|
36
36
|
})
|
@@ -68,7 +68,7 @@ export const loadMoreSearchResults = () => (dispatch, getState) => {
|
|
68
68
|
return Promise
|
69
69
|
.resolve()
|
70
70
|
.then(() => dispatch({
|
71
|
-
type:
|
71
|
+
type: LOAD_MORE_EVENTS_SEARCH_RESULTS,
|
72
72
|
offset: currentOffset + EVENTS_SEARCH_LIMIT
|
73
73
|
}))
|
74
74
|
.then(() => dispatch(fetchSearchResults()))
|
@@ -9,12 +9,12 @@ const middlewares = [ thunk ]
|
|
9
9
|
const mockStore = configureMockStore(middlewares)
|
10
10
|
|
11
11
|
import {
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
12
|
+
TRIGGER_EVENTS_SEARCH,
|
13
|
+
REQUEST_EVENTS_SEARCH_RESULTS,
|
14
|
+
RECEIVE_EVENTS_SEARCH_RESULTS,
|
15
|
+
REQUEST_EVENTS_SEARCH_RESULTS_FAILED,
|
16
16
|
ADD_FLASH_MESSAGE,
|
17
|
-
|
17
|
+
LOAD_MORE_EVENTS_SEARCH_RESULTS
|
18
18
|
} from 'actions'
|
19
19
|
|
20
20
|
import {
|
@@ -44,8 +44,8 @@ describe('actions/event-search', () => {
|
|
44
44
|
it('creates REQUEST and RECEIVE actions', (done) => {
|
45
45
|
store.dispatch(fetchSearchResults(event)).then(() => {
|
46
46
|
const actions = store.getActions()
|
47
|
-
expect(actions[0]).toEqual({ type:
|
48
|
-
expect(actions[1]).toEqual({ type:
|
47
|
+
expect(actions[0]).toEqual({ type: REQUEST_EVENTS_SEARCH_RESULTS })
|
48
|
+
expect(actions[1]).toEqual({ type: RECEIVE_EVENTS_SEARCH_RESULTS, events: [event], offset: 0 })
|
49
49
|
done()
|
50
50
|
})
|
51
51
|
.catch((e) => done.fail(`test failed with promise error: ${e.message}`))
|
@@ -70,8 +70,8 @@ describe('actions/event-search', () => {
|
|
70
70
|
it('creates REQUEST and RECEIVE actions using the filters', (done) => {
|
71
71
|
store.dispatch(fetchSearchResults(event)).then(() => {
|
72
72
|
const actions = store.getActions()
|
73
|
-
expect(actions[0]).toEqual({ type:
|
74
|
-
expect(actions[1]).toEqual({ type:
|
73
|
+
expect(actions[0]).toEqual({ type: REQUEST_EVENTS_SEARCH_RESULTS })
|
74
|
+
expect(actions[1]).toEqual({ type: RECEIVE_EVENTS_SEARCH_RESULTS, events: [event], offset: 0 })
|
75
75
|
done()
|
76
76
|
})
|
77
77
|
.catch((e) => done.fail(`test failed with promise error: ${e.message}`))
|
@@ -96,8 +96,8 @@ describe('actions/event-search', () => {
|
|
96
96
|
it('creates REQUEST and RECEIVE actions pointing to the correct offset', (done) => {
|
97
97
|
store.dispatch(fetchSearchResults(event)).then(() => {
|
98
98
|
const actions = store.getActions()
|
99
|
-
expect(actions[0]).toEqual({ type:
|
100
|
-
expect(actions[1]).toEqual({ type:
|
99
|
+
expect(actions[0]).toEqual({ type: REQUEST_EVENTS_SEARCH_RESULTS })
|
100
|
+
expect(actions[1]).toEqual({ type: RECEIVE_EVENTS_SEARCH_RESULTS, events: [event], offset: 4 })
|
101
101
|
done()
|
102
102
|
})
|
103
103
|
.catch((e) => done.fail(`test failed with promise error: ${e.message}`))
|
@@ -125,9 +125,9 @@ describe('actions/event-search', () => {
|
|
125
125
|
it('creates REQUEST and RECEIVE actions pointing to the correct offset', (done) => {
|
126
126
|
store.dispatch(fetchSearchResults(event)).then(() => {
|
127
127
|
const actions = store.getActions()
|
128
|
-
expect(actions[0]).toEqual({ type:
|
128
|
+
expect(actions[0]).toEqual({ type: REQUEST_EVENTS_SEARCH_RESULTS })
|
129
129
|
expect(actions[1]).toEqual({
|
130
|
-
type:
|
130
|
+
type: REQUEST_EVENTS_SEARCH_RESULTS_FAILED,
|
131
131
|
query: { offset: 0 }, error: 'some error'
|
132
132
|
})
|
133
133
|
expect(actions[2]).toEqual({
|
@@ -156,12 +156,12 @@ describe('actions/event-search', () => {
|
|
156
156
|
.response([event])
|
157
157
|
})
|
158
158
|
|
159
|
-
it('creates
|
159
|
+
it('creates TRIGGER_EVENTS_SEARCH and REQUEST actions', (done) => {
|
160
160
|
store.dispatch(triggerSearch()).then(() => {
|
161
161
|
const actions = store.getActions()
|
162
|
-
expect(actions[0]).toEqual({ type:
|
163
|
-
expect(actions[1]).toEqual({ type:
|
164
|
-
expect(actions[2]).toEqual({ type:
|
162
|
+
expect(actions[0]).toEqual({ type: TRIGGER_EVENTS_SEARCH })
|
163
|
+
expect(actions[1]).toEqual({ type: REQUEST_EVENTS_SEARCH_RESULTS })
|
164
|
+
expect(actions[2]).toEqual({ type: RECEIVE_EVENTS_SEARCH_RESULTS, events: [event], offset: 0 })
|
165
165
|
done()
|
166
166
|
})
|
167
167
|
.catch((e) => done.fail(`test failed with promise error: ${e.message}`))
|
@@ -183,12 +183,12 @@ describe('actions/event-search', () => {
|
|
183
183
|
.response([event])
|
184
184
|
})
|
185
185
|
|
186
|
-
it('creates
|
186
|
+
it('creates LOAD_MORE_EVENTS_SEARCH_RESULTS and REQUEST actions', (done) => {
|
187
187
|
store.dispatch(loadMoreSearchResults()).then(() => {
|
188
188
|
const actions = store.getActions()
|
189
|
-
expect(actions[0]).toEqual({ type:
|
190
|
-
expect(actions[1]).toEqual({ type:
|
191
|
-
expect(actions[2]).toEqual({ type:
|
189
|
+
expect(actions[0]).toEqual({ type: LOAD_MORE_EVENTS_SEARCH_RESULTS, offset: 4 + EVENTS_SEARCH_LIMIT })
|
190
|
+
expect(actions[1]).toEqual({ type: REQUEST_EVENTS_SEARCH_RESULTS })
|
191
|
+
expect(actions[2]).toEqual({ type: RECEIVE_EVENTS_SEARCH_RESULTS, events: [event], offset: 4 })
|
192
192
|
done()
|
193
193
|
})
|
194
194
|
.catch((e) => done.fail(`test failed with promise error: ${e.message}`))
|
@@ -0,0 +1,42 @@
|
|
1
|
+
import API, { parseResponseError } from 'api'
|
2
|
+
import { addFlashMessage } from 'actions/flash-messages'
|
3
|
+
|
4
|
+
import {
|
5
|
+
REQUEST_FAILURE_DETAILS,
|
6
|
+
RECEIVE_FAILURE_DETAILS,
|
7
|
+
REQUEST_FAILURE_DETAILS_FAILED
|
8
|
+
} from 'actions'
|
9
|
+
|
10
|
+
const requestFailureDetails = (failure) => ({
|
11
|
+
type: REQUEST_FAILURE_DETAILS,
|
12
|
+
failure
|
13
|
+
})
|
14
|
+
|
15
|
+
const receiveFailureDetails = (failure) => ({
|
16
|
+
type: RECEIVE_FAILURE_DETAILS,
|
17
|
+
failure
|
18
|
+
})
|
19
|
+
|
20
|
+
const requestFailureDetailsFailed = (failure, error) => ({
|
21
|
+
type: REQUEST_FAILURE_DETAILS_FAILED,
|
22
|
+
failure,
|
23
|
+
error
|
24
|
+
})
|
25
|
+
|
26
|
+
export const fetchFailureDetails = (failure) => (dispatch, getState) => {
|
27
|
+
dispatch(requestFailureDetails(failure))
|
28
|
+
|
29
|
+
return API.Failure
|
30
|
+
.findById({ id: failure.id })
|
31
|
+
.then((response) => dispatch(receiveFailureDetails(response.data)))
|
32
|
+
.catch((response) => {
|
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
|
+
})))
|
41
|
+
})
|
42
|
+
}
|
@@ -0,0 +1,71 @@
|
|
1
|
+
import 'babel-polyfill'
|
2
|
+
import Mappersmith from 'mappersmith'
|
3
|
+
import 'mappersmith/fixtures'
|
4
|
+
import configureMockStore from 'redux-mock-store'
|
5
|
+
import thunk from 'redux-thunk'
|
6
|
+
|
7
|
+
const middlewares = [ thunk ]
|
8
|
+
const mockStore = configureMockStore(middlewares)
|
9
|
+
|
10
|
+
import {
|
11
|
+
REQUEST_FAILURE_DETAILS,
|
12
|
+
RECEIVE_FAILURE_DETAILS,
|
13
|
+
REQUEST_FAILURE_DETAILS_FAILED
|
14
|
+
} from 'actions'
|
15
|
+
|
16
|
+
import { fetchFailureDetails } from 'actions/failures/details'
|
17
|
+
|
18
|
+
beforeEach(() => {
|
19
|
+
Mappersmith.Env.Fixture.clear()
|
20
|
+
})
|
21
|
+
|
22
|
+
describe('actions/failure-details', () => {
|
23
|
+
describe('#fetchFailureDetails', () => {
|
24
|
+
describe('when it succeeds', () => {
|
25
|
+
let failure, store
|
26
|
+
beforeEach(() => {
|
27
|
+
failure = { id: 1 }
|
28
|
+
store = mockStore({})
|
29
|
+
Mappersmith.Env.Fixture
|
30
|
+
.define('get')
|
31
|
+
.matching({ url: `/api/v1/failures/${failure.id}` })
|
32
|
+
.response(failure)
|
33
|
+
})
|
34
|
+
|
35
|
+
it('creates REQUEST and RECEIVE actions', (done) => {
|
36
|
+
store.dispatch(fetchFailureDetails(failure)).then(() => {
|
37
|
+
const actions = store.getActions()
|
38
|
+
expect(actions[0]).toEqual({ type: REQUEST_FAILURE_DETAILS, failure })
|
39
|
+
expect(actions[1]).toEqual({ type: RECEIVE_FAILURE_DETAILS, failure })
|
40
|
+
done()
|
41
|
+
})
|
42
|
+
.catch((e) => done.fail(`test failed with promise error: ${e.message}`))
|
43
|
+
})
|
44
|
+
})
|
45
|
+
|
46
|
+
describe('when it fails', () => {
|
47
|
+
it('creates REQUEST and REQUEST_FAILED actions', (done) => {
|
48
|
+
const failure = { id: 1 }
|
49
|
+
const store = mockStore({})
|
50
|
+
Mappersmith.Env.Fixture
|
51
|
+
.define('get')
|
52
|
+
.matching({ url: `/api/v1/failures/${failure.id}` })
|
53
|
+
.failure()
|
54
|
+
.response({
|
55
|
+
responseText: JSON.stringify({
|
56
|
+
error: true,
|
57
|
+
message: 'some error'
|
58
|
+
})
|
59
|
+
})
|
60
|
+
|
61
|
+
store.dispatch(fetchFailureDetails(failure)).then(() => {
|
62
|
+
const actions = store.getActions()
|
63
|
+
expect(actions[0]).toEqual({ type: REQUEST_FAILURE_DETAILS, failure })
|
64
|
+
expect(actions[1]).toEqual({ type: REQUEST_FAILURE_DETAILS_FAILED, failure, error: 'some error' })
|
65
|
+
done()
|
66
|
+
})
|
67
|
+
.catch((e) => done.fail(`test failed with promise error: ${e.message}`))
|
68
|
+
})
|
69
|
+
})
|
70
|
+
})
|
71
|
+
})
|
@@ -0,0 +1,14 @@
|
|
1
|
+
import {
|
2
|
+
FAILURE_SHOW_OVERVIEW,
|
3
|
+
FAILURE_HIDE_OVERVIEW
|
4
|
+
} from 'actions'
|
5
|
+
|
6
|
+
export const showFailureOverview = (failure) => ({
|
7
|
+
type: FAILURE_SHOW_OVERVIEW,
|
8
|
+
failure
|
9
|
+
})
|
10
|
+
|
11
|
+
export const hideFailureOverview = (failure) => ({
|
12
|
+
type: FAILURE_HIDE_OVERVIEW,
|
13
|
+
failure
|
14
|
+
})
|
@@ -0,0 +1,20 @@
|
|
1
|
+
import { FAILURE_SHOW_OVERVIEW, FAILURE_HIDE_OVERVIEW } from 'actions'
|
2
|
+
import { showFailureOverview, hideFailureOverview } from 'actions/failures/overview'
|
3
|
+
|
4
|
+
describe('actions/failures/overview', () => {
|
5
|
+
describe('#showFailureOverview', () => {
|
6
|
+
it('creates an action to show failure overview', () => {
|
7
|
+
const failure = { id: 1 }
|
8
|
+
const expectedAction = { type: FAILURE_SHOW_OVERVIEW, failure: failure }
|
9
|
+
expect(showFailureOverview(failure)).toEqual(expectedAction)
|
10
|
+
})
|
11
|
+
})
|
12
|
+
|
13
|
+
describe('#hideFailureOverview', () => {
|
14
|
+
it('creates an action to hide failure overview', () => {
|
15
|
+
const failure = { id: 1 }
|
16
|
+
const expectedAction = { type: FAILURE_HIDE_OVERVIEW, failure: failure }
|
17
|
+
expect(hideFailureOverview(failure)).toEqual(expectedAction)
|
18
|
+
})
|
19
|
+
})
|
20
|
+
})
|
@@ -0,0 +1,58 @@
|
|
1
|
+
import API, { parseResponseError } from 'api'
|
2
|
+
import { addFlashMessage } from 'actions/flash-messages'
|
3
|
+
|
4
|
+
import {
|
5
|
+
FAILURE_SHOW_RETRY,
|
6
|
+
FAILURE_HIDE_RETRY,
|
7
|
+
REQUEST_FAILURE_RETRY,
|
8
|
+
RECEIVE_FAILURE_RETRY,
|
9
|
+
REQUEST_FAILURE_RETRY_FAILED
|
10
|
+
} from 'actions'
|
11
|
+
|
12
|
+
export const showFailureRetry = (failure) => ({
|
13
|
+
type: FAILURE_SHOW_RETRY,
|
14
|
+
failure
|
15
|
+
})
|
16
|
+
|
17
|
+
export const hideFailureRetry = (failure) => ({
|
18
|
+
type: FAILURE_HIDE_RETRY,
|
19
|
+
failure
|
20
|
+
})
|
21
|
+
|
22
|
+
const requestFailureRetry = (failure) => ({
|
23
|
+
type: REQUEST_FAILURE_RETRY,
|
24
|
+
failure: failure
|
25
|
+
})
|
26
|
+
|
27
|
+
const receiveFailureRetry = (failure, data) => ({
|
28
|
+
type: RECEIVE_FAILURE_RETRY,
|
29
|
+
failure: failure,
|
30
|
+
acknowledged: data.acknowledged
|
31
|
+
})
|
32
|
+
|
33
|
+
const requestFailureRetryFailed = (failure, error) => ({
|
34
|
+
type: REQUEST_FAILURE_RETRY_FAILED,
|
35
|
+
failure: failure,
|
36
|
+
error
|
37
|
+
})
|
38
|
+
|
39
|
+
export const performFailureRetry = (failure) => (dispatch, getState) => {
|
40
|
+
dispatch(requestFailureRetry(failure))
|
41
|
+
return API.Failure
|
42
|
+
.retry({id: failure.id})
|
43
|
+
.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
|
+
})))
|
53
|
+
})
|
54
|
+
.catch((response) => {
|
55
|
+
const error = parseResponseError(response)
|
56
|
+
dispatch(requestFailureRetryFailed(failure, error.message))
|
57
|
+
})
|
58
|
+
}
|
@@ -0,0 +1,117 @@
|
|
1
|
+
import 'babel-polyfill'
|
2
|
+
import Mappersmith from 'mappersmith'
|
3
|
+
import 'mappersmith/fixtures'
|
4
|
+
import configureMockStore from 'redux-mock-store'
|
5
|
+
import thunk from 'redux-thunk'
|
6
|
+
|
7
|
+
const middlewares = [ thunk ]
|
8
|
+
const mockStore = configureMockStore(middlewares)
|
9
|
+
|
10
|
+
import {
|
11
|
+
FAILURE_SHOW_RETRY,
|
12
|
+
FAILURE_HIDE_RETRY,
|
13
|
+
REQUEST_FAILURE_RETRY,
|
14
|
+
RECEIVE_FAILURE_RETRY,
|
15
|
+
ADD_FLASH_MESSAGE,
|
16
|
+
REQUEST_FAILURE_RETRY_FAILED
|
17
|
+
} from 'actions'
|
18
|
+
|
19
|
+
import {
|
20
|
+
showFailureRetry,
|
21
|
+
hideFailureRetry,
|
22
|
+
performFailureRetry
|
23
|
+
} from 'actions/failures/retry'
|
24
|
+
|
25
|
+
beforeEach(() => {
|
26
|
+
Mappersmith.Env.Fixture.clear()
|
27
|
+
})
|
28
|
+
|
29
|
+
describe('actions/failures/retry', () => {
|
30
|
+
describe('#showFailureRetry', () => {
|
31
|
+
it('creates an action to show failure retry', () => {
|
32
|
+
const failure = { id: 1 }
|
33
|
+
const expectedAction = { type: FAILURE_SHOW_RETRY, failure }
|
34
|
+
expect(showFailureRetry(failure)).toEqual(expectedAction)
|
35
|
+
})
|
36
|
+
})
|
37
|
+
|
38
|
+
describe('#hideFailureRetry', () => {
|
39
|
+
it('creates an action to hide failure retry', () => {
|
40
|
+
const failure = { id: 1 }
|
41
|
+
const expectedAction = { type: FAILURE_HIDE_RETRY, failure }
|
42
|
+
expect(hideFailureRetry(failure)).toEqual(expectedAction)
|
43
|
+
})
|
44
|
+
})
|
45
|
+
|
46
|
+
describe('#performFailureRetry', () => {
|
47
|
+
describe('when it succeeds', () => {
|
48
|
+
let failure, store
|
49
|
+
beforeEach(() => {
|
50
|
+
failure = { id: 1 }
|
51
|
+
store = mockStore({})
|
52
|
+
Mappersmith.Env.Fixture
|
53
|
+
.define('post')
|
54
|
+
.matching({ url: `/api/v1/failures/${failure.id}/retry` })
|
55
|
+
.response({ acknowledged: true })
|
56
|
+
})
|
57
|
+
|
58
|
+
it('creates REQUEST and RECEIVE actions', (done) => {
|
59
|
+
store.dispatch(performFailureRetry(failure)).then(() => {
|
60
|
+
const actions = store.getActions()
|
61
|
+
expect(actions[0]).toEqual({ type: REQUEST_FAILURE_RETRY, failure })
|
62
|
+
expect(actions[1]).toEqual({ type: RECEIVE_FAILURE_RETRY, failure, acknowledged: true })
|
63
|
+
done()
|
64
|
+
})
|
65
|
+
.catch((e) => done.fail(`test failed with promise error: ${e.message}`))
|
66
|
+
})
|
67
|
+
|
68
|
+
it('creates an action to hide the failure retry', (done) => {
|
69
|
+
store.dispatch(performFailureRetry(failure)).then(() => {
|
70
|
+
const actions = store.getActions()
|
71
|
+
expect(actions[2]).toEqual({ type: FAILURE_HIDE_RETRY, failure })
|
72
|
+
done()
|
73
|
+
})
|
74
|
+
.catch((e) => done.fail(`test failed with promise error: ${e.message}`))
|
75
|
+
})
|
76
|
+
|
77
|
+
it('create an action to add a success flash message', (done) => {
|
78
|
+
store.dispatch(performFailureRetry(failure)).then(() => {
|
79
|
+
const actions = store.getActions()
|
80
|
+
expect(actions[3]).toEqual({ type: ADD_FLASH_MESSAGE, message: {
|
81
|
+
id: jasmine.any(String),
|
82
|
+
type: 'success',
|
83
|
+
text: 'Failure retried with success. Acknowledged: true',
|
84
|
+
autoClose: true
|
85
|
+
}})
|
86
|
+
done()
|
87
|
+
})
|
88
|
+
.catch((e) => done.fail(`test failed with promise error: ${e.message}`))
|
89
|
+
})
|
90
|
+
})
|
91
|
+
|
92
|
+
describe('when it fails', () => {
|
93
|
+
it('creates REQUEST and REQUEST_FAILED actions', (done) => {
|
94
|
+
const failure = { id: 1 }
|
95
|
+
const store = mockStore({})
|
96
|
+
Mappersmith.Env.Fixture
|
97
|
+
.define('post')
|
98
|
+
.matching({ url: `/api/v1/failures/${failure.id}/retry` })
|
99
|
+
.failure()
|
100
|
+
.response({
|
101
|
+
responseText: JSON.stringify({
|
102
|
+
error: true,
|
103
|
+
message: 'some error'
|
104
|
+
})
|
105
|
+
})
|
106
|
+
|
107
|
+
store.dispatch(performFailureRetry(failure)).then(() => {
|
108
|
+
const actions = store.getActions()
|
109
|
+
expect(actions[0]).toEqual({ type: REQUEST_FAILURE_RETRY, failure })
|
110
|
+
expect(actions[1]).toEqual({ type: REQUEST_FAILURE_RETRY_FAILED, failure, error: 'some error' })
|
111
|
+
done()
|
112
|
+
})
|
113
|
+
.catch((e) => done.fail(`test failed with promise error: ${e.message}`))
|
114
|
+
})
|
115
|
+
})
|
116
|
+
})
|
117
|
+
})
|
@@ -0,0 +1,76 @@
|
|
1
|
+
|
2
|
+
import API, { EVENTS_SEARCH_LIMIT, parseResponseError } from 'api'
|
3
|
+
import { addFlashMessage } from 'actions/flash-messages'
|
4
|
+
import { history } from 'routes'
|
5
|
+
|
6
|
+
import {
|
7
|
+
TRIGGER_FAILURES_SEARCH,
|
8
|
+
REQUEST_FAILURES_SEARCH_RESULTS,
|
9
|
+
RECEIVE_FAILURES_SEARCH_RESULTS,
|
10
|
+
REQUEST_FAILURES_SEARCH_RESULTS_FAILED,
|
11
|
+
LOAD_MORE_FAILURES_SEARCH_RESULTS
|
12
|
+
} from 'actions'
|
13
|
+
|
14
|
+
export const triggerSearch = () => (dispatch, getState) => {
|
15
|
+
const filters = getState().eventsFilters
|
16
|
+
return Promise
|
17
|
+
.resolve()
|
18
|
+
.then(() => history.push({ pathname: window.location.pathname, query: filters.value ? filters : {} }))
|
19
|
+
.then(() => dispatch({ type: TRIGGER_FAILURES_SEARCH }))
|
20
|
+
.then(() => dispatch(fetchSearchResults()))
|
21
|
+
}
|
22
|
+
|
23
|
+
const requestSearchResults = () => ({
|
24
|
+
type: REQUEST_FAILURES_SEARCH_RESULTS
|
25
|
+
})
|
26
|
+
|
27
|
+
const receiveSearchResults = (data, offset) => ({
|
28
|
+
type: RECEIVE_FAILURES_SEARCH_RESULTS,
|
29
|
+
failures: data,
|
30
|
+
offset
|
31
|
+
})
|
32
|
+
|
33
|
+
const requestSearchResultsFailed = (query, error) => ({
|
34
|
+
type: REQUEST_FAILURES_SEARCH_RESULTS_FAILED,
|
35
|
+
query,
|
36
|
+
error
|
37
|
+
})
|
38
|
+
|
39
|
+
export const fetchSearchResults = () => (dispatch, getState) => {
|
40
|
+
dispatch(requestSearchResults())
|
41
|
+
|
42
|
+
const filter = getState().eventsFilters
|
43
|
+
const currentOffset = getState().xhrStatus.currentEventsOffset
|
44
|
+
const query = filter.value
|
45
|
+
? {[filter.type]: filter.value}
|
46
|
+
: {}
|
47
|
+
|
48
|
+
Object.assign(query, { offset: currentOffset })
|
49
|
+
|
50
|
+
return API.Failure
|
51
|
+
.search(query)
|
52
|
+
.then((response) => {
|
53
|
+
dispatch(receiveSearchResults(response.data, currentOffset))
|
54
|
+
})
|
55
|
+
.catch((response) => {
|
56
|
+
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
|
+
})))
|
64
|
+
})
|
65
|
+
}
|
66
|
+
|
67
|
+
export const loadMoreSearchResults = () => (dispatch, getState) => {
|
68
|
+
const currentOffset = getState().xhrStatus.currentEventsOffset
|
69
|
+
return Promise
|
70
|
+
.resolve()
|
71
|
+
.then(() => dispatch({
|
72
|
+
type: LOAD_MORE_FAILURES_SEARCH_RESULTS,
|
73
|
+
offset: currentOffset + EVENTS_SEARCH_LIMIT
|
74
|
+
}))
|
75
|
+
.then(() => dispatch(fetchSearchResults()))
|
76
|
+
}
|