podio 0.4.1 → 0.5.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 (86) hide show
  1. data/README.md +36 -5
  2. data/Rakefile +3 -1
  3. data/lib/podio/active_podio/base.rb +311 -0
  4. data/lib/podio/active_podio/updatable.rb +22 -0
  5. data/lib/podio/client.rb +7 -4
  6. data/lib/podio/error.rb +1 -0
  7. data/lib/podio/middleware/error_response.rb +5 -1
  8. data/lib/podio/middleware/response_recorder.rb +1 -1
  9. data/lib/podio/models/app_store_share.rb +67 -0
  10. data/lib/podio/{areas → models}/application.rb +23 -7
  11. data/lib/podio/models/application_email.rb +22 -0
  12. data/lib/podio/models/application_field.rb +17 -0
  13. data/lib/podio/{areas → models}/bulletin.rb +16 -5
  14. data/lib/podio/models/by_line.rb +11 -0
  15. data/lib/podio/models/category.rb +49 -0
  16. data/lib/podio/models/comment.rb +63 -0
  17. data/lib/podio/{areas → models}/connection.rb +20 -4
  18. data/lib/podio/models/contact.rb +10 -0
  19. data/lib/podio/models/conversation.rb +72 -0
  20. data/lib/podio/models/conversation_message.rb +12 -0
  21. data/lib/podio/models/conversation_participant.rb +9 -0
  22. data/lib/podio/models/email_subscription_setting.rb +39 -0
  23. data/lib/podio/models/embed.rb +34 -0
  24. data/lib/podio/models/file_attachment.rb +127 -0
  25. data/lib/podio/models/form.rb +25 -0
  26. data/lib/podio/{areas → models}/hook.rb +15 -5
  27. data/lib/podio/{areas → models}/importer.rb +4 -6
  28. data/lib/podio/{areas → models}/integration.rb +40 -4
  29. data/lib/podio/models/item.rb +122 -0
  30. data/lib/podio/models/item_diff.rb +16 -0
  31. data/lib/podio/models/item_field.rb +19 -0
  32. data/lib/podio/models/item_revision.rb +18 -0
  33. data/lib/podio/models/news.rb +83 -0
  34. data/lib/podio/models/notification.rb +47 -0
  35. data/lib/podio/models/notification_group.rb +19 -0
  36. data/lib/podio/models/o_auth.rb +32 -0
  37. data/lib/podio/models/o_auth_client.rb +93 -0
  38. data/lib/podio/{areas → models}/organization.rb +39 -6
  39. data/lib/podio/models/organization_contact.rb +14 -0
  40. data/lib/podio/{areas → models}/organization_member.rb +13 -5
  41. data/lib/podio/models/organization_profile.rb +61 -0
  42. data/lib/podio/{areas/contact.rb → models/profile.rb} +23 -6
  43. data/lib/podio/{areas → models}/rating.rb +5 -7
  44. data/lib/podio/{areas → models}/search.rb +6 -7
  45. data/lib/podio/models/space.rb +45 -0
  46. data/lib/podio/models/space_contact.rb +23 -0
  47. data/lib/podio/models/space_invite.rb +57 -0
  48. data/lib/podio/models/space_member.rb +32 -0
  49. data/lib/podio/models/status.rb +35 -0
  50. data/lib/podio/{areas → models}/subscription.rb +8 -7
  51. data/lib/podio/{areas → models}/tag.rb +14 -7
  52. data/lib/podio/models/task.rb +153 -0
  53. data/lib/podio/models/task_label.rb +50 -0
  54. data/lib/podio/models/user.rb +66 -0
  55. data/lib/podio/models/user_status.rb +18 -0
  56. data/lib/podio/models/via.rb +7 -0
  57. data/lib/podio/{areas → models}/widget.rb +9 -5
  58. data/lib/podio/version.rb +1 -1
  59. data/lib/podio.rb +97 -39
  60. data/podio.gemspec +4 -3
  61. data/test/active_podio_test.rb +256 -0
  62. data/test/client_test.rb +20 -15
  63. data/test/fixtures/client/18a224aaf83ac57a7b8159cecdbb1263.rack +1 -0
  64. data/test/fixtures/client/a87c69a0624af0413a670094c6615651.rack +1 -0
  65. data/test/fixtures/client/ac493997db62308972c208afa76f8479.rack +1 -0
  66. data/test/fixtures/client/d7fbf422c77af768552423633d0389e8.rack +1 -0
  67. data/test/fixtures/client/e2d68afe39f5531195273ea259b63916.rack +1 -0
  68. data/test/fixtures/fixtures.yaml +34 -0
  69. data/test/models_sanity_test.rb +19 -0
  70. data/test/test_helper.rb +22 -28
  71. metadata +89 -64
  72. data/lib/podio/areas/app_store.rb +0 -69
  73. data/lib/podio/areas/comment.rb +0 -36
  74. data/lib/podio/areas/conversation.rb +0 -39
  75. data/lib/podio/areas/email.rb +0 -24
  76. data/lib/podio/areas/file.rb +0 -81
  77. data/lib/podio/areas/form.rb +0 -11
  78. data/lib/podio/areas/item.rb +0 -68
  79. data/lib/podio/areas/notification.rb +0 -39
  80. data/lib/podio/areas/oauth.rb +0 -107
  81. data/lib/podio/areas/organization_profile.rb +0 -32
  82. data/lib/podio/areas/space.rb +0 -77
  83. data/lib/podio/areas/status.rb +0 -19
  84. data/lib/podio/areas/task.rb +0 -108
  85. data/lib/podio/areas/user.rb +0 -31
  86. data/lib/podio/areas/user_status.rb +0 -11
