beautiful_scaffold 2.0.0.pre → 2.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -1
  3. data/CHANGELOG +45 -0
  4. data/Gemfile +5 -4
  5. data/README.rdoc +22 -4
  6. data/Rakefile +0 -3
  7. data/beautiful_scaffold.gemspec +0 -2
  8. data/lib/beautiful_scaffold/version.rb +1 -1
  9. data/lib/generators/USAGE +25 -11
  10. data/lib/generators/beautiful_cancancan_generator.rb +51 -0
  11. data/lib/generators/beautiful_jointable_generator.rb +3 -5
  12. data/lib/generators/beautiful_locale_generator.rb +15 -13
  13. data/lib/generators/beautiful_migration_generator.rb +3 -1
  14. data/lib/generators/beautiful_scaffold_common_methods.rb +10 -2
  15. data/lib/generators/beautiful_scaffold_generator.rb +2 -10
  16. data/lib/generators/beautiful_sorcery_generator.rb +137 -0
  17. data/lib/generators/beautiful_storage_generator.rb +61 -0
  18. data/lib/generators/templates/app/assets/javascripts/application-bs.js +0 -2
  19. data/lib/generators/templates/app/assets/javascripts/beautiful_scaffold.js +15 -30
  20. data/lib/generators/templates/app/assets/javascripts/bootstrap-datetimepicker-for-beautiful-scaffold.js +16 -15
  21. data/lib/generators/templates/app/assets/stylesheets/application-bs.css +0 -2
  22. data/lib/generators/templates/app/assets/stylesheets/beautiful-scaffold.css.scss +9 -1
  23. data/lib/generators/templates/app/controllers/user_sessions_controller.rb +20 -0
  24. data/lib/generators/templates/app/helpers/beautiful_helper.rb +19 -5
  25. data/lib/generators/templates/app/locales/beautiful_scaffold.en.yml +8 -0
  26. data/lib/generators/templates/app/locales/beautiful_scaffold.fr.yml +9 -1
  27. data/lib/generators/templates/app/locales/beautiful_scaffold.ja.yml +9 -2
  28. data/lib/generators/templates/app/mailers/user_mailer.rb +13 -0
  29. data/lib/generators/templates/app/models/ability.rb +39 -0
  30. data/lib/generators/templates/app/models/concerns/caption_concern.rb +1 -1
  31. data/lib/generators/templates/app/models/user.rb +11 -0
  32. data/lib/generators/templates/app/views/_form_habtm_tag.html.erb +3 -3
  33. data/lib/generators/templates/app/views/layout.html.erb +12 -2
  34. data/lib/generators/templates/app/views/login_logout/user_mailer/activation_needed_email.en.html.erb +16 -0
  35. data/lib/generators/templates/app/views/login_logout/user_mailer/activation_needed_email.en.text.erb +9 -0
  36. data/lib/generators/templates/app/views/login_logout/user_mailer/activation_needed_email.fr.html.erb +16 -0
  37. data/lib/generators/templates/app/views/login_logout/user_mailer/activation_needed_email.fr.text.erb +8 -0
  38. data/lib/generators/templates/app/views/login_logout/user_mailer/activation_success_email.en.html.erb +19 -0
  39. data/lib/generators/templates/app/views/login_logout/user_mailer/activation_success_email.en.text.erb +8 -0
  40. data/lib/generators/templates/app/views/login_logout/user_mailer/activation_success_email.fr.html.erb +19 -0
  41. data/lib/generators/templates/app/views/login_logout/user_mailer/activation_success_email.fr.text.erb +8 -0
  42. data/lib/generators/templates/app/views/login_logout/user_sessions/_form.html.erb +15 -0
  43. data/lib/generators/templates/app/views/login_logout/user_sessions/new.html.erb +3 -0
  44. data/lib/generators/templates/app/views/partials/_form_field.html.erb +33 -25
  45. data/lib/generators/templates/app/views/partials/_index_column.html.erb +2 -0
  46. data/lib/generators/templates/app/views/partials/_login_logout_register.html.erb +7 -0
  47. data/lib/generators/templates/app/views/partials/_show_field.html.erb +2 -0
  48. metadata +23 -15
  49. data/Gemfile.lock +0 -209
  50. data/lib/generators/beautiful_devisecancan_generator.rb +0 -128
  51. data/lib/generators/templates/app/assets/javascripts/bootstrap-colorpicker.js +0 -520
  52. data/lib/generators/templates/app/assets/javascripts/tagit.js +0 -489
  53. data/lib/generators/templates/app/assets/stylesheets/colorpicker.css +0 -127
  54. data/lib/generators/templates/app/assets/stylesheets/tagit-dark-grey.css +0 -135
  55. data/lib/generators/templates/app/views/partials/_register_form.html.erb +0 -44
  56. data/lib/generators/templates/app/views/partials/_sign_in_form.html.erb +0 -18
  57. data/lib/generators/templates/app/views/partials/_sign_in_sign_out.html.erb +0 -19
  58. data/lib/generators/templates/lib/custom_failure.rb +0 -15
