Skip to content

Commit b3795cf

Browse files
committed
Merge branch 'add_event_utilities_to_async_action_form_transition' into develop
2 parents a34e92f + 35f08ee commit b3795cf

File tree

20 files changed

+913
-110
lines changed

20 files changed

+913
-110
lines changed

app/concepts/matestack/ui/core/action/action.js

Lines changed: 120 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -17,51 +17,132 @@ const componentDef = {
1717
(self.componentConfig["confirm"] == undefined) || confirm(self.componentConfig["confirm_text"])
1818
)
1919
{
20-
axios({
20+
if (self.componentConfig["emit"] != undefined) {
21+
matestackEventHub.$emit(self.componentConfig["emit"]);
22+
}
23+
if (self.componentConfig["delay"] != undefined) {
24+
setTimeout(function () {
25+
self.sendRequest()
26+
}, parseInt(self.componentConfig["delay"]));
27+
} else {
28+
this.sendRequest()
29+
}
30+
}
31+
},
32+
sendRequest: function(){
33+
const self = this
34+
axios({
2135
method: self.componentConfig["method"],
2236
url: self.componentConfig["action_path"],
2337
data: self.componentConfig["data"],
2438
headers: {
2539
'X-CSRF-Token': document.getElementsByName("csrf-token")[0].getAttribute('content')
2640
}
27-
})
28-
.then(function(response){
29-
if (self.componentConfig["success"] != undefined && self.componentConfig["success"]["emit"] != undefined) {
30-
matestackEventHub.$emit(self.componentConfig["success"]["emit"], response.data);
31-
}
32-
if (self.componentConfig["success"] != undefined
33-
&& self.componentConfig["success"]["transition"] != undefined
34-
&& (
35-
self.componentConfig["success"]["transition"]["follow_response"] == undefined
36-
||
37-
self.componentConfig["success"]["transition"]["follow_response"] === false
38-
)
39-
&& self.$store != undefined
40-
) {
41-
let path = self.componentConfig["success"]["transition"]["path"]
42-
self.$store.dispatch('navigateTo', {url: path, backwards: false})
43-
return;
44-
}
45-
if (self.componentConfig["success"] != undefined
46-
&& self.componentConfig["success"]["transition"] != undefined
47-
&& self.componentConfig["success"]["transition"]["follow_response"] === true
48-
&& self.$store != undefined
49-
) {
50-
let path = response.data["transition_to"] || response.request.responseURL;
51-
self.$store.dispatch('navigateTo', {url: path, backwards: false});
52-
return;
53-
}
54-
})
55-
.catch(function(error){
56-
if (self.componentConfig["failure"] != undefined && self.componentConfig["failure"]["emit"] != undefined) {
57-
matestackEventHub.$emit(self.componentConfig["failure"]["emit"], error.response.data);
58-
}
59-
if (self.componentConfig["failure"] != undefined && self.componentConfig["failure"]["transition"] != undefined && self.$store != undefined) {
60-
let path = self.componentConfig["failure"]["transition"]["path"]
61-
self.$store.dispatch('navigateTo', {url: path, backwards: false})
62-
}
63-
})
64-
}
41+
}
42+
)
43+
.then(function(response){
44+
if (self.componentConfig["success"] != undefined && self.componentConfig["success"]["emit"] != undefined) {
45+
matestackEventHub.$emit(self.componentConfig["success"]["emit"], response.data);
46+
}
47+
48+
// transition handling
49+
if (self.componentConfig["success"] != undefined
50+
&& self.componentConfig["success"]["transition"] != undefined
51+
&& (
52+
self.componentConfig["success"]["transition"]["follow_response"] == undefined
53+
||
54+
self.componentConfig["success"]["transition"]["follow_response"] === false
55+
)
56+
&& self.$store != undefined
57+
) {
58+
let path = self.componentConfig["success"]["transition"]["path"]
59+
self.$store.dispatch('navigateTo', {url: path, backwards: false})
60+
return;
61+
}
62+
if (self.componentConfig["success"] != undefined
63+
&& self.componentConfig["success"]["transition"] != undefined
64+
&& self.componentConfig["success"]["transition"]["follow_response"] === true
65+
&& self.$store != undefined
66+
) {
67+
let path = response.data["transition_to"] || response.request.responseURL
68+
self.$store.dispatch('navigateTo', {url: path, backwards: false})
69+
return;
70+
}
71+
// redirect handling
72+
if (self.componentConfig["success"] != undefined
73+
&& self.componentConfig["success"]["redirect"] != undefined
74+
&& (
75+
self.componentConfig["success"]["redirect"]["follow_response"] == undefined
76+
||
77+
self.componentConfig["success"]["redirect"]["follow_response"] === false
78+
)
79+
&& self.$store != undefined
80+
) {
81+
let path = self.componentConfig["success"]["redirect"]["path"]
82+
window.location.href = path
83+
return;
84+
}
85+
if (self.componentConfig["success"] != undefined
86+
&& self.componentConfig["success"]["redirect"] != undefined
87+
&& self.componentConfig["success"]["redirect"]["follow_response"] === true
88+
&& self.$store != undefined
89+
) {
90+
let path = response.data["redirect_to"] || response.request.responseURL
91+
window.location.href = path
92+
return;
93+
}
94+
})
95+
.catch(function(error){
96+
if (self.componentConfig["failure"] != undefined && self.componentConfig["failure"]["emit"] != undefined) {
97+
matestackEventHub.$emit(self.componentConfig["failure"]["emit"], error.response.data);
98+
}
99+
// transition handling
100+
if (self.componentConfig["failure"] != undefined
101+
&& self.componentConfig["failure"]["transition"] != undefined
102+
&& (
103+
self.componentConfig["failure"]["transition"]["follow_response"] == undefined
104+
||
105+
self.componentConfig["failure"]["transition"]["follow_response"] === false
106+
)
107+
&& self.$store != undefined
108+
) {
109+
let path = self.componentConfig["failure"]["transition"]["path"]
110+
self.$store.dispatch('navigateTo', {url: path, backwards: false})
111+
return;
112+
}
113+
if (self.componentConfig["failure"] != undefined
114+
&& self.componentConfig["failure"]["transition"] != undefined
115+
&& self.componentConfig["failure"]["transition"]["follow_response"] === true
116+
&& self.$store != undefined
117+
) {
118+
let path = error.response.data["transition_to"] || response.request.responseURL
119+
self.$store.dispatch('navigateTo', {url: path, backwards: false})
120+
return;
121+
}
122+
// redirect handling
123+
if (self.componentConfig["failure"] != undefined
124+
&& self.componentConfig["failure"]["redirect"] != undefined
125+
&& (
126+
self.componentConfig["failure"]["redirect"]["follow_response"] == undefined
127+
||
128+
self.componentConfig["failure"]["redirect"]["follow_response"] === false
129+
)
130+
&& self.$store != undefined
131+
) {
132+
let path = self.componentConfig["failure"]["redirect"]["path"]
133+
window.location.href = path
134+
return;
135+
}
136+
if (self.componentConfig["failure"] != undefined
137+
&& self.componentConfig["failure"]["redirect"] != undefined
138+
&& self.componentConfig["failure"]["redirect"]["follow_response"] === true
139+
&& self.$store != undefined
140+
) {
141+
let path = error.response.data["redirect_to"] || response.request.responseURL
142+
window.location.href = path
143+
return;
144+
}
145+
})
65146
}
66147
}
67148
}

