mautic 2.3.9 → 2.6.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 59800fcfc64665ad1873fc20ef004bffe54edd38c2bb4da6263e702c0caba571
4
- data.tar.gz: e32ddec1e3707e5cf8fab1232de729a6c8df75d30f2520dc1620eec57bf857c7
3
+ metadata.gz: 8369fa0948409afca63ba594d3c630729dd160bc27fd9808dbaa941fab2e6a6e
4
+ data.tar.gz: 0cbc398f5515825575367d69866f176659713af2835df403901ee7321bdd0d85
5
5
  SHA512:
6
- metadata.gz: 0b8433f04ee7a96e9474a0f8b39a883637d68b5b2135203f150fc697d5a495e3a7447311c1d27171fe7545c74b979ee4b7727397ba279fde1ce9472b2ed29809
7
- data.tar.gz: 495c134933d712de9598cc618bf308f5b297e59bf86040d3e1c25b7ad636ee910932b08adc46c3a1a7144459b3f17e49dbb8cb57b167d28084715f8e19ed8197
6
+ metadata.gz: 623bedbe8dce28df4d92147ba646ff88506e1e2ddb883903ac687cfba6927164579279011307fbe53587d6940cd94a71feb55a31ef0a4642a7140a1e86f80253
7
+ data.tar.gz: e33d151ab4d0b44b4c978c347f6b56b1b4407520d814d9c62a2f0db1b363dab893cea944727158eab115ef17d9c9a0dec754c80ef25aaaf85bcfa3be5a556320
data/README.md CHANGED
@@ -94,11 +94,11 @@ end
94
94
  ```
95
95
  Get specify contact:
96
96
  ```ruby
97
- contact = m.contact.find(1) # => #<Mautic::Contact id=1 ...>
97
+ contact = m.contact.find(1) # => #<Mautic::Contact id=1 ...>
98
98
  ```
99
99
  Collections of contacts:
100
100
  ```ruby
101
- m.contacts.where("gmail").each do |contact|
101
+ m.contacts.where(search: "gmail").each do |contact|
102
102
  #<Mautic::Contact id=12 ...>
103
103
  #<Mautic::Contact id=21 ...>
104
104
  #<Mautic::Contact id=99 ...>
@@ -115,7 +115,7 @@ end
115
115
  contact.save # => false
116
116
  contact.errors # => [{"code"=>400, "message"=>"email: This field is required.", "details"=>{"email"=>["This field is required."]}}]
117
117
  ```
118
- Do not contact
118
+ #### Do not contact
119
119
  ```ruby
120
120
  contact.do_not_contact? # => false
121
121
  contact.do_not_contact! message: "Some reason"
@@ -127,6 +127,18 @@ end
127
127
  contact.remove_do_not_contact!
128
128
  contact.do_not_contact? # => false
