effective_resources 2.23.0 → 2.25.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b5203021d6f8cd741603bcf0459f4277f6227c56fde16fd21fb99cae45564667
4
- data.tar.gz: 505149510d60183e7b0935a043f6be30d96dbb79099225a89c6fdc136ad1100d
3
+ metadata.gz: 3a0aa5a3bcbd09397c6cd7815465cdfe0882045fba170ced84f6dbf59732db87
4
+ data.tar.gz: 0f78f2cce168bbda0d6221d6f8ea41b143c080d97b52ad78c7193c659d1aafa7
5
5
  SHA512:
6
- metadata.gz: 5efcc14c75d711551ae84574fd1bb64970273a170c7135a645af656b55be45ea8b71520827950933b13d636a32c51c5b0a4a58326666bbcf8722394ae086b6ad
7
- data.tar.gz: ca89163745a47fe5be4342149df505800565cf6afc6991a9d765de4099d8b2efe17f570f27026eadaa5f7c6629edcd6d7f25c4f0ba5e6a13ea6b840f52c49f15
6
+ metadata.gz: 035ca01e53c2d094b2174048e9a1f27f01b64e9cf12539587ac94350402b4569562e3be33322eb44f23182a88d5eb2fa68df4d8ff491ad0b6cbc95f2d2da3c09
7
+ data.tar.gz: 1df2b4a3f3ba19cd4e3d2b1875cd1d58627f3ab181bdb8cf0ebf268fcec8ea8e161754ec7a1f91618dbecb71e6d8c94ee7f5163aa833444a1e616c8c066712cf
@@ -28,6 +28,10 @@ module Effective
28
28
  params[resource_name].to_unsafe_h
29
29
  end
30
30
 
31
+ to_assign ||= if params[effective_resource_name].present? && params[effective_resource_name].respond_to?(:to_unsafe_h)
32
+ params[effective_resource_name].to_unsafe_h
33
+ end
34
+
31
35
  to_assign ||= if params.present?
32
36
  params.to_unsafe_h.except(:controller, :action, :id, :duplicate_id)
33
37
  end
@@ -103,6 +103,10 @@ module Effective
103
103
  effective_resource.name
104
104
  end
105
105
 
106
+ def effective_resource_name # effective_notification
107
+ effective_resource.resource_name
108
+ end
109
+
106
110
  def resource_name_id
107
111
  (effective_resource.name + '_id').to_sym
108
112
  end
@@ -69,7 +69,7 @@ module Effective
69
69
 
70
70
  def build_wizard_resource
71
71
  resource = resource_scope.new
72
- resource.strict_loading!(false) if resource.respond_to?(:strict_loading!)
72
+ (resource.strict_loading!(false) rescue false) if resource.respond_to?(:strict_loading!)
73
73
  resource
74
74
  end
75
75
 