app/concepts/matestack/ui/core/async/async.js

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,19 @@ const componentDef = {
4545
},
4646
created: function () {
4747
const self = this
48-
matestackEventHub.$on(this.componentConfig["rerender_on"], self.rerender)
49-
matestackEventHub.$on(this.componentConfig["show_on"], self.show)
50-
matestackEventHub.$on(this.componentConfig["hide_on"], self.hide)
48+
if(this.componentConfig["show_on"] != undefined){
49+
this.showing = false
50+
var show_events = this.componentConfig["show_on"].split(",")
51+
show_events.forEach(show_event => matestackEventHub.$on(show_event.trim(), self.show));
52+
}
53+
if(this.componentConfig["hide_on"] != undefined){
54+
var hide_events = this.componentConfig["hide_on"].split(",")
55+
hide_events.forEach(hide_event => matestackEventHub.$on(hide_event.trim(), self.hide));
56+
}
57+
if(this.componentConfig["rerender_on"] != undefined){
58+
var rerender_events = this.componentConfig["rerender_on"].split(",")
59+
rerender_events.forEach(rerender_event => matestackEventHub.$on(rerender_event.trim(), self.rerender));
60+
}
5161
if(this.componentConfig["show_on"] != undefined){
5262
this.showing = false
5363
}
@@ -68,6 +78,18 @@ const componentDef = {
6878
matestackEventHub.$off(this.componentConfig["rerender_on"], self.rerender);
6979
matestackEventHub.$off(this.componentConfig["show_on"], self.show);
7080
matestackEventHub.$off(this.componentConfig["hide_on"], self.hide);
81+
if(this.componentConfig["show_on"] != undefined){
82+
var shown_events = this.componentConfig["show_on"].split(",")
83+
shown_events.forEach(show_event => matestackEventHub.$off(show_event.trim(), self.show));
84+
}
85+
if(this.componentConfig["hide_on"] != undefined){
86+
var hiden_events = this.componentConfig["hide_on"].split(",")
87+
hiden_events.forEach(hide_event => matestackEventHub.$off(hide_event.trim(), self.hide));
88+
}
89+
if(this.componentConfig["rerender_on"] != undefined){
90+
var rerender_events = this.componentConfig["rerender_on"].split(",")
91+
rerender_events.forEach(rerender_event => matestackEventHub.$off(rerender_event.trim(), self.rerender));
92+
}
7193
},
7294
}
7395