129
129
  ```
130
+ #### Campaigns
131
+ list of contacts campaigns (where contact is a member) and remove it from one
132
+ ```ruby
133
+ contact.campaigns #=> [Mautic::Campaign, ...]
134
+ campaign = contact.campaigns.find { |campaign| campaign.name == "Newsletter" }
135
+ campaign.remove_contact! contact.id
136
+ ```
137
+ or add contact back
138
+ ```ruby
139
+ campaign = connection.campaigns.where(search: "Newsletter").first
140
+ campaign.add_contact! contact.id
141
+ ```
130
142
  Of course you can use more than contact: `assets`, `emails`, `companies`, `forms`, `points` ...
131
143
  ### Gem provides simple Mautic form submit
132
144
  There are two options of usage:
@@ -0,0 +1,22 @@
1
+ module Mautic
2
+ class Campaign < Model
3
+
4
+ # @see https://developer.mautic.org/#add-contact-to-a-campaign
5
+ # @param [Integer] id of Mautic::Contact
6
+ def add_contact!(id)
7
+ json = @connection.request(:post, "api/campaigns/#{self.id}/contact/#{id}/add")
8
+ json["success"]
9
+ rescue RequestError => _e
10
+ false
11
+ end
12
+
13
+ # @see https://developer.mautic.org/#remove-contact-from-a-campaign
14
+ # @param [Integer] id of Mautic::Contact
15
+ def remove_contact!(id)
16
+ json = @connection.request(:post, "api/campaigns/#{self.id}/contact/#{id}/remove")
17
+ json["success"]
18
+ rescue RequestError => _e
19
+ false
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,11 @@
1
+ module Mautic
2
+ class CompanyField < Model
3
+ def self.endpoint
4
+ "fields/company"
5
+ end
6
+
7
+ def self.in(connection)
8
+ Proxy.new(connection, endpoint, klass: name, data_name: "field")
9
+ end
10
+ end
11
+ end
@@ -1,6 +1,9 @@
1
1
  module Mautic
2
2
  class Contact < Model
3
3
 
4
+ around_create :ensure_stage, if: ->(contact) { contact.changes.has_key?(:stage_id) }
5
+ around_update :ensure_stage, if: ->(contact) { contact.changes.has_key?(:stage_id) }
6
+
4
7
  alias_attribute :first_name, :firstname
5
8
  alias_attribute :last_name, :lastname
6
9
 
@@ -41,17 +44,19 @@ module Mautic
41
44
 
42
45
  if source
43
46
  self.owner = source['owner'] || {}
47
+ self.stage = source['stage'] || {}
48
+ tags = (source['tags'] || []).map { |t| Mautic::Tag.new(self, t) }.sort_by(&:name)
44
49
  self.attributes = {
45
- tags: (source['tags'] || []).collect { |t| Mautic::Tag.new(@connection, t) }.sort_by(&:name),
50
+ tags: Tag::Collection.new(self, *tags),
46
51
  doNotContact: source['doNotContact'] || [],
47
52
  owner: owner['id'],
53
+ stage_id: stage&.id,
48
54
  }
49
55
  end
50
56
  end
51
57
 
52
58
  def to_mautic(data = @table)
53
59
  data.delete(:doNotContact)
54
- data.delete(:tags)
55
60
  super(data)
56
61
  end
57
62
 
@@ -96,7 +101,7 @@ module Mautic
96
101
  self.errors = e.errors
97
102
  end
98
103
 
99
- self.errors.blank?
104
+ errors.blank?
100
105
  end
101
106
 
102
107
  alias add_dnc do_not_contact!
@@ -117,11 +122,64 @@ module Mautic
117
122
 
118
123
  # !endgroup
119
124
 
125
+ # @!group Campaigns
126
+
127
+ # @return [Array<Mautic::Campaign>]
128
+ def campaigns
129
+ return @campaigns if @campaigns
130
+
131
+ json = @connection.request(:get, "api/contacts/#{id}/campaigns")
132
+
133
+ @campaigns = json["campaigns"].collect do |_campaign_id, campaign_attributes|
134
+ Mautic::Campaign.new @connection, campaign_attributes
135
+ end
136
+ rescue RequestError => _e
137
+ []
138
+ end
139
+
140
+ # !endgroup
141
+
142
+ # @!group Stage
143
+
144
+ # @return [Mautic::Stage, nil]
145
+ def stage
146
+ @stage
147
+ end
148
+
149
+ # @param [Mautic:::Stage,Hash, nil] hash
150
+ def stage=(object_or_hash)
151
+ @stage = case object_or_hash
152
+ when Mautic::Stage
153
+ object_or_hash
154
+ when Hash
155
+ Mautic::Stage.new(connection, object_or_hash)
156
+ end
157
+ @table[:stage_id] = @stage&.id
158
+ @stage
159
+ end
160
+
161
+ # !endgroup
162
+
120
163
  private
121
164
 
122
165
  def clear_change
123
166
  super
124
167
  remove_instance_variable :@do_not_contact
125
168
  end
169
+
170
+ # Add or Remove contact in stage after contact save
171
+ def ensure_stage
172
+ stage_id_change = changes[:stage_id]
173
+ yield
174
+ if stage_id_change
175
+ self.stage = Mautic::Stage.in(connection).find(stage_id_change)
176
+ stage.add_contact!(id)
177
+ @table[:stage_id] = stage.id
178
+ else
179
+ stage.remove_contact!(id)
180
+ @table.delete(:stage_id)
181
+ end
182
+ clear_changes
183
+ end
126
184
  end
127
- end
185
+ end
@@ -0,0 +1,11 @@
1
+ module Mautic
2
+ class ContactField < Model
3
+ def self.endpoint
4
+ "fields/contact"
5
+ end
6
+
7
+ def self.in(connection)
8
+ Proxy.new(connection, endpoint, klass: name, data_name: "field")
9
+ end
10
+ end
11
+ end
@@ -5,5 +5,34 @@ module Mautic
5
5
  self.attributes = { name: source['name'], fields: source['fields'] } if source.is_a? Hash
6
6
  end
7
7
 
8
+ # @param [Integer] submission_id
9
+ # @return Mautic::Submissions::Form
10
+ # @see https://developer.mautic.org/#get-form-submission
11
+ def submission(submission_id)
12
+ json = @connection.request(:get, "api/forms/#{id}/submissions/#{submission_id}")
13
+ Mautic::Submissions::Form.new @connection, json["submission"]
14
+ rescue Mautic::RecordNotFound => _e
15
+ nil
16
+ end
17
+
18
+ # @see https://developer.mautic.org/#list-form-submissions
19
+ # @param [Hash] options
20
+ # @option options [String] :search String or search command to filter entities by.
21
+ # @option options [String] :start Starting row for the entities returned. Defaults to 0.
22
+ # @option options [String] :limit Limit number of entities to return. Defaults to the system configuration for pagination (30).
23
+ # @option options [String] :orderBy Column to sort by. Can use any column listed in the response, also can use column of joined table with prefix. Sort by submitted date is s.date_submitted
24
+ # @option options [String] :orderByDir Sort direction: asc or desc.
25
+ # @option options [String] :publishedOnly Only return currently published entities.
26
+ # @option options [String] :minimal Return only array of entities without additional lists in it.
27
+ # @return Array[Mautic::Submissions::Form]
28
+ def submissions(**options)
29
+ json = @connection.request(:get, "api/forms/#{id}/submissions", params: options)
30
+ @submissions = json["submissions"].collect do |attributes|
31
+ Mautic::Submissions::Form.new @connection, attributes
32
+ end
33
+ rescue RequestError => _e
34
+ []
35
+ end
36
+
8
37
  end
9
- end
38
+ end
@@ -0,0 +1,22 @@
1
+ module Mautic
2
+ class Stage < Model
3
+
4
+ # @see https://developer.mautic.org/#add-contact-to-a-stage
5
+ # @param [Integer] id of Mautic::Contact
6
+ def add_contact!(id)
7
+ json = @connection.request(:post, "api/stages/#{self.id}/contact/#{id}/add")
8
+ json["success"]
9
+ rescue RequestError => _e
10
+ false
11
+ end
12
+
13
+ # @see https://developer.mautic.org/#remove-contact-from-a-stage
14
+ # @param [Integer] id of Mautic::Contact
15
+ def remove_contact!(id)
16
+ json = @connection.request(:post, "api/stages/#{self.id}/contact/#{id}/remove")
17
+ json["success"]
18
+ rescue RequestError => _e
19
+ false
20
+ end
21
+ end
22
+ end
@@ -1,6 +1,34 @@
1
1
  module Mautic
2
2
  class Tag < Model
3
3
 
4
+ class Collection < Array
5
+ attr_reader :model
6
+
7
+ # @param [Mautic::Model] model
8
+ def initialize(model, *several_variants)
9
+ @model = model
10
+ @tags_to_remove = []
11
+ super(several_variants)
12
+ end
13
+
14
+ def <<(item)
15
+ @model.changed = true
16
+ item = Tag.new(@model, { tag: item }) if item.is_a?(String)
17
+ super(item)
18
+ end
19
+
20
+ def remove(item)
21
+ @model.changed = true
22
+ item = detect { |t| t.name == item } if item.is_a?(String)
23
+ @tags_to_remove << "-#{item}"
24
+ delete item
25
+ end
26
+
27
+ def to_mautic
28
+ map(&:name) + @tags_to_remove
29
+ end
30
+ end
31
+
4
32
  # alias for attribute :tag
5
33
  def name
6
34
  tag
@@ -12,10 +12,10 @@ module Mautic
12
12
 
13
13
  def form_submissions
14
14
  @forms ||= Array.wrap(@params.require("mautic.form_on_submit")).collect do |data|
15
- p = data.permit(submission: [:id, form: {}, lead: {}, results: {}]).to_h
15
+ p = data.permit(submission: [:id, :referer, form: {}, lead: {}, results: {}]).to_h
16
16
  ::Mautic::Submissions::Form.new(@connection, p["submission"]) if p["submission"]
17
17
  end.compact
18
18
  end
19
19
 
20
20
  end
21
- end
21
+ end
@@ -2,8 +2,6 @@
2
2
  <html>
3
3
  <head>
4
4
  <title>Mautic</title>
5
- <%= stylesheet_link_tag "mautic/application", media: "all" %>
6
- <%= javascript_include_tag "mautic/application" %>
7
5
  <%= csrf_meta_tags %>
8
6
  </head>
9
7
  <body>
data/lib/mautic/model.rb CHANGED
@@ -2,6 +2,7 @@ module Mautic
2
2
  # Virtual model for Mautic endpoint
3
3
  # @see https://developer.mautic.org/#endpoints
4
4
  class Model < OpenStruct
5
+ extend ActiveModel::Callbacks
5
6
 
6
7
  class MauticHash < Hash
7
8
 
@@ -37,8 +38,11 @@ module Mautic
37
38
 
38
39
  end
39
40
 
41
+ define_model_callbacks :create, :update, :save
42
+
40
43
  attr_reader :connection
41
44
  attr_accessor :errors
45
+ attr_writer :changed
42
46
 
43
47
  # @param [Mautic::Connection] connection
44
48
  def initialize(connection, hash = nil)
@@ -54,21 +58,25 @@ module Mautic
54
58
  end
55
59
 
56
60
  def save(force = false)
57
- id.present? ? update(force) : create
61
+ run_callbacks :save do
62
+ id.present? ? update(force) : create
63
+ end
58
64
  end
59
65
 
60
66
  def update(force = false)
61
- return false if changes.blank?
67
+ return false unless changed?
62
68
 
63
69
  begin
64
- json = @connection.request((force && :put || :patch), "api/#{endpoint}/#{id}/edit", body: to_mautic)
65
- assign_attributes json[endpoint.singularize]
70
+ run_callbacks :create do
71
+ json = @connection.request((force && :put || :patch), "api/#{endpoint}/#{id}/edit", body: to_mautic)
72
+ assign_attributes json[endpoint.singularize]
73
+ end
66
74
  clear_changes
67
75
  rescue ValidationError => e
68
76
  self.errors = e.errors
69
77
  end
70
78
 
71
- self.errors.blank?
79
+ errors.blank?
72
80
  end
73
81
 
74
82
  def update_columns(attributes = {})
@@ -81,14 +89,16 @@ module Mautic
81
89
 
82
90
  def create
83
91
  begin
84
- json = @connection.request(:post, "api/#{endpoint}/#{id && "#{id}/"}new", body: to_mautic)
85
- assign_attributes json[endpoint.singularize]
92
+ run_callbacks :create do
93
+ json = @connection.request(:post, "api/#{endpoint}/#{id && "#{id}/"}new", body: to_mautic)
94
+ assign_attributes json[endpoint.singularize]
95
+ end
86
96
  clear_changes
87
97
  rescue ValidationError => e
88
98
  self.errors = e.errors
89
99
  end
90
100
 
91
- self.errors.blank?
101
+ errors.blank?
92
102
  end
93
103
 
94
104
  def destroy
@@ -105,6 +115,12 @@ module Mautic
105
115
  @table.changes
106
116
  end
107
117
 
118
+ def changed?
119
+ return @changed unless @changed.nil?
120
+
121
+ @changed = !changes.empty?
122
+ end
123
+
108
124
  def attributes
109
125
  @table.to_h
110
126
  end
@@ -117,14 +133,21 @@ module Mautic
117
133
  end
118
134
 
119
135
  def to_mautic(data = @table)
120
- data.each_with_object({}) do |(key, val), mem|
121
- mem[key] = val.is_a?(Array) ? val.join("|") : val
136
+ data.transform_values do |val|
137
+ if val.respond_to?(:to_mautic)
138
+ val.to_mautic
139
+ elsif val.is_a?(Array)
140
+ val.join("|")
141
+ else
142
+ val
143
+ end
122
144
  end
123
145
  end
124
146
 
125
147
  private
126
148
 
127
149
  def clear_changes
150
+ @changed = nil
128
151
  @table.instance_variable_set(:@changes, nil)
129
152
  end
130
153
 
data/lib/mautic/proxy.rb CHANGED
@@ -14,7 +14,7 @@ module Mautic
14
14
  end
15
15
 
16
16
  def data_name
17
- @endpoint.split("/").last
17
+ @options[:data_name] || @endpoint.split("/").last
18
18
  end
19
19
 
20
20
  def build_instance(data)
@@ -79,4 +79,4 @@ module Mautic
79
79
  end
80
80
 
81
81
  end
82
- end
82
+ end
@@ -1,5 +1,6 @@
1
1
  module Mautic
2
2
  module Submissions
3
+ # @see https://developer.mautic.org/#get-form-submissions
3
4
  class Form
4
5
  attr_reader :id
5
6
 
@@ -30,6 +31,17 @@ module Mautic
30
31
  def contact
31
32
  @contact ||= @connection.contacts.new(@raw["lead"])
32
33
  end
34
+
35
+ # @return [String]
36
+ def referer
37
+ @raw["referer"].to_s
38
+ end
39
+
40
+ # @return [Hash]
41
+ def results
42
+ @raw["results"]
43
+ end
44
+
33
45
  end
34
46
  end
35
- end
47
+ end
@@ -1,3 +1,3 @@
1
1
  module Mautic
2
- VERSION = '2.3.9'
2
+ VERSION = '2.6.0'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mautic
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.9
4
+ version: 2.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lukáš Pokorný
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-07-07 00:00:00.000000000 Z
11
+ date: 2021-02-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -160,12 +160,6 @@ files:
160
160
  - MIT-LICENSE
161
161
  - README.md
162
162
  - Rakefile
163
- - app/assets/config/mautic_manifest.js
164
- - app/assets/javascripts/mautic/application.js
165
- - app/assets/javascripts/mautic/mautic_connections.js
166
- - app/assets/stylesheets/mautic/application.css
167
- - app/assets/stylesheets/mautic/mautic_connections.css
168
- - app/assets/stylesheets/scaffold.css
169
163
  - app/controllers/concerns/mautic/connections_controller_concern.rb
170
164
  - app/controllers/concerns/mautic/receive_web_hooks.rb
171
165
  - app/controllers/mautic/application_controller.rb
@@ -174,11 +168,15 @@ files:
174
168
  - app/jobs/mautic/application_job.rb
175
169
  - app/mailers/mautic/application_mailer.rb
176
170
  - app/models/mautic/application_record.rb
171
+ - app/models/mautic/campaign.rb
172
+ - app/models/mautic/company_field.rb
177
173
  - app/models/mautic/connection.rb
178
174
  - app/models/mautic/connections/oauth2.rb
179
175
  - app/models/mautic/contact.rb
176
+ - app/models/mautic/contact_field.rb
180
177
  - app/models/mautic/event.rb
181
178
  - app/models/mautic/form.rb
179
+ - app/models/mautic/stage.rb
182
180
  - app/models/mautic/tag.rb
183
181
  - app/models/mautic/web_hook.rb
184
182
  - app/views/layouts/mautic/application.html.erb
@@ -222,7 +220,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
222
220
  - !ruby/object:Gem::Version
223
221
  version: '0'
224
222
  requirements: []
225
- rubygems_version: 3.0.6
223
+ rubygems_version: 3.0.8
226
224
  signing_key:
227
225
  specification_version: 4
228
226
  summary: Ruby on Rails Mautic integration
@@ -1,2 +0,0 @@
1
- //= link_directory ../javascripts/mautic .js
2
- //= link_directory ../stylesheets/mautic .css
@@ -1,14 +0,0 @@
1
- // This is a manifest file that'll be compiled into application.js, which will include all the files
2
- // listed below.
3
- //
4
- // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
5
- // or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
6
- //
7
- // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
8
- // compiled file. JavaScript code in this file should be added after the last require_* statement.
9
- //
10
- // Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
11
- // about supported directives.
12
- //
13
- // require rails-ujs
14
- //= require_tree .
@@ -1,2 +0,0 @@
1
- // Place all the behaviors and hooks related to the matching controller here.
2
- // All this logic will automatically be available in application.js.
@@ -1,15 +0,0 @@
1
- /*
2
- * This is a manifest file that'll be compiled into application.css, which will include all the files
3
- * listed below.
4
- *
5
- * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
- * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
7
- *
8
- * You're free to add application-wide styles to this file and they'll appear at the bottom of the
9
- * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
10
- * files in this directory. Styles in this file should be added after the last require_* statement.
11
- * It is generally better to create a new file per style scope.
12
- *
13
- *= require_tree .
14
- *= require_self
15
- */
@@ -1,4 +0,0 @@
1
- /*
2
- Place all the styles related to the matching controller here.
3
- They will automatically be included in application.css.
4
- */
@@ -1,80 +0,0 @@
1
- body {
2
- background-color: #fff;
3
- color: #333;
4
- margin: 33px;
5
- }
6
-
7
- body, p, ol, ul, td {
8
- font-family: verdana, arial, helvetica, sans-serif;
9
- font-size: 13px;
10
- line-height: 18px;
11
- }
12
-
13
- pre {
14
- background-color: #eee;
15
- padding: 10px;
16
- font-size: 11px;
17
- }
18
-
19
- a {
20
- color: #000;
21
- }
22
-
23
- a:visited {
24
- color: #666;
25
- }
26
-
27
- a:hover {
28
- color: #fff;
29
- background-color: #000;
30
- }
31
-
32
- th {
33
- padding-bottom: 5px;
34
- }
35
-
36
- td {
37
- padding: 0 5px 7px;
38
- }
39
-
40
- div.field,
41
- div.actions {
42
- margin-bottom: 10px;
43
- }
44
-
45
- #notice {
46
- color: green;
47
- }
48
-
49
- .field_with_errors {
50
- padding: 2px;
51
- background-color: red;
52
- display: table;
53
- }
54
-
55
- #error_explanation {
56
- width: 450px;
57
- border: 2px solid red;
58
- padding: 7px 7px 0;
59
- margin-bottom: 20px;
60
- background-color: #f0f0f0;
61
- }
62
-
63
- #error_explanation h2 {
64
- text-align: left;
65
- font-weight: bold;
66
- padding: 5px 5px 5px 15px;
67
- font-size: 12px;
68
- margin: -7px -7px 0;
69
- background-color: #c00;
70
- color: #fff;
71
- }
72
-
73
- #error_explanation ul li {
74
- font-size: 12px;
75
- list-style: square;
76
- }
77
-
78
- label {
79
- display: block;
80
- }