matestack-ui-core 1.0.1 → 1.3.2

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 (57) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +782 -16
  3. data/app/concepts/matestack/ui/core/async/async.js +6 -28
  4. data/app/concepts/matestack/ui/core/async/async.rb +7 -10
  5. data/app/concepts/matestack/ui/core/cable/cable.haml +4 -0
  6. data/app/concepts/matestack/ui/core/cable/cable.js +100 -0
  7. data/app/concepts/matestack/ui/core/cable/cable.rb +28 -0
  8. data/app/concepts/matestack/ui/core/cable/children_wrapper.haml +2 -0
  9. data/app/concepts/matestack/ui/core/collection/content/content.js +2 -2
  10. data/app/concepts/matestack/ui/core/collection/content/content.rb +1 -1
  11. data/app/concepts/matestack/ui/core/component/base.rb +10 -4
  12. data/app/concepts/matestack/ui/core/component/component.js +18 -1
  13. data/app/concepts/matestack/ui/core/component/dynamic.rb +1 -1
  14. data/app/concepts/matestack/ui/core/form/checkbox/base.rb +120 -0
  15. data/app/concepts/matestack/ui/core/form/checkbox/checkbox.js +15 -0
  16. data/app/concepts/matestack/ui/core/form/checkbox/checkbox.rb +7 -70
  17. data/app/concepts/matestack/ui/core/form/checkbox/mixin.js +80 -0
  18. data/app/concepts/matestack/ui/core/form/form.js +15 -46
  19. data/app/concepts/matestack/ui/core/form/input/base.rb +75 -0
  20. data/app/concepts/matestack/ui/core/form/input/input.js +15 -0
  21. data/app/concepts/matestack/ui/core/form/input/input.rb +8 -52
  22. data/app/concepts/matestack/ui/core/form/input/mixin.js +55 -0
  23. data/app/concepts/matestack/ui/core/form/radio/base.rb +90 -0
  24. data/app/concepts/matestack/ui/core/form/radio/mixin.js +62 -0
  25. data/app/concepts/matestack/ui/core/form/radio/radio.js +15 -0
  26. data/app/concepts/matestack/ui/core/form/radio/radio.rb +7 -62
  27. data/app/concepts/matestack/ui/core/form/select/base.rb +98 -0
  28. data/app/concepts/matestack/ui/core/form/select/mixin.js +58 -0
  29. data/app/concepts/matestack/ui/core/form/select/select.js +15 -0
  30. data/app/concepts/matestack/ui/core/form/select/select.rb +11 -60
  31. data/app/concepts/matestack/ui/core/form/submit/base.rb +12 -0
  32. data/app/concepts/matestack/ui/core/form/submit/submit.js +19 -0
  33. data/app/concepts/matestack/ui/core/form/submit/submit.rb +9 -6
  34. data/app/concepts/matestack/ui/core/form/textarea/base.rb +49 -0
  35. data/app/concepts/matestack/ui/core/form/textarea/mixin.js +41 -0
  36. data/app/concepts/matestack/ui/core/form/textarea/textarea.js +15 -0
  37. data/app/concepts/matestack/ui/core/form/textarea/textarea.rb +10 -21
  38. data/app/concepts/matestack/ui/core/js/core.js +12 -0
  39. data/app/concepts/matestack/ui/core/{form/submit/submit.haml → select/select.haml} +1 -1
  40. data/app/concepts/matestack/ui/core/select/select.rb +7 -0
  41. data/app/helpers/matestack/ui/core/application_helper.rb +6 -3
  42. data/app/javascript/matestack-ui-core/index.js +12 -2
  43. data/app/lib/matestack/ui/core/has_view_context.rb +4 -2
  44. data/app/lib/matestack/ui/core/rendering/main_renderer.rb +4 -1
  45. data/lib/matestack/ui/core/components.rb +4 -1
  46. data/lib/matestack/ui/core/version.rb +1 -1
  47. data/vendor/assets/javascripts/dist/matestack-ui-core.js +768 -98
  48. data/vendor/assets/javascripts/dist/matestack-ui-core.js.map +1 -1
  49. data/vendor/assets/javascripts/dist/matestack-ui-core.min.js +1 -1
  50. data/vendor/assets/javascripts/dist/matestack-ui-core.min.js.br +0 -0
  51. data/vendor/assets/javascripts/dist/matestack-ui-core.min.js.gz +0 -0
  52. data/vendor/assets/javascripts/dist/matestack-ui-core.min.js.map +1 -1
  53. data/vendor/assets/javascripts/dist/matestack-ui-core.min.js.map.br +0 -0
  54. data/vendor/assets/javascripts/dist/matestack-ui-core.min.js.map.gz +0 -0
  55. metadata +25 -7
  56. data/app/concepts/matestack/ui/core/component/rerender.rb +0 -8
  57. data/app/concepts/matestack/ui/core/form/select/select.haml +0 -9
