podio 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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}"