@@ -0,0 +1,137 @@
1
+ # encoding : utf-8
2
+ class BeautifulSorceryGenerator < Rails::Generators::Base
3
+ require_relative 'beautiful_scaffold_common_methods'
4
+ include BeautifulScaffoldCommonMethods
5
+
6
+ source_root File.expand_path('../templates', __FILE__)
7
+
8
+ #argument :model, :type => :string, :desc => "Name of model (ex: User)"
9
+
10
+ def install_sorcery
11
+ model = "User"
12
+ view_path = "app/views/"
13
+
14
+ if !File.read('Gemfile').include?("sorcery")
15
+ gem("sorcery", "0.16.0")
16
+ end
17
+
18
+ Bundler.with_unbundled_env do
19
+ run "bundle install"
20
+ end
21
+
22
+ raise "Model must be specified" if model.blank?
23
+
24
+ # Install sorcery
25
+ generate("sorcery:install", "remember_me reset_password user_activation brute_force_protection external --model #{model}")
26
+
27
+ # If exist users migration just add columns
28
+ create_user_migration = Dir.glob("db/migrate/*create_users.rb").first
29
+ if create_user_migration
30
+ already_email = File.read(create_user_migration).include?(":email")
31
+ sorcery_core_file = Dir.glob("db/migrate/*sorcery_core.rb").first
32
+ File.open(sorcery_core_file, "w+") do |f|
33
+ f.write("class SorceryCore < ActiveRecord::Migration[6.1]
34
+ def change
35
+ #{(already_email ? '' : 'add_column :users, :email, :string')}
36
+ add_column :users, :crypted_password, :string
37
+ add_column :users, :salt, :string
38
+
39
+ #{(already_email ? '' : 'add_index :users, :email, unique: true')}
40
+ end
41
+ end")
42
+ end
43
+ end
44
+
45
+ # Generate mailer
46
+ copy_file("app/mailers/user_mailer.rb")
47
+
48
+ # Install controllers
49
+ copy_file("app/controllers/user_sessions_controller.rb")
50
+
51
+ # ===== Controller
52
+ inject_into_file("app/controllers/users_controller.rb",
53
+ "\n
54
+ skip_before_action :require_login, only: [:new, :create, :activate]
55
+ \n", after: "< BeautifulController")
56
+
57
+ inject_into_file("app/controllers/users_controller.rb",
58
+ "def activate
59
+ if @user = User.load_from_activation_token(params[:id])
60
+ @user.activate!
61
+ redirect_to(login_path, :notice => 'User was successfully activated.')
62
+ else
63
+ not_authenticated
64
+ end
65
+ end\n\n ", before: "private")
66
+
67
+ # ====== Model
68
+ # Add password & password_confirmation in model
69
+ inject_into_file("app/models/user.rb",
70
+ "\n
71
+ validates :password, length: { minimum: 3 }, if: -> { new_record? || changes[:crypted_password] }
72
+ validates :password, confirmation: true, if: -> { new_record? || changes[:crypted_password] }
73
+ validates :password_confirmation, presence: true, if: -> { new_record? || changes[:crypted_password] }
74
+
75
+ before_update :setup_activation, if: -> { email_changed? }
76
+ after_update :send_activation_needed_email!, if: -> { previous_changes['email'].present? }\n",
77
+ after: "ApplicationRecord")
78
+
79
+ inject_into_file("app/models/user.rb", ":password,:password_confirmation,", :after => "def self.permitted_attributes\n return ")
80
+
81
+ # ====== Views
82
+ inject_into_file("app/views/users/_form.html.erb",
83
+ ' <div class="form-group">
84
+ <%= f.label :password, t(\'app.models.user.bs_attributes.password\', :default => \'password\').capitalize, :class => "control-label" %><br />
85
+ <%= f.password_field :password, :class => "form-control" %>
86
+ </div>
87
+ <div class="form-group">
88
+ <%= f.label :password_confirmation, t(\'app.models.user.bs_attributes.password_confirmation\', :default => \'password_confirmation\').capitalize, :class => "control-label" %><br />
89
+ <%= f.password_field :password_confirmation, :class => "form-control" %>
90
+ </div>', before: '<!-- Beautiful_scaffold - AddField - Do not remove -->')
91
+
92
+ # Install all views for login/logout
93
+ directory "app/views/login_logout", "app/views"
94
+
95
+ # Domain in action_mailer
96
+ for current_env in ['production', 'development', 'test']
97
+ inject_into_file("config/environments/#{current_env}.rb", " config.action_mailer.default_url_options = { :host => 'localhost:3000' }", :after => "Rails.application.configure do\n" )
98
+ end
99
+
100
+ # In model
101
+ #remove_file("app/models/user.rb") # remove generated by sorcery
102
+ #copy_file("app/models/user.rb") # copy BS version ;)
103
+
104
+ # Limited access
105
+ inject_into_file("app/controllers/beautiful_controller.rb",
106
+ "\n before_action :require_login, except: [:dashboard]\n",
107
+ :after => 'layout "beautiful_layout"' + "\n")
108
+
109
+ inject_into_file("config/initializers/sorcery.rb",
110
+ "\nuser.user_activation_mailer = UserMailer\n",
111
+ :after => "# user.user_activation_mailer =\n")
112
+
113
+ # Routes (session)
114
+ inject_into_file("config/routes.rb",
115
+ '
116
+ resources :user_sessions, only: [:create]
117
+ get "login" => "user_sessions#new", :as => :login
118
+ post "logout" => "user_sessions#destroy", :as => :logout' + "\n\n\n",
119
+ :after => "Rails.application.routes.draw do\n")
120
+
121
+ # Activate
122
+ inject_into_file("config/routes.rb", " do
123
+ member do
124
+ get :activate
125
+ end
126
+ end", after: 'resources :users, concerns: :bs_routes')
127
+
128
+ copy_file("#{view_path}partials/_login_logout_register.html.erb", "#{view_path}layouts/_login_logout_register.html.erb")
129
+
130
+ # Sign in sign out
131
+ inject_into_file("#{view_path}layouts/beautiful_layout.html.erb",
132
+ "\n<%= render :partial => 'layouts/login_logout_register' %>\n",
133
+ :after => "<!-- Beautiful_scaffold - Signin - Do not remove -->")
134
+
135
+ say "Beautiful-Scaffold enable 'user_activation' sorcery module for you, so when you sign up, find in logs the activation link. You can't sign in yourself until you activate the account"
136
+ end
137
+ end
@@ -0,0 +1,61 @@
1
+ # encoding : utf-8
2
+ class BeautifulStorageGenerator < Rails::Generators::Base
3
+ require_relative 'beautiful_scaffold_common_methods'
4
+ include BeautifulScaffoldCommonMethods
5
+
6
+ source_root File.expand_path('../templates', __FILE__)
7
+
8
+ # TODO voir pour engine
9
+
10
+ argument :model, :type => :string, :desc => "Name of model (ex: user)"
11
+ argument :storage_name, :type => :string, :desc => "Storage's name (ex: picture_file)"
12
+
13
+ class_option :mountable_engine, default: nil
14
+
15
+ def install_storage
16
+
17
+ #if !File.read('Gemfile').include?("image_processing")
18
+ gem("image_processing", '~> 1.2')
19
+ #end
20
+
21
+ Bundler.with_unbundled_env do
22
+ run "bundle install"
23
+ end
24
+
25
+ # Install activestorage
26
+ run "bin/rails active_storage:install"
27
+ #run "rake db:migrate"
28
+
29
+ raise "Model must be specified" if model.blank?
30
+ raise "Attachment must be specified" if storage_name.blank?
31
+
32
+ # ===== Model
33
+ inject_into_file("app/models/#{engine_name}#{model}.rb",
34
+ "\n
35
+ has_one_attached :#{storage_name}
36
+ \n", after: "< ApplicationRecord")
37
+ inject_into_file("app/models/#{engine_name}#{model}.rb", ":#{storage_name},", :after => "def self.permitted_attributes\n return ")
38
+
39
+ # ====== Views
40
+ inject_into_file("app/views/#{engine_name}#{model_pluralize}/_form.html.erb",
41
+ " <div class='form-group'>
42
+ <%= f.label :#{storage_name}, t('app.models.#{model}.bs_attributes.#{storage_name}', :default => '#{storage_name}').capitalize, :class => 'control-label' %><br />
43
+ <%= f.file_field :#{storage_name}, direct_upload: true, :class => 'form-control' %>
44
+ </div>\n", before: '<!-- Beautiful_scaffold - AddField - Do not remove -->')
45
+
46
+ inject_into_file("app/views/#{engine_name}#{model_pluralize}/_form.html.erb",
47
+ ", multipart: true", after: "form_for(@#{model}")
48
+
49
+ inject_into_file("app/views/#{engine_name}#{model_pluralize}/show.html.erb",
50
+ "<p><b><%= t('app.models.#{model}.bs_attributes.#{storage_name}', :default => '#{storage_name}') %>:</b><br><%= image_tag @#{model}.#{storage_name}.variant(resize_to_limit: [100, 100]) %></p>",
51
+ before: "<!-- Beautiful_scaffold - AddField - Field - Do not remove -->")
52
+
53
+ # Controller
54
+ #inject_into_file("app/controllers/#{engine_name}#{model_pluralize}_controller.rb",
55
+ # "\n before_action :require_login, except: [:dashboard]\n",
56
+ # :after => 'layout "beautiful_layout"' + "\n")
57
+
58
+ say "You must run 'rake db:migrate' to create activestorage migrations !"
59
+
60
+ end
61
+ end
@@ -4,14 +4,12 @@
4
4
  //= require popper
5
5
  //= require bootstrap-sprockets
6
6
  //= require a-wysihtml5-0.3.0.min
7
- //= require bootstrap-colorpicker
8
7
  //= require moment
9
8
  //= require moment/fr
10
9
  //= require tempusdominus-bootstrap-4.js
11
10
  //= require bootstrap-datetimepicker-for-beautiful-scaffold
12
11
  //= require bootstrap-wysihtml5
13
12
  //= require jstree.min.js
14
- //= require tagit.js
15
13
  //= require jquery-barcode
16
14
  //= require beautiful_scaffold
17
15
  //= require fixed_menu
@@ -18,42 +18,27 @@ function bs_init(){
18
18
  return false;
19
19
  });
20
20
 
21
- // Tagit
21
+ // habtm (select2 - tag)
22
22
  $('.bs-tagit').each(function( index ) {
23
23
  var tagitelt = this;
24
- $(tagitelt).tagit({
25
- tagSource : function( request, response ) {
26
-
27
- var par = $(tagitelt).attr("data-param");
28
- var url = $(tagitelt).attr("data-url");
29
- var result = $(tagitelt).attr("data-result");
30
- var data_to_send = {
31
- "skip_save_search": true
32
- };
33
- data_to_send[par] = request.term;
34
- $.ajax({
35
- url: url,
36
- type: "POST",
37
- data: data_to_send,
38
- dataType: "json",
39
- success: function( data ) {
40
- response( $.map( data, function( item ) {
41
- return { label: item[result], value: item.id };
42
- }));
43
- }
44
- });
45
- },
46
- triggerKeys:['enter', 'comma', 'tab'],
47
- select : true,
48
- allowNewTags : false
24
+ $(tagitelt).select2({
25
+ ajax: {
26
+ processResults: function (data) {
27
+ // Transforms the top-level key of the response object from 'items' to 'results'
28
+ return {
29
+ results: $.map(data, function (obj) {
30
+ obj.id = obj.id;
31
+ obj.text = obj.caption;
32
+ return obj;
33
+ })
34
+ };
35
+ }
36
+ }
49
37
  });
50
- // Bootstrap...
51
- $('.tagit-input').addClass("form-control");
52
38
  });
53
39
 
54
- // Wysiwyg and color field
40
+ // Wysiwyg field
55
41
  $('.wysiwyg-editor').wysihtml5({"html": true});
56
- $('.color').colorpicker({format: 'rgba'});
57
42
 
58
43
  // Processing
59
44
  $(document).on('click', '#checkall', function(){
@@ -1,21 +1,22 @@
1
1
  function datetimepicker_init(){
2
- $('.tpicker').datetimepicker({ format: 'LT' }).on('change.datetimepicker', function(elt){
3
- console.log('===============> time');
4
- console.log(elt);
5
- console.log($(elt.target).attr('data-field'));
2
+ $('.tpicker').datetimepicker({ format: 'LT', widgetPositioning: {
3
+ horizontal: 'auto',
4
+ vertical: 'auto'
5
+ } });
6
+ $('.tpicker').on('change.datetimepicker', function(elt){
6
7
  var eltid = $(elt.target).attr('data-field');
7
- $('#' + eltid + '_4i').val(elt.date.hour());
8
- $('#' + eltid + '_5i').val(elt.date.minute());
8
+ $('#' + eltid + '4i').val(elt.date.hour());
9
+ $('#' + eltid + '5i').val(elt.date.minute());
9
10
  });
10
-
11
- $('.dpicker').datetimepicker({ format: 'L' }).on('change.datetimepicker', function(elt){
12
- console.log('===============> date');
13
- console.log(elt);
14
- console.log($(elt.target).attr('data-field'));
11
+ $('.dpicker').datetimepicker({ format: 'L', widgetPositioning: {
12
+ horizontal: 'auto',
13
+ vertical: 'auto'
14
+ } });
15
+ $('.dpicker').on('change.datetimepicker', function(elt){
15
16
  var eltid = $(elt.target).attr('data-field');
16
- $('#' + eltid + '_3i').val(elt.date.date());
17
- $('#' + eltid + '_2i').val(elt.date.month()+1);
18
- $('#' + eltid + '_1i').val(elt.date.year());
17
+ $('#' + eltid + '3i').val(elt.date.date());
18
+ $('#' + eltid + '2i').val(elt.date.month()+1);
19
+ $('#' + eltid + '1i').val(elt.date.year());
19
20
  });
20
21
  $(document).on('click', '.dpicker', function(e){
21
22
  $(this).datetimepicker('show');
@@ -24,6 +25,6 @@ function datetimepicker_init(){
24
25
  $(this).datetimepicker('show');
25
26
  });
26
27
  $(".datetimepicker-input").each(function(i, elt){
27
- $(elt).removeAttr("name");
28
+ $(elt).removeAttr("name");
28
29
  });
29
30
  }
@@ -11,8 +11,6 @@
11
11
  *= require_self
12
12
  *= require jquery-ui
13
13
  *= require beautiful-scaffold
14
- *= require tagit-dark-grey
15
- *= require colorpicker
16
14
  *= require bootstrap-wysihtml5
17
15
  *= require themes/default/style
18
16
  */
@@ -177,10 +177,12 @@ html, body {
177
177
  margin-bottom: 0px;
178
178
  margin-left: 20px;
179
179
  }
180
+ /*
180
181
  .search-and-filter .form-group label{
181
182
  margin-bottom: 0;
182
183
  margin-top: 5px;
183
184
  }
185
+ */
184
186
 
185
187
  /*
186
188
  div.filler.show-menu{
@@ -199,4 +201,10 @@ div.fixed.hide-menu{
199
201
 
200
202
  .title-index{
201
203
  font-size: 30px;
202
- }
204
+ }
205
+
206
+ .overview-color{
207
+ display:inline-block;
208
+ width: 40px;
209
+ height: 24px;
210
+ }
@@ -0,0 +1,20 @@
1
+ class UserSessionsController < BeautifulController
2
+
3
+ skip_before_action :require_login, only: [:new, :create]
4
+
5
+ def create
6
+ @user = login(params[:email], params[:password])
7
+
8
+ if @user
9
+ redirect_back_or_to(:users, notice: 'Login successful')
10
+ else
11
+ flash.now[:alert] = 'Login failed'
12
+ render action: 'new'
13
+ end
14
+ end
15
+
16
+ def destroy
17
+ logout
18
+ redirect_to(:users, notice: 'Logged out!')
19
+ end
20
+ end
@@ -92,12 +92,15 @@ module BeautifulHelper
92
92
 
93
93
  cap = i18n_translate_path(model_name, attribute_name)
94
94
 
95
+ type_of_column = ar_model.columns_hash[attribute_name].type unless ar_model.columns_hash[attribute_name].nil?
96
+ type_of_column ||= :other
97
+
95
98
  infostr = ''
96
99
  response = '' # See at end
100
+ response += '<div class="form-check form-check-inline">' if type_of_column == :boolean
97
101
  response += f.label name_field, t(cap, :default => default_caption).capitalize, :class => "control-label"
102
+ response += '</div>' if type_of_column == :boolean
98
103
 
99
- type_of_column = ar_model.columns_hash[attribute_name].type unless ar_model.columns_hash[attribute_name].nil?
100
- type_of_column ||= :other
101
104
  case type_of_column
102
105
  when :date, :datetime
103
106
  dt = (type_of_column == :datetime)
@@ -178,9 +181,20 @@ module BeautifulHelper
178
181
  infostr = info_input(model_name, [(name_field + "_dp_lt").to_sym, (name_field + "_tp_lt").to_sym, (name_field + "_dp_gt").to_sym, (name_field + "_tp_gt").to_sym])
179
182
  when :boolean
180
183
  # Specify a default value (false) in rails migration
181
- response += f.label name_field + "_eq_true", raw(f.radio_button((name_field + "_eq").to_sym, true)) + " " + h(t(:yes, :default => "Yes")), :class => "checkbox inline"
182
- response += f.label name_field + "_eq_false", raw(f.radio_button((name_field + "_eq").to_sym, false)) + " " + h(t(:no, :default => "No")), :class => "checkbox inline"
183
- response += f.label name_field + "_eq", raw(f.radio_button((name_field + "_eq").to_sym, nil)) + " " + h(t(:all, :default => "All")), :class => "checkbox inline"
184
+ response += '<div class="form-check form-check-inline">'
185
+ response += f.radio_button((name_field + "_eq").to_sym, true, { class: 'form-check-input'})
186
+ response += f.label name_field + "_eq_true", h(t(:yes, default: "Yes")), class: "form-check-label"
187
+ response += '</div>'
188
+
189
+ response += '<div class="form-check form-check-inline">'
190
+ response += f.radio_button((name_field + "_eq").to_sym, false, { class: 'form-check-input'})
191
+ response += f.label name_field + "_eq_false", h(t(:no, default: "No")), class: "form-check-label"
192
+ response += '</div>'
193
+
194
+ response += '<div class="form-check form-check-inline">'
195
+ response += f.radio_button((name_field + "_eq").to_sym, nil, { class: 'form-check-input'})
196
+ response += f.label name_field + "_eq", h(t(:all, default: "All")), class: "form-check-label"
197
+ response += '</div>'
184
198
 
185
199
  infostr = (begin session['search'][model_name][(name_field + "_eq").to_sym] == "on" ? "" : "info" rescue "" end)
186
200
  when :string
@@ -47,3 +47,11 @@ en:
47
47
  register: "Register"
48
48
  search_and_filter: "Search and filter"
49
49
  more_options: "More options..."
50
+ edit_profile: "edit profile"
51
+ logout: "Logout"
52
+ register: "Register"
53
+ login: "Login"
54
+ logged_out: "Logged out"
55
+ login_failed: "Login failed"
56
+ login_successful: "Login successful"
57
+ crypted_password: "Crypted password"
@@ -46,4 +46,12 @@ fr:
46
46
  send_me_reset_password_instructions: "Me ré-envoyer les instructions de réinitialisation du mot de passe"
47
47
  register: "Inscription"
48
48
  search_and_filter: "Option de filtre"
49
- more_options: "Plus d'options..."
49
+ more_options: "Plus d'options..."
50
+ edit_profile: "Editer mon profil"
51
+ logout: "Déconnexion"
52
+ register: "S'incrire"
53
+ login: "S'identifier"
54
+ logged_out: "déconnecté"
55
+ login_failed: "Erreur d'identification"
56
+ login_successful: "Identification réussie"
57
+ crypted_password: "Crypted password"