alchemy-ajax-form 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +310 -0
  4. data/Rakefile +36 -0
  5. data/app/assets/config/alchemy_ajax_form_manifest.js +3 -0
  6. data/app/assets/images/ajax_form.png +0 -0
  7. data/app/assets/images/alchemy/ajax_form.png +0 -0
  8. data/app/assets/javascripts/ajax_forms.js.erb +185 -0
  9. data/app/controllers/alchemy/admin/ajax_forms_controller.rb +53 -0
  10. data/app/controllers/alchemy/ajax_forms_controller.rb +34 -0
  11. data/app/mailers/alchemy/ajax_forms_mailer.rb +42 -0
  12. data/app/models/alchemy/ajax_form.rb +68 -0
  13. data/app/models/alchemy/ajax_form_ability.rb +22 -0
  14. data/app/views/alchemy/admin/ajax_forms/_table.html.erb +22 -0
  15. data/app/views/alchemy/ajax_forms/create.json.jbuilder +6 -0
  16. data/app/views/alchemy/ajax_forms_mailer/mjml_notify_message.mjml.erb +1 -0
  17. data/app/views/alchemy/ajax_forms_mailer/mjml_notify_user_message.mjml.erb +1 -0
  18. data/app/views/alchemy/ajax_forms_mailer/notify_message.html.erb +1 -0
  19. data/app/views/alchemy/ajax_forms_mailer/notify_user_message.html.erb +1 -0
  20. data/app/views/layouts/alchemy/base_mailer.html.erb +323 -0
  21. data/app/views/layouts/alchemy/mjml_base_mailer.mjml +23 -0
  22. data/config/initializer/assets.rb +1 -0
  23. data/config/locales/it.yml +56 -0
  24. data/config/routes.rb +4 -0
  25. data/lib/alchemy/ajax/form.rb +18 -0
  26. data/lib/alchemy/ajax/form/engine.rb +21 -0
  27. data/lib/alchemy/ajax/form/version.rb +7 -0
  28. data/lib/alchemy/ajax_form_resource.rb +45 -0
  29. data/lib/generators/custom_form/USAGE +8 -0
  30. data/lib/generators/custom_form/custom_form_generator.rb +191 -0
  31. data/lib/generators/custom_form/templates/app/controllers/admin/generic_controller.rb.tt +3 -0
  32. data/lib/generators/custom_form/templates/app/controllers/generic_controller.rb.tt +3 -0
  33. data/lib/generators/custom_form/templates/app/lib/generic_resource.rb.tt +4 -0
  34. data/lib/generators/custom_form/templates/app/model/generic_ability.rb.tt +18 -0
  35. data/lib/generators/custom_form/templates/app/model/generic_form.rb.tt +15 -0
  36. data/lib/generators/custom_form/templates/app/views/alchemy/ajax_forms_mailer/_generic_form.html.erb.tt +38 -0
  37. data/lib/generators/custom_form/templates/app/views/alchemy/ajax_forms_mailer/_generic_user_form.html.erb.tt +39 -0
  38. data/lib/generators/custom_form/templates/app/views/alchemy/elements/_generic_ajax_form_view.html.erb.tt +50 -0
  39. data/lib/generators/custom_form/templates/config/initializers/alchemy_ajax_forms.rb.tt +26 -0
  40. data/lib/generators/custom_form/templates/db/migrate/generic_migration.rb.tt +12 -0
  41. data/lib/tasks/alchemy/ajax/form_tasks.rake +4 -0
  42. metadata +182 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 45ab672b66d4ffa39f450d9a4ad2eb4f1e1b8534