@@ -0,0 +1,102 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EffectiveResourcesEmailHelper
4
+ def mailer_froms_collection(froms: nil)
5
+ froms ||= EffectiveResources.mailer_froms
6
+
7
+ froms.map do |from|
8
+ html = content_tag(:span, escape_once(from))
9
+ [from, from, 'data-html': html]
10
+ end
11
+ end
12
+
13
+ # acts_as_email_form
14
+ def email_form_fields(form, action = nil, skip: true, to: nil, variables: nil, partial: nil)
15
+ raise('expected a form') unless form.respond_to?(:object)
16
+
17
+ resource = form.object
18
+
19
+ # Intended for acts_as_email_form but sometimes we use a duck typed object to save these fields as well
20
+ unless resource.class.respond_to?(:acts_as_email_form?) || resource.respond_to?("email_form_action=")
21
+ raise('expected an acts_as_email_form resource or one that responds to email_form_action')
22
+ end
23
+
24
+ # Load the template.
25
+ email_template = if action.present? && defined?(EffectiveEmailTemplates)
26
+ action.kind_of?(Effective::EmailTemplate) ? action : Effective::EmailTemplate.where(template_name: action).first!
27
+ end
28
+
29
+ # These defaults are only used when there is no email_template
30
+ email_defaults = form.object.email_form_defaults(action) unless email_template.present?
31
+
32
+ from = email_template&.from || email_defaults[:from] || EffectiveResources.mailer_froms.first
33
+ subject = email_template&.subject || email_defaults[:subject] || ''
34
+ body = email_template&.body || email_defaults[:body] || ''
35
+ content_type = email_template&.content_type || email_defaults[:content_type] || ''
36
+
37
+ locals = {
38
+ form: form,
39
+ email_to: to,
40
+ email_from: from,
41
+ email_subject: subject,
42
+ email_body: body,
43
+ email_content_type: content_type,
44
+ email_skip: skip,
45
+ email_action: (action || true),
46
+ email_template: email_template,
47
+ email_variables: variables
48
+ }
49
+
50
+ render(partial: (partial || 'effective/acts_as_email_form/fields'), locals: locals)
51
+ end
52
+
53
+ # acts_as_email_notification
54
+ def email_notification_fields(form, action, partial: nil, variables: nil)
55
+ raise('expected a form') unless form.respond_to?(:object)
56
+
57
+ resource = form.object
58
+
59
+ # Intended for acts_as_email_notification
60
+ raise('expected an acts_as_email_notification resource') unless resource.class.respond_to?(:acts_as_email_notification?)
61
+
62
+ # Load the template.
63
+ email_template = if action.present? && defined?(EffectiveEmailTemplates)
64
+ action.kind_of?(Effective::EmailTemplate) ? action : Effective::EmailTemplate.where(template_name: action).first!
65
+ end
66
+
67
+ raise('expected an Effective::EmailTemplate') unless email_template.kind_of?(Effective::EmailTemplate)
68
+
69
+ locals = {
70
+ form: form,
71
+
72
+ email_from: email_template.try(:from),
73
+ email_subject: email_template.try(:subject),
74
+ email_body: email_template.try(:body),
75
+ email_cc: email_template.try(:cc),
76
+ email_bcc: email_template.try(:bcc),
77
+ email_content_type: email_template.try(:content_type),
78
+
79
+ email_template: email_template,
80
+ email_variables: variables
81
+ }
82
+
83
+ render(partial: (partial || 'effective/acts_as_email_notification/fields'), locals: locals)
84
+ end
85
+
86
+ def email_message_html?(message)
87
+ message.parts.find { |part| part.content_type.start_with?('text/html') }.present?
88
+ end
89
+
90
+ def email_message_plain?(message)
91
+ message.parts.find { |part| part.content_type.start_with?('text/html') }.blank?
92
+ end
93
+
94
+ def email_message_body(message)
95
+ html_body = message.parts.find { |part| part.content_type.start_with?('text/html') }.try(:body).to_s
96
+ plain_body = message.parts.find { |part| part.content_type.start_with?('text/plain') }.try(:body).to_s
97
+ message_body = message.body.to_s
98
+
99
+ html_body.presence || plain_body.presence || message_body.presence
100
+ end
101
+
102
+ end
@@ -49,24 +49,24 @@ module ActsAsEmailForm
49
49
  validates :email_form_subject, liquid: true
50
50
  validates :email_form_body, liquid: true
51
51
  end
52
+ end
52
53
 
53
- def email_form_params
54
- { from: email_form_from, subject: email_form_subject, body: email_form_body }.compact
55
- end
56
-
57
- def email_form_skip?
58
- EffectiveResources.truthy?(email_form_skip)
59
- end
54
+ module ClassMethods
55
+ def acts_as_email_form?; true; end
56
+ end
60
57
 
61
- # Only considered when not using an effective email template
62
- def email_form_defaults(action)
63
- { from: nil, subject: nil, body: nil, content_type: 'text/plain' }
64
- end
58
+ # Instance methods
59
+ def email_form_params
60
+ { from: email_form_from, subject: email_form_subject, body: email_form_body }.compact
61
+ end
65
62
 
63
+ def email_form_skip?
64
+ EffectiveResources.truthy?(email_form_skip)
66
65
  end
67
66
 
68
- module ClassMethods
69
- def acts_as_email_form?; true; end
67
+ # Only considered when not using an effective email template
68
+ def email_form_defaults(action)
69
+ { from: nil, subject: nil, body: nil, content_type: 'text/plain' }
70
70
  end
71
71
 
72
72
  end