@@ -0,0 +1,11 @@
1
+ # Wraps common byline hashes. See https://hoist.podio.com/api/item/56084
2
+ class Podio::ByLine < ActivePodio::Base
3
+ property :type, :string
4
+ property :id, :integer
5
+ property :avatar_type, :string
6
+ property :avatar_id, :integer
7
+ property :image, :hash
8
+ property :name, :string
9
+ property :url, :string
10
+ property :avatar, :integer # Sometimes used by older operations
11
+ end
@@ -0,0 +1,49 @@
1
+ class Podio::Category < ActivePodio::Base
2
+ property :category_id, :integer
3
+ property :type, :string
4
+ property :name, :string
5
+
6
+ alias_method :id, :category_id
7
+
8
+ class << self
9
+ def create(attributes)
10
+ response = Podio.connection.post do |req|
11
+ req.url "/app_store/category/"
12
+ req.body = attributes
13
+ end
14
+
15
+ response.status
16
+ end
17
+
18
+ def update(id, attributes)
19
+ response = Podio.connection.put do |req|
20
+ req.url "/app_store/category/#{id}"
21
+ req.body = attributes
22
+ end
23
+
24
+ response.status
25
+ end
26
+
27
+ def delete(id)
28
+ Podio.connection.delete("/app_store/category/#{id}").status
29
+ end
30
+
31
+ def find(id)
32
+ member Podio.connection.get("/app_store/category/#{id}").body
33
+ end
34
+
35
+ def find_all
36
+ collection Podio.connection.get("/app_store/category/").body
37
+ end
38
+
39
+ private
40
+
41
+ def collection(response)
42
+ return Struct.new(:functional, :vertical).new([], []) if response.blank?
43
+ functionals = response['functional'].map! { |cat| member(cat) }
44
+ verticals = response['vertical'].map! { |cat| member(cat) }
45
+ Struct.new(:functional, :vertical).new(functionals, verticals)
46
+ end
47
+
48
+ end
49
+ end
@@ -0,0 +1,63 @@
1
+ class Podio::Comment < ActivePodio::Base
2
+ property :comment_id, :integer
3
+ property :value, :string
4
+ property :external_id, :integer
5
+ property :space_id, :integer
6
+ property :created_on, :datetime
7
+ property :files, :array # when outputting comments
8
+ property :file_ids, :array # when inputting comments
9
+ property :embed_id, :integer #optional, when inputting comments
10
+ property :embed_file_id, :integer #optional, when inputting comments
11
+
12
+ has_one :embed, :class => 'Embed'
13
+ has_one :embed_file, :class => 'FileAttachment'
14
+
15
+ has_one :created_by, :class => 'ByLine'
16
+ has_one :created_via, :class => 'Via'
17
+ has_many :files, :class => 'FileAttachment'
18
+
19
+ alias_method :id, :comment_id
20
+ attr_accessor :commentable_type, :commentable_id
21
+
22
+ def create
23
+ self.comment_id = Comment.create(commentable_type, commentable_id, attributes)
24
+ end
25
+
26
+ class << self
27
+ def create(commentable_type, commentable_id, attributes)
28
+ response = Podio.connection.post do |req|
29
+ req.url "/comment/#{commentable_type}/#{commentable_id}"
30
+ req.body = attributes
31
+ end
32
+
33
+ response.body['comment_id']
34
+ end
35
+
36
+ def update(id, attributes)
37
+ response = Podio.connection.put do |req|
38
+ req.url "/comment/#{id}"
39
+ req.body = attributes
40
+ end
41
+
42
+ response.status
43
+ end
44
+
45
+ def delete(id)
46
+ Podio.connection.delete("/comment/#{id}").status
47
+ end
48
+
49
+ def find(id)
50
+ member Podio.connection.get("/comment/#{id}").body
51
+ end
52
+
53
+ def find_all_for(commentable_type, commentable_id)
54
+ list Podio.connection.get("/comment/#{commentable_type}/#{commentable_id}").body
55
+ end
56
+
57
+ def find_recent_for_share
58
+ #Internal
59
+ list Podio.connection.get("/comment/share/").body
60
+ end
61
+
62
+ end
63
+ end
@@ -1,8 +1,23 @@
1
- module Podio
2
- module Connection
3
- include Podio::ResponseWrapper
4
- extend self
1
+ class Podio::Connection < ActivePodio::Base
2
+ property :connection_id, :integer
3
+ property :type, :string
4
+ property :name, :string
5
+ property :last_load_on, :datetime
6
+ property :created_on, :datetime
5
7
 