@@ -0,0 +1,15 @@
1
+ import Vue from "vue/dist/vue.esm";
2
+
3
+ import formCheckboxMixin from "./mixin";
4
+ import componentMixin from "../../component/component";
5
+
6
+ const componentDef = {
7
+ mixins: [componentMixin, formCheckboxMixin],
8
+ data() {
9
+ return {};
10
+ }
11
+ }
12
+
13
+ let component = Vue.component("matestack-ui-core-form-checkbox", componentDef);
14
+
15
+ export default componentDef;
@@ -1,79 +1,16 @@
1
- require_relative '../utils'
2
- require_relative '../has_input_html_attributes'
3
- require_relative '../has_errors'
1
+ require_relative './base'
2
+
4
3
  module Matestack::Ui::Core::Form::Checkbox
5
- class Checkbox < Matestack::Ui::Core::Component::Static
6
- include Matestack::Ui::Core::Form::Utils
7
- include Matestack::Ui::Core::Form::HasInputHtmlAttributes
8
- include Matestack::Ui::Core::Form::HasErrors
4
+ class Checkbox < Base
9
5
 
10
- requires :key
11
- optional :value, :false_value, :multiple, :init, for: { as: :input_for }, label: { as: :input_label }, options: { as: :checkbox_options }
6
+ vue_js_component_name "matestack-ui-core-form-checkbox"
12
7
 
13
8
  def response
14
- # multiple values
15
- if checkbox_options
16
- checkbox_options.to_a.each do |item|
17
- input html_attributes.merge(
18
- attributes: vue_attributes,
19
- type: :checkbox,
20
- id: "#{id_for_item(item_value(item))}",
21
- name: item_name(item),
22
- value: item_value(item)
23
- )
24
- label text: item_name(item), for: id_for_item(item_value(item))
25
- end
26
- # checked/unchecked checkbox
27
- else
28
- form_input type: :hidden, key: key, value: (false_value || 0), errors: false
29
- form_input type: :checkbox, key: key, value: checked_value, id: id_for_item(value), errors: false
30
- label text: input_label, for: id_for_item(value)
31
- end
32
- render_errors
33
- end
34
-
35
- def vue_attributes
36
- (options[:attributes] || {}).merge({
37
- "@change": change_event,
38
- ref: "select.multiple.#{attr_key}",
39
- 'init-value': init_value,
40
- 'v-bind:class': "{ '#{input_error_class}': #{error_key} }",
41
- 'value-type': value_type,
42
- "#{v_model_type}": input_key,
43
- })
44
- end
45
-
46
- def value_type
47
- item_value(checkbox_options.first).is_a?(Integer) ? Integer : nil
48
- end
49
-
50
- def item_value(item)
51
- item.is_a?(Array) ? item.last : item
52
- end
53
-
54
- def item_name(item)
55
- item.is_a?(Array) ? item.first : item
56
- end
57
-
58
- def checked_value
59
- value || 1
60
- end
61
-
62
- def v_model_type
63
- if checkbox_options && checkbox_options.first.is_a?(Integer)
64
- 'v-model.number'
65
- else
66
- 'v-model'
9
+ div class: "matestack-ui-core-form-checkbox" do
10
+ render_options
11
+ render_errors
67
12
  end
68
13
  end
69
14
 
70
- def change_event
71
- "inputChanged('#{attr_key}')"
72
- end
73
-
74
- def id_for_item(value)
75
- "#{html_attributes[:id]}_#{value}"
76
- end
77
-
78
15
  end
79
16
  end
