glib-web 0.5.71 → 0.5.72

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 (185) hide show
  1. checksums.yaml +4 -4
  2. data/app/channels/glib/channel/is_typing_channel.rb +34 -34
  3. data/app/channels/glib/channel/online_channel.rb +36 -36
  4. data/app/controllers/concerns/glib/analytics/funnel.rb +61 -61
  5. data/app/controllers/concerns/glib/auth/policy.rb +148 -148
  6. data/app/controllers/concerns/glib/json/dynamic_text.rb +126 -126
  7. data/app/controllers/concerns/glib/json/libs.rb +149 -149
  8. data/app/controllers/concerns/glib/json/new_dynamic_text.rb +122 -122
  9. data/app/controllers/concerns/glib/json/transformation.rb +11 -11
  10. data/app/controllers/concerns/glib/json/traversal.rb +92 -92
  11. data/app/controllers/concerns/glib/json/ui.rb +88 -88
  12. data/app/controllers/concerns/glib/json/validation.rb +13 -13
  13. data/app/controllers/glib/home_controller.rb +54 -54
  14. data/app/helpers/glib/app_feature_support_helper.rb +16 -16
  15. data/app/helpers/glib/dynamic_images_helper.rb +55 -55
  16. data/app/helpers/glib/dynamic_texts_helper.rb +42 -42
  17. data/app/helpers/glib/enum_helper.rb +18 -8
  18. data/app/helpers/glib/forms_helper.rb +15 -15
  19. data/app/helpers/glib/json_ui/abstract_builder.rb +309 -309
  20. data/app/helpers/glib/json_ui/action_builder.rb +140 -140
  21. data/app/helpers/glib/json_ui/action_builder/dialogs.rb +58 -58
  22. data/app/helpers/glib/json_ui/action_builder/http.rb +39 -39
  23. data/app/helpers/glib/json_ui/action_builder/panels.rb +14 -14
  24. data/app/helpers/glib/json_ui/action_builder/sheets.rb +15 -15
  25. data/app/helpers/glib/json_ui/action_builder/snackbars.rb +41 -41
  26. data/app/helpers/glib/json_ui/action_builder/windows.rb +33 -33
  27. data/app/helpers/glib/json_ui/analytics_helper.rb +17 -17
  28. data/app/helpers/glib/json_ui/dynamic_field_builders.rb +25 -25
  29. data/app/helpers/glib/json_ui/generic_builders.rb +28 -28
  30. data/app/helpers/glib/json_ui/list_builders.rb +110 -110
  31. data/app/helpers/glib/json_ui/menu_builder.rb +94 -94
  32. data/app/helpers/glib/json_ui/page_helper.rb +221 -221
  33. data/app/helpers/glib/json_ui/response_helper.rb +25 -25
  34. data/app/helpers/glib/json_ui/split_builders.rb +32 -32
  35. data/app/helpers/glib/json_ui/styling_helper.rb +55 -55
  36. data/app/helpers/glib/json_ui/table_builders.rb +74 -74
  37. data/app/helpers/glib/json_ui/view_builder.rb +240 -240
  38. data/app/helpers/glib/json_ui/view_builder/banners.rb +26 -26
  39. data/app/helpers/glib/json_ui/view_builder/charts.rb +33 -33
  40. data/app/helpers/glib/json_ui/view_builder/fields.rb +278 -279
  41. data/app/helpers/glib/json_ui/view_builder/panels.rb +256 -256
  42. data/app/helpers/glib/urls_helper.rb +12 -12
  43. data/app/models/glib/active_storage/attachment.rb +9 -9
  44. data/app/models/glib/active_storage/blob.rb +9 -9
  45. data/app/models/glib/application_record.rb +18 -18
  46. data/app/models/glib/dynamic_text_record.rb +9 -9
  47. data/app/models/glib/text.rb +95 -95
  48. data/app/policies/glib/application_policy.rb +161 -161
  49. data/app/validators/email_typo_validator.rb +38 -38
  50. data/app/validators/email_validator.rb +7 -7
  51. data/app/validators/url_validator.rb +20 -20
  52. data/app/views/json_ui/garage/_nav_menu.json.jbuilder +70 -70
  53. data/app/views/json_ui/garage/actions/_dialogs.json.jbuilder +104 -104
  54. data/app/views/json_ui/garage/actions/_http.json.jbuilder +24 -24
  55. data/app/views/json_ui/garage/actions/_panels.json.jbuilder +18 -18
  56. data/app/views/json_ui/garage/actions/_reload.json.jbuilder +17 -17
  57. data/app/views/json_ui/garage/actions/_sheets.json.jbuilder +18 -18
  58. data/app/views/json_ui/garage/actions/_snackbars.json.jbuilder +33 -33
  59. data/app/views/json_ui/garage/actions/_timeouts.json.jbuilder +24 -24
  60. data/app/views/json_ui/garage/actions/_windows.json.jbuilder +24 -24
  61. data/app/views/json_ui/garage/actions/dialogs_oauth_post.json.jbuilder +6 -6
  62. data/app/views/json_ui/garage/actions/index.json.jbuilder +24 -24
  63. data/app/views/json_ui/garage/forms/_alert_post_data.json.jbuilder +6 -6
  64. data/app/views/json_ui/garage/forms/basic.json.jbuilder +21 -21
  65. data/app/views/json_ui/garage/forms/basic_post.json.jbuilder +8 -8
  66. data/app/views/json_ui/garage/forms/checkboxes.json.jbuilder +43 -43
  67. data/app/views/json_ui/garage/forms/conditional_value.json.jbuilder +36 -36
  68. data/app/views/json_ui/garage/forms/dynamic_group.json.jbuilder +39 -39
  69. data/app/views/json_ui/garage/forms/dynamic_select.json.jbuilder +24 -22
  70. data/app/views/json_ui/garage/forms/dynamic_select_data.json.jbuilder +38 -38
  71. data/app/views/json_ui/garage/forms/file_upload.json.jbuilder +32 -37
  72. data/app/views/json_ui/garage/forms/floating_submit.json.jbuilder +19 -19
  73. data/app/views/json_ui/garage/forms/generic_post.json.jbuilder +3 -3
  74. data/app/views/json_ui/garage/forms/get_request.json.jbuilder +27 -27
  75. data/app/views/json_ui/garage/forms/index.json.jbuilder +113 -113
  76. data/app/views/json_ui/garage/forms/new_rich_text.json.jbuilder +39 -39
  77. data/app/views/json_ui/garage/forms/online_participant1.json.jbuilder +25 -25
  78. data/app/views/json_ui/garage/forms/online_participant2.json.jbuilder +25 -25
  79. data/app/views/json_ui/garage/forms/pickers.json.jbuilder +81 -81
  80. data/app/views/json_ui/garage/forms/ratings.json.jbuilder +49 -49
  81. data/app/views/json_ui/garage/forms/rich_text.json.jbuilder +40 -40
  82. data/app/views/json_ui/garage/forms/selects.json.jbuilder +91 -84
  83. data/app/views/json_ui/garage/forms/show_hide.json.jbuilder +130 -130
  84. data/app/views/json_ui/garage/forms/styled_boxes.json.jbuilder +35 -35
  85. data/app/views/json_ui/garage/forms/submission_flow.json.jbuilder +17 -17
  86. data/app/views/json_ui/garage/forms/submission_flow_post.json.jbuilder +26 -26
  87. data/app/views/json_ui/garage/forms/submission_indicator.json.jbuilder +63 -63
  88. data/app/views/json_ui/garage/forms/submission_indicator_post.json.jbuilder +25 -25
  89. data/app/views/json_ui/garage/forms/text_validation.json.jbuilder +81 -81
  90. data/app/views/json_ui/garage/forms/timers.json.jbuilder +120 -120
  91. data/app/views/json_ui/garage/home/blank.json.jbuilder +10 -10
  92. data/app/views/json_ui/garage/home/index.json.jbuilder +36 -36
  93. data/app/views/json_ui/garage/home/slow.json.jbuilder +11 -11
  94. data/app/views/json_ui/garage/lists/_autoload_section.json.jbuilder +28 -28
  95. data/app/views/json_ui/garage/lists/autoload_all.json.jbuilder +32 -32
  96. data/app/views/json_ui/garage/lists/autoload_as_needed.json.jbuilder +35 -35
  97. data/app/views/json_ui/garage/lists/chat_ui.json.jbuilder +94 -94
  98. data/app/views/json_ui/garage/lists/edit_actions.json.jbuilder +62 -62
  99. data/app/views/json_ui/garage/lists/fab.json.jbuilder +12 -12
  100. data/app/views/json_ui/garage/lists/index.json.jbuilder +38 -38
  101. data/app/views/json_ui/garage/lists/reordering.json.jbuilder +34 -34
  102. data/app/views/json_ui/garage/lists/templating.json.jbuilder +35 -35
  103. data/app/views/json_ui/garage/notifications/action_cable.json.jbuilder +114 -114
  104. data/app/views/json_ui/garage/notifications/android_post.json.jbuilder +48 -48
  105. data/app/views/json_ui/garage/notifications/index.json.jbuilder +36 -36
  106. data/app/views/json_ui/garage/notifications/web_socket.json.jbuilder +60 -60
  107. data/app/views/json_ui/garage/pages/flat_centered.json.jbuilder +29 -29
  108. data/app/views/json_ui/garage/pages/full_width.json.jbuilder +29 -29
  109. data/app/views/json_ui/garage/pages/full_width_height.json.jbuilder +16 -16
  110. data/app/views/json_ui/garage/pages/index.json.jbuilder +62 -62
  111. data/app/views/json_ui/garage/pages/layout.json.jbuilder +18 -18
  112. data/app/views/json_ui/garage/pages/lifecycle_hooks.json.jbuilder +13 -13
  113. data/app/views/json_ui/garage/pages/loading_indicator.json.jbuilder +10 -10
  114. data/app/views/json_ui/garage/pages/nav_buttons.json.jbuilder +21 -21
  115. data/app/views/json_ui/garage/pages/nested_scroll.json.jbuilder +40 -40
  116. data/app/views/json_ui/garage/pages/tab_bar.json.jbuilder +31 -31
  117. data/app/views/json_ui/garage/panels/_styled.json.jbuilder +78 -78
  118. data/app/views/json_ui/garage/panels/card.json.jbuilder +4 -4
  119. data/app/views/json_ui/garage/panels/carousel.json.jbuilder +37 -37
  120. data/app/views/json_ui/garage/panels/custom.json.jbuilder +17 -17
  121. data/app/views/json_ui/garage/panels/flow.json.jbuilder +59 -59
  122. data/app/views/json_ui/garage/panels/horizontal.json.jbuilder +91 -91
  123. data/app/views/json_ui/garage/panels/index.json.jbuilder +138 -134
  124. data/app/views/json_ui/garage/panels/outlined.json.jbuilder +4 -4
  125. data/app/views/json_ui/garage/panels/responsive.json.jbuilder +98 -98
  126. data/app/views/json_ui/garage/panels/split.json.jbuilder +182 -182
  127. data/app/views/json_ui/garage/panels/ul.json.jbuilder +33 -0
  128. data/app/views/json_ui/garage/panels/vertical.json.jbuilder +55 -55
  129. data/app/views/json_ui/garage/panels/web.json.jbuilder +15 -15
  130. data/app/views/json_ui/garage/services/dynamic_text.json.jbuilder +13 -13
  131. data/app/views/json_ui/garage/services/image.json.jbuilder +47 -47
  132. data/app/views/json_ui/garage/services/index.json.jbuilder +17 -17
  133. data/app/views/json_ui/garage/tables/_autoload_section.json.jbuilder +16 -16
  134. data/app/views/json_ui/garage/tables/autoload_all.json.jbuilder +43 -43
  135. data/app/views/json_ui/garage/tables/autoload_as_needed.json.jbuilder +50 -50
  136. data/app/views/json_ui/garage/tables/export_import.json.jbuilder +29 -29
  137. data/app/views/json_ui/garage/tables/horizontal_scroll.json.jbuilder +26 -26
  138. data/app/views/json_ui/garage/tables/index.json.jbuilder +25 -25
  139. data/app/views/json_ui/garage/tables/layout.json.jbuilder +40 -40
  140. data/app/views/json_ui/garage/views/_chart_data.json.jbuilder +17 -17
  141. data/app/views/json_ui/garage/views/banners.json.jbuilder +63 -63
  142. data/app/views/json_ui/garage/views/calendar_data.json.jbuilder +30 -30
  143. data/app/views/json_ui/garage/views/charts.json.jbuilder +115 -115
  144. data/app/views/json_ui/garage/views/controls.json.jbuilder +37 -37
  145. data/app/views/json_ui/garage/views/icon_names.json.jbuilder +1450 -1450
  146. data/app/views/json_ui/garage/views/icons.json.jbuilder +15 -14
  147. data/app/views/json_ui/garage/views/images.json.jbuilder +89 -89
  148. data/app/views/json_ui/garage/views/index.json.jbuilder +67 -67
  149. data/app/views/json_ui/garage/views/links.json.jbuilder +70 -70
  150. data/app/views/json_ui/garage/views/map_cluster_data.json.jbuilder +41 -41
  151. data/app/views/json_ui/garage/views/map_data.json.jbuilder +51 -51
  152. data/app/views/json_ui/garage/views/maps.json.jbuilder +31 -31
  153. data/app/views/json_ui/garage/views/markdowns.json.jbuilder +41 -41
  154. data/app/views/json_ui/garage/views/misc.json.jbuilder +34 -34
  155. data/app/views/json_ui/garage/views/texts.json.jbuilder +35 -35
  156. data/app/views/layouts/json_ui/renderer.html.erb +35 -35
  157. data/config/routes.rb +7 -7
  158. data/lib/generators/glib/install_generator.rb +24 -24
  159. data/lib/generators/templates/20191017062519_create_texts.rb +12 -12
  160. data/lib/generators/templates/20191024063257_add_scope_to_texts.rb +7 -7
  161. data/lib/generators/templates/20191112095018_add_lang_to_texts.rb +7 -7
  162. data/lib/generators/templates/20191126071051_create_active_storage_tables.active_storage.rb +27 -27
  163. data/lib/generators/templates/database.yml +107 -107
  164. data/lib/generators/templates/dynamic_text.rb +2 -2
  165. data/lib/glib-web.rb +9 -9
  166. data/lib/glib/crypt/utils.rb +26 -26
  167. data/lib/glib/dynamic_text/config.rb +21 -21
  168. data/lib/glib/engine.rb +7 -7
  169. data/lib/glib/json_crawler.rb +11 -11
  170. data/lib/glib/json_crawler/action_crawler.rb +23 -23
  171. data/lib/glib/json_crawler/action_crawlers/action_http.rb +11 -11
  172. data/lib/glib/json_crawler/action_crawlers/forms_submit.rb +48 -48
  173. data/lib/glib/json_crawler/action_crawlers/menu.rb +12 -12
  174. data/lib/glib/json_crawler/action_crawlers/nav_initiate.rb +19 -19
  175. data/lib/glib/json_crawler/action_crawlers/run_multiple.rb +13 -13
  176. data/lib/glib/json_crawler/action_crawlers/windows_open.rb +33 -33
  177. data/lib/glib/json_crawler/coverage.rb +20 -20
  178. data/lib/glib/json_crawler/http.rb +120 -120
  179. data/lib/glib/json_crawler/router.rb +98 -98
  180. data/lib/glib/mailer_tester.rb +36 -36
  181. data/lib/glib/test_helpers.rb +52 -52
  182. data/lib/glib/value.rb +7 -7
  183. data/lib/glib/version.rb +5 -5
  184. data/lib/tasks/db.rake +95 -95
  185. metadata +3 -3
