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,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Tramway::HasAndBelongsToManyRecordsController < Tramway::ApplicationController
4
+ def create
5
+ base_object = model_class.find params[:object_id]
6
+ @record_form = form_class.new base_object
7
+ @sending_params = params[params[:model_class].underscore] || params[form_class.associated_as]
8
+ redirect_to path
9
+ end
10
+
11
+ def destroy
12
+ base_object = model_class.find params[:object_id]
13
+ @record_form = params[:form].constantize.new base_object
14
+ redirect_to path
15
+ end
16
+
17
+ private
18
+
19
+ def path
20
+ params[:redirect].present? ? params[:redirect] : record_path(base_object, model: base_object.class)
21
+ end
22
+
23
+ def form_class
24
+ params[:form].constantize
25
+ end
26
+ end
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Tramway::RecordsController < Tramway::ApplicationController
4
+ def index
5
+ records = model_class.order(id: :desc).send scope
6
+ records = full_text_search records
7
+ records = filtering records
8
+ records = list_filtering records
9
+ records = records.public_send current_user_role_scope, current_user.id
10
+ @records = decorator_class.decorate records.page params[:page]
11
+ end
12
+
13
+ def show
14
+ @record = decorator_class.decorate model_class.find params[:id]
15
+ end
16
+
17
+ def new
18
+ @record_form = admin_form_class.new model_class.new
19
+ end
20
+
21
+ def create
22
+ @record_form = admin_form_class.new model_class.new
23
+ if @record_form.submit params[attributes_key]
24
+ redirect_to params[:redirect].present? ? params[:redirect] : record_path(@record_form.model)
25
+ else
26
+ render :new
27
+ end
28
+ end
29
+
30
+ def edit
31
+ @record_form = admin_form_class.new model_class.find params[:id]
32
+ end
33
+
34
+ def update
35
+ @record_form = admin_form_class.new model_class.find params[:id]
36
+ if state_event.present?
37
+ if record_state_event?
38
+ record_make_state_event!
39
+ default_redirect
40
+ end
41
+ elsif @record_form.submit params[attributes_key]
42
+ default_redirect
43
+ else
44
+ render :edit
45
+ end
46
+ end
47
+
48
+ def destroy
49
+ record = model_class.find params[:id]
50
+ record.destroy
51
+ redirect_to params[:redirect].present? ? params[:redirect] : records_path
52
+ end
53
+
54
+ private
55
+
56
+ def default_redirect
57
+ redirect_to params[:redirect].present? ? params[:redirect] : record_path(@record_form.model)
58
+ end
59
+
60
+ def record_state_event?
61
+ @record_form.model.public_send("may_#{state_event}?")
62
+ end
63
+
64
+ def record_make_state_event!
65
+ @record_form.model.send("#{state_event}!")
66
+ end
67
+
68
+ def state_event
69
+ params[attributes_key][:aasm_event]
70
+ end
71
+
72
+ def scope
73
+ params[:scope].present? ? params[:scope] : :all
74
+ end
75
+
76
+ def full_text_search(records)
77
+ params[:search].present? ? records.full_text_search(params[:search]) : records
78
+ end
79
+
80
+ def attributes_key
81
+ old_key_name = model_class.to_s.underscore
82
+ actual_key_name = :record
83
+
84
+ params[old_key_name].present? ? old_key_name : actual_key_name
85
+ end
86
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ # FIXME: configurate load_path
4
+ load "#{Tramway.root}/app/controllers/concerns/auth_management.rb"
5
+
6
+ class Tramway::SessionsController < Tramway::ApplicationController
7
+ before_action :redirect_if_signed_in, except: :destroy
8
+
9
+ # FIXME: should be included in Tramway::ApplicationController
10
+ include Tramway::AuthManagement
11
+
12
+ def new
13
+ @session_form = Tramway::SessionForm.new Tramway::User.new
14
+ end
15
+
16
+ def create
17
+ @session_form = Tramway::SessionForm.new record
18
+
19
+ if @session_form.validate params[:user]
20
+ sign_in @session_form.model
21
+ redirect_to root_path
22
+ else
23
+ render :new
24
+ end
25
+ end
26
+
27
+ def destroy
28
+ root_path = Tramway::Engine.routes.url_helpers.root_path
29
+ sign_out
30
+
31
+ redirect_to params[:redirect] || root_path
32
+ end
33
+
34
+ private
35
+
36
+ def redirect_if_signed_in
37
+ if params[:model].present? && signed_in? && request.env['PATH_INFO'] != Tramway.root_path_for(current_user.class)
38
+ redirect_to Tramway.root_path_for(current_user.class)
39
+ end
40
+ end
41
+
42
+ def record
43
+ @record ||= params[:model].constantize.find_by email: params[:user][:email]
44
+ end
45
+
46
+ def root_path
47
+ Tramway::Engine.routes.url_helpers.root_path[0..-2]
48
+ end
49
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tramway
4
+ class SingletonsController < ApplicationController
5
+ def show
6
+ if model_class.first.present?
7
+ @singleton = decorator_class.decorate model_class.first
8
+ else
9
+ @singleton_form = admin_form_class.new model_class.new
10
+ render :new
11
+ nil
12
+ end
13
+ end
14
+
15
+ def edit
16
+ @singleton_form = admin_form_class.new model_class.first
17
+ end
18
+
19
+ def create
20
+ @singleton_form = admin_form_class.new model_class.new
21
+ if @singleton_form.submit params[:singleton]
22
+ redirect_to params[:redirect] || singleton_path(model: params[:model])
23
+ else
24
+ render :edit
25
+ end
26
+ end
27
+
28
+ def update
29
+ @singleton_form = admin_form_class.new model_class.first
30
+ if @singleton_form.submit params[:singleton]
31
+ redirect_to params[:redirect] || singleton_path(model: params[:model])
32
+ else
33
+ render :edit
34
+ end
35
+ end
36
+ end
37
+
38
+ private
39
+
40
+ # FIXME: replace to module
41
+ def singleton_path(*args, **options)
42
+ super args, options.merge(model: params[:model])
43
+ end
44
+
45
+ def edit_singleton_path(*args, **options)
46
+ super args, options.merge(model: params[:model])
47
+ end
48
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ # FIXME: configurate load_path
4
+ load "#{Tramway.root}/app/controllers/concerns/auth_management.rb"
5
+
6
+ class Tramway::WelcomeController < Tramway::ApplicationController
7
+ skip_before_action :check_available!
8
+
9
+ # FIXME: should be included in Tramway::ApplicationController
10
+ include Tramway::AuthManagement
11
+
12
+ before_action :authenticate_user!
13
+
14
+ def index
15
+ instance_exec(&::Tramway.welcome_page_actions) if ::Tramway.welcome_page_actions.present?
16
+ end
17
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Tramway::ApplicationDecoratedCollection < Array
4
+ def initialize(array, original_array)
5
+ @original_array = original_array
6
+ super(array)
7
+ end
8
+
9
+ attr_reader :original_array
10
+
11
+ delegate :total_pages, to: :original_array
12
+ delegate :total_count, to: :original_array
13
+ delegate :current_page, to: :original_array
14
+ delegate :limit_value, to: :original_array
15
+ end
@@ -0,0 +1,124 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'tramway/error'
4
+ require 'tramway/class_name_helpers'
5
+
6
+ class Tramway::ApplicationDecorator
7
+ include ActionView::Helpers
8
+ include ActionView::Context
9
+ include FontAwesome5::Rails::IconHelper
10
+ include Tramway::CopyToClipboardHelper
11
+ include Tramway::Associations::ObjectHelper
12
+ include Tramway::Attributes::ViewHelper
13
+ include Tramway::Concerns::TableBuilder
14
+ include Tramway::ClassNameHelpers
15
+
16
+ def initialize(object)
17
+ @object = object
18
+ end
19
+
20
+ def name
21
+ object.try(:name) || object.try(:title) || title
22
+ end
23
+
24
+ def title
25
+ Tramway::Error.raise_error(
26
+ :tramway, :application_decorator, :title, :please_implement_title,
27
+ class_name: self.class, object_class: object.class
28
+ )
29
+ end
30
+
31
+ def present?
32
+ object.present?
33
+ end
34
+
35
+ def render(view, **locals)
36
+ view_name = view.split('/').map.with_index do |dir, index|
37
+ if index == view.split('/').length - 1
38
+ "_#{dir}"
39
+ else
40
+ dir
41
+ end
42
+ end.join('/')
43
+ Haml::Engine.new(File.read("#{Rails.root}/app/views/#{view_name}.html.haml")).render(self, locals)
44
+ end
45
+
46
+ def listed_state_machines
47
+ nil
48
+ end
49
+
50
+ delegate :id, to: :object
51
+
52
+ class << self
53
+ include Tramway::Associations::ClassHelper
54
+ include Tramway::Delegating::ClassHelper
55
+ include Tramway::Default::ValuesHelper
56
+
57
+ def decorate(object_or_array)
58
+ is_activerecord_relation = object_or_array.class.superclass == ActiveRecord::Relation
59
+ is_activerecord_association_relation = object_or_array.class.to_s.include?('ActiveRecord_AssociationRelation')
60
+ if is_activerecord_relation || is_activerecord_association_relation
61
+ decorated_array = object_or_array.map do |obj|
62
+ new obj
63
+ end
64
+ Tramway::ApplicationDecoratedCollection.new decorated_array, object_or_array
65
+ else
66
+ new object_or_array
67
+ end
68
+ end
69
+
70
+ def model_class
71
+ to_s.sub(/Decorator$/, '').constantize
72
+ end
73
+
74
+ def model_name
75
+ model_class.try(:model_name)
76
+ end
77
+ end
78
+
79
+ def link
80
+ if object.try :file
81
+ object.file.url
82
+ else
83
+ Tramway::Error.raise_error :tramway, :application_decorator, :link, :method_link_uses_file_attribute
84
+ end
85
+ end
86
+
87
+ def additional_buttons
88
+ { show: [], index: [] }
89
+ end
90
+
91
+ def public_path; end
92
+
93
+ def model
94
+ object
95
+ end
96
+
97
+ def associations(associations_type)
98
+ object.class.reflect_on_all_associations(associations_type).map do |association|
99
+ association unless association.name == :audits
100
+ end.compact
101
+ end
102
+
103
+ include Tramway::Concerns::AttributesDecoratorHelper
104
+
105
+ RESERVED_WORDS = ['fields'].freeze
106
+
107
+ def attributes
108
+ object.attributes.reduce({}) do |hash, attribute|
109
+ if attribute[0].in? RESERVED_WORDS
110
+ Tramway::Error.raise_error(
111
+ :tramway, :application_decorator, :attributes, :method_is_reserved_word,
112
+ attribute_name: attribute[0], class_name: self.class.name
113
+ )
114
+ end
115
+ hash.merge! attribute[0] => build_viewable_value(object, attribute)
116
+ end
117
+ end
118
+
119
+ protected
120
+
121
+ attr_reader :object
122
+
123
+ def association_class_name; end
124
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tramway::Associations::ClassHelper
4
+ def decorate_association(association_name, decorator: nil, as: nil, state_machines: [])
5
+ @@decorated_associations ||= []
6
+ @@decorated_associations << association_name
7
+
8
+ define_main_association_method association_name, decorator
9
+
10
+ define_method "#{association_name}_as" do
11
+ as
12
+ end
13
+
14
+ define_method "#{association_name}_state_machines" do
15
+ state_machines
16
+ end
17
+
18
+ define_method "add_#{association_name}_form" do
19
+ add_association_form_class_name(object, association_name).new object
20
+ end
21
+ end
22
+
23
+ def decorate_associations(*association_names)
24
+ association_names.each do |association_name|
25
+ decorate_association association_name
26
+ end
27
+ end
28
+
29
+ def define_main_association_method(association_name, decorator)
30
+ define_method association_name do
31
+ association = object.class.reflect_on_association(association_name)
32
+ type = association_type(association)
33
+ return if association_has_one_without_object(object, association_name, type)
34
+
35
+ check_association object, association_name, association
36
+ decorator_class_name = decorator || decorator_class_name(class_name(association))
37
+ case type
38
+ when :has_many, :has_and_belongs_to_many
39
+ associations_collection(object, association_name, decorator_class_name)
40
+ when :belongs_to, :has_one
41
+ decorator_class_name.decorate(association_object(object, association_name))
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tramway::Associations::ObjectHelper
4
+ def class_name(association)
5
+ if association.polymorphic?
6
+ object.send(association.name).class
7
+ else
8
+ unless association.options[:class_name]
9
+ Tramway::Error.raise_error(
10
+ :tramway, :associations, :object_helper, :please_specify_association_name,
11
+ association_name: association.name, object_class: object.class,
12
+ association_class_name: association.name.to_s.singularize.camelize
13
+ )
14
+ end
15
+ association.options[:class_name]
16
+ end
17
+ end
18
+
19
+ def check_association(object, association_name, association)
20
+ return unless association.nil?
21
+
22
+ Tramway::Error.raise_error(
23
+ :tramway, :associations, :class_helper, :model_does_not_have_association,
24
+ object_class: object.class, association_name: association_name
25
+ )
26
+ end
27
+
28
+ def association_type(association)
29
+ association.class.to_s.split('::').last.sub(/Reflection$/, '').underscore.to_sym
30
+ end
31
+
32
+ def associations_collection(object, association_name, decorator_class_name)
33
+ object.send(association_name).map do |association_object|
34
+ decorator_class_name.decorate association_object
35
+ end
36
+ end
37
+
38
+ def add_association_form_class_name(object, association_name)
39
+ form_class = "Admin::#{object.class.to_s.pluralize}::Add#{association_name.to_s.camelize.singularize}Form"
40
+
41
+ begin
42
+ form_class.constantize
43
+ rescue StandardError
44
+ Tramway::Error.raise_error(
45
+ :tramway, :associations, :object_helper, :habtm_add_class_not_defined,
46
+ class: form_class, association_name: association_name
47
+ )
48
+ end
49
+ end
50
+
51
+ def association_has_one_without_object(object, association_name, association_type)
52
+ association_type == :has_one && object.send(association_name).nil?
53
+ end
54
+
55
+ def association_object(object, association_name)
56
+ object.send association_name
57
+ end
58
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tramway::Attributes::ViewHelper
4
+ def build_viewable_value(object, attribute)
5
+ value = try(attribute[0]) ? send(attribute[0]) : object.send(attribute[0])
6
+ return state_machine_view(object, attribute[0]) if state_machine? object, attribute[0]
7
+
8
+ view_by_value object, value, attribute
9
+ end
10
+
11
+ def state_machine?(object, attribute_name)
12
+ attribute_name.to_s.in? object.class.state_machines_names.map(&:to_s)
13
+ end
14
+
15
+ def view_by_value(object, value, attribute)
16
+ if value.class.in? [ActiveSupport::TimeWithZone, DateTime, Time]
17
+ datetime_view(attribute[1])
18
+ elsif value.instance_of?(PhotoUploader)
19
+ image_view(object.send(attribute[0]))
20
+ elsif value.instance_of?(FileUploader)
21
+ file_view(object.send(attribute[0]))
22
+ elsif value.is_a? Enumerize::Value
23
+ enumerize_view(value)
24
+ elsif value.is_a? Hash
25
+ yaml_view(value)
26
+ else
27
+ value
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,97 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tramway::Concerns::AttributesDecoratorHelper
4
+ def date_view(value)
5
+ I18n.l value.to_date if value
6
+ end
7
+
8
+ def datetime_view(value)
9
+ I18n.l value if value
10
+ end
11
+
12
+ def state_machine_view(object, attribute_name)
13
+ state = object.send(attribute_name)
14
+ I18n.t("state_machines.#{object.class.model_name.to_s.underscore}.#{attribute_name}.states.#{state}")
15
+ rescue StandardError
16
+ object.aasm.human_state
17
+ end
18
+
19
+ BASE64_REGEXP = %r{^(?:[a-zA-Z0-9+/]{4})*(?:|(?:[a-zA-Z0-9+/]{3}=)|
20
+ (?:[a-zA-Z0-9+/]{2}==)|(?:[a-zA-Z0-9+/]{1}===))$}x.freeze
21
+
22
+ def image_view(original, thumb: nil, filename: nil)
23
+ return unless original.present?
24
+
25
+ filename ||= build_filename(original)
26
+ content_tag(:div) do
27
+ build_div_content src_original(original), src_thumb(original, thumb), filename || build_filename(original)
28
+ end
29
+ end
30
+
31
+ def file_view(original, filename: nil)
32
+ return unless original.present?
33
+
34
+ filename ||= build_filename(original)
35
+ content_tag(:div) do
36
+ concat filename
37
+ concat ' '
38
+ concat download_button(filename: filename, original: original) if filename
39
+ end
40
+ end
41
+
42
+ def enumerize_view(value)
43
+ value.text
44
+ end
45
+
46
+ def yaml_view(value)
47
+ content_tag(:pre) { value.to_yaml }
48
+ end
49
+
50
+ private
51
+
52
+ def src_thumb(original, thumb)
53
+ thumb ||= original.is_a?(CarrierWave::Uploader::Base) ? original.small : nil
54
+ if thumb.is_a?(CarrierWave::Uploader::Base)
55
+ thumb.url
56
+ elsif thumb&.match(BASE64_REGEXP)
57
+ "data:image/jpeg;base64,#{thumb}"
58
+ else
59
+ thumb
60
+ end
61
+ end
62
+
63
+ def src_original(original)
64
+ case original
65
+ when CarrierWave::Uploader::Base
66
+ original.url
67
+ when BASE64_REGEXP
68
+ "data:image/jpeg;base64,#{original}"
69
+ else
70
+ original
71
+ end
72
+ end
73
+
74
+ def build_filename(original)
75
+ original.is_a?(CarrierWave::Uploader::Base) ? original.path&.split('/')&.last : nil
76
+ end
77
+
78
+ def build_div_content(original, thumb, filename)
79
+ begin
80
+ concat image_tag src_thumb(original, thumb) || src_original(original)
81
+ rescue NoMethodError => e
82
+ Tramway::Error.raise_error(
83
+ :tramway, :concerns, :attributes_decorator_helper, :you_should_mount_photo_uploader,
84
+ message: e.message, attribute_name: attribute_name
85
+ )
86
+ end
87
+ concat download_button(filename: filename, original: original) if filename
88
+ end
89
+
90
+ def download_button(filename:, original:)
91
+ link_to(fa_icon(:download), src_original(original), class: 'btn btn-success', download: filename)
92
+ end
93
+
94
+ def yes_no(boolean_attr)
95
+ boolean_attr.to_s == 'true' ? I18n.t('helpers.yes') : I18n.t('helpers.no')
96
+ end
97
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tramway::Concerns::TableBuilder
4
+ def table(**options, &block)
5
+ content_tag(:table, class: 'table table-bordered table-striped', **options) do
6
+ yield if block
7
+ end
8
+ end
9
+
10
+ def thead(**options, &block)
11
+ content_tag(:thead, **options) do
12
+ yield if block
13
+ end
14
+ end
15
+
16
+ def th(**options, &block)
17
+ content_tag(:th, **options) do
18
+ yield if block
19
+ end
20
+ end
21
+
22
+ def td(**options, &block)
23
+ content_tag(:td, **options) do
24
+ yield if block
25
+ end
26
+ end
27
+
28
+ def tr(**options, &block)
29
+ content_tag(:tr, **options) do
30
+ yield if block
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tramway::Default::ValuesHelper
4
+ def collections
5
+ [:all]
6
+ end
7
+
8
+ def list_attributes
9
+ []
10
+ end
11
+
12
+ def show_attributes
13
+ []
14
+ end
15
+
16
+ def show_associations
17
+ []
18
+ end
19
+
20
+ def list_filters
21
+ {}
22
+ end
23
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tramway::Delegating::ClassHelper
4
+ def delegate_attributes(*attributes)
5
+ attributes.each do |attr|
6
+ delegate attr, to: :object
7
+ end
8
+ end
9
+ end