matestack-ui-vuejs 3.0.0.rc1

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 (77) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +20 -0
  3. data/README.md +492 -0
  4. data/Rakefile +64 -0
  5. data/lib/matestack/ui/component.rb +1 -0
  6. data/lib/matestack/ui/isolated_component.rb +1 -0
  7. data/lib/matestack/ui/vue_js/components/action.js +70 -0
  8. data/lib/matestack/ui/vue_js/components/action.rb +46 -0
  9. data/lib/matestack/ui/vue_js/components/app.js +122 -0
  10. data/lib/matestack/ui/vue_js/components/app.rb +46 -0
  11. data/lib/matestack/ui/vue_js/components/async.js +104 -0
  12. data/lib/matestack/ui/vue_js/components/async.rb +84 -0
  13. data/lib/matestack/ui/vue_js/components/cable.js +96 -0
  14. data/lib/matestack/ui/vue_js/components/cable.rb +69 -0
  15. data/lib/matestack/ui/vue_js/components/collection/content.js +96 -0
  16. data/lib/matestack/ui/vue_js/components/collection/content.rb +32 -0
  17. data/lib/matestack/ui/vue_js/components/collection/filter.js +45 -0
  18. data/lib/matestack/ui/vue_js/components/collection/filter.rb +29 -0
  19. data/lib/matestack/ui/vue_js/components/collection/filter_reset.rb +19 -0
  20. data/lib/matestack/ui/vue_js/components/collection/helper.rb +128 -0
  21. data/lib/matestack/ui/vue_js/components/collection/next.rb +19 -0
  22. data/lib/matestack/ui/vue_js/components/collection/order.js +45 -0
  23. data/lib/matestack/ui/vue_js/components/collection/order.rb +28 -0
  24. data/lib/matestack/ui/vue_js/components/collection/order_toggle.rb +21 -0
  25. data/lib/matestack/ui/vue_js/components/collection/order_toggle_indicator.rb +30 -0
  26. data/lib/matestack/ui/vue_js/components/collection/page.rb +21 -0
  27. data/lib/matestack/ui/vue_js/components/collection/previous.rb +19 -0
  28. data/lib/matestack/ui/vue_js/components/form/base.rb +179 -0
  29. data/lib/matestack/ui/vue_js/components/form/checkbox.js +13 -0
  30. data/lib/matestack/ui/vue_js/components/form/checkbox.rb +109 -0
  31. data/lib/matestack/ui/vue_js/components/form/checkbox_mixin.js +90 -0
  32. data/lib/matestack/ui/vue_js/components/form/context.rb +15 -0
  33. data/lib/matestack/ui/vue_js/components/form/fields_for_add_item.js +50 -0
  34. data/lib/matestack/ui/vue_js/components/form/fields_for_add_item.rb +35 -0
  35. data/lib/matestack/ui/vue_js/components/form/fields_for_remove_item.rb +19 -0
  36. data/lib/matestack/ui/vue_js/components/form/form.js +276 -0
  37. data/lib/matestack/ui/vue_js/components/form/form.rb +77 -0
  38. data/lib/matestack/ui/vue_js/components/form/input.js +13 -0
  39. data/lib/matestack/ui/vue_js/components/form/input.rb +54 -0
  40. data/lib/matestack/ui/vue_js/components/form/input_mixin.js +79 -0
  41. data/lib/matestack/ui/vue_js/components/form/nested_form.js +153 -0
  42. data/lib/matestack/ui/vue_js/components/form/nested_form.rb +57 -0
  43. data/lib/matestack/ui/vue_js/components/form/radio.js +13 -0
  44. data/lib/matestack/ui/vue_js/components/form/radio.rb +85 -0
  45. data/lib/matestack/ui/vue_js/components/form/radio_mixin.js +75 -0
  46. data/lib/matestack/ui/vue_js/components/form/select.js +13 -0
  47. data/lib/matestack/ui/vue_js/components/form/select.rb +96 -0
  48. data/lib/matestack/ui/vue_js/components/form/select_mixin.js +76 -0
  49. data/lib/matestack/ui/vue_js/components/form/textarea.js +13 -0
  50. data/lib/matestack/ui/vue_js/components/form/textarea.rb +37 -0
  51. data/lib/matestack/ui/vue_js/components/form/textarea_mixin.js +54 -0
  52. data/lib/matestack/ui/vue_js/components/helpers.js +5 -0
  53. data/lib/matestack/ui/vue_js/components/isolated.js +105 -0
  54. data/lib/matestack/ui/vue_js/components/isolated.rb +86 -0
  55. data/lib/matestack/ui/vue_js/components/mixin.js +66 -0
  56. data/lib/matestack/ui/vue_js/components/onclick.js +18 -0
  57. data/lib/matestack/ui/vue_js/components/onclick.rb +37 -0
  58. data/lib/matestack/ui/vue_js/components/page_switch.js +24 -0
  59. data/lib/matestack/ui/vue_js/components/page_switch.rb +35 -0
  60. data/lib/matestack/ui/vue_js/components/runtime_render.js +17 -0
  61. data/lib/matestack/ui/vue_js/components/toggle.js +70 -0
  62. data/lib/matestack/ui/vue_js/components/toggle.rb +38 -0
  63. data/lib/matestack/ui/vue_js/components/transition.js +44 -0
  64. data/lib/matestack/ui/vue_js/components/transition.rb +40 -0
  65. data/lib/matestack/ui/vue_js/components/transition_handling_mixin.js +100 -0
  66. data/lib/matestack/ui/vue_js/components.rb +118 -0
  67. data/lib/matestack/ui/vue_js/event_hub.js +12 -0
  68. data/lib/matestack/ui/vue_js/helpers/query_params_helper.js +56 -0
  69. data/lib/matestack/ui/vue_js/index.js +94 -0
  70. data/lib/matestack/ui/vue_js/initialize.rb +10 -0
  71. data/lib/matestack/ui/vue_js/utils.rb +67 -0
  72. data/lib/matestack/ui/vue_js/version.rb +7 -0
  73. data/lib/matestack/ui/vue_js/vue.rb +75 -0
  74. data/lib/matestack/ui/vue_js/vue_attributes.rb +13 -0
  75. data/lib/matestack/ui/vue_js.rb +52 -0
  76. data/lib/matestack/ui/vue_js_component.rb +1 -0
  77. metadata +150 -0
