Skip to content

Commit 9113098

Browse files
committed
introducing collection component, undocumented, untested
1 parent e3f5da2 commit 9113098

File tree

32 files changed

+1322
-220
lines changed

32 files changed

+1322
-220
lines changed

Gemfile.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
PATH
22
remote: .
33
specs:
4-
matestack-ui-core (0.6.0)
4+
matestack-ui-core (0.7.0)
55
cells-haml
66
cells-rails
77
haml
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
import Vue from 'vue/dist/vue.esm'
2+
3+
import matestackEventHub from 'js/event-hub'
4+
5+
import componentMixin from 'component/component'
6+
import asyncMixin from 'async/async'
7+
8+
const componentDef = {
9+
mixins: [componentMixin, asyncMixin],
10+
data: function(){
11+
return {
12+
currentLimit: null,
13+
currentOffset: null,
14+
currentFilteredCount: null
15+
}
16+
},
17+
methods: {
18+
next: function(){
19+
if (this.currentTo() < this.currentFilteredCount){
20+
this.currentOffset += this.currentLimit
21+
var url = this.updateQueryParams(this.componentConfig["id"] + "-offset", this.currentOffset)
22+
window.history.pushState({matestackApp: true, url: url}, null, url);
23+
matestackEventHub.$emit(this.componentConfig["id"] + "-update")
24+
}
25+
},
26+
previous: function(){
27+
if ((this.currentOffset - this.currentLimit)*-1 != this.currentLimit){
28+
if((this.currentOffset - this.currentLimit) < 0){
29+
this.currentOffset = 0
30+
} else {
31+
this.currentOffset -= this.currentLimit
32+
}
33+
var url = this.updateQueryParams(this.componentConfig["id"] + "-offset", this.currentOffset)
34+
window.history.pushState({matestackApp: true, url: url}, null, url);
35+
matestackEventHub.$emit(this.componentConfig["id"] + "-update")
36+
}
37+
},
38+
currentTo: function(){
39+
var to = parseInt(this.currentOffset) + parseInt(this.currentLimit)
40+
if (to > parseInt(this.currentFilteredCount)){
41+
return this.currentFilteredCount;
42+
} else {
43+
return to;
44+
}
45+
},
46+
goToPage: function(page){
47+
this.currentOffset = parseInt(this.currentLimit) * (parseInt(page)-1)
48+
var url = this.updateQueryParams(this.componentConfig["id"] + "-offset", this.currentOffset)
49+
window.history.pushState({matestackApp: true, url: url}, null, url);
50+
matestackEventHub.$emit(this.componentConfig["id"] + "-update")
51+
},
52+
updateQueryParams: function (key, value, url) {
53+
if (!url) url = window.location.href;
54+
var re = new RegExp("([?&])" + key + "=.*?(&|#|$)(.*)", "gi"),
55+
hash;
56+
57+
if (re.test(url)) {
58+
if (typeof value !== 'undefined' && value !== null)
59+
return url.replace(re, '$1' + key + "=" + value + '$2$3');
60+
else {
61+
hash = url.split('#');
62+
url = hash[0].replace(re, '$1$3').replace(/(&|\?)$/, '');
63+
if (typeof hash[1] !== 'undefined' && hash[1] !== null)
64+
url += '#' + hash[1];
65+
return url;
66+
}
67+
}
68+
else {
69+
if (typeof value !== 'undefined' && value !== null) {
70+
var separator = url.indexOf('?') !== -1 ? '&' : '?';
71+
hash = url.split('#');
72+
url = hash[0] + separator + key + '=' + value;
73+
if (typeof hash[1] !== 'undefined' && hash[1] !== null)
74+
url += '#' + hash[1];
75+
return url;
76+
}
77+
else
78+
return url;
79+
}
80+
},
81+
getQueryParam: function (name, url) {
82+
if (!url) url = window.location.href;
83+
name = name.replace(/[\[\]]/g, '\\$&');
84+
var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'),
85+
results = regex.exec(url);
86+
if (!results) return null;
87+
if (!results[2]) return '';
88+
return decodeURIComponent(results[2].replace(/\+/g, ' '));
89+
}
90+
},
91+
beforeCreate: function() {
92+
if(this.$options.propsData.componentConfig["rerender_on"] == undefined){
93+
this.$options.propsData.componentConfig["rerender_on"] = this.$options.propsData.componentConfig["id"] + "-update"
94+
}
95+
},
96+
mounted: function(){
97+
if(this.getQueryParam(this.componentConfig["id"] + "-offset") != null){
98+
this.currentOffset = parseInt(this.getQueryParam(this.componentConfig["id"] + "-offset"))
99+
} else {
100+
if(this.componentConfig["init_offset"] != undefined){
101+
this.currentOffset = this.componentConfig["init_offset"]
102+
} else {
103+
this.currentOffset = 0
104+
}
105+
}
106+
107+
if(this.getQueryParam(this.componentConfig["id"] + "-limit") != null){
108+
this.currentOffset = parseInt(this.getQueryParam(this.componentConfig["id"] + "-limit"))
109+
} else {
110+
if(this.componentConfig["init_limit"] != undefined){
111+
this.currentLimit = this.componentConfig["init_limit"]
112+
} else {
113+
this.currentLimit = 10
114+
}
115+
}
116+
117+
if(this.componentConfig["filtered_count"] != undefined){
118+
this.currentFilteredCount = this.componentConfig["filtered_count"]
119+
}
120+
}
121+
}
122+
123+
let component = Vue.component('matestack-ui-core-collection-content', componentDef)
124+
125+
export default componentDef
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
module Matestack::Ui::Core::Collection::Content
2+
class Content < Matestack::Ui::Core::Component::Dynamic
3+
4+
def setup
5+
@rerender = true
6+
@component_config = @component_config.except(:data, :paginated_data)
7+
end
8+
9+
10+
def response
11+
components {
12+
div attributes: {"v-if": "showing"} do
13+
yield_components
14+
end
15+
}
16+
end
17+
18+
19+
end
20+
end
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
%a{@tag_attributes, "@click": "next()"}
2+
- if block_given?
3+
= yield
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module Matestack::Ui::Core::Collection::Content::Next
2+
class Next < Matestack::Ui::Core::Component::Static
3+
4+
end
5+
end
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
%a{@tag_attributes, "@click": "goToPage(#{@options[:page]})"}
2+
- if block_given?
3+
= yield
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module Matestack::Ui::Core::Collection::Content::Page::Link
2+
class Link < Matestack::Ui::Core::Component::Static
3+
4+
end
5+
end
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
%a{@tag_attributes, "@click": "previous()"}
2+
- if block_given?
3+
= yield
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module Matestack::Ui::Core::Collection::Content::Previous
2+
class Previous < Matestack::Ui::Core::Component::Static
3+
4+
end
5+
end
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import Vue from 'vue/dist/vue.esm'
2+
3+
import matestackEventHub from 'js/event-hub'
4+
5+
import componentMixin from 'component/component'
6+
7+
const componentDef = {
8+
mixins: [componentMixin],
9+
data: function(){
10+
return {
11+
filter: {}
12+
}
13+
},
14+
methods: {
15+
submitFilter: function(){
16+
var url;
17+
for (var key in this.filter) {
18+
url = this.updateQueryParams(this.componentConfig["id"] + "-filter-" + key, this.filter[key])
19+
url = this.updateQueryParams(this.componentConfig["id"] + "-offset", 0, url)
20+
}
21+
window.history.pushState({matestackApp: true, url: url}, null, url);
22+
matestackEventHub.$emit(this.componentConfig["id"] + "-update")
23+
},
24+
resetFilter: function(){
25+
var url;
26+
for (var key in this.filter) {
27+
url = this.updateQueryParams(this.componentConfig["id"] + "-filter-" + key, null)
28+
this.filter[key] = null;
29+
this.$forceUpdate();
30+
}
31+
window.history.pushState({matestackApp: true, url: url}, null, url);
32+
matestackEventHub.$emit(this.componentConfig["id"] + "-update")
33+
},
34+
updateQueryParams: function (key, value, url) {
35+
if (!url) url = window.location.href;
36+
var re = new RegExp("([?&])" + key + "=.*?(&|#|$)(.*)", "gi"),
37+
hash;
38+
39+
if (re.test(url)) {
40+
if (typeof value !== 'undefined' && value !== null)
41+
return url.replace(re, '$1' + key + "=" + value + '$2$3');
42+
else {
43+
hash = url.split('#');
44+
url = hash[0].replace(re, '$1$3').replace(/(&|\?)$/, '');
45+
if (typeof hash[1] !== 'undefined' && hash[1] !== null)
46+
url += '#' + hash[1];
47+
return url;
48+
}
49+
}
50+
else {
51+
if (typeof value !== 'undefined' && value !== null) {
52+
var separator = url.indexOf('?') !== -1 ? '&' : '?';
53+
hash = url.split('#');
54+
url = hash[0] + separator + key + '=' + value;
55+
if (typeof hash[1] !== 'undefined' && hash[1] !== null)
56+
url += '#' + hash[1];
57+
return url;
58+
}
59+
else
60+
return url;
61+
}
62+
},
63+
getQueryParam: function (name, url) {
64+
if (!url) url = window.location.href;
65+
name = name.replace(/[\[\]]/g, '\\$&');
66+
var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'),
67+
results = regex.exec(url);
68+
if (!results) return null;
69+
if (!results[2]) return '';
70+
return decodeURIComponent(results[2].replace(/\+/g, ' '));
71+
},
72+
queryParamsToObject: function(){
73+
var search = window.location.search.substring(1);
74+
if(search.length === 0){
75+
return {}
76+
} else {
77+
var result = JSON.parse(
78+
'{"' + search.replace(/&/g, '","').replace(/=/g,'":"') + '"}',
79+
function(key, value) { return key===""?value:decodeURIComponent(value) }
80+
)
81+
return result;
82+
}
83+
}
84+
},
85+
created: function(){
86+
var self = this;
87+
var queryParamsObject = this.queryParamsToObject()
88+
Object.keys(queryParamsObject).forEach(function(key){
89+
if (key.startsWith(self.componentConfig["id"] + "-filter-")){
90+
self.filter[key.replace(self.componentConfig["id"] + "-filter-", "")] = queryParamsObject[key]
91+
}
92+
})
93+
}
94+
}
95+
96+
let component = Vue.component('matestack-ui-core-collection-filter', componentDef)
97+
98+
export default componentDef

0 commit comments

Comments
 (0)