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,133 @@
1
+ # frozen_string_literal: true
2
+
3
+ SimpleForm.setup do |config|
4
+ config.error_notification_class = 'alert alert-danger'
5
+ config.button_class = 'btn btn-default'
6
+ config.boolean_label_class = nil
7
+
8
+ config.wrappers :vertical_form, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
9
+ b.use :html5
10
+ b.use :placeholder
11
+ b.optional :maxlength
12
+ b.optional :pattern
13
+ b.optional :min_max
14
+ b.optional :readonly
15
+ b.use :label, class: 'control-label'
16
+
17
+ b.use :input, class: 'form-control'
18
+ b.use :error, wrap_with: { tag: 'span', class: 'help-block' }
19
+ b.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
20
+ end
21
+
22
+ config.wrappers :vertical_file_input, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
23
+ b.use :html5
24
+ b.use :placeholder
25
+ b.optional :maxlength
26
+ b.optional :readonly
27
+ b.use :label, class: 'control-label'
28
+
29
+ b.use :input
30
+ b.use :error, wrap_with: { tag: 'span', class: 'help-block' }
31
+ b.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
32
+ end
33
+
34
+ config.wrappers :vertical_boolean, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
35
+ b.use :html5
36
+ b.optional :readonly
37
+
38
+ b.wrapper tag: 'div', class: 'checkbox' do |ba|
39
+ ba.use :label_input
40
+ end
41
+
42
+ b.use :error, wrap_with: { tag: 'span', class: 'help-block' }
43
+ b.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
44
+ end
45
+
46
+ config.wrappers :vertical_radio_and_checkboxes, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
47
+ b.use :html5
48
+ b.optional :readonly
49
+ b.use :label, class: 'control-label'
50
+ b.use :input
51
+ b.use :error, wrap_with: { tag: 'span', class: 'help-block' }
52
+ b.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
53
+ end
54
+
55
+ config.wrappers :horizontal_form, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
56
+ b.use :html5
57
+ b.use :placeholder
58
+ b.optional :maxlength
59
+ b.optional :pattern
60
+ b.optional :min_max
61
+ b.optional :readonly
62
+ b.use :label, class: 'col-sm-3 control-label'
63
+
64
+ b.wrapper tag: 'div', class: 'col-sm-9' do |ba|
65
+ ba.use :input, class: 'form-control'
66
+ ba.use :error, wrap_with: { tag: 'span', class: 'help-block' }
67
+ ba.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
68
+ end
69
+ end
70
+
71
+ config.wrappers :horizontal_file_input, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
72
+ b.use :html5
73
+ b.use :placeholder
74
+ b.optional :maxlength
75
+ b.optional :readonly
76
+ b.use :label, class: 'col-sm-3 control-label'
77
+
78
+ b.wrapper tag: 'div', class: 'col-sm-9' do |ba|
79
+ ba.use :input
80
+ ba.use :error, wrap_with: { tag: 'span', class: 'help-block' }
81
+ ba.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
82
+ end
83
+ end
84
+
85
+ config.wrappers :horizontal_boolean, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
86
+ b.use :html5
87
+ b.optional :readonly
88
+
89
+ b.wrapper tag: 'div', class: 'col-sm-offset-3 col-sm-9' do |wr|
90
+ wr.wrapper tag: 'div', class: 'checkbox' do |ba|
91
+ ba.use :label_input, class: 'col-sm-9'
92
+ end
93
+
94
+ wr.use :error, wrap_with: { tag: 'span', class: 'help-block' }
95
+ wr.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
96
+ end
97
+ end
98
+
99
+ config.wrappers :horizontal_radio_and_checkboxes, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
100
+ b.use :html5
101
+ b.optional :readonly
102
+
103
+ b.use :label, class: 'col-sm-3 control-label'
104
+
105
+ b.wrapper tag: 'div', class: 'col-sm-9' do |ba|
106
+ ba.use :input
107
+ ba.use :error, wrap_with: { tag: 'span', class: 'help-block' }
108
+ ba.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
109
+ end
110
+ end
111
+
112
+ config.wrappers :inline_form, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
113
+ b.use :html5
114
+ b.use :placeholder
115
+ b.optional :maxlength
116
+ b.optional :pattern
117
+ b.optional :min_max
118
+ b.optional :readonly
119
+ b.use :label, class: 'sr-only'
120
+
121
+ b.use :input, class: 'form-control'
122
+ b.use :error, wrap_with: { tag: 'span', class: 'help-block' }
123
+ b.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
124
+ end
125
+
126
+ config.default_wrapper = :vertical_form
127
+ config.wrapper_mappings = {
128
+ check_boxes: :vertical_radio_and_checkboxes,
129
+ radio_buttons: :vertical_radio_and_checkboxes,
130
+ file: :vertical_file_input,
131
+ boolean: :vertical_boolean
132
+ }
133
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tramway::Generators
4
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tramway::Navbar
4
+ def navbar_structure(*links, project:)
5
+ @navbar_structure ||= {}
6
+ @navbar_structure.merge! project => links
7
+ end
8
+
9
+ def navbar_items_for(project, role:)
10
+ project = project.underscore.to_sym unless project.is_a? Symbol
11
+
12
+ return [] unless @navbar_structure&.dig(project).present?
13
+
14
+ @navbar_structure[project].map { |item| add_to_navbar item, project, role }.compact || []
15
+ end
16
+
17
+ private
18
+
19
+ def should_be_in_navbar_as(item, project, role)
20
+ if singleton_models_for(project, role: role).map(&:to_s).include?(item.to_s)
21
+ { item.to_s => :singleton }
22
+ elsif available_models_for(project, role: role).map(&:to_s).include?(item.to_s)
23
+ { item.to_s => :record }
24
+ elsif item.is_a? Symbol
25
+ :divider
26
+ end
27
+ end
28
+
29
+ def parse_hash_options_to_navbar(item, project, role)
30
+ sub_items = item.values.first.map do |sub_item|
31
+ should_be_in_navbar_as sub_item, project, role
32
+ end.compact
33
+ { item.keys.first => sub_items } if sub_items.any?
34
+ end
35
+
36
+ def add_to_navbar(item, project, role)
37
+ case item
38
+ when Class, String
39
+ should_be_in_navbar_as item, project, role
40
+ when Hash
41
+ parse_hash_options_to_navbar item, project, role
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tramway::Notifications
4
+ def set_notificable_queries(**queries)
5
+ @notificable_queries ||= {}
6
+ @notificable_queries.merge! queries
7
+ end
8
+
9
+ def notificable_queries
10
+ @notificable_queries
11
+ end
12
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tramway::RecordRoutesHelper
4
+ def record_path(*args, **options)
5
+ options[:model] ||= params[:model]
6
+ super args, options
7
+ end
8
+
9
+ def edit_record_path(*args, **options)
10
+ options[:model] ||= params[:model]
11
+ super args, options
12
+ end
13
+
14
+ def new_record_path(*args, **options)
15
+ options[:model] ||= params[:model]
16
+ super args, options
17
+ end
18
+
19
+ def records_path(*args, **options)
20
+ options[:model] ||= params[:model]
21
+ super args, options
22
+ end
23
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tramway::RecordsModels
4
+ def set_available_models(*models, project:, role: :admin)
5
+ initialize_available_models_for project, role
6
+
7
+ models.each do |model|
8
+ if model.instance_of?(Class) || model.instance_of?(String)
9
+ @available_models[project][role].merge! model.to_s => %i[index show update create destroy]
10
+ elsif model.instance_of?(Hash)
11
+ @available_models[project][role].merge! model
12
+ end
13
+ end
14
+ @available_models = @available_models.with_indifferent_access
15
+ end
16
+
17
+ def available_models_for(project, role: :admin)
18
+ project = project.underscore.to_sym unless project.is_a? Symbol
19
+ models = get_models_by_key(@available_models, project, role)
20
+ models = available_models_for_engine(project, role, models) if project_is_engine?(project)
21
+
22
+ models.map do |model|
23
+ model.instance_of?(String) ? model.constantize : model
24
+ end
25
+ end
26
+
27
+ def available_models(role:)
28
+ models_array models_type: :available, role: role
29
+ end
30
+
31
+ def clear_available_models!
32
+ @available_models = {}
33
+ end
34
+
35
+ private
36
+
37
+ def initialize_available_models_for(project, role)
38
+ @available_models ||= {}
39
+ @available_models[project] ||= {}
40
+ @available_models[project][role] ||= {}
41
+ end
42
+
43
+ def available_models_for_engine(project, role, models)
44
+ models + engine_class(project).dependencies.map do |dependency|
45
+ if @available_models&.dig(dependency, role).present?
46
+ @available_models&.dig(dependency, role)&.keys
47
+ else
48
+ Tramway::Error.raise_error :records, :there_is_no_dependency, dependency: dependency, project: project
49
+ end
50
+ end.flatten.compact
51
+ end
52
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tramway::SingletonModels
4
+ def set_singleton_models(*models, project:, role: :admin)
5
+ @singleton_models ||= {}
6
+ @singleton_models[project] ||= {}
7
+ @singleton_models[project][role] ||= {}
8
+ models.each do |model|
9
+ if model.instance_of?(Class)
10
+ @singleton_models[project][role].merge! model.to_s => %i[index show update create destroy]
11
+ elsif model.instance_of?(Hash)
12
+ @singleton_models[project][role].merge! model.to_s
13
+ end
14
+ end
15
+ @singleton_models = @singleton_models.with_indifferent_access
16
+ end
17
+
18
+ def singleton_models_for(project, role: :admin)
19
+ project = project.underscore.to_sym unless project.is_a? Symbol
20
+ models = get_models_by_key(@singleton_models, project, role)
21
+ if project_is_engine?(project)
22
+ models += engine_class(project).dependencies.map do |dependency|
23
+ @singleton_models&.dig(dependency, role)&.keys
24
+ end.flatten.compact
25
+ end
26
+ models
27
+ end
28
+
29
+ def singleton_models(role:)
30
+ models_array models_type: :singleton, role: role
31
+ end
32
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NavbarHelper
4
+ def click_on_dropdown(text)
5
+ first('ul.navbar-nav li.nav-item.dropdown a.nav-link.dropdown-toggle', text: text, visible: true).click
6
+ end
7
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TramwayHelpers
4
+ def click_on_association_delete_button(object)
5
+ delete_path = ::Tramway::Engine.routes.url_helpers.record_path(
6
+ object.id,
7
+ model: object.class
8
+ )
9
+ row = find("td[colspan='2'] td a[href='#{delete_path}']").parent_node(level: 2)
10
+ row.find('td button.delete[type="submit"]').click
11
+ end
12
+
13
+ def click_on_tab(text)
14
+ find('li.nav-item a.nav-link', text: text).click
15
+ end
16
+
17
+ def click_on_table_item(text)
18
+ find('table td a', text: text).click
19
+ end
20
+
21
+ def click_on_delete_button(object)
22
+ delete_path = ::Tramway::Engine.routes.url_helpers.record_path(
23
+ object.id,
24
+ model: object.class
25
+ )
26
+ form = find("form[action='#{delete_path}']")
27
+ form.find('button[type="submit"]').click
28
+ end
29
+
30
+ def fill_in_ckeditor(name, with:)
31
+ id = name.gsub(']', '').split('[').join('_')
32
+ content = with.to_json # convert to a safe javascript string
33
+ page.execute_script <<-SCRIPT
34
+ CKEDITOR.instances['#{id}'].setData(#{content});
35
+ $('textarea##{id}').text(#{content});
36
+ SCRIPT
37
+ end
38
+
39
+ def fill_in_datepicker(name, with:)
40
+ return unless with.present?
41
+
42
+ input = find("input[name=#{name.gsub('[', '\[').gsub(']', '\]')}]")
43
+ input.click
44
+
45
+ find('td.day', text: /^#{with.day}$/, match: :first).click
46
+ end
47
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Tramway
2
- VERSION = "0.1.0"
4
+ VERSION = '0.1.1'
3
5
  end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tramway::WelcomePageActions
4
+ attr_accessor :welcome_page_actions
5
+ end
@@ -0,0 +1,49 @@
1
+ tramway:
2
+ project:
3
+ no_instance_of_application_class: "Looks like you have not create at least one instance of %{application_class} model OR Tramway Application Model is nil"
4
+ collections:
5
+ helper:
6
+ collection_list_by:
7
+ there_no_such_collection: "There no such collection named %{name_camelize}. Please create class with self method `list` and extended of `Tramway::Collection`. You should reload your server after creating this collection."
8
+ input_helper:
9
+ association_params:
10
+ defined_with_property_method: "It seems you've defined association attributes with `property` method. Please, use `association` method. `association :%{property}`"
11
+ use_polymorphic_association: "It seems you've used `association` input type in the Form. Please, use `polymorphic_association` type. `%{property}: :polymorphic_association`"
12
+ title_helper:
13
+ title:
14
+ you_should_set_tramway_application: "You should set Tramway::Core::Application class using `::Tramway::Core.initialize_application model_class: #{model_class_name}` in config/initializers/tramway.rb OR maybe you don't have any records of application model"
15
+ application_form:
16
+ initialize:
17
+ polymorphic_class_is_nil: "Polymorphic association class is nil. Maybe, you should write `assocation #{association_name}` after `properties #{association_name}_id, #{association_name}_type`"
18
+ validates:
19
+ you_need_to_set_model_class: 'You need to set `model_class` name while using validations. Just write `self.model_class = YOUR_MODEL_NAME` in the class area.'
20
+ submit:
21
+ params_should_not_be_nil: "ApplicationForm::Params should not be nil"
22
+ save:
23
+ looks_like_you_have_method: "Looks like you have method `%{method_name}` in %{model_class}. You should rename it or rename property in %{class_name}"
24
+ argument_error: "We have ArgumentError with message: %{message}"
25
+ model_class:
26
+ there_is_not_model_class: "There is not model class name for %{name}. Should be %{model_class_name} or you can use another class to initialize form object or just initialize form with object."
27
+ concerns:
28
+ attribute_decorator_helper:
29
+ you_should_mount_photo_uploader: "You should mount PhotoUploader to your model. Just add `mount_uploader %{attribute_name}, PhotoUploader` to your model. %{message}"
30
+ associations:
31
+ object_helper:
32
+ please_specify_association_name: "Please, specify `%{association_name}` association class_name in %{object_class} model. For example: `has_many :%{association_name}, class_name: '%{association_class_name}'`"
33
+ habtm_add_class_not_defined: "You should define class `%{class}` to be able add and remove `%{association_name}`"
34
+ class_helper:
35
+ model_does_not_have_association: "Model %{object_class} does not have association named `%{association_name}`"
36
+ application_decorator:
37
+ attributes:
38
+ method_is_reserved_word: "Method `%{attribute_name}` is reserved word. Please, create or delegate method in %{class_name} with another name."
39
+ title:
40
+ please_implement_title: "Please, implement `title` method in a %{class_name} or delegate it to %{object_class}"
41
+ link:
42
+ method_link_uses_file_attribute: "Method `link` uses `file` attribute of the decorated object. If decorated object doesn't contain `file`, you shouldn't use `link` method."
43
+ generators:
44
+ install: 'Initialize Tramway application before running generators. Add `Tramway.initialize_application name: :your_application_name` to `config/initializers/tramway.rb`'
45
+ records:
46
+ there_is_no_dependency: "There is no dependency `%{dependency}` for plugin: %{project}. Please, check file `tramway-%{project}/lib/tramway/%{project}/%{project}.rb`"
47
+ application_controller:
48
+ create_form_for_role: "Tramway - you should create form for role `%{role}` to edit %{model_class} model. It should be named %{class_name}"
49
+ model_or_form_not_available: 'Tramway - Model or Form is not available. Looks like current user does not have access to change this model. Update your tramway initializer file'
data/lib/tramway.rb CHANGED
@@ -1,5 +1,146 @@
1
- require "tramway/version"
1
+ # frozen_string_literal: true
2
+
3
+ require 'tramway/engine'
4
+ require 'tramway/collection'
5
+ require 'tramway/collections/helper'
6
+ require 'font_awesome5_rails'
7
+ require 'pg_search'
8
+ require 'validators/presence_validator'
9
+ require 'tramway/singleton_models'
10
+ require 'tramway/records_models'
11
+ require 'tramway/forms'
12
+ require 'tramway/notifications'
13
+ require 'tramway/welcome_page_actions'
14
+ require 'tramway/navbar'
15
+ require 'tramway/error'
16
+ require 'tramway/generators/install_generator'
17
+ require 'tramway/class_name_helpers'
2
18
 
3
19
  module Tramway
4
- # Your code goes here...
20
+ class << self
21
+ def initialize_application(**options)
22
+ @application ||= Tramway::Application.new
23
+
24
+ options.each { |attr, value| @application.send "#{attr}=", value }
25
+ end
26
+
27
+ def application_object
28
+ @application&.model_class.present? ? @application.model_class.first : @application
29
+ end
30
+
31
+ def root
32
+ File.dirname __dir__
33
+ end
34
+
35
+ attr_reader :application, :customized_admin_navbar
36
+
37
+ include Tramway::RecordsModels
38
+ include Tramway::SingletonModels
39
+ include Tramway::Forms
40
+ include Tramway::Notifications
41
+ include Tramway::WelcomePageActions
42
+ include Tramway::Navbar
43
+
44
+ def engine_class(project)
45
+ class_name = "Tramway::#{project.to_s.camelize}"
46
+ class_name.classify.safe_constantize
47
+ end
48
+
49
+ def project_is_engine?(project)
50
+ engine_class(project)
51
+ end
52
+
53
+ def get_models_by_key(checked_models, project, role)
54
+ unless project.present?
55
+ Tramway::Error.raise_error(
56
+ :tramway,
57
+ :project,
58
+ :no_instance_of_application_class,
59
+ application_class: Tramway.application.model_class
60
+ )
61
+ end
62
+
63
+ checked_models && checked_models[project]&.dig(role)&.keys || []
64
+ end
65
+
66
+ def models_array(models_type:, role:)
67
+ instance_variable_get("@#{models_type}_models")&.map { |projects| projects.last[role]&.keys }&.flatten || []
68
+ end
69
+
70
+ def action_is_available?(record, project:, role:, model_name:, action:)
71
+ project = project.underscore.to_sym unless project.is_a? Symbol
72
+ actions = select_actions(project: project, role: role.to_sym, model_name: model_name)
73
+ availability = compute_availability actions, action
74
+
75
+ return false unless availability.present?
76
+ return true if availability.is_a? Symbol
77
+
78
+ availability.call record
79
+ end
80
+
81
+ def compute_availability(actions, action)
82
+ case actions
83
+ when Array
84
+ actions.select { |a| a.to_sym == action.to_sym }.first
85
+ when Hash
86
+ actions[action.to_sym]
87
+ end
88
+ end
89
+
90
+ def select_actions(project:, role:, model_name:)
91
+ stringify = ->(models) { stringify_keys(models&.dig(project, role))&.dig(model_name) }
92
+ stringify.call(@singleton_models) || stringify.call(@available_models)
93
+ end
94
+
95
+ def stringify_keys(hash)
96
+ hash&.reduce({}) { |new_hash, pair| new_hash.merge! pair[0].to_s => pair[1] }
97
+ end
98
+
99
+ def admin_model
100
+ auth_config.first[:user_model]
101
+ end
102
+
103
+ def auth_config
104
+ @@auth_config ||= [{ user_model: Tramway::User, auth_attributes: :email }]
105
+ @@auth_config
106
+ end
107
+
108
+ def auth_config=(params)
109
+ case params
110
+ when Hash
111
+ @@auth_config = [params]
112
+ when Array
113
+ @@auth_config = params
114
+ end
115
+ end
116
+
117
+ def user_based_models
118
+ @@auth_config ||= []
119
+ @@auth_config.map do |conf|
120
+ conf[:user_model]
121
+ end
122
+ end
123
+
124
+ def auth_attributes
125
+ @@auth_config ||= []
126
+ @@auth_config.reduce({}) do |hash, conf|
127
+ hash.merge! conf[:user_model] => conf[:auth_attributes]
128
+ end
129
+ end
130
+
131
+ def root_path_for=(**options)
132
+ @root_path ||= {}
133
+ @root_path.merge! options
134
+ end
135
+
136
+ def root_path_for(user_class)
137
+ @root_path&.dig(user_class) || '/'
138
+ end
139
+ end
140
+ end
141
+
142
+ # HACK: FIXME
143
+
144
+ class ActiveModel::Errors
145
+ def merge!(*args); end
5
146
  end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ class PresenceValidator
4
+ def initialize(attributes); end
5
+
6
+ def valid?(value)
7
+ value.present?
8
+ end
9
+ end