@@ -1,42 +1,42 @@
1
- module Glib
2
- module DynamicTextsHelper
3
- def dt(key, default_value = '', **args)
4
- new_key = key
5
- options = {
6
- scope: args.fetch(:scope, 'itinerarybuilder'),
7
- lang: args.fetch(:lang, 'en')
8
- }
9
-
10
- if key.starts_with?('.')
11
- new_key = "#{controller_name}.#{action_name}#{key}"
12
- end
13
-
14
- content, text_object = Glib::Text.get_content(new_key, default_value, options: options)
15
- content = content.gsub(/\{\{(\w+)\}\}/) { args.fetch($1.to_sym, "{{#{$1}}}") }
16
-
17
- if text_object.images.attached?
18
- content = content.gsub(/\{\{image(\d)\}\}/) {
19
- if image = text_object.images[$1.to_i - 1]
20
- glib_dynamic_image_url(image.blob.key)
21
- else
22
- "{{image#{$1}}}"
23
- end
24
- }
25
- end
26
-
27
- content
28
- end
29
-
30
- def dt_json(key, default_value = '', **args)
31
- new_key = key
32
-
33
- if key.starts_with?('.')
34
- new_key = "#{controller_name}.#{action_name}#{key}"
35
- end
36
-
37
- {
38
- dt_key: new_key
39
- }.merge(args)
40
- end
41
- end
42
- end
1
+ module Glib
2
+ module DynamicTextsHelper
3
+ def dt(key, default_value = '', **args)
4
+ new_key = key
5
+ options = {
6
+ scope: args.fetch(:scope, 'itinerarybuilder'),
7
+ lang: args.fetch(:lang, 'en')
8
+ }
9
+
10
+ if key.starts_with?('.')
11
+ new_key = "#{controller_name}.#{action_name}#{key}"
12
+ end
13
+
14
+ content, text_object = Glib::Text.get_content(new_key, default_value, options: options)
15
+ content = content.gsub(/\{\{(\w+)\}\}/) { args.fetch($1.to_sym, "{{#{$1}}}") }
16
+
17
+ if text_object.images.attached?
18
+ content = content.gsub(/\{\{image(\d)\}\}/) {
19
+ if image = text_object.images[$1.to_i - 1]
20
+ glib_dynamic_image_url(image.blob.key)
21
+ else
22
+ "{{image#{$1}}}"
23
+ end
24
+ }
25
+ end
26
+
27
+ content
28
+ end
29
+
30
+ def dt_json(key, default_value = '', **args)
31
+ new_key = key
32
+
33
+ if key.starts_with?('.')
34
+ new_key = "#{controller_name}.#{action_name}#{key}"
35
+ end
36
+
37
+ {
38
+ dt_key: new_key
39
+ }.merge(args)
40
+ end
41
+ end
42
+ end
@@ -1,8 +1,18 @@
1
- module Glib
2
- module EnumHelper
3
- def glib_enum_options(clazz, enum_field, keys = nil)
4
- keys ||= clazz.send("#{enum_field}s").keys
5
- keys.map { |i| { text: clazz.glib_enum_humanize(enum_field, i), value: i } }
6
- end
7
- end
8
- end
1
+ module Glib
2
+ module EnumHelper
3
+ def glib_enum_options(clazz, enum_field, keys = nil)
4
+ keys ||= clazz.send("#{enum_field}s").keys
5
+ keys.map { |i| { text: clazz.glib_enum_humanize(enum_field, i), value: i } }
6
+ end
7
+
8
+ # See https://en.wikipedia.org/wiki/List_of_tz_database_time_zones and description
9
+ def glib_time_zone_options
10
+ ActiveSupport::TimeZone.all.sort { |a, b|
11
+ a.utc_offset <=> b.utc_offset
12
+ }.collect { |tz|
13
+ utc_offset = "#{tz.utc_offset >= 0 ? '+' : ''}#{tz.utc_offset / 60 / 60}h"
14
+ { value: tz.tzinfo.identifier, text: "#{utc_offset} #{tz.name}" }
15
+ }
16
+ end
17
+ end
18
+ end
@@ -1,15 +1,15 @@
1
- module Glib
2
- module FormsHelper
3
- def glib_form_field_label(model_name, prop, args = {})
4
- I18n.t("dt_models.#{model_name}.#{prop}.label", args.merge(default: nil)) || I18n.t("activerecord.attributes.#{model_name}.#{prop}", args)
5
- end
6
-
7
- def glib_form_hint_label(model_name, prop, args = {})
8
- I18n.t("dt_models.#{model_name}.#{prop}.hint", args.merge(default: nil))
9
- end
10
-
11
- def glib_form_placeholder_label(model_name, prop, args = {})
12
- I18n.t("dt_models.#{model_name}.#{prop}.placeholder", args.merge(default: nil))
13
- end
14
- end
15
- end
1
+ module Glib
2
+ module FormsHelper
3
+ def glib_form_field_label(model_name, prop, args = {})
4
+ I18n.t("dt_models.#{model_name}.#{prop}.label", args.merge(default: nil)) || I18n.t("activerecord.attributes.#{model_name}.#{prop}", args)
5
+ end
6
+
7
+ def glib_form_hint_label(model_name, prop, args = {})
8
+ I18n.t("dt_models.#{model_name}.#{prop}.hint", args.merge(default: nil))
9
+ end
10
+
11
+ def glib_form_placeholder_label(model_name, prop, args = {})
12
+ I18n.t("dt_models.#{model_name}.#{prop}.placeholder", args.merge(default: nil))
13
+ end
14
+ end
15
+ end
@@ -1,309 +1,309 @@
1
- module Glib
2
- module JsonUi
3
- class AbstractBuilder
4
- attr_reader :json, :page
5
-
6
- def initialize(json, page)
7
- @json = json
8
- @page = page
9
- end
10
-
11
- private
12
- def capitalize_first_letter_and_leave_others_alone(str)
13
- str.slice(0, 1).capitalize + str.slice(1..-1)
14
- end
15
-
16
- def add_singleton_element(type, name, *args)
17
- name_components = name.to_s.split('_')
18
- json.set! type, "#{name_components.join('/')}" if type
19
- args = [yield] if block_given?
20
-
21
- # TODO: consider caching these instances
22
- "#{self.class.name}::#{name_components.map { |str| capitalize_first_letter_and_leave_others_alone(str) }.join('::')}".constantize.new(json, @page).props(*args)
23
- end
24
-
25
- def add_element_to_array(type, name, *args)
26
- json.child! do
27
- add_singleton_element type, name, *args
28
- end
29
- end
30
-
31
- # TODO: Consider removing this in favour of non 'v1' suffix
32
- def add_singleton_element_v1(type, name, *args)
33
- name_components = name.to_s.split('_')
34
- json.set! type, "#{name_components.join('/')}-v1" if type
35
- args = [yield] if block_given?
36
- "#{self.class.name}::#{name_components.map { |str| capitalize_first_letter_and_leave_others_alone(str) }.join('::')}".constantize.new(json, @page).props(*args)
37
- end
38
-
39
- # TODO: Consider removing this in favour of non 'v1' suffix
40
- def add_element_to_array_v1(type, name, *args)
41
- json.child! do
42
- add_singleton_element_v1 type, name, *args
43
- end
44
- end
45
-
46
- end
47
-
48
- class JsonUiElement
49
- attr_reader :json, :page
50
-
51
- @@_required_properties = {}
52
-
53
- def initialize(json, page)
54
- @json = json
55
- @page = page
56
- end
57
-
58
- def props(args = {})
59
- @args = args
60
-
61
- if args.is_a? Hash
62
- args.each do |k, v|
63
- send(k, v)
64
- end
65
-
66
- required_properties = @@_required_properties[self.class.component_name] || []
67
- required_properties.each do |prop|
68
- raise "Property required: #{prop}. Properties provided: #{args}. Component: #{self.class.component_name}" unless args[prop].present?
69
- end
70
- else
71
- raise "Invalid properties: #{args}"
72
- end
73
-
74
- created
75
- end
76
-
77
- private
78
- def self.component_name
79
- @component_name ||= self.name.sub('Glib::JsonUi::ActionBuilder::', '')
80
- end
81
-
82
- def self.any(propName)
83
- define_method(propName) do |value|
84
- json.set! propName, value
85
- end
86
- end
87
-
88
- def self.date(propName)
89
- define_method(propName) do |value|
90
- json.set! propName, value&.to_date
91
-
92
- # if (value = value&.to_s)
93
- # if !Rails.env.production?
94
- # raise "Invalid date for #{propName}: #{value}" unless value =~ /^\d{4}-\d{2}-\d{2}$/
95
- # end
96
-
97
- # json.set! propName, value
98
- # end
99
- end
100
- end
101
-
102
- def self.date_time(propName)
103
- define_method(propName) do |value|
104
- json.set! propName, value&.to_datetime
105
-
106
- # if (value = value&.to_s)
107
- # if !Rails.env.production?
108
- # try Date.parse(value) rescue raise "Invalid date: #{value}"
109
- # end
110
-
111
- # json.set! propName, value
112
- # end
113
- end
114
- end
115
-
116
- def self.color(propName)
117
- define_method(propName) do |value|
118
- if (value = value&.to_s)
119
- if !Rails.env.production?
120
- if !value.match /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/i
121
- raise "Invalid color: #{value}"
122
- end
123
- end
124
-
125
- json.set! propName, value
126
- end
127
- end
128
- end
129
-
130
- def self.length(propName)
131
- define_method(propName) do |value|
132
- if value
133
- if !Rails.env.production?
134
- case value
135
- when 'matchParent'
136
- when 'wrapContent'
137
- else
138
- if !value.is_a? Integer
139
- raise "Invalid length: #{value}"
140
- end
141
- end
142
- end
143
-
144
- json.set! propName, value
145
- end
146
- end
147
- end
148
-
149
- def self.string(propName, options = {})
150
- define_method(propName) do |value|
151
- str = value&.to_s
152
- instance_variable_set("@#{propName}", str) if options[:cache]
153
- json.set! propName, str
154
- end
155
- end
156
-
157
- # Support either string or dynamic_text hash
158
- def self.text(propName, options = {})
159
- define_method(propName) do |value|
160
- if value.is_a?(Hash)
161
- json.set! propName, value
162
- else
163
- json.set! propName, value&.to_s
164
- end
165
- end
166
- end
167
-
168
- def self.int(propName)
169
- define_method(propName) do |value|
170
- json.set! propName, value&.to_i
171
- end
172
- end
173
-
174
- def self.float(propName)
175
- define_method(propName) do |value|
176
- json.set! propName, value&.to_f
177
- end
178
- end
179
-
180
- def self.bool(propName, options = {})
181
- define_method(propName) do |value|
182
- bool = value == true
183
- instance_variable_set("@#{propName}", bool) if options[:cache]
184
- json.set! propName, bool
185
- end
186
- end
187
-
188
- def self.icon(propName, options = {})
189
- define_method(propName) do |value|
190
-
191
- if value.is_a?(Hash)
192
- data = value
193
- name = data[:name]
194
- else
195
- data = {}
196
- name = value
197
- # data = { material: { name: value } }
198
-
199
- # name = value
200
-
201
- # TODO: deprecated
202
- # json.set!(propName) do
203
- # json.name name
204
- # end
205
- end
206
-
207
- json.set!(propName) do
208
- if name
209
- data[:material] ||= {}
210
- data[:material][:name] = name
211
- end
212
-
213
- if (material = data[:material])
214
- json.material do
215
- json.name material[:name]
216
- json.size material[:size] if material[:size]
217
- end
218
- end
219
-
220
- if (fa = data[:fa])
221
- json.fa do
222
- json.name fa[:name]
223
- json.size fa[:size] if fa[:size]
224
- end
225
- end
226
-
227
- if (custom = data[:custom])
228
- json.custom do
229
- json.name custom[:name]
230
- json.size custom[:size] if custom[:size]
231
- end
232
- end
233
-
234
- if (badge = data[:badge])
235
- if badge.is_a?(Hash)
236
- json.badge badge
237
- else
238
- json.badge do
239
- json.text badge
240
- end
241
- end
242
- end
243
-
244
- end
245
-
246
- # raise "Invalid properties: #{options.keys}" if options.size > 0
247
-
248
- # instance_variable_set("@#{propName}", name) if options[:cache]
249
-
250
- end
251
- end
252
-
253
- def self.action(propName)
254
- define_method(propName) do |value|
255
- json.set!(propName) { value.call(page.action_builder) }
256
- end
257
- end
258
-
259
- def self.views(propName)
260
- define_method(propName) do |value|
261
- json.set!(propName) { value.call(page.view_builder) }
262
- end
263
- end
264
-
265
- def self.array(propName)
266
- define_method(propName) do |value|
267
- json.set! propName, value&.to_a
268
- end
269
- end
270
-
271
- def self.hash(propName)
272
- define_method(propName) do |value|
273
- json.set! propName, value
274
- end
275
- end
276
-
277
- def self.menu(propName)
278
- define_method(propName) do |value|
279
- json.set! propName do
280
- value.call(page.menu_builder)
281
- end
282
- end
283
- end
284
-
285
- def self.singleton_array(singletonName, arrayName)
286
- array arrayName
287
-
288
- define_method(singletonName) do |value|
289
- json.set! arrayName, [value]
290
- end
291
- end
292
-
293
- def self.panels_builder(propName, *panelNames)
294
- define_method(propName) do |value|
295
- value.call(page.content_builder(panelNames))
296
- end
297
- end
298
-
299
- def self.required(*prop_names)
300
- @@_required_properties[self.component_name] = prop_names
301
- end
302
-
303
- def created
304
- # To be overridden
305
- end
306
-
307
- end
308
- end
309
- end
1
+ module Glib
2
+ module JsonUi
3
+ class AbstractBuilder
4
+ attr_reader :json, :page
5
+
6
+ def initialize(json, page)
7
+ @json = json
8
+ @page = page
9
+ end
10
+
11
+ private
12
+ def capitalize_first_letter_and_leave_others_alone(str)
13
+ str.slice(0, 1).capitalize + str.slice(1..-1)
14
+ end
15
+
16
+ def add_singleton_element(type, name, *args)
17
+ name_components = name.to_s.split('_')
18
+ json.set! type, "#{name_components.join('/')}" if type
19
+ args = [yield] if block_given?
20
+
21
+ # TODO: consider caching these instances
22
+ "#{self.class.name}::#{name_components.map { |str| capitalize_first_letter_and_leave_others_alone(str) }.join('::')}".constantize.new(json, @page).props(*args)
23
+ end
24
+
25
+ def add_element_to_array(type, name, *args)
26
+ json.child! do
27
+ add_singleton_element type, name, *args
28
+ end
29
+ end
30
+
31
+ # TODO: Consider removing this in favour of non 'v1' suffix
32
+ def add_singleton_element_v1(type, name, *args)
33
+ name_components = name.to_s.split('_')
34
+ json.set! type, "#{name_components.join('/')}-v1" if type
35
+ args = [yield] if block_given?
36
+ "#{self.class.name}::#{name_components.map { |str| capitalize_first_letter_and_leave_others_alone(str) }.join('::')}".constantize.new(json, @page).props(*args)
37
+ end
38
+
39
+ # TODO: Consider removing this in favour of non 'v1' suffix
40
+ def add_element_to_array_v1(type, name, *args)
41
+ json.child! do
42
+ add_singleton_element_v1 type, name, *args
43
+ end
44
+ end
45
+
46
+ end
47
+
48
+ class JsonUiElement
49
+ attr_reader :json, :page
50
+
51
+ @@_required_properties = {}
52
+
53
+ def initialize(json, page)
54
+ @json = json
55
+ @page = page
56
+ end
57
+
58
+ def props(args = {})
59
+ @args = args
60
+
61
+ if args.is_a? Hash
62
+ args.each do |k, v|
63
+ send(k, v)
64
+ end
65
+
66
+ required_properties = @@_required_properties[self.class.component_name] || []
67
+ required_properties.each do |prop|
68
+ raise "Property required: #{prop}. Properties provided: #{args}. Component: #{self.class.component_name}" unless args[prop].present?
69
+ end
70
+ else
71
+ raise "Invalid properties: #{args}"
72
+ end
73
+
74
+ created
75
+ end
76
+
77
+ private
78
+ def self.component_name
79
+ @component_name ||= self.name.sub('Glib::JsonUi::ActionBuilder::', '')
80
+ end
81
+
82
+ def self.any(propName)
83
+ define_method(propName) do |value|
84
+ json.set! propName, value
85
+ end
86
+ end
87
+
88
+ def self.date(propName)
89
+ define_method(propName) do |value|
90
+ json.set! propName, value&.to_date
91
+
92
+ # if (value = value&.to_s)
93
+ # if !Rails.env.production?
94
+ # raise "Invalid date for #{propName}: #{value}" unless value =~ /^\d{4}-\d{2}-\d{2}$/
95
+ # end
96
+
97
+ # json.set! propName, value
98
+ # end
99
+ end
100
+ end
101
+
102
+ def self.date_time(propName)
103
+ define_method(propName) do |value|
104
+ json.set! propName, value&.to_datetime
105
+
106
+ # if (value = value&.to_s)
107
+ # if !Rails.env.production?
108
+ # try Date.parse(value) rescue raise "Invalid date: #{value}"
109
+ # end
110
+
111
+ # json.set! propName, value
112
+ # end
113
+ end
114
+ end
115
+
116
+ def self.color(propName)
117
+ define_method(propName) do |value|
118
+ if (value = value&.to_s)
119
+ if !Rails.env.production?
120
+ if !value.match /^#([A-Fa-f0-9]{8}|[A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/i
121
+ raise "Invalid color: #{value}"
122
+ end
123
+ end
124
+
125
+ json.set! propName, value
126
+ end
127
+ end
128
+ end
129
+
130
+ def self.length(propName)
131
+ define_method(propName) do |value|
132
+ if value
133
+ if !Rails.env.production?
134
+ case value
135
+ when 'matchParent'
136
+ when 'wrapContent'
137
+ else
138
+ if !value.is_a? Integer
139
+ raise "Invalid length: #{value}"
140
+ end
141
+ end
142
+ end
143
+
144
+ json.set! propName, value
145
+ end
146
+ end
147
+ end
148
+
149
+ def self.string(propName, options = {})
150
+ define_method(propName) do |value|
151
+ str = value&.to_s
152
+ instance_variable_set("@#{propName}", str) if options[:cache]
153
+ json.set! propName, str
154
+ end
155
+ end
156
+
157
+ # Support either string or dynamic_text hash
158
+ def self.text(propName, options = {})
159
+ define_method(propName) do |value|
160
+ if value.is_a?(Hash)
161
+ json.set! propName, value
162
+ else
163
+ json.set! propName, value&.to_s
164
+ end
165
+ end
166
+ end
167
+
168
+ def self.int(propName)
169
+ define_method(propName) do |value|
170
+ json.set! propName, value&.to_i
171
+ end
172
+ end
173
+
174
+ def self.float(propName)
175
+ define_method(propName) do |value|
176
+ json.set! propName, value&.to_f
177
+ end
178
+ end
179
+
180
+ def self.bool(propName, options = {})
181
+ define_method(propName) do |value|
182
+ bool = value == true
183
+ instance_variable_set("@#{propName}", bool) if options[:cache]
184
+ json.set! propName, bool
185
+ end
186
+ end
187
+
188
+ def self.icon(propName, options = {})
189
+ define_method(propName) do |value|
190
+
191
+ if value.is_a?(Hash)
192
+ data = value
193
+ name = data[:name]
194
+ else
195
+ data = {}
196
+ name = value
197
+ # data = { material: { name: value } }
198
+
199
+ # name = value
200
+
201
+ # TODO: deprecated
202
+ # json.set!(propName) do
203
+ # json.name name
204
+ # end
205
+ end
206
+
207
+ json.set!(propName) do
208
+ if name
209
+ data[:material] ||= {}
210
+ data[:material][:name] = name
211
+ end
212
+
213
+ if (material = data[:material])
214
+ json.material do
215
+ json.name material[:name]
216
+ json.size material[:size] if material[:size]
217
+ end
218
+ end
219
+
220
+ if (fa = data[:fa])
221
+ json.fa do
222
+ json.name fa[:name]
223
+ json.size fa[:size] if fa[:size]
224
+ end
225
+ end
226
+
227
+ if (custom = data[:custom])
228
+ json.custom do
229
+ json.name custom[:name]
230
+ json.size custom[:size] if custom[:size]
231
+ end
232
+ end
233
+
234
+ if (badge = data[:badge])
235
+ if badge.is_a?(Hash)
236
+ json.badge badge
237
+ else
238
+ json.badge do
239
+ json.text badge
240
+ end
241
+ end
242
+ end
243
+
244
+ end
245
+
246
+ # raise "Invalid properties: #{options.keys}" if options.size > 0
247
+
248
+ # instance_variable_set("@#{propName}", name) if options[:cache]
249
+
250
+ end
251
+ end
252
+
253
+ def self.action(propName)
254
+ define_method(propName) do |value|
255
+ json.set!(propName) { value.call(page.action_builder) }
256
+ end
257
+ end
258
+
259
+ def self.views(propName)
260
+ define_method(propName) do |value|
261
+ json.set!(propName) { value.call(page.view_builder) }
262
+ end
263
+ end
264
+
265
+ def self.array(propName)
266
+ define_method(propName) do |value|
267
+ json.set! propName, value&.to_a
268
+ end
269
+ end
270
+
271
+ def self.hash(propName)
272
+ define_method(propName) do |value|
273
+ json.set! propName, value
274
+ end
275
+ end
276
+
277
+ def self.menu(propName)
278
+ define_method(propName) do |value|
279
+ json.set! propName do
280
+ value.call(page.menu_builder)
281
+ end
282
+ end
283
+ end
284
+
285
+ def self.singleton_array(singletonName, arrayName)
286
+ array arrayName
287
+
288
+ define_method(singletonName) do |value|
289
+ json.set! arrayName, [value]
290
+ end
291
+ end
292
+
293
+ def self.panels_builder(propName, *panelNames)
294
+ define_method(propName) do |value|
295
+ value.call(page.content_builder(panelNames))
296
+ end
297
+ end
298
+
299
+ def self.required(*prop_names)
300
+ @@_required_properties[self.component_name] = prop_names
301
+ end
302
+
303
+ def created
304
+ # To be overridden
305
+ end
306
+
307
+ end
308
+ end
309
+ end