app/concepts/matestack/ui/core/form/form.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,19 @@ const componentDef = {
104104
}
105105
},
106106
perform: function(){
107+
const self = this
108+
if (self.componentConfig["emit"] != undefined) {
109+
matestackEventHub.$emit(self.componentConfig["emit"]);
110+
}
111+
if (self.componentConfig["delay"] != undefined) {
112+
setTimeout(function () {
113+
self.sendRequest()
114+
}, parseInt(self.componentConfig["delay"]));
115+
} else {
116+
this.sendRequest()
117+
}
118+
},
119+
sendRequest: function(){
107120
const self = this
108121
let payload = {}
109122
payload[self.componentConfig["for"]] = self.data

app/concepts/matestack/ui/core/transition/transition.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import Vue from 'vue/dist/vue.esm'
22
import Vuex from 'vuex'
33
import componentMixin from '../component/component'
4+
import matestackEventHub from '../js/event-hub'
45

56
const componentDef = {
67
mixins: [componentMixin],
@@ -17,6 +18,17 @@ const componentDef = {
1718
}),
1819
methods: {
1920
navigateTo: function(url){
21+
const self = this
22+
matestackEventHub.$emit("page_loading_triggered", url);
23+
if (self.componentConfig["delay"] != undefined) {
24+
setTimeout(function () {
25+
self.performNavigation(url)
26+
}, parseInt(self.componentConfig["delay"]));
27+
} else {
28+
this.performNavigation(url)
29+
}
30+
},
31+
performNavigation: function(url){
2032
this.$store.dispatch('navigateTo', {url: url, backwards: false}).then((response) => {
2133
// self.asyncTemplate = response;
2234
})

docker-compose.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ services:
3535
dockerfile: ./Dockerfile.test
3636
environment:
3737
RAILS_ENV: test
38+
ports:
39+
- "33123:33123"
3840
volumes:
3941
- ./:/app
4042
- gem-volume:/usr/local/bundle

docs/components/action.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,22 @@ If no `text` is given, the default text "Are you sure?" will be used.
5454
confirm: true
5555
```
5656

57+
### Emit
58+
59+
This event gets emitted right after triggering the action. In contrast to the `sucsess` or `failure` events, it will be emitted regardless of the server response.
60+
61+
```ruby
62+
emit: "action_submitted"
63+
```
64+
65+
### Delay
66+
67+
You can use this attribute if you want to delay the actual action submit request. It will not delay the event specified with the `emit` attribute.
68+
69+
```ruby
70+
delay: 1000 # means 1000 ms
71+
```
72+
5773
### Success
5874

5975
The success part of the action component gets triggered once the action we wanted to perform returns a success code, usually the `200` HTTP status code.

docs/components/async.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ Lazy (or defered) loading can be configured like shown [here](#defer).
2828

2929
If you want to simply hide the async component on initial pageload and display it later on, read below how to use `show_on`, which can be combined with `rerender_on`.
3030

31+
You can pass in multiple, comma-separated events on which the component should rerender.
32+
33+
```ruby
34+
async rerender_on: 'my_event, some_other_event'
35+
```
36+
3137
### Show_on
3238

3339
The `show_on` option lets us define an event on which the component gets shown. The content is still rendered on init pageload, but simply hidden in the browser until the event is emitted. If you want to have proper deferred loading, please refer to [defer](#defer)
@@ -40,6 +46,12 @@ async show_on: 'my_event' do
4046
end
4147
```
4248

49+
You can pass in multiple, comma-separated events on which the component should be shown.
50+
51+
```ruby
52+
async show_on: 'my_event, some_other_event'
53+
```
54+
4355
### Hide_on
4456

4557
The `hide_on` option lets us define an event on which the component gets hidden.
@@ -52,6 +64,13 @@ async hide_on: 'my_event' do
5264
end
5365
```
5466

67+
You can pass in multiple, comma-separated events on which the component should be hidden.
68+
69+
```ruby
70+
async hide_on: 'my_event, some_other_event'
71+
```
72+
73+
5574
### Hide_after
5675

5776
The `hide_after` option lets us define a timespan in milliseconds after which the component gets hidden.

docs/components/form.md

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,21 @@ Using the standard Rails params, we can pass information to our route!
106106
params: { id: 42 }
107107
```
108108

109+
### Emit
110+
111+
This event gets emitted right after form submit. In contrast to the `sucsess` or `failure` events, it will be emitted regardless of the server response.
112+
113+
```ruby
114+
emit: "form_submitted"
115+
```
116+
117+
### Delay
118+
119+
You can use this attribute if you want to delay the actual form submit request. It will not delay the event specified with the `emit` attribute.
120+
121+
```ruby
122+
delay: 1000 # means 1000 ms
123+
```
109124

110125
### Success
111126

@@ -1348,4 +1363,4 @@ datalist id: 'datalist-id' do
13481363
option value: 10
13491364
option value: 20
13501365
end
1351-
```
1366+
```

docs/components/transition.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,25 @@ Currently active: `/some_page/child_page` --> Parent gets `child-active`
4242

4343
Query params do not interfere with this behavior.
4444

45+
### Delay
46+
47+
You can use this attribute if you want to delay the actual transition. It will not delay the `page_loading_triggered` event
48+
49+
```ruby
50+
delay: 1000 # means 1000 ms
51+
```
52+
53+
### Events
54+
55+
The `transition` component automatically emits events on:
56+
57+
* transition triggered by user action -> "page_loading_triggered"
58+
* *optional client side delay via `delay` attribute*
59+
* start to get new page from server -> "page_loading"
60+
* *server side/network delay*
61+
* successfully received new page from server -> "page_loaded"
62+
* failed to receive new page from server -> "page_loading_error"
63+
4564
## Examples
4665

4766
The transition core component renders the HTML `<a>` tag and performs a page transition

spec/spec_helper.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,9 @@
4949
config.display_try_failure_messages = true
5050

5151
# run retry only on features
52-
config.around :each, :js do |ex|
53-
ex.run_with_retry retry: 3
54-
end
52+
# config.around :each, :js do |ex|
53+
# ex.run_with_retry retry: 3
54+
# end
5555

5656
# callback to be run between retries
5757
config.retry_callback = proc do |ex|

0 commit comments

Comments
 (0)