@@ -0,0 +1,80 @@
1
+ const formCheckboxMixin = {
2
+ methods: {
3
+ initialize: function(){
4
+ const self = this
5
+ let data = {};
6
+
7
+ for (let key in self.$refs) {
8
+ let initValue = self.$refs[key]["attributes"]["init-value"];
9
+ let valueType = self.$refs[key]["attributes"]["value-type"];
10
+
11
+ if (key.startsWith("select.")) {
12
+ if (key.startsWith("select.multiple.")) {
13
+ if (initValue) {
14
+ data[key.replace("select.multiple.", "")] = JSON.parse(initValue["value"]);
15
+ Object.assign(self.$parent.data, data);
16
+ self.afterInitialize(JSON.parse(initValue["value"]))
17
+ } else {
18
+ data[key.replace("select.multiple.", "")] = [];
19
+ Object.assign(self.$parent.data, data);
20
+ self.afterInitialize([])
21
+ }
22
+ } else {
23
+ if (initValue) {
24
+ if (valueType && valueType["value"] == "Integer") {
25
+ data[key.replace("select.", "")] = parseInt(initValue["value"]);
26
+ Object.assign(self.$parent.data, data);
27
+ self.afterInitialize(parseInt(initValue["value"]))
28
+ } else {
29
+
30
+ data[key.replace("select.", "")] = initValue["value"];
31
+ Object.assign(self.$parent.data, data);
32
+ self.afterInitialize(initValue["value"])
33
+ }
34
+ } else {
35
+ data[key.replace("select.", "")] = null;
36
+ Object.assign(self.$parent.data, data);
37
+ self.afterInitialize(null)
38
+ }
39
+ }
40
+ } else {
41
+ if (initValue) {
42
+ if(initValue["value"] === "true"){
43
+ data[key.replace("input.", "")] = true;
44
+ Object.assign(self.$parent.data, data);
45
+ self.afterInitialize(true)
46
+ }
47
+ if(initValue["value"] === "false"){
48
+ data[key.replace("input.", "")] = false;
49
+ Object.assign(self.$parent.data, data);
50
+ self.afterInitialize(false)
51
+ }
52
+ } else {
53
+ data[key.replace("input.", "")] = null;
54
+ Object.assign(self.$parent.data, data);
55
+ self.afterInitialize(null)
56
+ }
57
+ }
58
+ }
59
+
60
+ //without the timeout it's somehow not working
61
+ setTimeout(function () {
62
+ self.$forceUpdate()
63
+ }, 1);
64
+ },
65
+ inputChanged: function (key) {
66
+ this.$parent.resetErrors(key);
67
+ this.$forceUpdate();
68
+ },
69
+ afterInitialize: function(value){
70
+ // can be used in the main component for further initialization steps
71
+ },
72
+ setValue: function (value){
73
+ this.$parent.data[this.componentConfig["key"]] = value
74
+ this.$forceUpdate();
75
+ }
76
+ }
77
+
78
+ }
79
+
80
+ export default formCheckboxMixin
@@ -18,9 +18,6 @@ const componentDef = {
18
18
  initDataKey: function (key, initValue) {
19
19
  this.data[key] = initValue;
20
20
  },
21
- inputChanged: function (key) {
22
- this.resetErrors(key);
23
- },
24
21
  updateFormValue: function (key, value) {
25
22
  this.data[key] = value;
26
23
  },
@@ -44,11 +41,11 @@ const componentDef = {
44
41
  flat[i] = newVal;
45
42
  } else if (flat[i] instanceof File){
46
43
  flat[i] = newVal;
47
- this.$refs["input."+i].value = newVal
44
+ this.$refs["input-component-for-"+i].value = newVal
48
45
  } else if (flat[i] instanceof Array) {
49
46
  if(flat[i][0] instanceof File){
50
47
  flat[i] = newVal
51
- this.$refs["input."+i].value = newVal
48
+ this.$refs["input-component-for-"+i].value = newVal
52
49
  }
53
50
  } else if (typeof flat[i] === "object" && !(flat[i] instanceof Array)) {
54
51
  setProps(flat[i], newVal);
@@ -57,54 +54,26 @@ const componentDef = {
57
54
  }
58
55
  }
59
56
  },