@@ -0,0 +1,124 @@
1
+ # ActsAsEmailNotification
2
+ # Used for email notification resources that are initialized from an effective_email_template but save their own liquid template content.
3
+ # Effective::EventNotification, Effective::PollNotification, Effective::Notification
4
+
5
+ module ActsAsEmailNotification
6
+ extend ActiveSupport::Concern
7
+
8
+ module Base
9
+ def acts_as_email_notification
10
+ include ::ActsAsEmailNotification
11
+ end
12
+ end
13
+
14
+ included do
15
+ if respond_to?(:effective_resource)
16
+ effective_resource do
17
+ from :string
18
+ cc :string
19
+ bcc :string
20
+
21
+ subject :string
22
+ body :text
23
+
24
+ content_type :string
25
+ end
26
+ end
27
+
28
+ validates :from, presence: true, email: true
29
+ validates :cc, email_cc: true
30
+ validates :bcc, email_cc: true
31
+
32
+ validates :subject, presence: true
33
+ validates :body, presence: true
34
+
35
+ validates :content_type, presence: true, inclusion: { in: ['text/plain', 'text/html'] }
36
+
37
+ validates :email_template, presence: true
38
+
39
+ with_options(if: -> { defined?(EffectiveEmailTemplates) }) do
40
+ validates :body, liquid: true
41
+ validates :subject, liquid: true
42
+ end
43
+
44
+ validate(if: -> { email_notification_html? && body.present? }) do
45
+ errors.add(:body, 'expected html tags in body') if email_notification_body_plain?
46
+ end
47
+
48
+ validate(if: -> { email_notification_plain? && body.present? }) do
49
+ errors.add(:body, 'unexpected html tags found in body') if email_notification_body_html?
50
+ end
51
+
52
+ validate(if: -> { email_notification_subject_template.present? }) do
53
+ if(invalid = email_notification_subject_variables - email_template_variables).present?
54
+ errors.add(:subject, "Invalid variable: #{invalid.to_sentence}")
55
+ end
56
+ end
57
+
58
+ validate(if: -> { email_notification_body_template.present? }) do
59
+ if(invalid = email_notification_body_variables - email_template_variables).present?
60
+ errors.add(:body, "Invalid variable: #{invalid.to_sentence}")
61
+ end
62
+ end
63
+ end
64
+
65
+ module ClassMethods
66
+ def acts_as_email_notification?; true; end
67
+ end
68
+
69
+ # To be overrided
70
+ def email_template
71
+ raise('to be implemented')
72
+ end
73
+
74
+ def email_template_variables
75
+ raise('to be implemented')
76
+ end
77
+
78
+ def email_notification_params
79
+ { from: from, cc: cc.presence, bcc: bcc.presence, subject: subject, body: body, content_type: content_type }
80
+ end
81
+
82
+ def email_notification_html?
83
+ content_type == 'text/html'
84
+ end
85
+
86
+ def email_notification_plain?
87
+ content_type == 'text/plain'
88
+ end
89
+
90
+ def email_notification_body_html?
91
+ body.present? && (body.include?('</p>') || body.include?('</div>'))
92
+ end
93
+
94
+ def email_notification_body_plain?
95
+ body.present? && !(body.include?('</p>') || body.include?('</div>'))
96
+ end
97
+
98
+ def email_notification_body_template
99
+ Liquid::Template.parse(body) rescue nil
100
+ end
101
+
102
+ def email_notification_subject_template
103
+ Liquid::Template.parse(subject) rescue nil
104
+ end
105
+
106
+ def email_notification_body_variables
107
+ template = email_notification_body_template()
108
+ return unless template.present?
109
+
110
+ Liquid::ParseTreeVisitor.for(template.root).add_callback_for(Liquid::VariableLookup) do |node|
111
+ [node.name, *node.lookups].join('.')
112
+ end.visit.flatten.uniq.compact
113
+ end
114
+
115
+ def email_notification_subject_variables
116
+ template = email_notification_subject_template()
117
+ return unless template.present?
118
+
119
+ Liquid::ParseTreeVisitor.for(template.root).add_callback_for(Liquid::VariableLookup) do |node|
120
+ [node.name, *node.lookups].join('.')
121
+ end.visit.flatten.uniq.compact
122
+ end
123
+
124
+ end
@@ -4,24 +4,35 @@
4
4
  = form.check_box :email_form_skip, label: 'Do not send email'
5
5
 
6
6
  = form.hide_if :email_form_skip, true do
7
- - errors = form.object.errors.present?
8
-
9
7
  - if email_to.present?
10
8
  = form.static_field :email_form_to, label: 'To', value: (email_to.try(:email) || email_to)
11
9
 