8
+ property :contact_count, :integer
9
+
10
+ alias_method :id, :connection_id
11
+
12
+ def reload
13
+ Connection.reload(id)
14
+ end
15
+
16
+ def destroy
17
+ Connection.delete(id)
18
+ end
19
+
20
+ class << self
6
21
  def create(attributes)
7
22
  response = Podio.connection.post do |req|
8
23
  req.url '/connection/'
@@ -27,5 +42,6 @@ module Podio
27
42
  def all(options={})
28
43
  list Podio.connection.get('/connection/').body
29
44
  end
45
+
30
46
  end
31
47
  end
@@ -0,0 +1,10 @@
1
+ class Podio::Contact < Podio::Profile
2
+ property :is_selected, :bool
3
+ property :user_id, :integer
4
+ property :organization, :string
5
+ property :role, :string # Only available when getting contacts for a space
6
+ property :type, :string # user, space, connection - blank probably means it's a real user / Podio member
7
+ property :link, :string
8
+
9
+ alias_method :id, :user_id
10
+ end
@@ -0,0 +1,72 @@
1
+ class Podio::Conversation < ActivePodio::Base
2
+ property :conversation_id, :integer
3
+ property :subject, :string
4
+
5
+ # When inputting conversation
6
+ property :text, :string
7
+ property :participants, :array
8
+ property :file_ids, :array
9
+ property :embed_id, :integer
10
+ property :embed_file_id, :integer
11
+
12
+ # When outputting conversation(s)
13
+ property :created_on, :datetime
14
+ has_one :created_by, :class => 'ByLine'
15
+ has_many :files, :class => 'FileAttachment'
16
+ has_many :messages, :class => 'ConversationMessage'
17
+ has_many :participants_full, :class => 'ConversationParticipant'
18
+
19
+ alias_method :id, :conversation_id
20
+ alias_method :name, :subject # So tasks can refer to ref.name on all types of references
21
+
22
+ def save
23
+ self[:file_ids] ||= []
24
+ response = Conversation.create(self.attributes)
25
+ self.conversation_id = response['conversation_id']
26
+ end
27
+
28
+ handle_api_errors_for :save # Call must be made after the methods to handle have been defined
29
+
30
+ class << self
31
+ def find(conversation_id)
32
+ member Podio.connection.get("/conversation/#{conversation_id}").body
33
+ end
34
+
35
+ def find_all_for_reference(ref_type, ref_id)
36
+ list Podio.connection.get("/conversation/#{ref_type}/#{ref_id}/").body
37
+ end
38
+
39
+ def create(attributes)
40
+ response = Podio.connection.post do |req|
41
+ req.url '/conversation/'
42
+ req.body = attributes
43
+ end
44
+ response.body
45
+ end
46
+
47
+ def create_for_reference(ref_type, ref_id, attributes)
48
+ response = Podio.connection.post do |req|
49
+ req.url "/conversation/#{ref_type}/#{ref_id}/"
50
+ req.body = attributes
51
+ end
52
+ response.body
53
+ end
54
+
55
+ def create_reply(conversation_id, text, file_ids = [])
56
+ response = Podio.connection.post do |req|
57
+ req.url "/conversation/#{conversation_id}/reply"
58
+ req.body = { :text => text, :file_ids => file_ids }
59
+ end
60
+ response.body['message_id']
61
+ end
62
+
63
+ def add_participant(conversation_id, user_id)
64
+ response = Podio.connection.post do |req|
65
+ req.url "/conversation/#{conversation_id}/participant/"
66
+ req.body = { :user_id => user_id }
67
+ end
68
+ response.body
69
+ end
70
+
71
+ end
72
+ end
@@ -0,0 +1,12 @@
1
+ class Podio::ConversationMessage < ActivePodio::Base
2
+ property :message_id, :integer
3
+ property :embed_id, :integer
4
+ property :embed_file_id, :integer
5
+ property :text, :string
6
+ property :created_on, :datetime
7
+
8
+ has_one :created_by, :class => 'ByLine'
9
+ has_many :files, :class => 'FileAttachment'
10
+
11
+ alias_method :id, :message_id
12
+ end
@@ -0,0 +1,9 @@
1
+ class Podio::ConversationParticipant < ActivePodio::Base
2
+ property :created_on, :datetime
3
+
4
+ has_one :user, :class => 'User'
5
+ has_one :created_by, :class => 'ByLine'
6
+ has_one :created_via, :class => 'Via'
7
+
8
+ delegate :id, :name, :avatar, :link, :to => :user, :prefix => false
9
+ end
@@ -0,0 +1,39 @@
1
+ class Podio::EmailSubscriptionSetting < ActivePodio::Base
2
+ include ActivePodio::Updatable
3
+
4
+ property :digest, :boolean
5
+ property :bulletin, :boolean
6
+ property :reference, :boolean
7
+ property :message, :boolean
8
+ property :space, :boolean
9
+ property :subscription, :boolean
10
+
11
+ def self.find_for_current_user
12
+ self.get_groups
13
+ end
14
+
15
+ def update
16
+ self.class.update_groups(self.attributes)
17
+ end
18
+
19
+ class << self
20
+ def get_groups()
21
+ member Podio.connection.get { |req|
22
+ req.url("/email/group/", {})
23
+ }.body
24
+ end
25
+
26
+ def update_groups(options)
27
+ Podio.connection.put { |req|
28
+ req.url "/email/group/"
29
+ req.body = options
30
+ }.body
31
+ end
32
+
33
+ def unsubscribe(username)
34
+ Podio.connection.post("/email/unsubscribe/#{username}").status
35
+ end
36
+
37
+ end
38
+
39
+ end
@@ -0,0 +1,34 @@
1
+ class Podio::Embed < ActivePodio::Base
2
+
3
+ property :embed_id, :integer
4
+ property :original_url, :string
5
+ property :resolved_url, :string
6
+ property :type, :string
7
+ property :title, :string
8
+ property :description, :string
9
+ property :created_on, :datetime
10
+ property :provider_name, :string
11
+ property :embed_html, :string
12
+ property :embed_height, :boolean
13
+ property :embed_width, :integer
14
+
15
+ has_many :files, :class => 'FileAttachment'
16
+
17
+ alias_method :id, :embed_id
18
+
19
+ class << self
20
+
21
+ def create(url)
22
+ response = Podio.connection.post do |req|
23
+ req.url '/embed/'
24
+ req.body = {:url => url }
25
+ end
26
+ member response.body
27
+ end
28
+
29
+ def find(id)
30
+ member Podio.connection.get("/embed/#{id}").body
31
+ end
32
+
33
+ end
34
+ end
@@ -0,0 +1,127 @@
1
+ class Podio::FileAttachment < ActivePodio::Base
2
+ property :file_id, :integer
3
+ property :link, :string
4
+ property :name, :string
5
+ property :description, :string
6
+ property :mimetype, :string
7
+ property :size, :integer
8
+ property :created_on, :datetime
9
+
10
+ has_one :created_by, :class => 'ByLine'
11
+ has_one :created_via, :class => 'Via'
12
+ has_many :replaces, :class => 'FileAttachment'
13
+
14
+ alias_method :id, :file_id
15
+
16
+ def image?
17
+ ['image/png', 'image/jpeg', 'image/gif', 'image/tiff', 'image/bmp'].include?(self.mimetype)
18
+ end
19
+
20
+ class << self
21
+
22
+ # Accepts an open file stream along with a content type and a file name and uploads the file to Podio
23
+ # Returns an instantiated FileAttachment model with id, link, name and mimetype set
24
+ # If you use Ruby on Rails 3 or higher you can also pass the file in params directly to +upload_from_rails_param+
25
+ def upload(file_stream, content_type, file_name)
26
+ response = Podio.client.raw_connection.post do |req|
27
+ req.url "/file/v2/"
28
+ req.body = {:source => Faraday::UploadIO.new(file_stream, content_type, file_name), :filename => file_name}
29
+ end
30
+ file_attributes = ActiveSupport::JSON.decode(response.body) # Using raw_connection means response is not automatically decoded to json
31
+ file_attributes.merge!(:name => file_name, :mimetype => content_type)
32
+ member file_attributes
33
+ end
34
+
35
+ # Accepts a ActionDispatch::Http::UploadedFile or similar and uploads the file to Podio
36
+ # Optionally attaches the file to the given ref type and ref id
37
+ # Returns an instantiated FileAttachment model with id, link, name and mimetype set
38
+ def upload_from_rails_param(uploaded_file, ref_type = nil, ref_id = nil)
39
+ p uploaded_file
40
+ file_attachment = self.upload(uploaded_file.tempfile, uploaded_file.content_type, uploaded_file.original_filename)
41
+ if ref_type.present? && ref_id.present?
42
+ self.attach(file_attachment.id, ref_type, ref_id)
43
+ end
44
+ file_attachment
45
+ end
46
+
47
+ # Attach a file to an existing reference
48
+ def attach(id, ref_type, ref_id)
49
+ Podio.connection.post do |req|
50
+ req.url "/file/#{id}/attach"
51
+ req.body = { :ref_type => ref_type, :ref_id => ref_id }
52
+ end
53
+ end
54
+
55
+ def copy(id)
56
+ Podio.connection.post("/file/#{id}/copy").body['file_id']
57
+ end
58
+
59
+ def delete(id)
60
+ Podio.connection.delete("/file/#{id}")
61
+ end
62
+
63
+ def find(id)
64
+ member Podio.connection.get("/file/#{id}").body
65
+ end
66
+
67
+ def find_for_app(app_id, options={})
68
+ collection Podio.connection.get { |req|
69
+ req.url("/file/app/#{app_id}/", options)
70
+ }.body
71
+ end
72
+
73
+ def find_for_space(space_id, options={})
74
+ collection Podio.connection.get { |req|
75
+ req.url("/file/space/#{space_id}/", options)
76
+ }.body
77
+ end
78
+
79
+ def find_latest_for_app(app_id, options={})
80
+ collection Podio.connection.get { |req|
81
+ req.url("/file/app/#{app_id}/latest/", options)
82
+ }.body
83
+ end
84
+
85
+ def find_latest_for_space(space_id, options={})
86
+ collection Podio.connection.get { |req|
87
+ req.url("/file/space/#{space_id}/latest/", options)
88
+ }.body
89
+ end
90
+
91
+ def replace(old_file_id, new_file_id)
92
+ Podio.connection.post { |req|
93
+ req.url "/file/#{new_file_id}/replace"
94
+ req.body = { :old_file_id => old_file_id }
95
+ }.body
96
+ end
97
+
98
+ def update(id, description)
99
+ Podio.connection.put { |req|
100
+ req.url "/file/#{file_id}"
101
+ req.body = { :description => description }
102
+ }.body
103
+ end
104
+
105
+
106
+ #
107
+ # Obsolete way of uploading files, use upload method instead
108
+ #
109
+
110
+ # Uploading a file is a two-step operation
111
+ # First, the file must be created to get a file id and the path to move it to
112
+ def create(name, content_type)
113
+ response = Podio.connection.post do |req|
114
+ req.url "/file/"
115
+ req.body = { :name => name, :mimetype => content_type }
116
+ end
117
+
118
+ response.body
119
+ end
120
+
121
+ # Then, when the file has been moved, it must be marked as available
122
+ def set_available(id)
123
+ Podio.connection.post "/file/#{id}/available"
124
+ end
125
+
126
+ end
127
+ end
@@ -0,0 +1,25 @@
1
+ class Podio::Form < ActivePodio::Base
2
+ property :form_id, :integer
3
+ property :app_id, :integer
4
+ property :settings, :hash
5
+ property :domains, :array
6
+ property :field_ids, :array
7
+ property :attachments, :boolean
8
+
9
+ alias_method :id, :form_id
10
+
11
+ class << self
12
+ def create(app_id, attributes)
13
+ response = Podio.connection.post do |req|
14
+ req.url "/form/app/#{app_id}/"
15
+ req.body = attributes
16
+ end
17
+
18
+ response.body['form_id']
19
+ end
20
+
21
+ def find(form_id)
22
+ member Podio.connection.get("/form/#{form_id}").body
23
+ end
24
+ end
25
+ end
@@ -1,8 +1,18 @@
1
- module Podio
2
- module Hook
3
- include Podio::ResponseWrapper
4
- extend self
5
-
1
+ class Podio::Hook < ActivePodio::Base
2
+ property :hook_id, :integer
3
+ property :status, :string
4
+ property :type, :string
5
+ property :url, :string
6
+
7
+ alias_method :id, :hook_id
8
+
9
+ attr_accessor :hookable_type, :hookable_id
10
+
11
+ def create
12
+ self.hook_id = self.class.create(self.hookable_type, self.hookable_id, attributes)
13
+ end
14
+
15
+ class << self
6
16
  def create(hookable_type, hookable_id, attributes)
