tybo 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (141) hide show
  1. checksums.yaml +4 -4
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +23 -0
  4. data/Rakefile +8 -0
  5. data/app/assets/config/tybo_manifest.js +1 -0
  6. data/app/assets/stylesheets/tybo/application.css +15 -0
  7. data/{lib/app → app}/components/attachment_card_component.html.erb +0 -0
  8. data/{lib/app → app}/components/attachment_card_component.rb +0 -0
  9. data/{lib/app → app}/components/attachments_list_component.html.erb +0 -0
  10. data/{lib/app → app}/components/attachments_list_component.rb +0 -0
  11. data/{lib/app → app}/components/current_user_mini_card_component.html.erb +2 -2
  12. data/{lib/app → app}/components/current_user_mini_card_component.rb +0 -0
  13. data/{lib/app → app}/components/form_component.html.erb +0 -0
  14. data/{lib/app → app}/components/form_component.rb +0 -0
  15. data/{lib/app → app}/components/forms/breadcrumb_component.html.erb +0 -0
  16. data/{lib/app → app}/components/forms/breadcrumb_component.rb +0 -0
  17. data/{lib/app → app}/components/forms/delete_button_component.html.erb +0 -0
  18. data/{lib/app → app}/components/forms/delete_button_component.rb +0 -0
  19. data/{lib/app → app}/components/forms/divider_component.html.erb +0 -0
  20. data/{lib/app → app}/components/forms/divider_component.rb +0 -0
  21. data/{lib/app → app}/components/forms/submit_button_component.html.erb +0 -0
  22. data/{lib/app → app}/components/forms/submit_button_component.rb +0 -0
  23. data/{lib/app → app}/components/forms/subtitle_component.html.erb +0 -0
  24. data/{lib/app → app}/components/forms/subtitle_component.rb +0 -0
  25. data/{lib/app → app}/components/forms/title_component.html.erb +0 -0
  26. data/{lib/app → app}/components/forms/title_component.rb +0 -0
  27. data/{lib/app → app}/components/icons/collection_component.html.erb +0 -0
  28. data/{lib/app → app}/components/icons/collection_component.rb +0 -0
  29. data/{lib/app → app}/components/icons/home_component.html.erb +0 -0
  30. data/{lib/app → app}/components/icons/home_component.rb +0 -0
  31. data/{lib/app → app}/components/icons/mic_component.html.erb +0 -0
  32. data/{lib/app → app}/components/icons/mic_component.rb +0 -0
  33. data/{lib/app → app}/components/icons/news_paper_component.html.erb +0 -0
  34. data/{lib/app → app}/components/icons/news_paper_component.rb +0 -0
  35. data/{lib/app → app}/components/icons/office_building_component.html.erb +0 -0
  36. data/{lib/app → app}/components/icons/office_building_component.rb +0 -0
  37. data/{lib/app → app}/components/icons/question_mark_circle_component.html.erb +0 -0
  38. data/{lib/app → app}/components/icons/question_mark_circle_component.rb +0 -0
  39. data/{lib/app → app}/components/icons/trash_component.html.erb +0 -0
  40. data/{lib/app → app}/components/icons/trash_component.rb +0 -0
  41. data/{lib/app → app}/components/icons/users_component.html.erb +0 -0
  42. data/{lib/app → app}/components/icons/users_component.rb +0 -0
  43. data/{lib/app → app}/components/index_component.html.erb +0 -0
  44. data/{lib/app → app}/components/index_component.rb +0 -0
  45. data/{lib/app → app}/components/index_header_add_component.html.erb +0 -0
  46. data/{lib/app → app}/components/index_header_add_component.rb +0 -0
  47. data/{lib/app → app}/components/index_header_component.html.erb +0 -0
  48. data/{lib/app → app}/components/index_header_component.rb +0 -0
  49. data/{lib/app → app}/components/input/file_component.html.erb +0 -0
  50. data/{lib/app → app}/components/input/file_component.rb +0 -0
  51. data/{lib/app → app}/components/sidebar_component.html.erb +0 -0
  52. data/{lib/app → app}/components/sidebar_component.rb +0 -0
  53. data/{lib/app → app}/components/sidebar_item_component.html.erb +0 -0
  54. data/{lib/app → app}/components/sidebar_item_component.rb +0 -0
  55. data/{lib/app → app}/components/sign_out_button_component.html.erb +1 -1
  56. data/{lib/app → app}/components/sign_out_button_component.rb +3 -0
  57. data/{lib/app → app}/components/tables/active_record_th_component.html.erb +0 -0
  58. data/{lib/app → app}/components/tables/active_record_th_component.rb +1 -0
  59. data/{lib/app → app}/components/tables/table_component.html.erb +0 -0
  60. data/{lib/app → app}/components/tables/table_component.rb +0 -0
  61. data/{lib/app → app}/components/tables/tbody_component.html.erb +0 -0
  62. data/{lib/app → app}/components/tables/tbody_component.rb +0 -0
  63. data/{lib/app → app}/components/tables/td_component.html.erb +1 -1
  64. data/{lib/app → app}/components/tables/td_component.rb +0 -0
  65. data/{lib/app → app}/components/tables/th_component.html.erb +0 -0
  66. data/{lib/app → app}/components/tables/th_component.rb +0 -0
  67. data/{lib/app → app}/components/tables/thead_component.html.erb +0 -0
  68. data/{lib/app → app}/components/tables/thead_component.rb +0 -0
  69. data/{lib/app → app}/components/tables/tr_component.html.erb +0 -0
  70. data/{lib/app → app}/components/tables/tr_component.rb +0 -0
  71. data/app/controllers/tybo/application_controller.rb +4 -0
  72. data/app/controllers/tybo/login_controller.rb +8 -0
  73. data/app/helpers/tybo/application_helper.rb +5 -0
  74. data/app/helpers/tybo/flash_helper.rb +12 -0
  75. data/app/jobs/tybo/application_job.rb +4 -0
  76. data/app/mailers/tybo/application_mailer.rb +6 -0
  77. data/app/models/tybo/application_record.rb +5 -0
  78. data/app/views/devise/confirmations/new.html.erb +20 -0
  79. data/app/views/devise/login/home.html.erb +20 -0
  80. data/app/views/devise/mailer/_reset_password_instructions.html.erb +8 -0
  81. data/app/views/devise/mailer/confirmation_instructions.html.erb +5 -0
  82. data/app/views/devise/mailer/email_changed.html.erb +7 -0
  83. data/app/views/devise/mailer/password_change.html.erb +3 -0
  84. data/app/views/devise/mailer/unlock_instructions.html.erb +7 -0
  85. data/app/views/devise/passwords/edit.html.erb +36 -0
  86. data/app/views/devise/passwords/new.html.erb +34 -0
  87. data/app/views/devise/registrations/edit.html.erb +35 -0
  88. data/app/views/devise/registrations/new.html.erb +25 -0
  89. data/app/views/devise/sessions/new.html.erb +50 -0
  90. data/app/views/devise/shared/_devise_errors.html.erb +26 -0
  91. data/app/views/devise/shared/_error_messages.html.erb +15 -0
  92. data/app/views/devise/shared/_links.html.erb +65 -0
  93. data/app/views/devise/unlocks/new.html.erb +19 -0
  94. data/app/views/layouts/_errors.html.erb +22 -0
  95. data/app/views/layouts/_flash.html.erb +24 -0
  96. data/app/views/layouts/devise_admin.html.erb +16 -0
  97. data/app/views/layouts/tybo/application.html.erb +14 -0
  98. data/app/views/login/home.html.erb +19 -0
  99. data/app/views/shared/_pagination.html.erb +36 -0
  100. data/config/initializers/devise.rb +311 -0
  101. data/config/initializers/pagy.rb +246 -0
  102. data/config/initializers/ransack.rb +13 -0
  103. data/config/locales/devise.en.yml +65 -0
  104. data/config/routes.rb +3 -0
  105. data/lib/generators/bo/USAGE +12 -0
  106. data/lib/generators/bo/bo_generator.rb +88 -0
  107. data/lib/generators/bo/templates/_form.html.erb +32 -0
  108. data/lib/generators/bo/templates/_search_bar.html.erb +96 -0
  109. data/lib/generators/bo/templates/_table.html.erb +29 -0
  110. data/lib/generators/bo/templates/controller.rb +66 -0
  111. data/lib/generators/bo/templates/index.html.erb +19 -0
  112. data/lib/generators/bo/templates/item.html.erb +17 -0
  113. data/lib/generators/bo/templates/new.html.erb +1 -0
  114. data/lib/generators/bo/templates/show.html.erb +1 -0
  115. data/lib/generators/bo/utils/files/fr.json +19 -0
  116. data/lib/generators/bo/utils/translations.rb +47 -0
  117. data/lib/generators/bo_namespace/USAGE +11 -0
  118. data/lib/generators/bo_namespace/bo_namespace_generator.rb +50 -0
  119. data/lib/generators/bo_namespace/templates/admin.html.erb +27 -0
  120. data/lib/generators/bo_namespace/templates/admin_controller.rb +7 -0
  121. data/lib/generators/bo_namespace/templates/seeds.rb +9 -0
  122. data/lib/generators/bo_namespace/templates/side_bar.html.erb +4 -0
  123. data/lib/generators/tybo_install/templates/application.tailwind.css +112 -0
  124. data/lib/generators/tybo_install/templates/simple_form_tailwind.rb +147 -0
  125. data/lib/generators/tybo_install/templates/tailwind.config.js +40 -0
  126. data/lib/generators/tybo_install/templates/tom-select.css +458 -0
  127. data/lib/generators/tybo_install/tybo_install_generator.rb +44 -0
  128. data/lib/tybo/engine.rb +19 -0
  129. data/lib/tybo/version.rb +3 -0
  130. data/lib/tybo.rb +4 -43
  131. metadata +186 -98
  132. data/lib/app/helpers/application_helper.rb +0 -5
  133. data/lib/app/helpers/flash_helper.rb +0 -16
  134. data/lib/app/javascript/controllers/attachments_controller.js +0 -14
  135. data/lib/app/javascript/controllers/dropdown_controller.js +0 -15
  136. data/lib/app/javascript/controllers/flash_controller.js +0 -7
  137. data/lib/app/javascript/controllers/index.js +0 -6
  138. data/lib/app/javascript/controllers/questions_controller.js +0 -61
  139. data/lib/app/javascript/controllers/search_form_controller.js +0 -20
  140. data/lib/app/javascript/controllers/ts/search_controller.js +0 -35
  141. data/lib/app/javascript/controllers/ts/select_controller.js +0 -9