60
- filesAdded: function (key) {
61
- const dataTransfer = event.dataTransfer || event.target;
62
- const files = dataTransfer.files;
63
- if (event.target.attributes.multiple) {
64
- this.data[key] = [];
65
- for (let index in files) {
66
- if (files[index] instanceof File) {
67
- this.data[key].push(files[index]);
68
- }
69
- }
70
- } else {
71
- this.data[key] = files[0];
72
- }
73
- },
74
57
  initValues: function () {
75
58
  let self = this;
76
59
  let data = {};
77
60
  for (let key in self.$refs) {
78
- let initValue = self.$refs[key]["attributes"]["init-value"];
79
- let valueType = self.$refs[key]["attributes"]["value-type"];
80
-
81
- if (key.startsWith("input.")) {
82
- if (initValue) {
83
- data[key.replace("input.", "")] = initValue["value"];
84
- } else {
85
- data[key.replace("input.", "")] = null;
86
- }
61
+ if (key.startsWith("input-component")) {
62
+ self.$refs[key].initialize()
87
63
  }
88
- if (key.startsWith("select.")) {
89
- if (key.startsWith("select.multiple.")) {
90
- if (initValue) {
91
- data[key.replace("select.multiple.", "")] = JSON.parse(initValue["value"]);
92
- } else {
93
- data[key.replace("select.multiple.", "")] = [];
94
- }
95
- } else {
96
- if (initValue) {
97
- if (valueType && valueType["value"] == "Integer") data[key.replace("select.", "")] = parseInt(initValue["value"]);
98
- else {
99
- data[key.replace("select.", "")] = initValue["value"];
100
- }
101
- } else {
102
- data[key.replace("select.", "")] = null;
103
- }
104
- }
64
+ if (key.startsWith("textarea-component")) {
65
+ self.$refs[key].initialize()
66
+ }
67
+ if (key.startsWith("select-component")) {
68
+ self.$refs[key].initialize()
69
+ }
70
+ if (key.startsWith("radio-component")) {
71
+ self.$refs[key].initialize()
72
+ }
73
+ if (key.startsWith("checkbox-component")) {
74
+ self.$refs[key].initialize()
105
75
  }
106
76
  }
107
- self.data = data;
108
77
  },
109
78
  shouldResetFormOnSuccessfulSubmit() {
110
79
  const self = this;
@@ -0,0 +1,75 @@
1
+ require_relative '../utils'
2
+ require_relative '../has_input_html_attributes'
3
+ require_relative '../has_errors'
4
+ module Matestack::Ui::Core::Form::Input
5
+ class Base < Matestack::Ui::Core::Component::Dynamic
6
+ include Matestack::Ui::Core::Form::Utils
7
+ include Matestack::Ui::Core::Form::HasInputHtmlAttributes
8
+ include Matestack::Ui::Core::Form::HasErrors
9
+
10
+ requires :key, :type
11
+ optional :multiple, :init, for: { as: :input_for }, label: { as: :input_label }
12
+
13
+ def setup
14
+ @component_config[:init_value] = init_value
15
+ end
16
+
17
+ def component_id
18
+ "input-component-for-#{attr_key}"
19
+ end
20
+
21
+ def input_attributes
22
+ html_attributes.merge(attributes: vue_attributes)
23
+ end
24
+
25
+ def input_key
26
+ "$parent.data[\"#{key}\"]"
27
+ end
28
+
29
+ def error_key
30
+ "$parent.errors[\"#{key}\"]"
31
+ end
32
+
33
+ def change_event
34
+ "inputChanged('#{attr_key}'); #{ "filesAdded('#{attr_key}');" if type == :file }".strip
35
+ end
36
+
37
+ def vue_attributes
38
+ (options[:attributes] || {}).merge({
39
+ "@change": change_event,
40
+ ref: "input.#{attr_key}",
41
+ 'init-value': init_value,
42
+ 'v-bind:class': "{ '#{input_error_class}': #{error_key} }"
43
+ }).merge(
44
+ type != :file ? { "#{v_model_type}": input_key } : {}
45
+ ) # file inputs are readonly, no v-model possible
46
+ end
47
+
48
+ def v_model_type
49
+ if type == :number || init_value.is_a?(Integer)
50
+ 'v-model.number'
51
+ else
52
+ 'v-model'
53
+ end
54
+ end
55
+
56
+ def custom_options_validation
57
+ raise "included form config is missing, please add ':include' to parent form component" if @included_config.nil?
58
+ end
59
+
60
+ def attr_key
61
+ super + "#{'[]' if multiple && type == :file}"
62
+ end
63
+
64
+ private
65
+
66
+ def parse_value(value)
67
+ if [true, false].include? value
68
+ value ? 1 : 0
69
+ else
70
+ return value
71
+ end
72
+ end
73
+
74
+ end
75
+ end
@@ -0,0 +1,15 @@
1
+ import Vue from "vue/dist/vue.esm";
2
+
3
+ import formInputMixin from "./mixin";
4
+ import componentMixin from "../../component/component";
5
+
6
+ const componentDef = {
7
+ mixins: [componentMixin, formInputMixin],
8
+ data() {
9
+ return {};
10
+ }
11
+ }
12
+
13
+ let component = Vue.component("matestack-ui-core-form-input", componentDef);
14
+
15
+ export default componentDef;
@@ -1,59 +1,15 @@
1
- require_relative '../utils'
2
- require_relative '../has_input_html_attributes'
3
- require_relative '../has_errors'
1
+ require_relative './base'
2
+
4
3
  module Matestack::Ui::Core::Form::Input
5
- class Input < Matestack::Ui::Core::Component::Static
6
- include Matestack::Ui::Core::Form::Utils
7
- include Matestack::Ui::Core::Form::HasInputHtmlAttributes
8
- include Matestack::Ui::Core::Form::HasErrors
4
+ class Input < Base
9
5
 
10
- requires :key, :type
11
- optional :multiple, :init, for: { as: :input_for }, label: { as: :input_label }
6
+ vue_js_component_name "matestack-ui-core-form-input"
12
7
 
13
8
  def response
14
- label text: input_label if input_label
15
- input html_attributes.merge(attributes: vue_attributes)
16
- render_errors
17
- end
18
-
19
- def vue_attributes
20
- (options[:attributes] || {}).merge({
21
- "@change": change_event,
22
- ref: "input.#{attr_key}",
23
- 'init-value': init_value,
24
- 'v-bind:class': "{ '#{input_error_class}': #{error_key} }"
25
- }).merge(
26
- type != :file ? { "#{v_model_type}": input_key } : {}
27
- ) # file inputs are readonly, no v-model possible
28
- end
29
-
30
- def v_model_type
31
- if type == :number || init_value.is_a?(Integer)
32
- 'v-model.number'
33
- else
34
- 'v-model'
35
- end
36
- end
37
-
38
- def change_event
39
- "inputChanged('#{attr_key}'); #{ "filesAdded('#{attr_key}');" if type == :file }".strip
40
- end
41
-
42
- def custom_options_validation
43
- raise "included form config is missing, please add ':include' to parent form component" if @included_config.nil?
44
- end
45
-
46
- def attr_key
47
- super + "#{'[]' if multiple && type == :file}"
48
- end
49
-
50
- private
51
-
52
- def parse_value(value)
53
- if [true, false].include? value
54
- value ? 1 : 0
55
- else
56
- return value
9
+ div class: "matestack-ui-core-form-input" do
10
+ label text: input_label if input_label
11
+ input input_attributes
12
+ render_errors
57
13
  end
58
14
  end
59
15
 
@@ -0,0 +1,55 @@
1
+ const formInputMixin = {
2
+ methods: {
3
+ initialize: function(){
4
+ const self = this
5
+ let data = {};
6
+
7
+ for (let key in this.$refs) {
8
+ let initValue = this.$refs[key]["attributes"]["init-value"];
9
+
10
+ if (initValue) {
11
+ data[key.replace("input.", "")] = initValue["value"];
12
+ Object.assign(self.$parent.data, data);
13
+ self.afterInitialize(initValue["value"])
14
+ } else {
15
+ data[key.replace("input.", "")] = null;
16
+ Object.assign(self.$parent.data, data);
17
+ self.afterInitialize(null)
18
+ }
19
+ }
20
+
21
+ //without the timeout it's somehow not working
22
+ setTimeout(function () {
23
+ self.$forceUpdate()
24
+ }, 1);
25
+ },
26
+ filesAdded: function (key) {
27
+ const dataTransfer = event.dataTransfer || event.target;
28
+ const files = dataTransfer.files;
29
+ if (event.target.attributes.multiple) {
30
+ this.$parent.data[key] = [];
31
+ for (let index in files) {
32
+ if (files[index] instanceof File) {
33
+ this.$parent.data[key].push(files[index]);
34
+ }
35
+ }
36
+ } else {
37
+ this.$parent.data[key] = files[0];
38
+ }
39
+ },
40
+ inputChanged: function (key) {
41
+ this.$parent.resetErrors(key);
42
+ this.$forceUpdate();
43
+ },
44
+ afterInitialize: function(value){
45
+ // can be used in the main component for further initialization steps
46
+ },
47
+ setValue: function (value){
48
+ this.$parent.data[this.componentConfig["key"]] = value
49
+ this.$forceUpdate();
50
+ }
51
+ }
52
+
53
+ }
54
+
55
+ export default formInputMixin