@@ -0,0 +1,45 @@
1
+ import matestackEventHub from '../../event_hub'
2
+ import queryParamsHelper from '../../helpers/query_params_helper'
3
+ import componentHelpers from '../helpers'
4
+
5
+ import formMixin from '../form/form'
6
+
7
+ const componentDef = {
8
+ mixins: [formMixin],
9
+ template: componentHelpers.inlineTemplate,
10
+ methods: {
11
+ perform: function(){
12
+ var url;
13
+ var filter = this.data
14
+ for (var key in this.data) {
15
+ if(this.data[key] != null){
16
+ url = queryParamsHelper.updateQueryParams(this.props["id"] + "-filter-" + key, JSON.stringify(this.data[key]), url)
17
+ }
18
+ }
19
+ url = queryParamsHelper.updateQueryParams(this.props["id"] + "-offset", 0, url)
20
+ window.history.pushState({matestackApp: true, url: url}, null, url);
21
+ matestackEventHub.$emit(this.props["id"] + "-update")
22
+ },
23
+ resetFilter: function(){
24
+ var url;
25
+ for (var key in this.data) {
26
+ url = queryParamsHelper.updateQueryParams(this.props["id"] + "-filter-" + key, null, url)
27
+ this.data[key] = null;
28
+ }
29
+ this.initValues();
30
+ window.history.pushState({matestackApp: true, url: url}, null, url);
31
+ matestackEventHub.$emit(this.props["id"] + "-update")
32
+ }
33
+ },
34
+ created: function(){
35
+ var self = this;
36
+ var queryParamsObject = queryParamsHelper.queryParamsToObject()
37
+ Object.keys(queryParamsObject).forEach(function(key){
38
+ if (key.startsWith(self.props["id"] + "-filter-")){
39
+ self.data[key.replace(self.props["id"] + "-filter-", "")] = JSON.parse(queryParamsObject[key])
40
+ }
41
+ })
42
+ }
43
+ }
44
+
45
+ export default componentDef
@@ -0,0 +1,29 @@
1
+ module Matestack
2
+ module Ui
3
+ module VueJs
4
+ module Components
5
+ module Collection
6
+
7
+ class Filter < Matestack::Ui::VueJs::Components::Form::Form
8
+ vue_name 'matestack-ui-core-collection-filter'
9
+
10
+ required :id
11
+ required :filter_state
12
+
13
+ def vue_props
14
+ super.merge({
15
+ id: ctx.id
16
+ })
17
+ end
18
+
19
+ def for_option
20
+ OpenStruct.new(ctx.filter_state)
21
+ end
22
+
23
+ end
24
+
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,19 @@
1
+ module Matestack
2
+ module Ui
3
+ module VueJs
4
+ module Components
5
+ module Collection
6
+ class FilterReset < Matestack::Ui::Component
7
+
8
+ def response
9
+ a 'v-on:click': 'vc.resetFilter()' do
10
+ yield
11
+ end
12
+ end
13
+
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,128 @@
1
+ module Matestack::Ui::VueJs::Components::Collection
2
+ module Helper
3
+
4
+ def get_collection_filter collection_id, key=nil
5
+ filter_hash = {}
6
+ controller_params.each do |param_key, param_value|
7
+ if param_key.start_with?("#{collection_id}-filter-")
8
+ param_key.gsub("#{collection_id}-filter-", "")
9
+ filter_hash[param_key.gsub("#{collection_id}-filter-", "").to_sym] = JSON.parse(param_value)
10
+ end
11
+ end
12
+ if key.nil?
13
+ return filter_hash
14
+ else
15
+ return filter_hash[key]
16
+ end
17
+ end
18
+
19
+ def get_collection_order collection_id, key=nil
20
+ order_hash = {}
21
+ controller_params.each do |param_key, param_value|
22
+ if param_key.start_with?("#{collection_id}-order-")
23
+ param_key.gsub("#{collection_id}-order-", "")
24
+ order_hash[param_key.gsub("#{collection_id}-order-", "").to_sym] = param_value
25
+ end
26
+ end
27
+ if key.nil?
28
+ return order_hash
29
+ else
30
+ return order_hash[key]
31
+ end
32
+ end
33
+
34
+ # since ruby 3 changed hash <-> keyword argument transformation, we need to
35
+ # adjust this method call in order to stay compatible with ruby 2.x and ruby 3.x
36
+ def set_collection options_hash
37
+ _set_collection **options_hash
38
+ end
39
+
40
+ def _set_collection id: nil, init_offset: 0, init_limit: nil, base_count: nil, filtered_count: nil, data: nil
41
+ @collections = {} if @collections.nil?
42
+
43
+ collection_config = CollectionConfig.new(
44
+ id,
45
+ init_offset,
46
+ init_limit,
47
+ filtered_count,
48
+ base_count,
49
+ data,
50
+ controller_params,
51
+ get_collection_filter(id)
52
+ )
53
+
54
+ @collections[id.to_sym] = collection_config
55
+
56
+ return collection_config
57
+ end
58
+
59
+ def controller_params
60
+ return params.to_unsafe_h if defined? params
61
+ raise 'collection component is missing access to params or context'
62
+ end
63
+
64
+ end
65
+
66
+ CollectionConfig = Struct.new(:id, :init_offset, :init_limit, :filtered_count, :base_count, :data, :params, :filter_state) do
67
+
68
+ def paginated_data
69
+ resulting_data = data
70
+ resulting_data = resulting_data.offset(get_collection_offset) unless get_collection_offset == 0
71
+ resulting_data = resulting_data.limit(get_collection_limit) unless get_collection_limit == 0
72
+
73
+ return resulting_data
74
+ end
75
+
76
+ def get_collection_offset
77
+ (params["#{id}-offset".to_sym] ||= init_offset).to_i
78
+ end
79
+
80
+ def get_collection_limit
81
+ (params["#{id}-limit".to_sym] ||= init_limit).to_i
82
+ end
83
+
84
+ def pages
85
+ offset = get_collection_offset
86
+ limit = get_collection_limit
87
+ if filtered_count.present?
88
+ count = filtered_count
89
+ else
90
+ count = base_count
91
+ end
92
+ page_count = count/limit
93
+ page_count += 1 if count%limit > 0
94
+ return (1..page_count).to_a
95
+ end
96
+
97
+ def from
98
+ return get_collection_offset + 1 if to > 0
99
+ return 0 if to == 0
100
+ end
101
+
102
+ def to
103
+ current_to = get_collection_offset + get_collection_limit
104
+ if filtered_count.present?
105
+ if current_to > filtered_count
106
+ return filtered_count
107
+ else
108
+ return current_to
109
+ end
110
+ else
111
+ if current_to > base_count
112
+ return base_count
113
+ else
114
+ return current_to
115
+ end
116
+ end
117
+ end
118
+
119
+ def filter_state
120
+
121
+ end
122
+
123
+ def config
124
+ self.to_h.except(:context)
125
+ end
126
+
127
+ end
128
+ end
@@ -0,0 +1,19 @@
1
+ module Matestack
2
+ module Ui
3
+ module VueJs
4
+ module Components
5
+ module Collection
6
+ class Next < Matestack::Ui::Component
7
+
8
+ def response
9
+ a options.merge('v-on:click': 'vc.next()') do
10
+ yield
11
+ end
12
+ end
13
+
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,45 @@
1
+ import matestackEventHub from '../../event_hub'
2
+ import queryParamsHelper from '../../helpers/query_params_helper'
3
+ import componentMixin from '../mixin'
4
+ import componentHelpers from '../helpers'
5
+
6
+ const componentDef = {
7
+ mixins: [componentMixin],
8
+ template: componentHelpers.inlineTemplate,
9
+ data: function(){
10
+ return {
11
+ ordering: {}
12
+ }
13
+ },
14
+ methods: {
15
+ toggleOrder: function(key){
16
+ if (this.ordering[key] == undefined) {
17
+ this.ordering[key] = "asc"
18
+ } else if (this.ordering[key] == "asc") {
19
+ this.ordering[key] = "desc"
20
+ } else if (this.ordering[key] == "desc") {
21
+ this.ordering[key] = undefined
22
+ }
23
+ var url;
24
+ url = queryParamsHelper.updateQueryParams(this.props["id"] + "-order-" + key, this.ordering[key])
25
+ url = queryParamsHelper.updateQueryParams(this.props["id"] + "-offset", 0, url)
26
+ window.history.pushState({matestackApp: true, url: url}, null, url);
27
+ matestackEventHub.$emit(this.props["id"] + "-update")
28
+ this.$forceUpdate()
29
+ },
30
+ orderIndicator(key, indicators){
31
+ return indicators[this.ordering[key]]
32
+ }
33
+ },
34
+ created: function(){
35
+ var self = this;
36
+ var queryParamsObject = queryParamsHelper.queryParamsToObject()
37
+ Object.keys(queryParamsObject).forEach(function(key){
38
+ if (key.startsWith(self.props["id"] + "-order-")){
39
+ self.ordering[key.replace(self.props["id"] + "-order-", "")] = queryParamsObject[key]
40
+ }
41
+ })
42
+ }
43
+ }
44
+
45
+ export default componentDef
@@ -0,0 +1,28 @@
1
+ module Matestack
2
+ module Ui
3
+ module VueJs
4
+ module Components
5
+ module Collection
6
+ class Order < Matestack::Ui::VueJs::Vue
7
+ vue_name 'matestack-ui-core-collection-order'
8
+
9
+ required :id
10
+
11
+ def response
12
+ div do
13
+ yield
14
+ end
15
+ end
16
+
17
+ def vue_props
18
+ {
19
+ id: ctx.id
20
+ }
21
+ end
22
+
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,21 @@
1
+ module Matestack
2
+ module Ui
3
+ module VueJs
4
+ module Components
5
+ module Collection
6
+ class OrderToggle < Matestack::Ui::Component
7
+
8
+ required :key
9
+
10
+ def response
11
+ a 'v-on:click': "vc.toggleOrder(\"#{ctx.key}\")" do
12
+ yield
13
+ end
14
+ end
15
+
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,30 @@
1
+ module Matestack
2
+ module Ui
3
+ module VueJs
4
+ module Components
5
+ module Collection
6
+ class OrderToggleIndicator < Matestack::Ui::Component
7
+
8
+ required :key, :asc, :desc
9
+ optional :default
10
+
11
+ def response
12
+ span do
13
+ span "v-if": "vc.ordering['#{ctx.key}'] === undefined" do
14
+ plain ctx.default
15
+ end
16
+ unescaped "{{
17
+ vc.orderIndicator(
18
+ '#{ctx.key}',
19
+ { asc: '#{ctx.asc}', desc: '#{ctx.desc}'}
20
+ )
21
+ }}"
22
+ end
23
+ end
24
+
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,21 @@
1
+ module Matestack
2
+ module Ui
3
+ module VueJs
4
+ module Components
5
+ module Collection
6
+ class Page < Matestack::Ui::Component
7
+
8
+ required :page
9
+
10
+ def response
11
+ a options.merge('v-on:click': "vc.goToPage(#{ctx.page})") do
12
+ yield
13
+ end
14
+ end
15
+
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,19 @@
1
+ module Matestack
2
+ module Ui
3
+ module VueJs
4
+ module Components
5
+ module Collection
6
+ class Previous < Matestack::Ui::Component
7
+
8
+ def response
9
+ a options.merge('v-on:click': 'vc.previous()') do
10
+ yield
11
+ end
12
+ end
13
+
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,179 @@
1
+ module Matestack
2
+ module Ui
3
+ module VueJs
4
+ module Components
5
+ module Form
6
+ class Base < Matestack::Ui::VueJs::Vue
7
+
8
+ optional :key, :type, :label, :init, :errors, :id, :multiple, :placeholder
9
+
10
+ def form_context
11
+ Matestack::Ui::VueJs::Components::Form::Context.form_context
12
+ end
13
+
14
+ def component_attributes
15
+ super.merge("matestack-ui-core-ref": "#{form_context.component_uid}-#{component_id}")
16
+ end
17
+
18
+ def component_id
19
+ # defined in subclass
20
+ end
21
+
22
+ # options/settings
23
+
24
+ def key
25
+ ctx.key
26
+ end
27
+
28
+ def type
29
+ ctx.type
30
+ end
31
+
32
+ def input_label
33
+ ctx.label
34
+ end
35
+
36
+ def init
37
+ ctx.init
38
+ end
39
+
40
+ def error_config
41
+ ctx.errors
42
+ end
43
+
44
+ def id
45
+ if ctx.id.present?
46
+ "'#{ctx.id}'"
47
+ else
48
+ "'#{key}'+vc.parentNestedFormRuntimeId"
49
+ end
50
+ end
51
+
52
+ def multiple
53
+ ctx.multiple
54
+ end
55
+
56
+ def placeholder
57
+ ctx.placeholder
58
+ end
59
+
60
+ # calculated attributes
61
+
62
+ def attributes
63
+ (options || {}).merge({
64
+ "matestack-ui-core-ref": scoped_ref("input.#{attribute_key}"),
65
+ ":id": id,
66
+ type: ctx.type,
67
+ multiple: ctx.multiple,
68
+ placeholder: ctx.placeholder,
69
+ 'v-on:change': change_event,
70
+ 'init-value': init_value,
71
+ 'v-bind:class': "{ '#{input_error_class}': #{error_key} }",
72
+ }).tap do |attrs|
73
+ attrs[:"#{v_model_type}"] = input_key unless type == :file
74
+ end
75
+ end
76
+
77
+ def attribute_key
78
+ key.to_s + "#{'[]' if ctx.multiple && ctx.type == :file}"
79
+ end
80
+
81
+ def name
82
+ attribute_key
83
+ end
84
+
85
+ def init_value
86
+ return init unless init.nil?
87
+ if form_context.for_option.respond_to?(key)
88
+ form_context.for_option.send(key)
89
+ end
90
+ end
91
+
92
+ def change_event
93
+ input_changed = "vc.inputChanged('#{attribute_key}');"
94
+ input_changed << "vc.filesAdded('#{attribute_key}');" if type == :file
95
+ input_changed
96
+ end
97
+
98
+ def input_key
99
+ "vc.parentFormData['#{key}']"
100
+ end
101
+
102
+ # set v-model.number for all numeric init values or options
103
+ def v_model_type(item=nil)
104
+ if item.nil?
105
+ (type == :number || init_value.is_a?(Numeric)) ? 'v-model.number' : 'v-model'
106
+ else
107
+ item.is_a?(Integer) ? 'v-model.number' : 'v-model'
108
+ end
109
+ end
110
+
111
+ # set value-type "Integer" for all numeric init values or options
112
+ def value_type(item=nil)
113
+ if item.nil?
114
+ (type == :number || init_value.is_a?(Numeric)) ? Integer : nil
115
+ else
116
+ item.is_a?(Integer)? Integer : nil
117
+ end
118
+ end
119
+
120
+ # error rendering
121
+
122
+ def display_errors?
123
+ if form_context.ctx.errors == false
124
+ error_config ? true : false
125
+ else
126
+ error_config != false
127
+ end
128
+ end
129
+
130
+ def error_key
131
+ "vc.parentFormErrors['#{key}']"
132
+ end
133
+
134
+ def error_class
135
+ get_from_error_config(:class) || 'error'
136
+ end
137
+
138
+ def error_tag
139
+ get_from_error_config(:tag) || :div
140
+ # error_config.is_a?(Hash) && error_config.dig(:tag) || :div
141
+ end
142
+
143
+ def input_error_class
144
+ get_from_error_config(:input, :class) || 'error'
145
+ # error_config.is_a?(Hash) && error_config.dig(:input, :class) || 'error'
146
+ end
147
+
148
+ def wrapper_tag
149
+ get_from_error_config(:wrapper, :tag) || :div
150
+ # error_config.is_a?(Hash) && error_config.dig(:wrapper, :tag) || :div
151
+ end
152
+
153
+ def wrapper_error_class
154
+ get_from_error_config(:wrapper, :class) || 'errors'
155
+ # error_config.is_a?(Hash) && error_config.dig(:wrapper, :class) || 'errors'
156
+ end
157
+
158
+ def get_from_error_config(*keys)
159
+ comp_error_config = error_config.dig(*keys) if error_config.is_a?(Hash)
160
+ form_error_config = form_context.ctx.errors.dig(*keys) if form_context.ctx.errors.is_a?(Hash)
161
+ comp_error_config || form_error_config
162
+ end
163
+
164
+ def render_errors
165
+ if display_errors?
166
+ Matestack::Ui::Component.new(wrapper_tag, class: wrapper_error_class, 'v-if': error_key) do
167
+ Matestack::Ui::Component.new(error_tag, class: error_class, 'v-for': "error in #{error_key}") do
168
+ plain vue.error
169
+ end
170
+ end
171
+ end
172
+ end
173
+
174
+ end
175
+ end
176
+ end
177
+ end
178
+ end
179
+ end
@@ -0,0 +1,13 @@
1
+ import formCheckboxMixin from "./checkbox_mixin";
2
+ import componentMixin from "../mixin";
3
+ import componentHelpers from "../helpers";
4
+
5
+ const componentDef = {
6
+ mixins: [componentMixin, formCheckboxMixin],
7
+ template: componentHelpers.inlineTemplate,
8
+ data() {
9
+ return {};
10
+ }
11
+ }
12
+
13
+ export default componentDef;