@@ -0,0 +1,246 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Pagy initializer file (5.10.1)
4
+ # Customize only what you really need and notice that the core Pagy works also without any of the following lines.
5
+ # Should you just cherry pick part of this file, please maintain the require-order of the extras
6
+
7
+
8
+ # Pagy DEFAULT Variables
9
+ # See https://ddnexus.github.io/pagy/api/pagy#variables
10
+ # All the Pagy::DEFAULT are set for all the Pagy instances but can be overridden per instance by just passing them to
11
+ # Pagy.new|Pagy::Countless.new|Pagy::Calendar::*.new or any of the #pagy* controller methods
12
+
13
+
14
+ # Instance variables
15
+ # See https://ddnexus.github.io/pagy/api/pagy#instance-variables
16
+ # Pagy::DEFAULT[:page] = 1 # default
17
+ Pagy::DEFAULT[:items] = 20 # default
18
+ # Pagy::DEFAULT[:outset] = 0 # default
19
+
20
+
21
+ # Other Variables
22
+ # See https://ddnexus.github.io/pagy/api/pagy#other-variables
23
+ # Pagy::DEFAULT[:size] = [1,4,4,1] # default
24
+ # Pagy::DEFAULT[:page_param] = :page # default
25
+ # The :params can be also set as a lambda e.g ->(params){ params.exclude('useless').merge!('custom' => 'useful') }
26
+ # Pagy::DEFAULT[:params] = {} # default
27
+ # Pagy::DEFAULT[:fragment] = '#fragment' # example
28
+ # Pagy::DEFAULT[:link_extra] = 'data-remote="true"' # example
29
+ # Pagy::DEFAULT[:i18n_key] = 'pagy.item_name' # default
30
+ # Pagy::DEFAULT[:cycle] = true # example
31
+
32
+
33
+ # Extras
34
+ # See https://ddnexus.github.io/pagy/extras
35
+
36
+
37
+ # Backend Extras
38
+
39
+ # Array extra: Paginate arrays efficiently, avoiding expensive array-wrapping and without overriding
40
+ # See https://ddnexus.github.io/pagy/extras/array
41
+ # require 'pagy/extras/array'
42
+
43
+ # Calendar extra: Add pagination filtering by calendar time unit (year, quarter, month, week, day)
44
+ # See https://ddnexus.github.io/pagy/extras/calendar
45
+ # require 'pagy/extras/calendar'
46
+ # Default for each unit
47
+ # Pagy::Calendar::Year::DEFAULT[:order] = :asc # Time direction of pagination
48
+ # Pagy::Calendar::Year::DEFAULT[:format] = '%Y' # strftime format
49
+ #
50
+ # Pagy::Calendar::Quarter::DEFAULT[:order] = :asc # Time direction of pagination
51
+ # Pagy::Calendar::Quarter::DEFAULT[:format] = '%Y-Q%q' # strftime format
52
+ #
53
+ # Pagy::Calendar::Month::DEFAULT[:order] = :asc # Time direction of pagination
54
+ # Pagy::Calendar::Month::DEFAULT[:format] = '%Y-%m' # strftime format
55
+ #
56
+ # Pagy::Calendar::Week::DEFAULT[:order] = :asc # Time direction of pagination
57
+ # Pagy::Calendar::Week::DEFAULT[:format] = '%Y-%W' # strftime format
58
+ #
59
+ # Pagy::Calendar::Day::DEFAULT[:order] = :asc # Time direction of pagination
60
+ # Pagy::Calendar::Day::DEFAULT[:format] = '%Y-%m-%d' # strftime format
61
+ #
62
+ # Uncomment the following lines, if you need calendar localization without using the I18n extra
63
+ # module LocalizePagyCalendar
64
+ # def localize(time, opts)
65
+ # ::I18n.l(time, **opts)
66
+ # end
67
+ # end
68
+ # Pagy::Calendar.prepend LocalizePagyCalendar
69
+
70
+ # Countless extra: Paginate without any count, saving one query per rendering
71
+ # See https://ddnexus.github.io/pagy/extras/countless
72
+ # require 'pagy/extras/countless'
73
+ # Pagy::DEFAULT[:countless_minimal] = false # default (eager loading)
74
+
75
+ # Elasticsearch Rails extra: Paginate `ElasticsearchRails::Results` objects
76
+ # See https://ddnexus.github.io/pagy/extras/elasticsearch_rails
77
+ # Default :pagy_search method: change only if you use also
78
+ # the searchkick or meilisearch extra that defines the same
79
+ # Pagy::DEFAULT[:elasticsearch_rails_pagy_search] = :pagy_search
80
+ # Default original :search method called internally to do the actual search
81
+ # Pagy::DEFAULT[:elasticsearch_rails_search] = :search
82
+ # require 'pagy/extras/elasticsearch_rails'
83
+
84
+ # Headers extra: http response headers (and other helpers) useful for API pagination
85
+ # See http://ddnexus.github.io/pagy/extras/headers
86
+ # require 'pagy/extras/headers'
87
+ # Pagy::DEFAULT[:headers] = { page: 'Current-Page',
88
+ # items: 'Page-Items',
89
+ # count: 'Total-Count',
90
+ # pages: 'Total-Pages' } # default
91
+
92
+ # Meilisearch extra: Paginate `Meilisearch` result objects
93
+ # See https://ddnexus.github.io/pagy/extras/meilisearch
94
+ # Default :pagy_search method: change only if you use also
95
+ # the elasticsearch_rails or searchkick extra that define the same method
96
+ # Pagy::DEFAULT[:meilisearch_pagy_search] = :pagy_search
97
+ # Default original :search method called internally to do the actual search
98
+ # Pagy::DEFAULT[:meilisearch_search] = :ms_search
99
+ # require 'pagy/extras/meilisearch'
100
+
101
+ # Metadata extra: Provides the pagination metadata to Javascript frameworks like Vue.js, react.js, etc.
102
+ # See https://ddnexus.github.io/pagy/extras/metadata
103
+ # you must require the frontend helpers internal extra (BEFORE the metadata extra) ONLY if you need also the :sequels
104
+ # require 'pagy/extras/frontend_helpers'
105
+ # require 'pagy/extras/metadata'
106
+ # For performance reasons, you should explicitly set ONLY the metadata you use in the frontend
107
+ # Pagy::DEFAULT[:metadata] = %i[scaffold_url page prev next last] # example
108
+
109
+ # Searchkick extra: Paginate `Searchkick::Results` objects
110
+ # See https://ddnexus.github.io/pagy/extras/searchkick
111
+ # Default :pagy_search method: change only if you use also
112
+ # the elasticsearch_rails or meilisearch extra that defines the same
113
+ # DEFAULT[:searchkick_pagy_search] = :pagy_search
114
+ # Default original :search method called internally to do the actual search
115
+ # Pagy::DEFAULT[:searchkick_search] = :search
116
+ # require 'pagy/extras/searchkick'
117
+ # uncomment if you are going to use Searchkick.pagy_search
118
+ # Searchkick.extend Pagy::Searchkick
119
+
120
+
121
+ # Frontend Extras
122
+
123
+ # Bootstrap extra: Add nav, nav_js and combo_nav_js helpers and templates for Bootstrap pagination
124
+ # See https://ddnexus.github.io/pagy/extras/bootstrap
125
+ # require 'pagy/extras/bootstrap'
126
+
127
+ # Bulma extra: Add nav, nav_js and combo_nav_js helpers and templates for Bulma pagination
128
+ # See https://ddnexus.github.io/pagy/extras/bulma
129
+ # require 'pagy/extras/bulma'
130
+
131
+ # Foundation extra: Add nav, nav_js and combo_nav_js helpers and templates for Foundation pagination
132
+ # See https://ddnexus.github.io/pagy/extras/foundation
133
+ # require 'pagy/extras/foundation'
134
+
135
+ # Materialize extra: Add nav, nav_js and combo_nav_js helpers for Materialize pagination
136
+ # See https://ddnexus.github.io/pagy/extras/materialize
137
+ # require 'pagy/extras/materialize'
138
+
139
+ # Navs extra: Add nav_js and combo_nav_js javascript helpers
140
+ # Notice: the other frontend extras add their own framework-styled versions,
141
+ # so require this extra only if you need the unstyled version
142
+ # See https://ddnexus.github.io/pagy/extras/navs
143
+ # require 'pagy/extras/navs'
144
+
145
+ # Semantic extra: Add nav, nav_js and combo_nav_js helpers for Semantic UI pagination
146
+ # See https://ddnexus.github.io/pagy/extras/semantic
147
+ # require 'pagy/extras/semantic'
148
+
149
+ # UIkit extra: Add nav helper and templates for UIkit pagination
150
+ # See https://ddnexus.github.io/pagy/extras/uikit
151
+ # require 'pagy/extras/uikit'
152
+
153
+ # Multi size var used by the *_nav_js helpers
154
+ # See https://ddnexus.github.io/pagy/extras/navs#steps
155
+ # Pagy::DEFAULT[:steps] = { 0 => [2,3,3,2], 540 => [3,5,5,3], 720 => [5,7,7,5] } # example
156
+
157
+
158
+ # Feature Extras
159
+
160
+ # Gearbox extra: Automatically change the number of items per page depending on the page number
161
+ # See https://ddnexus.github.io/pagy/extras/gearbox
162
+ # require 'pagy/extras/gearbox'
163
+ # set to false only if you want to make :gearbox_extra an opt-in variable
164
+ # Pagy::DEFAULT[:gearbox_extra] = false # default true
165
+ # Pagy::DEFAULT[:gearbox_items] = [15, 30, 60, 100] # default
166
+
167
+ # Items extra: Allow the client to request a custom number of items per page with an optional selector UI
168
+ # See https://ddnexus.github.io/pagy/extras/items
169
+ # require 'pagy/extras/items'
170
+ # set to false only if you want to make :items_extra an opt-in variable
171
+ # Pagy::DEFAULT[:items_extra] = false # default true
172
+ # Pagy::DEFAULT[:items_param] = :items # default
173
+ # Pagy::DEFAULT[:max_items] = 100 # default
174
+
175
+ # Overflow extra: Allow for easy handling of overflowing pages
176
+ # See https://ddnexus.github.io/pagy/extras/overflow
177
+ # require 'pagy/extras/overflow'
178
+ # Pagy::DEFAULT[:overflow] = :empty_page # default (other options: :last_page and :exception)
179
+
180
+ # Support extra: Extra support for features like: incremental, infinite, auto-scroll pagination
181
+ # See https://ddnexus.github.io/pagy/extras/support
182
+ # require 'pagy/extras/support'
183
+
184
+ # Trim extra: Remove the page=1 param from links
185
+ # See https://ddnexus.github.io/pagy/extras/trim
186
+ # require 'pagy/extras/trim'
187
+ # set to false only if you want to make :trim_extra an opt-in variable
188
+ # Pagy::DEFAULT[:trim_extra] = false # default true
189
+
190
+ # Standalone extra: Use pagy in non Rack environment/gem
191
+ # See https://ddnexus.github.io/pagy/extras/standalone
192
+ # require 'pagy/extras/standalone'
193
+ # Pagy::DEFAULT[:url] = 'http://www.example.com/subdir' # optional default
194
+
195
+
196
+ # Rails
197
+ # Enable the .js file required by the helpers that use javascript
198
+ # (pagy*_nav_js, pagy*_combo_nav_js, and pagy_items_selector_js)
199
+ # See https://ddnexus.github.io/pagy/extras#javascript
200
+
201
+ # With the asset pipeline
202
+ # Sprockets need to look into the pagy javascripts dir, so add it to the assets paths
203
+ # Rails.application.config.assets.paths << Pagy.root.join('javascripts')
204
+
205
+ # I18n
206
+
207
+ # Pagy internal I18n: ~18x faster using ~10x less memory than the i18n gem
208
+ # See https://ddnexus.github.io/pagy/api/frontend#i18n
209
+ # Notice: No need to configure anything in this section if your app uses only "en"
210
+ # or if you use the i18n extra below
211
+ #
212
+ # Examples:
213
+ # load the "de" built-in locale:
214
+ # Pagy::I18n.load(locale: 'de')
215
+ #
216
+ # load the "de" locale defined in the custom file at :filepath:
217
+ # Pagy::I18n.load(locale: 'de', filepath: 'path/to/pagy-de.yml')
218
+ #
219
+ # load the "de", "en" and "es" built-in locales:
220
+ # (the first passed :locale will be used also as the default_locale)
221
+ # Pagy::I18n.load({ locale: 'de' },
222
+ # { locale: 'en' },
223
+ # { locale: 'es' })
224
+ #
225
+ # load the "en" built-in locale, a custom "es" locale,
226
+ # and a totally custom locale complete with a custom :pluralize proc:
227
+ # (the first passed :locale will be used also as the default_locale)
228
+ # Pagy::I18n.load({ locale: 'en' },
229
+ # { locale: 'es', filepath: 'path/to/pagy-es.yml' },
230
+ # { locale: 'xyz', # not built-in
231
+ # filepath: 'path/to/pagy-xyz.yml',
232
+ # pluralize: lambda{ |count| ... } )
233
+
234
+
235
+ # I18n extra: uses the standard i18n gem which is ~18x slower using ~10x more memory
236
+ # than the default pagy internal i18n (see above)
237
+ # See https://ddnexus.github.io/pagy/extras/i18n
238
+ # require 'pagy/extras/i18n'
239
+
240
+ # Default i18n key
241
+ # Pagy::DEFAULT[:i18n_key] = 'pagy.item_name' # default
242
+
243
+
244
+ # When you are done setting your own default freeze it, so it will not get changed accidentally
245
+ Pagy::DEFAULT.freeze
246
+
@@ -0,0 +1,13 @@
1
+ Ransack.configure do |config|
2
+ config.add_predicate 'from_date',
3
+ arel_predicate: 'gteq',
4
+ formatter: proc { |v| v.beginning_of_day },
5
+ validator: proc { |v| v.present? },
6
+ type: :date
7
+
8
+ config.add_predicate 'to_date',
9
+ arel_predicate: 'lteq',
10
+ formatter: proc { |v| v.end_of_day },
11
+ validator: proc { |v| v.present? },
12
+ type: :date
13
+ end
@@ -0,0 +1,65 @@
1
+ # Additional translations at https://github.com/heartcombo/devise/wiki/I18n
2
+
3
+ en:
4
+ devise:
5
+ confirmations:
6
+ confirmed: "Your email address has been successfully confirmed."
7
+ send_instructions: "You will receive an email with instructions for how to confirm your email address in a few minutes."
8
+ send_paranoid_instructions: "If your email address exists in our database, you will receive an email with instructions for how to confirm your email address in a few minutes."
9
+ failure:
10
+ already_authenticated: "You are already signed in."
11
+ inactive: "Your account is not activated yet."
12
+ invalid: "Invalid %{authentication_keys} or password."
13
+ locked: "Your account is locked."
14
+ last_attempt: "You have one more attempt before your account is locked."
15
+ not_found_in_database: "Invalid %{authentication_keys} or password."
16
+ timeout: "Your session expired. Please sign in again to continue."
17
+ unauthenticated: "You need to sign in or sign up before continuing."
18
+ unconfirmed: "You have to confirm your email address before continuing."
19
+ mailer:
20
+ confirmation_instructions:
21
+ subject: "Confirmation instructions"
22
+ reset_password_instructions:
23
+ subject: "Reset password instructions"
24
+ unlock_instructions:
25
+ subject: "Unlock instructions"
26
+ email_changed:
27
+ subject: "Email Changed"
28
+ password_change:
29
+ subject: "Password Changed"
30
+ omniauth_callbacks:
31
+ failure: "Could not authenticate you from %{kind} because \"%{reason}\"."
32
+ success: "Successfully authenticated from %{kind} account."
33
+ passwords:
34
+ no_token: "You can't access this page without coming from a password reset email. If you do come from a password reset email, please make sure you used the full URL provided."
35
+ send_instructions: "You will receive an email with instructions on how to reset your password in a few minutes."
36
+ send_paranoid_instructions: "If your email address exists in our database, you will receive a password recovery link at your email address in a few minutes."
37
+ updated: "Your password has been changed successfully. You are now signed in."
38
+ updated_not_active: "Your password has been changed successfully."
39
+ registrations:
40
+ destroyed: "Bye! Your account has been successfully cancelled. We hope to see you again soon."
41
+ signed_up: "Welcome! You have signed up successfully."
42
+ signed_up_but_inactive: "You have signed up successfully. However, we could not sign you in because your account is not yet activated."
43
+ signed_up_but_locked: "You have signed up successfully. However, we could not sign you in because your account is locked."
44
+ signed_up_but_unconfirmed: "A message with a confirmation link has been sent to your email address. Please follow the link to activate your account."
45
+ update_needs_confirmation: "You updated your account successfully, but we need to verify your new email address. Please check your email and follow the confirmation link to confirm your new email address."
46
+ updated: "Your account has been updated successfully."
47
+ updated_but_not_signed_in: "Your account has been updated successfully, but since your password was changed, you need to sign in again."
48
+ sessions:
49
+ signed_in: "Signed in successfully."
50
+ signed_out: "Signed out successfully."
51
+ already_signed_out: "Signed out successfully."
52
+ unlocks:
53
+ send_instructions: "You will receive an email with instructions for how to unlock your account in a few minutes."
54
+ send_paranoid_instructions: "If your account exists, you will receive an email with instructions for how to unlock it in a few minutes."
55
+ unlocked: "Your account has been unlocked successfully. Please sign in to continue."
56
+ errors:
57
+ messages:
58
+ already_confirmed: "was already confirmed, please try signing in"
59
+ confirmation_period_expired: "needs to be confirmed within %{period}, please request a new one"
60
+ expired: "has expired, please request a new one"
61
+ not_found: "not found"
62
+ not_locked: "was not locked"
63
+ not_saved:
64
+ one: "1 error prohibited this %{resource} from being saved:"
65
+ other: "%{count} errors prohibited this %{resource} from being saved:"
data/config/routes.rb ADDED
@@ -0,0 +1,3 @@
1
+ Tybo::Engine.routes.draw do
2
+ root to: 'login#home'
3
+ end
@@ -0,0 +1,12 @@
1
+ Description:
2
+ Create CRUD views for a model
3
+ `rails g bo BlogPost`
4
+ By default it create views in the administrators namespace
5
+ Example:
6
+ `rails g bo BlogPost --namespace employers`
7
+ This will create:
8
+ - CRUD views
9
+ - CRUD controllers
10
+ - Base filters on index pages
11
+ - base routes
12
+ - base seeds
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ class BoGenerator < Rails::Generators::NamedBase
4
+ source_root File.expand_path('templates', __dir__)
5
+ require_relative "./utils/translations.rb"
6
+
7
+ check_class_collision suffix: 'bo'
8
+ class_option :namespace, type: :string, default: 'administrators'
9
+ def create_bo_file
10
+ # Template method
11
+ # First argument is the name of the template
12
+ # Second argument is where to create the resulting file. In this case, app/bo/my_bo.rb
13
+ template 'new.html.erb', File.join("app/views/#{options[:namespace]}", "#{plural_name}/new.html.erb")
14
+ template 'item.html.erb', File.join("app/views/#{options[:namespace]}", "#{plural_name}/_#{file_name.underscore}.html.erb")
15
+ template '_form.html.erb', File.join("app/views/#{options[:namespace]}", "#{plural_name}/_form.html.erb")
16
+ template 'index.html.erb', File.join("app/views/#{options[:namespace]}", "#{plural_name}/index.html.erb")
17
+ template '_table.html.erb', File.join("app/views/#{options[:namespace]}", "#{plural_name}/_table.html.erb")
18
+ template '_search_bar.html.erb', File.join("app/views/#{options[:namespace]}", "#{plural_name}/_search_bar.html.erb")
19
+ template 'show.html.erb', File.join("app/views/#{options[:namespace]}", "#{plural_name}/show.html.erb")
20
+ template 'controller.rb', File.join("app/controllers/#{options[:namespace]}", "#{plural_name}_controller.rb")
21
+ create_translations
22
+ end
23
+
24
+ def bo_model
25
+ class_name.constantize
26
+ end
27
+
28
+ def plural_name
29
+ file_name.pluralize
30
+ end
31
+
32
+ def create_routes
33
+ inject_into_file 'config/routes.rb', after: " namespace :#{options[:namespace]} do\n" do
34
+ " resources :#{plural_name} \n"
35
+ end
36
+ end
37
+
38
+ def model_columns
39
+ bo_model.column_names.map(&:to_sym)
40
+ end
41
+
42
+ def bo_model_title(model=nil)
43
+ return unless model
44
+
45
+ (%i[title name email id] & model.column_names.map(&:to_sym)).first
46
+ end
47
+
48
+ def excluded_columns
49
+ %i[id created_at updated_at]
50
+ end
51
+
52
+ def permited_params
53
+ params = {}
54
+ action_text_columns= has_one_assoc&.select {|a| a.name == :rich_text_content}
55
+ model_columns&.map do |col|
56
+ params["#{col}".to_sym] = nil
57
+ end
58
+ action_text_columns&.map do |col|
59
+ params["#{col.name.to_s.remove('rich_text_' )}".to_sym] = nil
60
+ end
61
+ has_many_assoc&.map do |association|
62
+ params["#{association.class_name.underscore}_ids".to_sym] = []
63
+ end
64
+ params
65
+ end
66
+
67
+ def has_many_assoc
68
+ bo_model.reflect_on_all_associations(:has_many)
69
+ end
70
+
71
+ def belongs_to_assoc
72
+ bo_model.reflect_on_all_associations(:belongs_to)
73
+ end
74
+
75
+ def has_one_assoc
76
+ bo_model.reflect_on_all_associations(:has_one)
77
+ end
78
+
79
+ def permited_columns
80
+ model_columns - excluded_columns
81
+ end
82
+
83
+ def add_link_to_side_bar
84
+ inject_into_file "app/views/#{options[:namespace]}/layouts/_side_bar.html.erb", before: " <%= sidebar.with_current_user_card(user: current_#{options[:namespace].singularize}) %>\n" do
85
+ " <%= sidebar.with_item(path: #{options[:namespace]}_#{plural_name}_path, icon: Icons::UsersComponent, label: I18n.t('bo.#{file_name}.others').capitalize) %>\n"
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,32 @@
1
+ <%%= simple_form_for [:<%= options[:namespace] %>, <%= class_name.underscore %>], html: { class: "<%= class_name.underscore %> form" } do |f| %>
2
+ <!-- Model columns -->
3
+ <%- bo_model.column_names.each do |column| -%>
4
+ <%- next if excluded_columns.include?(column.to_sym) || bo_model.reflect_on_all_associations.map(&:foreign_key).include?(column) -%>
5
+ <%%= f.input :<%= column %> %>
6
+ <%- end -%>
7
+ <!-- belongs_to Associations -->
8
+ <%- belongs_to_assoc.each do |association| -%>
9
+ <%%= f.association :<%= association.name %>, collection: <%= association.class_name %>.all.map { |item| [item.<%=bo_model_title(association.class_name.constantize)%>, item.id] } %>
10
+ <%- end -%>
11
+ <!-- has_one Associations -->
12
+ <%- has_one_assoc.each do |association| -%>
13
+ <%- if association.options[:class_name] == "ActionText::RichText" -%>
14
+ <%%= f.rich_text_area :<%= association.name.to_s.remove('rich_text_' )%> %>
15
+ <%- else -%>
16
+ <%%= f.input :<%= association.foreign_key %>, collection: <%= association.class_name %>.all.map { |item| [item.<%=bo_model_title(association.class_name.constantize)%>, item.id] } %>
17
+ <%- end -%>
18
+ <%- end -%>
19
+
20
+ <!-- has_many Associations -->
21
+ <%- has_many_assoc.each do |association| -%>
22
+ <div class="my-5 select">
23
+ <label class="block text-sm font-medium text-gray-700 string optional text-sm font-medium text-gray-600" for="<%= "#{class_name.underscore}_#{association.class_name.underscore}_ids" %>"><%= association.class_name.underscore%></label>
24
+ <%%= f.select :<%= "#{association.class_name.underscore}_ids" %>,
25
+ <%= association.class_name %>.all.map { |item| [item.<%=bo_model_title(association.class_name.constantize)%>, item.id] },
26
+ { include_blank: true },
27
+ multiple: true,
28
+ data: { controller: 'ts--select' } %>
29
+ </div>
30
+ <%- end -%>
31
+ <%%= render(Forms::SubmitButtonComponent.new) %>
32
+ <%% end %>
@@ -0,0 +1,96 @@
1
+ <div class="relative inline-block text-left" data-controller="dropdown">
2
+ <div>
3
+ <button data-action="click->dropdown#toggle click@window->dropdown#hide" type="button" class="inline-flex w-full justify-center rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 shadow-sm hover:bg-gray-50 focus:outline-none " id="menu-button" aria-expanded="true" aria-haspopup="true">
4
+ <%%= I18n.t('bo.filters') %>
5
+ <svg class="-mr-1 ml-2 h-5 w-5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
6
+ <path fill-rule="evenodd" d="M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z" clip-rule="evenodd" />
7
+ </svg>
8
+ </button>
9
+ </div>
10
+ <div data-dropdown-target="menu" class="drop-shadow-md hidden absolute py-5 px-5 left-0 z-10 mt-2 w-[40rem] origin-top-right rounded-md bg-white shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none" role="menu" aria-orientation="vertical" aria-labelledby="menu-button" tabindex="-1">
11
+ <%%= search_form_for [:<%=options[:namespace].underscore %>, @q], method: :post, class: "", data: { controller: "search-form", search_form_target: "form", turbo_frame: '<%=class_name.underscore.pluralize%>' } do |f| %>
12
+ <%- bo_model.columns.group_by(&:type).each do |type| -%>
13
+ <!-- columns -->
14
+ <%- type.second.sort_by(&:type).each do |col| -%>
15
+ <%- next if bo_model.reflect_on_all_associations.map(&:foreign_key).include?(col.name) -%>
16
+ <%- if col.type == :string || col.type == :text -%>
17
+ <div class="sm:grid sm:grid-cols-3 sm:items-start sm:gap-4 pt-5">
18
+ <label class="block text-sm font-medium text-gray-700 sm:mt-px sm:pt-2">
19
+ <%%= I18n.t('bo.<%= class_name.underscore %>.attributes.<%= col.name %>') %>
20
+ </label>
21
+ <div class="mt-1 sm:col-span-2 sm:mt-0">
22
+ <%%= f.text_field :<%= col.name %>_cont, placeholder: I18n.t('bo.<%= class_name.underscore %>.attributes.<%= col.name %>'), data: { action: "input->search-form#search" }, class: "block w-full max-w-lg rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:max-w-xs sm:text-sm" %>
23
+ </div>
24
+ </div>
25
+ <%- elsif col.type ==:integer -%>
26
+ <div class="sm:grid sm:grid-cols-3 sm:items-start sm:gap-4 pt-5">
27
+ <label class="block text-sm font-medium text-gray-700 sm:mt-px sm:pt-2">
28
+ <%%= I18n.t('bo.<%= class_name.underscore %>.attributes.<%= col.name %>') %>
29
+ </label>
30
+ <div class="mt-1 sm:col-span-2 sm:mt-0">
31
+ <%%= f.number_field :<%= col.name %>_eq, placeholder: I18n.t('bo.<%= class_name.underscore %>.attributes.<%= col.name %>'), data: { action: "input->search-form#search" }, class: "block w-full max-w-lg rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:max-w-xs sm:text-sm" %>
32
+ </div>
33
+ </div>
34
+ <%- elsif col.type == :boolean -%>
35
+ <div class="sm:grid sm:grid-cols-3 sm:items-start sm:gap-4 pt-5">
36
+ <label class="block text-sm font-medium text-gray-700 sm:mt-px sm:pt-2">
37
+ <%%= I18n.t('bo.<%= class_name.underscore %>.attributes.<%= col.name %>') %>
38
+ </label>
39
+ <div class="mt-1 sm:col-span-2 sm:mt-0">
40
+ <span class="isolate inline-flex rounded-md shadow-sm">
41
+ <button type="button"
42
+ data-target-id='q_<%= col.name %>_eq'
43
+ data-action="click->search-form#setBooleanField"
44
+ class="relative inline-flex items-center rounded-l-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 focus:z-10 focus:border-indigo-500 focus:outline-none focus:ring-1 focus:ring-indigo-500">
45
+ -
46
+ </button>
47
+ <button type="button"
48
+ data-action="click->search-form#setBooleanField"
49
+ data-value='true'
50
+ data-target-id='q_<%= col.name %>_eq'
51
+ class="relative inline-flex items-center rounded-l-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 focus:z-10 focus:border-indigo-500 focus:outline-none focus:ring-1 focus:ring-indigo-500">ON
52
+ </button>
53
+ <button type="button"
54
+ data-action="click->search-form#setBooleanField"
55
+ data-value='false'
56
+ data-target-id='q_<%= col.name %>_eq'
57
+ class="relative inline-flex items-center rounded-l-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 focus:z-10 focus:border-indigo-500 focus:outline-none focus:ring-1 focus:ring-indigo-500">OFF</button>
58
+ </span>
59
+ <%%= f.hidden_field :<%= col.name %>_eq, value: nil, data: { action: "change->search-form#search"}%>
60
+ </div>
61
+ </div>
62
+ <%- elsif col.type == :datetime || col.type == :date -%>
63
+ <div class="sm:grid sm:grid-cols-12 sm:items-start sm:gap-4 pt-5">
64
+ <div class="mt-1 sm:col-span-4 sm:mt-">
65
+ <label class="block text-sm font-medium text-gray-700 sm:mt-px sm:pt-2">
66
+ <%%= I18n.t('bo.<%= class_name.underscore %>.attributes.<%= col.name %>') %>
67
+ </label>
68
+ </div>
69
+ <div class="mt-1 sm:col-span-3 sm:mt-0">
70
+ <%%= f.date_field :<%= col.name %>_from_date, data: { action: "input->search-form#search" }, class: "rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm" %>
71
+ </div>
72
+ <div class="mt-1 sm:col-span-2 text-center">
73
+ to
74
+ </div>
75
+ <div class="mt-1 sm:col-span-3 sm:mt-0">
76
+ <%%= f.date_field :<%= col.name %>_to_date, data: { action: "input->search-form#search" }, class: "rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm" %>
77
+ </div>
78
+ </div>
79
+ <%- end -%>
80
+ <%- end -%>
81
+ <%- end -%>
82
+ <!-- belongs_to Associations -->
83
+ <%- belongs_to_assoc.each do |association| -%>
84
+ <div class="sm:grid sm:grid-cols-3 sm:items-start sm:gap-4 pt-5">
85
+ <label for="<%=association.name%>" class="block text-sm font-medium text-gray-700 sm:mt-px sm:pt-2">
86
+ <%%=I18n.t('bo.<%=association.klass.name.underscore%>.one')%>
87
+ </label>
88
+ <div class="mt-1 sm:col-span-2 sm:mt-0">
89
+ <%%= f.select :<%= association.foreign_key %>_eq, <%=association.klass.name.constantize%>.all.map { |value| [value.<%=bo_model_title(association.class_name.constantize)%>, value.id] }, { include_blank: true }, { class: "block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm", data: { action: "input->search-form#search" } } %>
90
+ </div>
91
+ </div>
92
+ <%- end -%>
93
+ <%% end %>
94
+ </div>
95
+ </div>
96
+
@@ -0,0 +1,29 @@
1
+ <%%= render(Tables::TableComponent.new) do |table| %>
2
+ <%% table.with_thead do |thead| %>
3
+ <%- bo_model.column_names.each do |column| -%>
4
+ <%%= thead.with_active_record_th(column_name: '<%= column %>', ransack_object: @q) %>
5
+ <%- end -%>
6
+ <%% end %>
7
+
8
+ <%% table.with_tbody do |tbody| %>
9
+ <%% @<%= class_name.underscore.pluralize %>&.each_with_index do |<%= class_name.underscore %>, i| %>
10
+ <%%= tbody.with_tr(index: i) do |tr| %>
11
+ <%- bo_model.column_names.each do |column| -%>
12
+ <%%= tr.with_td { <%= class_name.underscore %>.<%= column %>.to_s } -%>
13
+ <%- end -%>
14
+ <%%= tr.with_td do %>
15
+ <%%= link_to <%="#{options[:namespace]}_#{class_name.underscore}_path(#{class_name.underscore})"%>, class: "text-indigo-600 hover:text-indigo-900" do %>
16
+ Détails
17
+ <%% end %>
18
+ <%% end %>
19
+ <%%= tr.with_td do %>
20
+ <%%= link_to <%="#{options[:namespace]}_#{class_name.underscore}_path(#{class_name.underscore})"%>,
21
+ class: "text-indigo-600 hover:text-indigo-900",
22
+ data: {turbo_method: :delete, turbo_confirm: "êtes vous sur ?"} do %>
23
+ <%%= render(Icons::TrashComponent.new) %>
24
+ <%% end %>
25
+ <%% end %>
26
+ <%% end %>
27
+ <%% end %>
28
+ <%% end %>
29
+ <%% end %>
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ module <%= options[:namespace].camelize %>
4
+ class <%= class_name.pluralize %>Controller < <%= options[:namespace].singularize.camelize %>Controller
5
+ before_action :set_<%= class_name.underscore %>, only: %i[show edit destroy update]
6
+
7
+ def index
8
+ @q = <%=class_name%>.ransack(params[:q])
9
+ @pagy, @<%= class_name.pluralize.underscore %> = pagy(@q.result(distinct: true))
10
+ end
11
+
12
+ def show; end
13
+
14
+ def new
15
+ @<%= class_name.underscore %> = <%= class_name %>.new
16
+ end
17
+
18
+ def create
19
+ @<%= class_name.underscore %> = <%= class_name %>.new(<%= class_name.underscore %>_params)
20
+
21
+ if @<%= class_name.underscore %>.save
22
+ flash[:success] = t('bo.record.created')
23
+ redirect_to <%="#{options[:namespace]}_#{class_name.underscore.pluralize}_path"%>
24
+
25
+ else
26
+ render :new, status: :unprocessable_entity
27
+ end
28
+ end
29
+
30
+ def edit; end
31
+
32
+ def update
33
+ if @<%= class_name.underscore %>.update(<%= class_name.underscore %>_params)
34
+ flash[:success] = t('bo.record.updated')
35
+ redirect_to <%="#{options[:namespace]}_#{class_name.underscore}_path"%>
36
+ else
37
+ render :show, status: :unprocessable_entity
38
+ end
39
+ end
40
+
41
+ def destroy
42
+ @<%= class_name.underscore %>.destroy
43
+ flash[:success] = t('bo.record.destroyed')
44
+
45
+ redirect_to <%="#{options[:namespace]}_#{class_name.underscore.pluralize}_path"%>, status: :see_other
46
+ end
47
+
48
+ private
49
+
50
+ def set_<%= class_name.underscore %>
51
+ @<%= class_name.underscore %> = <%= class_name %>.find(params[:id])
52
+ end
53
+
54
+ def <%= class_name.underscore %>_params
55
+ params.require(:<%= class_name.underscore %>).permit(
56
+ <%-permited_params.each_with_index do |(key, value), index| -%>
57
+ <%- if value.nil? -%>
58
+ :<%= key %><%=permited_params.count == (index +1) ? '' : ',' %>
59
+ <%- else -%>
60
+ <%= "#{key}: []" %><%=permited_params.count == (index +1) ? '' : ',' %>
61
+ <%- end -%>
62
+ <%- end -%>
63
+ )
64
+ end
65
+ end
66
+ end