7
17
  response = Podio.connection.post do |req|
8
18
  req.url "/hook/#{hookable_type}/#{hookable_id}/"
@@ -1,8 +1,6 @@
1
- module Podio
2
- module Importer
3
- include Podio::ResponseWrapper
4
- extend self
5
-
1
+ class Podio::Importer < ActivePodio::Base
2
+
3
+ class << self
6
4
  def process_file(file_id, app_id, mappings)
7
5
  response = Podio.connection.post do |req|
8
6
  req.url "/importer/#{file_id}/process"
@@ -20,4 +18,4 @@ module Podio
20
18
  end
21
19
 
22
20
  end
23
- end
21
+ end
@@ -1,8 +1,44 @@
1
- module Podio
2
- module Integration
3
- include Podio::ResponseWrapper
4
- extend self
1
+ class Podio::Integration < ActivePodio::Base
2
+ include ActivePodio::Updatable
5
3
 
4
+ property :integration_id, :integer
5
+ property :app_id, :integer
6
+ property :status, :string
7
+ property :type, :string
8
+ property :silent, :boolean
9
+ property :config, :hash
10
+ property :mapping, :hash
11
+ property :updating, :boolean
12
+ property :last_updated_on, :datetime
13
+ property :created_on, :datetime
14
+
15
+ has_one :created_by, :class => 'ByLine'
16
+
17
+ alias_method :id, :integration_id
18
+
19
+ def create
20
+ self.integration_id = Integration.create(self.app_id, attributes)
21
+ end
22
+
23
+ def update
24
+ Integration.update(self.app_id, attributes)
25
+ end
26
+
27
+ def update_mapping
28
+ Integration.update_mapping(self.app_id, attributes)
29
+ end
30
+
31
+ def destroy
32
+ Integration.delete(self.app_id)
33
+ end
34
+
35
+ def refresh
36
+ Integration.refresh(self.app_id)
37
+ end
38
+
39
+ handle_api_errors_for :create, :update, :update_mapping
40
+
41
+ class << self
6
42
  def create(app_id, attributes)
7
43
  response = Podio.connection.post do |req|
8
44
  req.url "/integration/#{app_id}"