12
- = form.select :email_form_from, mailer_froms_collection(), label: 'From', value: (email_from unless errors)
13
- = form.text_field :email_form_subject, label: 'Subject', value: (email_subject unless errors)
14
-
15
- - if email_content_type == 'text/html'
16
- = form.article_editor :email_form_body, label: 'Body', mode: :email, value: (email_body unless errors)
17
- - else
18
- = form.text_area :email_form_body, label: 'Body', rows: 10, value: (email_body unless errors)
10
+ - # With errors
11
+ - if form.object.errors.present?
12
+ = form.select :email_form_from, mailer_froms_collection(), label: 'From'
13
+ = form.text_field :email_form_subject, label: 'Subject'
14
+
15
+ - if email_content_type == 'text/html'
16
+ = form.article_editor :email_form_body, label: 'Body', mode: :email
17
+ - else
18
+ = form.text_area :email_form_body, label: 'Body', rows: 10
19
+
20
+ - # With no errors
21
+ - if form.object.errors.blank?
22
+ = form.select :email_form_from, mailer_froms_collection(), label: 'From', value: email_from
23
+ = form.text_field :email_form_subject, label: 'Subject', value: email_subject
24
+
25
+ - if email_content_type == 'text/html'
26
+ = form.article_editor :email_form_body, label: 'Body', mode: :email, value: email_body
27
+ - else
28
+ = form.text_area :email_form_body, label: 'Body', rows: 10, value: email_body
19
29
 
20
30
  - if email_variables.present?
21
- %p The available variables are:
31
+ = card do
32
+ %p The available variables are:
22
33
 
