tramway 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (180) hide show
  1. checksums.yaml +5 -5
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +889 -15
  4. data/Rakefile +8 -8
  5. data/app/assets/config/tramway_core_manifest.js +2 -0
  6. data/app/assets/images/tramway/mona_lisa_from_prado.jpg +0 -0
  7. data/app/assets/images/tramway/mona_lisa_from_prado_square.jpg +0 -0
  8. data/app/assets/javascripts/bootstrap-datepicker-1.8.0.js +2035 -0
  9. data/app/assets/javascripts/bootstrap-datepicker-1.8.0.ru.min.js +64 -0
  10. data/app/assets/javascripts/ckeditor/config.js +30 -0
  11. data/app/assets/javascripts/ckeditor/plugins/image/dialogs/image.js +1259 -0
  12. data/app/assets/javascripts/ckeditor/plugins/image/icons/hidpi/image.png +0 -0
  13. data/app/assets/javascripts/ckeditor/plugins/image/icons/image.png +0 -0
  14. data/app/assets/javascripts/ckeditor/plugins/image/images/noimage.png +0 -0
  15. data/app/assets/javascripts/ckeditor/plugins/image/lang/en.js +25 -0
  16. data/app/assets/javascripts/ckeditor/plugins/image/lang/ru.js +25 -0
  17. data/app/assets/javascripts/ckeditor/plugins/image/plugin.js +184 -0
  18. data/app/assets/javascripts/ckeditor/plugins/youtube/images/icon-hdpi.png +0 -0
  19. data/app/assets/javascripts/ckeditor/plugins/youtube/images/icon.png +0 -0
  20. data/app/assets/javascripts/ckeditor/plugins/youtube/lang/en.js +25 -0
  21. data/app/assets/javascripts/ckeditor/plugins/youtube/lang/ru.js +25 -0
  22. data/app/assets/javascripts/ckeditor/plugins/youtube/plugin.js +449 -0
  23. data/app/assets/javascripts/tramway/application.js +60 -0
  24. data/app/assets/stylesheets/tramway/application.sass +60 -0
  25. data/app/assets/stylesheets/tramway/bootstrap-datepicker-1.8.0.css +477 -0
  26. data/app/controllers/concerns/auth_management.rb +26 -0
  27. data/app/controllers/concerns/filtering.rb +43 -0
  28. data/app/controllers/tramway/application_controller.rb +142 -0
  29. data/app/controllers/tramway/export/application_controller.rb +5 -0
  30. data/app/controllers/tramway/has_and_belongs_to_many_records_controller.rb +26 -0
  31. data/app/controllers/tramway/records_controller.rb +86 -0
  32. data/app/controllers/tramway/sessions_controller.rb +49 -0
  33. data/app/controllers/tramway/singletons_controller.rb +48 -0
  34. data/app/controllers/tramway/welcome_controller.rb +17 -0
  35. data/app/decorators/tramway/application_decorated_collection.rb +15 -0
  36. data/app/decorators/tramway/application_decorator.rb +124 -0
  37. data/app/decorators/tramway/associations/class_helper.rb +45 -0
  38. data/app/decorators/tramway/associations/object_helper.rb +58 -0
  39. data/app/decorators/tramway/attributes/view_helper.rb +30 -0
  40. data/app/decorators/tramway/concerns/attributes_decorator_helper.rb +97 -0
  41. data/app/decorators/tramway/concerns/table_builder.rb +33 -0
  42. data/app/decorators/tramway/default/values_helper.rb +23 -0
  43. data/app/decorators/tramway/delegating/class_helper.rb +9 -0
  44. data/app/decorators/tramway/user_decorator.rb +49 -0
  45. data/app/forms/admin/tramway/user_form.rb +24 -0
  46. data/app/forms/tramway/application_form.rb +124 -0
  47. data/app/forms/tramway/application_forms/association_class_helpers.rb +7 -0
  48. data/app/forms/tramway/application_forms/association_object_helpers.rb +36 -0
  49. data/app/forms/tramway/application_forms/constant_class_actions.rb +7 -0
  50. data/app/forms/tramway/application_forms/constant_object_actions.rb +20 -0
  51. data/app/forms/tramway/application_forms/frontend.rb +12 -0
  52. data/app/forms/tramway/application_forms/object_helpers.rb +15 -0
  53. data/app/forms/tramway/application_forms/properties_object_helper.rb +16 -0
  54. data/app/forms/tramway/application_forms/submit_helper.rb +26 -0
  55. data/app/forms/tramway/extendable_form.rb +15 -0
  56. data/app/forms/tramway/extendable_forms_helpers/class_builder.rb +34 -0
  57. data/app/forms/tramway/extendable_forms_helpers/ignored_properties_helper.rb +11 -0
  58. data/app/forms/tramway/extendable_forms_helpers/more_properties_helper.rb +31 -0
  59. data/app/forms/tramway/extendable_forms_helpers/properties_helper.rb +16 -0
  60. data/app/forms/tramway/extendable_forms_helpers/submit/class_helpers.rb +18 -0
  61. data/app/forms/tramway/extendable_forms_helpers/submit/object_helpers.rb +21 -0
  62. data/app/forms/tramway/extendable_forms_helpers/validators.rb +40 -0
  63. data/app/forms/tramway/extended_application_form.rb +23 -0
  64. data/app/forms/tramway/form_creator.rb +7 -0
  65. data/app/forms/tramway/session_form.rb +26 -0
  66. data/app/helpers/tramway/actions_helper.rb +45 -0
  67. data/app/helpers/tramway/additional_buttons_builder.rb +12 -0
  68. data/app/helpers/tramway/application_helper.rb +27 -0
  69. data/app/helpers/tramway/cases_helper.rb +13 -0
  70. data/app/helpers/tramway/copy_to_clipboard_helper.rb +11 -0
  71. data/app/helpers/tramway/focus_generator_helper.rb +10 -0
  72. data/app/helpers/tramway/frontend_helper.rb +26 -0
  73. data/app/helpers/tramway/inputs/associations_helper.rb +30 -0
  74. data/app/helpers/tramway/inputs/polymorphic_associations_helper.rb +24 -0
  75. data/app/helpers/tramway/inputs_helper.rb +96 -0
  76. data/app/helpers/tramway/model_helper.rb +7 -0
  77. data/app/helpers/tramway/navbar_helper.rb +11 -0
  78. data/app/helpers/tramway/records_helper.rb +120 -0
  79. data/app/helpers/tramway/russian_cases_helper.rb +26 -0
  80. data/app/helpers/tramway/singleton_helper.rb +12 -0
  81. data/app/helpers/tramway/state_machine_buttons_helper.rb +61 -0
  82. data/app/helpers/tramway/title_helper.rb +25 -0
  83. data/app/inputs/date_picker_input.rb +4 -0
  84. data/app/inputs/multiple_file_input.rb +7 -0
  85. data/app/models/tramway/application_record.rb +60 -0
  86. data/app/models/tramway/user.rb +23 -0
  87. data/app/uploaders/application_uploader.rb +22 -0
  88. data/app/uploaders/file_uploader.rb +4 -0
  89. data/app/uploaders/ico_uploader.rb +7 -0
  90. data/app/uploaders/image_defaults.rb +14 -0
  91. data/app/uploaders/photo_uploader.rb +54 -0
  92. data/app/views/layouts/tramway/application.html.haml +32 -0
  93. data/app/views/layouts/tramway/shared/_navbar.html.haml +46 -0
  94. data/app/views/tramway/404.haml +1 -0
  95. data/app/views/tramway/records/_form.html.haml +22 -0
  96. data/app/views/tramway/records/_list.html.haml +38 -0
  97. data/app/views/tramway/records/_search.html.haml +34 -0
  98. data/app/views/tramway/records/edit.html.haml +1 -0
  99. data/app/views/tramway/records/index.html.haml +31 -0
  100. data/app/views/tramway/records/new.html.haml +1 -0
  101. data/app/views/tramway/records/show.html.haml +1 -0
  102. data/app/views/tramway/sessions/new.html.haml +9 -0
  103. data/app/views/tramway/shared/_input.html.haml +34 -0
  104. data/app/views/tramway/shared/_input_extended.html.haml +14 -0
  105. data/app/views/tramway/shared/_messages.html.haml +10 -0
  106. data/app/views/tramway/shared/_show.html.haml +35 -0
  107. data/app/views/tramway/shared/errors/server_error.html.haml +12 -0
  108. data/app/views/tramway/shared/input_extended_types/_checkbox.html.haml +1 -0
  109. data/app/views/tramway/shared/input_extended_types/_select.html.haml +16 -0
  110. data/app/views/tramway/shared/input_extended_types/_simple.html.haml +4 -0
  111. data/app/views/tramway/shared/input_extended_types/_yes_no.html.haml +4 -0
  112. data/app/views/tramway/shared/show/_attribute_tr.html.haml +9 -0
  113. data/app/views/tramway/shared/show/associations/_habtm_row.html.haml +14 -0
  114. data/app/views/tramway/shared/show/associations/_list.html.haml +21 -0
  115. data/app/views/tramway/shared/show/associations/_row.html.haml +19 -0
  116. data/app/views/tramway/shared/show/associations/_table_row.html.haml +21 -0
  117. data/app/views/tramway/singletons/_form.html.haml +15 -0
  118. data/app/views/tramway/singletons/edit.html.haml +1 -0
  119. data/app/views/tramway/singletons/new.html.haml +1 -0
  120. data/app/views/tramway/singletons/show.html.haml +1 -0
  121. data/app/views/tramway/welcome/index.html.haml +4 -0
  122. data/config/initializers/assets.rb +7 -0
  123. data/config/initializers/carrierwave.rb +5 -0
  124. data/config/initializers/ckeditor.rb +9 -0
  125. data/config/initializers/plurals.rb +25 -0
  126. data/config/locales/en/collections.yml +4 -0
  127. data/config/locales/en/date.yml +16 -0
  128. data/config/locales/en/dates.yml +10 -0
  129. data/config/locales/en/helpers.yml +26 -0
  130. data/config/locales/en/locale.yml +11 -0
  131. data/config/locales/en/messages.yml +7 -0
  132. data/config/locales/en/models.yml +9 -0
  133. data/config/locales/en/simple_form_extension.yml +8 -0
  134. data/config/locales/en/state_machines.yml +8 -0
  135. data/config/locales/ru/collections.yml +4 -0
  136. data/config/locales/ru/date.yml +16 -0
  137. data/config/locales/ru/dates.yml +10 -0
  138. data/config/locales/ru/helpers.yml +30 -0
  139. data/config/locales/ru/locale.yml +6 -0
  140. data/config/locales/ru/messages.yml +7 -0
  141. data/config/locales/ru/models.yml +21 -0
  142. data/config/locales/ru/simple_form_extension.yml +8 -0
  143. data/config/locales/ru/state_machines.yml +8 -0
  144. data/config/routes.rb +13 -0
  145. data/lib/string.rb +18 -0
  146. data/lib/tramway/application.rb +10 -0
  147. data/lib/tramway/class_name_helpers.rb +15 -0
  148. data/lib/tramway/collection.rb +9 -0
  149. data/lib/tramway/collections/helper.rb +21 -0
  150. data/lib/tramway/collections.rb +4 -0
  151. data/lib/tramway/engine.rb +14 -0
  152. data/lib/tramway/error.rb +32 -0
  153. data/lib/tramway/forms.rb +5 -0
  154. data/lib/tramway/generators/install_generator.rb +49 -0
  155. data/lib/tramway/generators/model_generator.rb +105 -0
  156. data/lib/tramway/generators/templates/create_tramway_users.rb +18 -0
  157. data/lib/tramway/generators/templates/decorator.rb.erb +56 -0
  158. data/lib/tramway/generators/templates/form.rb.erb +22 -0
  159. data/lib/tramway/generators/templates/initializers/simple_form.rb +23 -0
  160. data/lib/tramway/generators/templates/initializers/simple_form_bootstrap.rb +133 -0
  161. data/lib/tramway/generators.rb +4 -0
  162. data/lib/tramway/navbar.rb +44 -0
  163. data/lib/tramway/notifications.rb +12 -0
  164. data/lib/tramway/record_routes_helper.rb +23 -0
  165. data/lib/tramway/records_models.rb +52 -0
  166. data/lib/tramway/singleton_models.rb +32 -0
  167. data/lib/tramway/spec/helpers/navbar_helper.rb +7 -0
  168. data/lib/tramway/spec/helpers/tramway_helpers.rb +47 -0
  169. data/lib/tramway/version.rb +3 -1
  170. data/lib/tramway/welcome_page_actions.rb +5 -0
  171. data/lib/tramway/yaml/errors.yml +49 -0
  172. data/lib/tramway.rb +143 -2
  173. data/lib/validators/presence_validator.rb +9 -0
  174. metadata +582 -25
  175. data/.gitignore +0 -9
  176. data/.travis.yml +0 -5
  177. data/Gemfile +0 -6
  178. data/bin/console +0 -14
  179. data/bin/setup +0 -8
  180. data/tramway.gemspec +0 -26
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Tramway::UserDecorator < Tramway::ApplicationDecorator
4
+ class << self
5
+ def collections
6
+ [:all]
7
+ end
8
+
9
+ def list_attributes
10
+ [:email]
11
+ end
12
+
13
+ def show_attributes
14
+ %i[email first_name last_name phone role created_at updated_at credential_text]
15
+ end
16
+
17
+ if defined? Tramway::Conference
18
+ def show_associations
19
+ [:social_networks]
20
+ end
21
+ end
22
+ end
23
+
24
+ decorate_association :social_networks, as: :record if defined? Tramway::Conference
25
+
26
+ delegate_attributes :first_name, :last_name, :email, :phone, :role, :created_at, :updated_at, :admin?
27
+
28
+ def name
29
+ "#{object&.first_name} #{object&.last_name}"
30
+ end
31
+
32
+ def credential_text
33
+ content_tag(:pre) do
34
+ id = "credential_text_#{object.id}"
35
+
36
+ concat(content_tag(:span, id: id) do
37
+ text = "URL: #{ENV['PROJECT_URL']}\n"
38
+ text += "Email: #{object.email}\n"
39
+ "#{text}Password: "
40
+ end)
41
+
42
+ concat(content_tag(:br))
43
+
44
+ concat copy_to_clipboard id
45
+ end
46
+ end
47
+
48
+ alias title name
49
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Admin::Tramway::UserForm < ::Tramway::ApplicationForm
4
+ self.model_class = Tramway::User
5
+
6
+ properties :email, :password, :first_name, :last_name, :role, :phone
7
+
8
+ # fix me
9
+ unless model_class.columns_hash['project_id'].present?
10
+ validates :email, email: true, uniqueness: true,
11
+ on: :destroy
12
+ end
13
+
14
+ def initialize(object)
15
+ super(object).tap do
16
+ form_properties email: :string,
17
+ password: :string,
18
+ first_name: :string,
19
+ last_name: :string,
20
+ phone: :string,
21
+ role: :default
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,124 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Tramway::ApplicationForm
4
+ include Tramway::ApplicationForms::AssociationObjectHelpers
5
+ include Tramway::ApplicationForms::ConstantObjectActions
6
+ include Tramway::ApplicationForms::PropertiesObjectHelper
7
+ include Tramway::ApplicationForms::ObjectHelpers
8
+ include Tramway::ApplicationForms::SubmitHelper
9
+
10
+ attr_accessor :submit_message
11
+
12
+ def initialize(object = nil)
13
+ tap do
14
+ @object = object
15
+ @@model_class = object.class
16
+ @@enumerized_attributes = object.class.try :enumerized_attributes
17
+ @@associations ||= []
18
+
19
+ self.class.full_class_name_associations&.each do |association, class_name|
20
+ define_association_method association, class_name
21
+ end
22
+
23
+ delegating object
24
+ end
25
+ end
26
+
27
+ def model_name
28
+ @@model_class.model_name
29
+ end
30
+
31
+ def associations
32
+ @@associations
33
+ end
34
+
35
+ class << self
36
+ include Tramway::ApplicationForms::AssociationClassHelpers
37
+ include Tramway::ApplicationForms::ConstantClassActions
38
+ include Tramway::ApplicationForms::Frontend
39
+
40
+ delegate :defined_enums, to: :model_class
41
+
42
+ def properties(*props)
43
+ props.each { |prop| property prop }
44
+ end
45
+
46
+ def property(prop)
47
+ @@properties ||= []
48
+ @@properties << prop
49
+ delegate prop, to: :model
50
+ define_method("#{prop}=") do |value|
51
+ model.send "#{prop}=", value
52
+ end
53
+ end
54
+
55
+ def association(property)
56
+ properties property
57
+ @@associations = ((defined?(@@associations) && @@associations) || []) + [property]
58
+ end
59
+
60
+ def full_class_name_associations
61
+ @@associations&.reduce({}) do |hash, association|
62
+ options = @@model_class.reflect_on_all_associations(:belongs_to).select do |a|
63
+ a.name == association.to_sym
64
+ end.first&.options
65
+ add_polymorphic_association hash, association, options
66
+ end
67
+ end
68
+
69
+ def add_polymorphic_association(hash, association, options)
70
+ if options&.dig(:polymorphic)
71
+ hash.merge association => @@model_class.send("#{association}_type").values
72
+ elsif options
73
+ hash.merge(association => (options[:class_name] || association.to_s.camelize).constantize)
74
+ else
75
+ hash
76
+ end
77
+ end
78
+
79
+ def full_class_name_association(association_name)
80
+ full_class_name_associations[association_name]
81
+ end
82
+
83
+ def reflect_on_association(*args)
84
+ @@model_class.reflect_on_association(*args)
85
+ end
86
+
87
+ def enumerized_attributes
88
+ @@enumerized_attributes
89
+ end
90
+
91
+ def model_class
92
+ if defined?(@@model_class) && @@model_class
93
+ @@model_class
94
+ else
95
+ model_class_name ||= name.to_s.sub(/Form$/, '')
96
+ begin
97
+ @@model_class = model_class_name.constantize
98
+ rescue StandardError
99
+ Tramway::Error.raise_error :tramway, :application_form, :model_class, :there_is_not_model_class,
100
+ name: name, model_class_name: model_class_name
101
+ end
102
+ end
103
+ end
104
+
105
+ def model_class=(name)
106
+ @@model_class = name
107
+ end
108
+
109
+ def validates(attribute, **options)
110
+ if !defined?(@@model_class) || @@model_class.nil?
111
+ Tramway::Error.raise_error(:tramway, :application_form, :validates, :you_need_to_set_model_class)
112
+ end
113
+ @@model_class.validates attribute, **options
114
+ end
115
+ end
116
+
117
+ private
118
+
119
+ def collecting_associations_errors
120
+ @@associations.each do |association|
121
+ model.send("#{association}=", send(association)) if errors.details[association] == [{ error: :blank }]
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tramway::ApplicationForms::AssociationClassHelpers
4
+ def associations(*properties)
5
+ properties.each { |property| association property }
6
+ end
7
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tramway::ApplicationForms::AssociationObjectHelpers
4
+ def define_association_method(association, class_name)
5
+ if class_name.is_a? Array
6
+ define_polymorphic_association association
7
+ else
8
+ self.class.send(:define_method, "#{association}=") do |value|
9
+ model.send "#{association}_id=", value
10
+ model.send "#{association}=", class_name.find(value)
11
+ end
12
+ end
13
+ end
14
+
15
+ def define_polymorphic_association(association)
16
+ self.class.send(:define_method, "#{association}=") do |value|
17
+ if value.present?
18
+ if association_class(value).nil?
19
+ Tramway::Error.raise_error :tramway, :application_form, :initialize, :polymorphic_class_is_nil,
20
+ association_name: association
21
+ else
22
+ model.send "#{association}=", association_class(value).find(value.split('_')[-1])
23
+ send "#{association}_type=", association_class(value).to_s
24
+ end
25
+ end
26
+ end
27
+ end
28
+
29
+ private
30
+
31
+ def association_class(value)
32
+ association_class_object = value.split('_')[0..-2].join('_').camelize
33
+ association_class_object = association_class_object.constantize if association_class_object.is_a? String
34
+ association_class_object
35
+ end
36
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tramway::ApplicationForms::ConstantClassActions
4
+ def validation_group_class
5
+ ActiveModel
6
+ end
7
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tramway::ApplicationForms::ConstantObjectActions
4
+ def delegating(object)
5
+ %i[to_key errors].each { |method| self.class.send(:define_method, method) { object.send method } }
6
+ end
7
+
8
+ def build_errors; end
9
+
10
+ def attributes
11
+ properties.reduce({}) do |hash, property|
12
+ value = if model.respond_to? :values
13
+ model.values[property.first.to_s]
14
+ else
15
+ model.send(property.first.to_s)
16
+ end
17
+ hash.merge! property.first => value
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tramway::ApplicationForms::Frontend
4
+ def react_component(on: false)
5
+ @react_component = on
6
+ end
7
+
8
+ def react_component?
9
+ @react_component ||= false
10
+ @react_component
11
+ end
12
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tramway::ApplicationForms::ObjectHelpers
4
+ def to_model
5
+ self
6
+ end
7
+
8
+ def persisted?
9
+ model.id.nil?
10
+ end
11
+
12
+ def model
13
+ @object
14
+ end
15
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tramway::ApplicationForms::PropertiesObjectHelper
4
+ def form_properties(**args)
5
+ @form_properties = args
6
+ end
7
+
8
+ def properties
9
+ @form_properties ||= {}
10
+ yaml_config_file_path = Rails.root.join('app', 'forms', "#{self.class.name.underscore}.yml")
11
+
12
+ return @form_properties unless File.exist? yaml_config_file_path
13
+
14
+ @form_properties.deep_merge YAML.load_file(yaml_config_file_path).deep_symbolize_keys
15
+ end
16
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tramway::ApplicationForms::SubmitHelper
4
+ def submit(params)
5
+ if params
6
+ params.each { |key, value| send("#{key}=", value) }
7
+ result = save
8
+ result.tap do
9
+ collecting_associations_errors unless result
10
+ end
11
+ else
12
+ Tramway::Error.raise_error(:tramway, :application_form, :submit, :params_should_not_be_nil)
13
+ end
14
+ end
15
+
16
+ def save
17
+ model.save
18
+ rescue ArgumentError => e
19
+ Tramway::Error.raise_error :tramway, :application_form, :save, :argument_error, message: e.message
20
+ rescue StandardError => e
21
+ raise e unless e.try :name
22
+
23
+ Tramway::Error.raise_error :tramway, :application_form, :save, :looks_like_you_have_method,
24
+ method_name: e.name.to_s.gsub('=', ''), model_class: model.class, class_name: self.class
25
+ end
26
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Tramway::ExtendableForm
4
+ class << self
5
+ include Tramway::ExtendableFormsHelpers::ClassBuilder
6
+
7
+ def new(name, simple_properties: {}, **more_properties)
8
+ if Object.const_defined? name
9
+ name.constantize
10
+ else
11
+ build_form_class name, simple_properties, more_properties
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tramway::ExtendableFormsHelpers::ClassBuilder
4
+ def build_form_class(name, simple_properties, more_properties)
5
+ Object.const_set(name, Class.new(::Tramway::ApplicationForm) do
6
+ properties(*simple_properties.keys) if simple_properties.keys.any?
7
+
8
+ include Tramway::ExtendableFormsHelpers::Submit::ObjectHelpers
9
+ include Tramway::ExtendableFormsHelpers::Validators
10
+ extend Tramway::ExtendableFormsHelpers::Submit::ClassHelpers
11
+ extend Tramway::ExtendableFormsHelpers::PropertiesHelper
12
+ extend Tramway::ExtendableFormsHelpers::MorePropertiesHelper
13
+ extend Tramway::ExtendableFormsHelpers::IgnoredPropertiesHelper
14
+
15
+ define_submit_method simple_properties, more_properties
16
+ define_properties_method simple_properties, more_properties
17
+ define_ignored_properties_method
18
+
19
+ more_properties.each do |property|
20
+ define_property_method property[0]
21
+
22
+ case property[1][:object].field_type
23
+ when 'file'
24
+ field = property[1][:object]
25
+ define_file_property_assignment_method property, field
26
+ else
27
+ # next unless property[1][:validates].present?
28
+
29
+ define_assignment_method property
30
+ end
31
+ end
32
+ end)
33
+ end
34
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tramway::ExtendableFormsHelpers::IgnoredPropertiesHelper
4
+ def define_ignored_properties_method
5
+ define_method :jsonb_ignored_properties do |properties|
6
+ properties.map do |property|
7
+ property[0].to_s if property[1][:object].field_type == 'file'
8
+ end.compact
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tramway::ExtendableFormsHelpers::MorePropertiesHelper
4
+ def define_property_method(property_name)
5
+ define_method property_name do
6
+ model.values[property_name] if model.values
7
+ end
8
+ end
9
+
10
+ def define_assignment_method(property)
11
+ define_method "#{property[0]}=" do |value|
12
+ if property[1][:validates].present?
13
+ property[1][:validates].each do |pair|
14
+ make_validates property[0], pair, value
15
+ end
16
+ else
17
+ model.values.merge property[0] => value
18
+ end
19
+ end
20
+ end
21
+
22
+ def define_file_property_assignment_method(property, field)
23
+ define_method "#{property[0]}=" do |value|
24
+ file_instance = property[1][:association_model].find_or_create_by(
25
+ "#{model.class.name.underscore}_id" => model.id, "#{field.class.name.underscore}_id" => field.id
26
+ )
27
+ file_instance.file = value
28
+ file_instance.save!
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tramway::ExtendableFormsHelpers::PropertiesHelper
4
+ def define_properties_method(simple_properties, more_properties)
5
+ define_method 'properties' do
6
+ hash = simple_properties.each_with_object({}) do |property, h|
7
+ h.merge! property[0] => property[1] unless model.class.state_machines_names.include?(property[0])
8
+ end
9
+ more_properties.reduce(hash) do |h, property|
10
+ h.merge! property[0] => {
11
+ extended_form_property: property[1][:object]
12
+ }
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tramway::ExtendableFormsHelpers::Submit::ClassHelpers
4
+ def define_submit_method(simple_properties, more_properties)
5
+ define_method 'submit' do |params|
6
+ model.values ||= {}
7
+ extended_params = extended(simple_properties, more_properties, params)
8
+ every_attribute_set params
9
+ model.values = extended_params.reduce(model.values) do |hash, (key, value)|
10
+ hash.merge! key => value
11
+ end
12
+
13
+ return unless model.errors.empty?
14
+
15
+ save_in_submit params
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tramway::ExtendableFormsHelpers::Submit::ObjectHelpers
4
+ def extended(simple_properties, more_properties, params)
5
+ params.except(*simple_properties.keys).except(*jsonb_ignored_properties(more_properties)).permit!.to_h
6
+ end
7
+
8
+ def every_attribute_set(params)
9
+ params.each do |key, value|
10
+ method_name = "#{key}="
11
+ send(method_name, value) if respond_to?(method_name)
12
+ end
13
+ end
14
+
15
+ def save_in_submit(_params)
16
+ result = save
17
+ result.tap do
18
+ collecting_associations_errors unless result
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tramway::ExtendableFormsHelpers::Validators
4
+ def make_validates(property_name, validation, value)
5
+ case validation[0].to_s
6
+ when 'presence'
7
+ presence_validator property_name, validation, value
8
+ when 'inclusion'
9
+ inclusion_validator property_name, validation, value
10
+ end
11
+ end
12
+
13
+ def presence_validator(property_name, validation, value)
14
+ validator_object = PresenceValidator.new(attributes: :not_blank)
15
+ return if validation[1] == 'false'
16
+ return if validation[1] == 'true' && validator_object.send(:valid?, value)
17
+
18
+ model.errors.add(
19
+ property_name,
20
+ I18n.t(
21
+ "activerecord.errors.models.#{model.class.name.underscore}.attributes.default.#{validation[0]}",
22
+ value: value
23
+ )
24
+ )
25
+ end
26
+
27
+ def inclusion_validator(property_name, validation, value)
28
+ in_array = validation[1][:in]
29
+
30
+ return if value.in? in_array
31
+
32
+ model.errors.add(
33
+ property_name,
34
+ I18n.t(
35
+ "activerecord.errors.models.#{model.class.name.underscore}.attributes.default.#{validation[0]}",
36
+ value: value
37
+ )
38
+ )
39
+ end
40
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Tramway::ExtendedApplicationForm < Tramway::ApplicationForm
4
+ class << self
5
+ def properties(*args)
6
+ @@extendable_properties ||= []
7
+ @@extendable_properties += args
8
+ super(*args)
9
+ end
10
+ end
11
+
12
+ def initialize(model)
13
+ @@extendable_properties.each do |prop|
14
+ next if model.respond_to? prop
15
+
16
+ model.class.define_method prop do
17
+ end
18
+ model.class.define_method "#{prop}=" do |value|
19
+ end
20
+ end
21
+ super
22
+ end
23
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Tramway::FormCreator
4
+ def self.create_form_class
5
+ raise 'Please, implement `create_form_class` for your class'
6
+ end
7
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Tramway::SessionForm < Tramway::ApplicationForm
4
+ properties :email
5
+ attr_accessor :password
6
+
7
+ def initialize(object)
8
+ object = Tramway::User.new unless object.present?
9
+
10
+ super
11
+ end
12
+
13
+ def validate(params)
14
+ (add_wrong_email_or_password_error && return) if model.new_record?
15
+
16
+ (!model.new_record? && model.authenticate(params[:password])).tap do |result|
17
+ add_wrong_email_or_password_error unless result
18
+ end
19
+ end
20
+
21
+ private
22
+
23
+ def add_wrong_email_or_password_error
24
+ errors.add(:email, I18n.t('errors.wrong_email_or_password'))
25
+ end
26
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tramway::ActionsHelper
4
+ def create_is_available?(model_class)
5
+ Tramway.action_is_available?(
6
+ nil,
7
+ project: (@application_engine || @application.name),
8
+ model_name: model_class,
9
+ role: current_user.role,
10
+ action: :create
11
+ )
12
+ end
13
+
14
+ def update_is_available?(object)
15
+ Tramway.action_is_available?(
16
+ object,
17
+ project: (@application_engine || @application.name),
18
+ model_name: object.model.class.name,
19
+ role: current_user.role,
20
+ action: :update
21
+ )
22
+ end
23
+
24
+ def destroy_is_available?(object)
25
+ Tramway.action_is_available?(
26
+ object,
27
+ project: (@application_engine || @application.name),
28
+ model_name: object.model.class.name,
29
+ role: current_user.role,
30
+ action: :destroy
31
+ )
32
+ end
33
+
34
+ # delete_button is in smart-buttons gem
35
+
36
+ def edit_button(url:, button_options:, &block)
37
+ link_to(url, **button_options, &block)
38
+ end
39
+
40
+ def habtm_destroy_is_available?(association_object, main_object)
41
+ main_model_name = main_object.model.class.to_s.underscore.pluralize
42
+
43
+ Tramway.forms&.include?("#{main_model_name}/remove_#{association_object.model.class.to_s.underscore}")
44
+ end
45
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tramway::AdditionalButtonsBuilder
4
+ def build_button(button)
5
+ options = button[:options] || {}
6
+ style = 'margin-right: 8px'
7
+ concat(link_to(button[:url], method: button[:method], class: "btn btn-#{button[:color]} btn-xs", style: style,
8
+ **options) do
9
+ button[:inner]&.call
10
+ end)
11
+ end
12
+ end