4
+ data.tar.gz: cca6ea5eb17fac0519450621a80d96b2b4148d1d
5
+ SHA512:
6
+ metadata.gz: 11917022577519167aca018ce66bd2c0192bd67dfdbd92643f6ed9986b377f77e51478d7ba16444df88468dc07829b9dde9b919ed63f47b51190995735b4d2f4
7
+ data.tar.gz: ccc002dd2b745626230d24a148a62bef65d8481a0c33d2af53d135e8ad1b3a8dcfd438425c1273b7fa97b7dbbdb81025cbf238183399ed2a6ddfc2a796fef771
@@ -0,0 +1,20 @@
1
+ Copyright 2018 Alessandro Baccanelli
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,310 @@
1
+ # Alchemy::Ajax::Form
2
+ A gem for semplify form creations in alchemy.
3
+
4
+ ## Installation
5
+ Add this line to your application's Gemfile:
6
+
7
+ ```ruby
8
+ gem 'alchemy-ajax-form', github: "ArchimediaZerogroup/alchemy-ajax-form"
9
+ ```
10
+
11
+ And then execute:
12
+ ```bash
13
+ $ bundle install
14
+ ```
15
+
16
+ Or install it yourself as:
17
+ ```bash
18
+ $ gem install alchemy-ajax-form
19
+ ```
20
+
21
+ install mjml 4.1.0 with npm globally (with sudo if necessary)
22
+ ```bash
23
+ $ npm install mjml@4.1.0 -g
24
+ ```
25
+
26
+
27
+ ## Usage
28
+ Launch the generator with this command:
29
+ ```bash
30
+ $ bin/rails generate custom_form name_of_form param:type
31
+ ```
32
+ example:
33
+ ```bash
34
+ $ bin/rails generate custom_form contact_form email:string firstname:string lastname:string message:text
35
+ ```
36
+
37
+ Ansawer to the questions step by step
38
+
39
+ Configure element in layoutpage
40
+
41
+ Restart Server
42
+
43
+ ### How use without generator
44
+ If you don't wont use the generator you have to follow these steps:
45
+
46
+ Let's assume we want to create the form "ContactForm"
47
+
48
+ #### Create Admin Controller
49
+
50
+ Create Admin::ContactFormsController (/app/controllers/admin/contact_forms_controller.rb)
51
+
52
+ ```ruby
53
+ class Admin::ContactFormsController < Alchemy::Admin::AjaxFormsController
54
+
55
+ end
56
+ ```
57
+
58
+ #### Create Controller
59
+ Create ContactFormsController (/app/controllers/admin/contact_forms_controller.rb)
60
+
61
+ ```ruby
62
+ class ContactFormsController < Alchemy::AjaxFormsController
63
+
64
+ end
65
+ ```
66
+
67
+ #### Create Resource
68
+ Create ContactFormResource (app/lib/contact_form_resource.rb)
69
+
70
+ ```ruby
71
+ class ContactFormResource < Alchemy::AjaxFormResource
72
+
73
+ end
74
+ ```
75
+
76
+ #### Create Model
77
+ Create ContactForm (app/models/contact_form.rb)
78
+
79
+ ```ruby
80
+ class ContactForm < Alchemy::AjaxForm
81
+
82
+ validates :check_privacy, inclusion: [true, '1']
83
+
84
+
85
+ def notify_subject
86
+ I18n.translate(:contact_form_notify, scope: [:ajax_form_mailer, :subjects])
87
+ end
88
+
89
+ def notify_user_subject
90
+ I18n.translate(:contact_form_user_notify, scope: [:ajax_form_mailer, :subjects])
91
+ end
92
+
93
+
94
+ end
95
+ ```
96
+
97
+ #### Create Ability
98
+ Create ContactFormAbility (app/models/contact_form_ability.rb)
99
+
100
+ ```ruby
101
+ class ContactFormAbility
102
+ include CanCan::Ability
103
+
104
+ def initialize(user)
105
+ if user.present? && user.is_admin?
106
+ can :manage, ContactForm
107
+ cannot :create, ContactForm
108
+ cannot :update, ContactForm
109
+ can :manage, :admin_contact_forms
110
+ cannot :create, :admin_contact_forms
111
+ cannot :update, :admin_contact_forms
112
+ end
113
+ end
114
+
115
+ end
116
+ ```
117
+
118
+ #### Create Migration
119
+ Create CreateContactForm (db/migrate/%Y%m%d%H%M%Screate_contact_form.rb)
120
+
121
+ ```ruby
122
+ class CreateContactForm < ActiveRecord::Migration[5.2]
123
+ def change
124
+ create_table :contact_forms do |t|
125
+
126
+ # insert all form fields
127
+
128
+ t.boolean :check_privacy
129
+ t.references :language, index: true
130
+ t.timestamps
131
+ end
132
+ end
133
+ end
134
+ ```
135
+
136
+ #### Create Element Configuration
137
+ Insert into file "config/alchemy/elements.yml"
138
+
139
+ ```yaml
140
+ - name: contact_form
141
+ hint: false
142
+ contents:
143
+ - name: privacy_page
144
+ type: EssenceText
145
+ settings:
146
+ linkable: true
147
+ - name: recipient_notification
148
+ type: EssenceText
149
+ default: "example@example.it"
150
+ - name: send_only
151
+ type: EssenceBoolean
152
+ - name: send_staff
153
+ type: EssenceBoolean
154
+ - name: send_user
155
+ type: EssenceBoolean\n
156
+
157
+ ```
158
+
159
+ #### Create Element View
160
+ Create contact form view "app/views/alchemy/elements/_contact_form_view.html.erb"
161
+
162
+ ```erbruby
163
+ <% cache(element) do %>
164
+ <%= element_view_for(element) do |el| -%>
165
+
166
+
167
+ <%
168
+ privacy_link = element.content_by_name(:privacy_page).essence.link
169
+ privacy_title = element.content_by_name(:privacy_page).essence.body
170
+ @contact_form = ContactForm.new
171
+ @contact_form.alcm_element = element.id
172
+ %>
173
+
174
+
175
+ <div class="messages"></div>
176
+
177
+
178
+ <%= form_for(@contact_form, url: main_app.contact_forms_path, method: :post, remote: true, multipart: true,html:{class: "ajax_forms"}) do |f| %>
179
+ <%= f.hidden_field :alcm_element %>
180
+ <div class="row">
181
+ #list of attributes
182
+ </div>
183
+
184
+ <% if !privacy_title.blank? %>
185
+ <div class="privacy">
186
+ <div class="single_privacy">
187
+ <%= f.check_box :check_privacy %>
188
+ <%= link_to privacy_link do %>
189
+ <label><%= privacy_title %></label>
190
+ <% end %>
191
+ </div>
192
+ </div>
193
+ <% else %>
194
+ <%= f.check_box :check_privacy %>
195
+ <% end %>
196
+
197
+
198
+ <div class="submit">
199
+ <%= f.submit t(:submit) %>
200
+ </div>
201
+
202
+ <% end %>
203
+
204
+
205
+
206
+ <%- end -%>
207
+ <%- end -%>
208
+ ```
209
+
210
+ #### Create or add entry to initializer
211
+
212
+ Create or edit alchemy_ahax_forms initializer ( config/initializers/alchemy_ajax_forms.rb)
213
+
214
+ ```ruby
215
+ Alchemy::Modules.register_module({
216
+ name: 'alchemy_ajax_forms',
217
+ order: 1,
218
+ navigation: {
219
+ name: 'modules.contact_forms',
220
+ controller: '/admin/contact_forms',
221
+ action: 'index',
222
+ image: 'alchemy/ajax_form.png',
223
+ sub_navigation: [
224
+ {
225
+ name: 'modules.contact_forms',
226
+ controller: '/admin/contact_forms',
227
+ action: 'index'
228
+ },
229
+ ]
230
+ }
231
+ })
232
+
233
+ Alchemy.register_ability(ContactFormAbility)
234
+
235
+ module Alchemy
236
+
237
+ EMAIL_NOTIFY= "example@example.it"
238
+ EMAIL_NOTIFY_FROM = "no-reply@example.it"
239
+
240
+ end
241
+ ```
242
+
243
+ If you add multiple form add only:
244
+ ```ruby
245
+ {
246
+ name: 'modules.contact_forms',
247
+ controller: '/admin/contact_forms',
248
+ action: 'index'
249
+ }
250
+ ```
251
+ and ability
252
+ ```ruby
253
+ Alchemy.register_ability(ContactFormAbility)
254
+ ```
255
+
256
+ #### Create Mail Template
257
+
258
+ Create email template ()app/views/alchemy/ajax_forms_mailer/_contact_form.mjml)
259
+ Create email template for user notification ()app/views/alchemy/ajax_forms_mailer/_contact_form_user.mjml)
260
+
261
+ ```ruby
262
+ <mj-column>
263
+ <mj-text align="left" color="#55575d" font-family="Arial, sans-serif" font-size="13px" line-height="22px" padding-bottom="0px" padding-top="5px" padding="10px 25px">
264
+ <p style="line-height: 16px; text-align: center; margin: 10px 0;font-size:12px;color:#000;font-family:'Times New Roman',Helvetica,Arial,sans-serif">
265
+ <span><b>attribute name:</b></span>
266
+ <span><%= rec.attribute_name %></span>
267
+ </p>
268
+ </mj-text>
269
+ </mj-column>
270
+ ```
271
+
272
+ #### Add Routes
273
+ Add right routes
274
+
275
+ ```ruby
276
+ namespace :admin do
277
+ resources :contact_forms
278
+
279
+ end
280
+ resources :contact_forms , only: [:create]
281
+ ```
282
+
283
+ #### Require assets
284
+ Add to app/assets/javascripts/application.js
285
+
286
+ ```ruby
287
+ //= require jquery3
288
+ //= require ajax_forms
289
+ ```
290
+
291
+ ### Run Migration
292
+ Run migration with rake task
293
+
294
+ ```bash
295
+ $ bin/rake db:migrate
296
+ ```
297
+
298
+ Configure element in layoutpage
299
+
300
+ Restart Server
301
+
302
+ ## Translations
303
+ Remember to check translations
304
+
305
+
306
+ ## Contributing
307
+ Contribution directions go here.
308
+
309
+ ## License
310
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
@@ -0,0 +1,36 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'Alchemy::Ajax::Form'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.md')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
18
+ load 'rails/tasks/engine.rake'
19
+
20
+
21
+ load 'rails/tasks/statistics.rake'
22
+
23
+
24
+
25
+ require 'bundler/gem_tasks'
26
+
27
+ require 'rake/testtask'
28
+
29
+ Rake::TestTask.new(:test) do |t|
30
+ t.libs << 'test'
31
+ t.pattern = 'test/**/*_test.rb'
32
+ t.verbose = false
33
+ end
34
+
35
+
36
+ task default: :test
@@ -0,0 +1,3 @@
1
+ //= link_tree ../images
2
+ //= link_directory ../javascripts .js
3
+ //= link_directory ../stylesheets .css
@@ -0,0 +1,185 @@
1
+ (function ($) {
2
+
3
+ var recaptha_disabled = <%= Recaptcha.configuration.skip_verify_env.include?(Rails.env.to_s ) %>
4
+
5
+
6
+ var print_results = function (element, result) {
7
+ if (result instanceof Array) {
8
+ var resp = "";
9
+
10
+ $.each(result, function (index, value) {
11
+
12
+ resp += "<span>" + value + "</span>";
13
+
14
+ });
15
+
16
+ } else {
17
+ resp = result
18
+ }
19
+
20
+ resp = '<div class="default_message">' + resp + '</div>';
21
+ $(element).append(resp);
22
+
23
+ };
24
+
25
+ var add_errors = function (form, errors) {
26
+
27
+ $.each(errors, function (name, value) {
28
+
29
+ var input = $(form).find("[name*='" + name + "']");
30
+
31
+
32
+ $(input).addClass("invalid");
33
+
34
+ if ($(input).parent().children('.error-message').length == 0) {
35
+ $(input).parent().append("<span class='error-message'>" + value + "</span>");
36
+ } else {
37
+ $('.error-message').show();
38
+ }
39
+
40
+ });
41
+ };
42
+
43
+
44
+ var clear_deafult_message = function (form) {
45
+ var message_box = $(form).parent().find(".messages")[0];
46
+ var default_message = $(message_box).find(".default_message");
47
+ var custom_message = $(message_box).find(".custom_message");
48
+ if ($(default_message).length > 0) {
49
+ $(default_message).remove();
50
+ }
51
+
52
+ if ($(custom_message).length == 0) {
53
+ $(message_box).html("");
54
+ }
55
+ }
56
+
57
+
58
+ var add_loader = function (form) {
59
+ if ($(form).children('.ajax_forms_loader').length == 0) {
60
+ $(form).append('<div class="ajax_forms_loader"> <i class="fa fa-circle-o-notch fa-spin"></i> </div>');
61
+ } else {
62
+ $(form).children('.ajax_forms_loader').fadeIn();
63
+ }
64
+ }
65
+
66
+ var hide_loader = function (form) {
67
+ $(form).children('.ajax_forms_loader').fadeOut();
68
+ }
69
+
70
+ var submit_function = function (form, method, action) {
71
+ $(form).trigger("submitted");
72
+ add_loader(form);
73
+
74
+ if ($(form).find("[name='_dontcare']").length < 1) {
75
+ $(form).append("<input type=\"hidden\" name=\"_dontcare\">")
76
+ }
77
+
78
+ var formdata = new FormData($(form)[0])
79
+ $.ajax({
80
+ method: method,
81
+ url: action,
82
+ dataType: "json",
83
+ data: formdata,
84
+ contentType: false,
85
+ processData: false,
86
+ success: function (response, status, xhr) {
87
+
88
+ clear_deafult_message(form);
89
+ var message_box = $(form).parent().find(".messages")[0];
90
+ if (!$(message_box).find(".custom_message").length > 0) {
91
+ print_results(message_box, response.messages);
92
+ }
93
+
94
+ $(form).trigger("successed");
95
+ $(message_box).addClass('ok');
96
+ $(form).trigger("reset");
97
+
98
+ },
99
+ error: function (xhr, status, errorThrown) {
100
+ var response = JSON.parse(xhr.responseText);
101
+ var message_box = $(form).parent().find(".messages")[0];
102
+ clear_deafult_message(form);
103
+ print_results(message_box, response.messages);
104
+ $(form).trigger("failed", [xhr, status, errorThrown]);
105
+ $(message_box).addClass('ko');
106
+ add_errors(form, response.errors);
107
+
108
+ },
109
+ complete: function () {
110
+ if (!recaptha_disabled) {
111
+ grecaptcha.reset();
112
+ }
113
+ $(form).find("input[type='submit']").attr("disabled", false);
114
+ hide_loader(form);
115
+ }
116
+ });
117
+ }
118
+
119
+ load_invisible_recaptcha = function () {
120
+
121
+
122
+ $(document).ready(function () {
123
+
124
+
125
+
126
+ $(".ajax_forms").each(function (element, index) {
127
+
128
+ var form = this;
129
+ var action = $(this).attr("action");
130
+ var method = $(this).attr("method");
131
+ var submit_button = $(form).find(".submit").last();
132
+
133
+
134
+ if (!recaptha_disabled) {
135
+ var container_div = $('<div class="invisible_recaptcha_container"></div>');
136
+ $(submit_button).before(container_div);
137
+
138
+ var widget_id = grecaptcha.render(container_div[0], {
139
+ 'sitekey': '<%= Recaptcha.configuration.site_key! %>',
140
+ 'badge': 'inline',
141
+ 'size': 'invisible',
142
+ 'callback': function () {
143
+ submit_function(form, method, action);
144
+ }
145
+ });
146
+
147
+ $(form).data("widget-id",widget_id)
148
+
149
+ }
150
+
151
+ $(form).children('.ajax_forms_loader').fadeOut();
152
+ });
153
+
154
+ $(document).on("submit", ".ajax_forms", function (event) {
155
+
156
+ event.preventDefault ? event.preventDefault() : (event.returnValue = false);
157
+
158
+ var form = $(event.target);//.closest("form");
159
+ var action = $(form).attr("action");
160
+ var method = $(form).attr("method");
161
+ var widget_id = $(form).data("widget-id");
162
+ // disable all submit buttons
163
+ $(form).find("input[type='submit']").attr("disabled", true)
164
+
165
+
166
+ if (!recaptha_disabled) {
167
+ grecaptcha.execute(widget_id)
168
+ } else {
169
+ submit_function(form, method, action);
170
+ }
171
+
172
+
173
+ });
174
+
175
+ $('.ajax_forms').on('change', '.invalid', function () {
176
+ $(this).removeClass("invalid");
177
+ $(this).parent().children('.error-message').hide();
178
+ });
179
+
180
+ });
181
+ };
182
+ $.getScript("//www.google.com/recaptcha/api.js?onload=load_invisible_recaptcha&render=explicit")
183
+
184
+
185
+ })(jQuery);