23
- %ul
24
- - email_variables.each do |variable|
25
- %li {{ #{variable} }}
34
+ %ul
35
+ - email_variables.each do |variable|
36
+ %li {{ #{variable} }}
26
37
 
27
- %small.text-muted Please contact us to add additional variables
38
+ %small.text-muted Please contact us to add additional variables
@@ -0,0 +1,53 @@
1
+ - if email_template.present?
2
+ %p The following #{link_to(email_template, effective_email_templates.edit_admin_email_template_path(email_template), target: '_blank')} email will be sent:
3
+
4
+ = form.hidden_field :content_type, value: email_content_type
5
+
6
+ - uid = effective_bootstrap_unique_id
7
+ - expanded = form.object.cc.present? || form.object.bcc.present?
8
+ - mailer_subject_prefix_hint = EffectiveResources.mailer_subject_prefix_hint.to_s.strip.presence
9
+
10
+ - if form.object.new_record? && form.object.errors.blank?
11
+ .row
12
+ .col-md-10
13
+ = form.select :from, mailer_froms_collection(), label: 'From', value: email_from
14
+ .col-md-2.my-4
15
+ %a{href: "#acts-as-email-notification-collapse-#{uid}", 'data-toggle': 'collapse', role: 'button', 'aria-expanded': expanded, 'aria-controls': "acts-as-email-notification-collapse-#{uid}"} more...
16
+
17
+ .collapse{id: "acts-as-email-notification-collapse-#{uid}", class: ('show' if expanded)}
18
+ = form.text_field :cc, label: 'CC', value: email_cc
19
+ = form.text_field :bcc, label: 'BCC', value: email_bcc
20
+
21
+ = form.text_field :subject, value: email_subject, hint: (mailer_subject_prefix_hint ? "The subject of your email. It will be automatically prefixed with: #{mailer_subject_prefix_hint}" : 'The subject of your email')
22
+
23
+ - if email_content_type == 'text/html'
24
+ = form.article_editor :body, label: 'Body', mode: :email, value: email_body
25
+ - else
26
+ = form.text_area :body, label: 'Body', rows: 10, value: email_body
27
+
28
+ - else
29
+ .row
30
+ .col-md-10
31
+ = form.select :from, mailer_froms_collection(), label: 'From'
32
+ .col-md-2.my-4
33
+ %a{href: "#acts-as-email-notification-collapse-#{uid}", 'data-toggle': 'collapse', role: 'button', 'aria-expanded': expanded, 'aria-controls': "acts-as-email-notification-collapse-#{uid}"} more...
34
+
35
+ .collapse{id: "acts-as-email-notification-collapse-#{uid}", class: ('show' if expanded)}
36
+ = form.text_field :cc, label: 'CC'
37
+ = form.text_field :bcc, label: 'BCC'
38
+
39
+ = form.text_field :subject, hint: (mailer_subject_prefix_hint ? "The subject of your email. It will be automatically prefixed with: #{mailer_subject_prefix_hint}" : 'The subject of your email')
40
+
41
+ - if email_content_type == 'text/html'
42
+ = form.article_editor :body, label: 'Body', mode: :email
43
+ - else
44
+ = form.text_area :body, label: 'Body', rows: 10
45
+
46
+ - if email_variables.present?
47
+ = card do
48
+ %p You can use the following variables in the subject and body:
49
+
50
+ %ul
51
+ - email_variables.each do |variable|
52
+ %li {{ #{variable} }}
53
+
@@ -24,6 +24,7 @@ module EffectiveResources
24
24
  app.config.to_prepare do
25
25
  ActiveRecord::Base.extend(ActsAsArchived::Base)
26
26
  ActiveRecord::Base.extend(ActsAsEmailForm::Base)
27
+ ActiveRecord::Base.extend(ActsAsEmailNotification::Base)
27
28
  ActiveRecord::Base.extend(ActsAsTokened::Base)
28
29
  ActiveRecord::Base.extend(ActsAsSlugged::Base)
29
30
  ActiveRecord::Base.extend(ActsAsStatused::Base)
@@ -1,3 +1,3 @@
1
1
  module EffectiveResources
2
- VERSION = '2.23.0'.freeze
2
+ VERSION = '2.25.0'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: effective_resources
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.23.0
4
+ version: 2.25.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Code and Effect
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-06-20 00:00:00.000000000 Z
11
+ date: 2024-06-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -194,13 +194,14 @@ files:
194
194
  - app/controllers/concerns/effective/wizard_controller/permitted_params.rb
195
195
  - app/controllers/concerns/effective/wizard_controller/save.rb
196
196
  - app/controllers/concerns/effective/wizard_controller/wicked_overrides.rb
197
- - app/helpers/effective_acts_as_email_form_helper.rb
197
+ - app/helpers/effective_resources_email_helper.rb
198
198
  - app/helpers/effective_resources_helper.rb
199
199
  - app/helpers/effective_resources_private_helper.rb
200
200
  - app/helpers/effective_resources_wizard_helper.rb
201
201
  - app/mailers/concerns/effective_mailer.rb
202
202
  - app/models/concerns/acts_as_archived.rb
203
203
  - app/models/concerns/acts_as_email_form.rb
204
+ - app/models/concerns/acts_as_email_notification.rb
204
205
  - app/models/concerns/acts_as_paginable.rb
205
206
  - app/models/concerns/acts_as_purchasable_wizard.rb
206
207
  - app/models/concerns/acts_as_slugged.rb
@@ -256,6 +257,7 @@ files:
256
257
  - app/views/application/show.js.erb
257
258
  - app/views/application/update.js.erb
258
259
  - app/views/effective/acts_as_email_form/_fields.html.haml
260
+ - app/views/effective/acts_as_email_notification/_fields.html.haml
259
261
  - app/views/effective/acts_as_wizard/_wizard_step.html.haml
260
262
  - app/views/effective/resource/_actions.html.haml
261
263
  - app/views/effective/resource/_actions_dropleft.html.haml
@@ -1,53 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module EffectiveActsAsEmailFormHelper
4
-
5
- def email_form_fields(form, action = nil, skip: true, to: nil, variables: nil, partial: nil)
6
- raise('expected a form') unless form.respond_to?(:object)
7
-
8
- resource = form.object
9
-
10
- # Intended for acts_as_email_form but sometimes we use a duck typed object to save these fields as well
11
- unless resource.class.respond_to?(:acts_as_email_form?) || resource.respond_to?("email_form_action=")
12
- raise('expected an acts_as_email_form resource or one that responds to email_form_action')
13
- end
14
-
15
- # Load the template.
16
- email_template = if action.present? && defined?(EffectiveEmailTemplates)
17
- action.kind_of?(Effective::EmailTemplate) ? action : Effective::EmailTemplate.where(template_name: action).first!
18
- end
19
-
20
- # These defaults are only used when there is no email_template
21
- email_defaults = form.object.email_form_defaults(action) unless email_template.present?
22
-
23
- from = email_template&.from || email_defaults[:from] || EffectiveResources.mailer_froms.first
24
- subject = email_template&.subject || email_defaults[:subject] || ''
25
- body = email_template&.body || email_defaults[:body] || ''
26
- content_type = email_template&.content_type || email_defaults[:content_type] || ''
27
-
28
- locals = {
29
- form: form,
30
- email_to: to,
31
- email_from: from,
32
- email_subject: subject,
33
- email_body: body,
34
- email_content_type: content_type,
35
- email_skip: skip,
36
- email_action: (action || true),
37
- email_template: email_template,
38
- email_variables: variables
39
- }
40
-
41
- render(partial: (partial || 'effective/acts_as_email_form/fields'), locals: locals)
42
- end
43
-
44
- def mailer_froms_collection(froms: nil)
45
- froms ||= EffectiveResources.mailer_froms
46
-
47
- froms.map do |from|
48
- html = content_tag(:span, escape_once(from))
49
- [from, from, 'data-html': html]
50
- end
51
- end
52
-
53
- end