teamlab 0.1.4 → 0.2.1
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.
- data/lib/teamlab/Config.rb +1 -2
- data/lib/teamlab/Modules/Calendar.rb +1 -1
- data/lib/teamlab/Modules/Community.rb +1 -1
- data/lib/teamlab/Modules/Crm.rb +1 -1
- data/lib/teamlab/Modules/Files.rb +9 -5
- data/lib/teamlab/Modules/Group.rb +1 -1
- data/lib/teamlab/Modules/Mail.rb +20 -1
- data/lib/teamlab/Modules/People.rb +2 -2
- data/lib/teamlab/Modules/Project.rb +70 -41
- data/lib/teamlab/Modules/Settings.rb +10 -10
- data/lib/teamlab/Request.rb +12 -8
- data/lib/teamlab/version.rb +1 -1
- data/lib/teamlab.rb +0 -9
- data/spec/lib/Teamlab_spec.rb +706 -177
- data/spec/support/http_data.rb +32 -56
- data/teamlab.gemspec +1 -1
- metadata +3 -3
data/lib/teamlab/Config.rb
CHANGED
@@ -8,8 +8,7 @@ module Teamlab
|
|
8
8
|
def self.configure(&block)
|
9
9
|
@config ||= Config.new
|
10
10
|
yield @config if block_given?
|
11
|
-
@config.
|
12
|
-
@config.token = Teamlab::Request.post('', {:userName => @config.username, :password => @config.password}).body['response']['token']
|
11
|
+
@config.token = Teamlab::Request.new('authentication').post('', {:userName => @config.username, :password => @config.password}).body['response']['token']
|
13
12
|
@config.headers = { 'authorization' => @config.token}
|
14
13
|
end
|
15
14
|
|
data/lib/teamlab/Modules/Crm.rb
CHANGED
@@ -2,7 +2,7 @@ module Teamlab
|
|
2
2
|
class Files
|
3
3
|
|
4
4
|
def initialize
|
5
|
-
@request = Teamlab::Request
|
5
|
+
@request = Teamlab::Request.new('files')
|
6
6
|
end
|
7
7
|
|
8
8
|
def get_my_files
|
@@ -41,8 +41,8 @@ module Teamlab
|
|
41
41
|
@request.get([folder_id.to_s, 'feeds'])
|
42
42
|
end
|
43
43
|
|
44
|
-
def
|
45
|
-
@request.put([file_id, 'sharedlink'], share: share)
|
44
|
+
def generate_shared_link(file_id, share)
|
45
|
+
@request.put([file_id.to_s, 'sharedlink'], share: share)
|
46
46
|
end
|
47
47
|
|
48
48
|
#================================== TODO: UPLOAD FILES ================================
|
@@ -117,6 +117,10 @@ module Teamlab
|
|
117
117
|
@request.put(%w(settings import terminate))
|
118
118
|
end
|
119
119
|
|
120
|
+
def import_from_third_party(source, folder_id, ignore_coincidence_files, data_to_import, options = {})
|
121
|
+
@request.put(['settings', 'import', source.to_s, 'data'], {folderId: folder_id.to_s, ignoreCoincidenceFiles: ignore_coincidence_files, dataToImport: data_to_import}.merge(options))
|
122
|
+
end
|
123
|
+
|
120
124
|
def delete_file(file_id)
|
121
125
|
@request.delete(['file', file_id.to_s])
|
122
126
|
end
|
@@ -129,11 +133,11 @@ module Teamlab
|
|
129
133
|
@request.get(%w(fileops))
|
130
134
|
end
|
131
135
|
|
132
|
-
def move_files(dest_folder_id, options)
|
136
|
+
def move_files(dest_folder_id, options = {})
|
133
137
|
@request.put(%w(fileops move), { destFolderId: dest_folder_id }.merge(options))
|
134
138
|
end
|
135
139
|
|
136
|
-
def copy_to_folder(dest_folder_id, options)
|
140
|
+
def copy_to_folder(dest_folder_id, options = {})
|
137
141
|
@request.put(%w(fileops copy), { destFolderId: dest_folder_id }.merge(options))
|
138
142
|
end
|
139
143
|
|
data/lib/teamlab/Modules/Mail.rb
CHANGED
@@ -2,7 +2,7 @@ module Teamlab
|
|
2
2
|
class Mail
|
3
3
|
|
4
4
|
def initialize
|
5
|
-
@request = Teamlab::Request
|
5
|
+
@request = Teamlab::Request.new('mail')
|
6
6
|
end
|
7
7
|
|
8
8
|
def get_message(id, options = {})
|
@@ -21,6 +21,8 @@ module Teamlab
|
|
21
21
|
@request.delete(['accounts', email.to_s])
|
22
22
|
end
|
23
23
|
|
24
|
+
#region Tags
|
25
|
+
|
24
26
|
def get_tag_list
|
25
27
|
@request.get(%w(tags))
|
26
28
|
end
|
@@ -29,6 +31,23 @@ module Teamlab
|
|
29
31
|
@request.post(%w(tags), {name: name}.merge(options))
|
30
32
|
end
|
31
33
|
|
34
|
+
def update_tag(id, name, options = {})
|
35
|
+
@request.put(['tags', id.to_s], {name: name}.merge(options))
|
36
|
+
end
|
37
|
+
|
38
|
+
def set_tag_to_messages(id, *message_ids)
|
39
|
+
@request.put(['tags', id.to_s, 'set'], messages: message_ids.flatten)
|
40
|
+
end
|
41
|
+
|
42
|
+
def remove_tag_from_messages(id, *message_ids)
|
43
|
+
@request.put(['tags', id.to_s, 'remove'], messages: message_ids.flatten)
|
44
|
+
end
|
45
|
+
|
46
|
+
def delete_tag(id)
|
47
|
+
@request.delete(['tags', id.to_s])
|
48
|
+
end
|
49
|
+
|
50
|
+
#endregion
|
32
51
|
end
|
33
52
|
end
|
34
53
|
|
@@ -3,7 +3,7 @@ module Teamlab
|
|
3
3
|
class People
|
4
4
|
|
5
5
|
def initialize
|
6
|
-
@request = Teamlab::Request
|
6
|
+
@request = Teamlab::Request.new('people')
|
7
7
|
end
|
8
8
|
|
9
9
|
def get_people
|
@@ -39,7 +39,7 @@ module Teamlab
|
|
39
39
|
end
|
40
40
|
|
41
41
|
def search_with_status(status, query)
|
42
|
-
@request.get(['status', status.to_s, '
|
42
|
+
@request.get(['status', status.to_s, 'search'], {query: query.to_s})
|
43
43
|
end
|
44
44
|
|
45
45
|
def add_user(is_visitor, email, firstname, lastname, options = {})
|
@@ -1,9 +1,11 @@
|
|
1
1
|
module Teamlab
|
2
2
|
class Project
|
3
3
|
def initialize
|
4
|
-
@request = Teamlab::Request
|
4
|
+
@request = Teamlab::Request.new('project')
|
5
5
|
end
|
6
6
|
|
7
|
+
#region Import
|
8
|
+
|
7
9
|
def get_import_status
|
8
10
|
@request.get(['import'])
|
9
11
|
end
|
@@ -17,66 +19,78 @@ module Teamlab
|
|
17
19
|
@request.post(%w(import projects), url: url, userName: username, password: password)
|
18
20
|
end
|
19
21
|
|
20
|
-
|
22
|
+
#endregion
|
23
|
+
|
24
|
+
#region Discussions
|
25
|
+
|
26
|
+
def get_latest_discussion_messages #есть тест
|
21
27
|
@request.get(['message'])
|
22
28
|
end
|
23
29
|
|
24
|
-
def get_message_by_filter(options = {})
|
30
|
+
def get_message_by_filter(options = {}) #есть тест
|
25
31
|
@request.get(%w(message filter), options)
|
26
32
|
end
|
27
33
|
|
28
|
-
def get_messages(project_id)
|
34
|
+
def get_messages(project_id) #есть тест
|
29
35
|
@request.get([project_id.to_s, 'message'])
|
30
36
|
end
|
31
37
|
|
32
|
-
def check_subscription_to_discussion(message_id)
|
38
|
+
def check_subscription_to_discussion(message_id) #есть тест
|
33
39
|
@request.get(['message', message_id.to_s, 'subscribe'])
|
34
40
|
end
|
35
41
|
|
36
|
-
def add_message(project_id, title, content, participants, options =
|
37
|
-
@request.
|
42
|
+
def add_message(project_id, title, content, participants, options = {}) #есть тест
|
43
|
+
@request.post([project_id.to_s, 'message'], { title: title, content: content, participants: participants }.merge(options))
|
38
44
|
end
|
39
45
|
|
40
|
-
def update_message(message_id, project_id, title, content, options = {})
|
46
|
+
def update_message(message_id, project_id, title, content, options = {}) #есть тест
|
41
47
|
@request.put(['message', message_id.to_s], { projectid: project_id, title: title, content: content }.merge(options))
|
42
48
|
end
|
43
49
|
|
44
|
-
def
|
50
|
+
def subscribe_to_message_action(message_id) #есть тест
|
45
51
|
@request.put(['message', message_id.to_s, 'subscribe'])
|
46
52
|
end
|
47
53
|
|
48
|
-
def delete_message(message_id)
|
54
|
+
def delete_message(message_id) #есть тест
|
49
55
|
@request.delete(['message', message_id.to_s])
|
50
56
|
end
|
51
57
|
|
52
|
-
|
58
|
+
#endregion
|
59
|
+
|
60
|
+
#region Files
|
61
|
+
|
62
|
+
def get_task_files(task_id) #есть тест
|
53
63
|
@request.get(['task', task_id.to_s, 'files'])
|
54
64
|
end
|
55
65
|
|
56
|
-
def get_entity_files(entity_id, entity_type)
|
66
|
+
def get_entity_files(entity_id, entity_type) #есть тест
|
57
67
|
@request.get([entity_id.to_s, 'entityfiles'], entityType: entity_type)
|
58
68
|
end
|
59
69
|
|
60
|
-
def get_message_files(message_id)
|
70
|
+
def get_message_files(message_id) #есть тест
|
61
71
|
@request.get(['message', message_id.to_s, 'files'])
|
62
72
|
end
|
63
73
|
|
64
|
-
def upload_file_to_task(task_id, *files)
|
74
|
+
def upload_file_to_task(task_id, *files) #есть тест
|
65
75
|
@request.post(['task', task_id.to_s, 'files'], files: files.flatten)
|
66
76
|
end
|
67
77
|
|
68
|
-
def upload_file_to_message(message_id, *files)
|
78
|
+
def upload_file_to_message(message_id, *files) #есть тест
|
69
79
|
@request.post(['message', message_id.to_s, 'files'], files: files.flatten)
|
70
80
|
end
|
71
81
|
|
72
|
-
def detach_file_from_task(task_id, file_id)
|
82
|
+
def detach_file_from_task(task_id, file_id) #есть тест
|
73
83
|
@request.delete(['task', task_id.to_s, 'files'], fileid: file_id)
|
74
84
|
end
|
75
85
|
|
76
|
-
def detach_file_from_message(message_id, file_id)
|
86
|
+
def detach_file_from_message(message_id, file_id) #есть тест
|
77
87
|
@request.delete(['task', message_id.to_s, 'files'], fileid: file_id)
|
78
88
|
end
|
79
89
|
|
90
|
+
#endregion
|
91
|
+
|
92
|
+
#region Comment
|
93
|
+
|
80
94
|
def get_comment(comment_id)
|
81
95
|
@request.get(['comment', comment_id.to_s])
|
82
96
|
end
|
@@ -89,27 +103,31 @@ module Teamlab
|
|
89
103
|
@request.get(['message', message_id.to_s, 'comment'])
|
90
104
|
end
|
91
105
|
|
92
|
-
def add_task_comment(task_id, content, options = {})
|
106
|
+
def add_task_comment(task_id, content, options = {}) #есть тест
|
93
107
|
@request.post(['task', task_id.to_s, 'comment'], { content: content }.merge(options))
|
94
108
|
end
|
95
109
|
|
96
|
-
def add_message_comment(message_id, content, options = {})
|
110
|
+
def add_message_comment(message_id, content, options = {}) #есть тест
|
97
111
|
@request.post(['task', message_id.to_s, 'comment'], { content: content }.merge(options))
|
98
112
|
end
|
99
113
|
|
100
|
-
def update_comment(comment_id, content)
|
114
|
+
def update_comment(comment_id, content) #есть тест
|
101
115
|
@request.put(['comment', comment_id.to_s], content: content)
|
102
116
|
end
|
103
117
|
|
104
|
-
def delete_comment(comment_id)
|
118
|
+
def delete_comment(comment_id) #есть тест
|
105
119
|
@request.delete(['comment', comment_id.to_s])
|
106
120
|
end
|
107
121
|
|
108
|
-
|
122
|
+
#endregion
|
123
|
+
|
124
|
+
#region Report Template
|
125
|
+
|
126
|
+
def create_report_template(name, options = {})
|
109
127
|
@request.post(['report'], { name: name }.merge(options))
|
110
128
|
end
|
111
129
|
|
112
|
-
def update_report_template(report_id, name, options)
|
130
|
+
def update_report_template(report_id, name, options = {})
|
113
131
|
@request.put(['report', report_id.to_s], { name: name }.merge(options))
|
114
132
|
end
|
115
133
|
|
@@ -117,6 +135,10 @@ module Teamlab
|
|
117
135
|
@request.delete(['report', report_id.to_s])
|
118
136
|
end
|
119
137
|
|
138
|
+
#endregion
|
139
|
+
|
140
|
+
#region Projects
|
141
|
+
|
120
142
|
def get_projects
|
121
143
|
@request.get
|
122
144
|
end
|
@@ -129,11 +151,11 @@ module Teamlab
|
|
129
151
|
@request.get(['@self'])
|
130
152
|
end
|
131
153
|
|
132
|
-
def filter_projects(options)
|
154
|
+
def filter_projects(options = {})
|
133
155
|
@request.get(['filter'], options)
|
134
156
|
end
|
135
157
|
|
136
|
-
def
|
158
|
+
def get_followed_projects
|
137
159
|
@request.get(['@follow'])
|
138
160
|
end
|
139
161
|
|
@@ -177,13 +199,12 @@ module Teamlab
|
|
177
199
|
@request.post('', { title: title, description: description, responsibleid: responsible_id, tags: tags, private: private}.merge(options))
|
178
200
|
end
|
179
201
|
|
180
|
-
def create_template(title
|
181
|
-
@request.post(['template'], { title: title
|
202
|
+
def create_template(title)
|
203
|
+
@request.post(['template'], { title: title })
|
182
204
|
end
|
183
205
|
|
184
|
-
def add_milestone(project_id, title, deadline,
|
185
|
-
@request.post([project_id.to_s, 'milestone'], title: title, deadline: deadline,
|
186
|
-
description: description, responsible: responsible, notifyResponsible: notify_responsible)
|
206
|
+
def add_milestone(project_id, title, deadline, responsible_id, options = {})
|
207
|
+
@request.post([project_id.to_s, 'milestone'], {title: title, deadline: deadline, responsible: responsible_id}.merge(options))
|
187
208
|
end
|
188
209
|
|
189
210
|
def update_project_tags(id, tags)
|
@@ -194,8 +215,8 @@ module Teamlab
|
|
194
215
|
@request.put([id.to_s, 'status'], status: status)
|
195
216
|
end
|
196
217
|
|
197
|
-
def update_template(id, title
|
198
|
-
@request.put(['template', id.to_s], title: title
|
218
|
+
def update_template(id, title)
|
219
|
+
@request.put(['template', id.to_s], title: title)
|
199
220
|
end
|
200
221
|
|
201
222
|
def follow_unfollow_project(project_id)
|
@@ -214,20 +235,22 @@ module Teamlab
|
|
214
235
|
@request.delete(['task', id.to_s])
|
215
236
|
end
|
216
237
|
|
217
|
-
|
218
|
-
|
238
|
+
#endregion
|
239
|
+
|
240
|
+
def get_tasks_by_ids(*task_ids)
|
241
|
+
@request.get(['task'], taskid: task_ids.flatten)
|
219
242
|
end
|
220
243
|
|
221
|
-
def get_task_order(
|
222
|
-
@request.get([
|
244
|
+
def get_task_order(project_id)
|
245
|
+
@request.get([project_id.to_s, 'order'])
|
223
246
|
end
|
224
247
|
|
225
248
|
def get_simple_task_by_filter(project_id, options = {})
|
226
249
|
@request.get(%w(task filter simple), { projectid: project_id }.merge(options))
|
227
250
|
end
|
228
251
|
|
229
|
-
def add_link(
|
230
|
-
@request.post(['task',
|
252
|
+
def add_link(parent_task_id, dependence_task_id, link_type)
|
253
|
+
@request.post(['task', parent_task_id.to_s, 'link'], dependenceTaskId: dependence_task_id, linkType: link_type)
|
231
254
|
end
|
232
255
|
|
233
256
|
def update_project(id, title, responsible_id, options = {})
|
@@ -242,12 +265,14 @@ module Teamlab
|
|
242
265
|
@request.put(['task', task_id.to_s], {title: title.to_s}.merge(options))
|
243
266
|
end
|
244
267
|
|
268
|
+
#region Team
|
269
|
+
|
245
270
|
def get_project_team(project_id)
|
246
271
|
@request.get([project_id.to_s, 'team'])
|
247
272
|
end
|
248
273
|
|
249
|
-
def get_projects_teams(project_ids)
|
250
|
-
@request.post(%w(team), ids: project_ids)
|
274
|
+
def get_projects_teams(*project_ids)
|
275
|
+
@request.post(%w(team), ids: project_ids.flatten)
|
251
276
|
end
|
252
277
|
|
253
278
|
def add_to_team(project_id, user_id)
|
@@ -266,6 +291,10 @@ module Teamlab
|
|
266
291
|
@request.delete([project_id.to_s, 'team'], userId: user_id)
|
267
292
|
end
|
268
293
|
|
294
|
+
#endregion
|
295
|
+
|
296
|
+
#region Tasks
|
297
|
+
|
269
298
|
def get_my_tasks
|
270
299
|
@request.get(%w(task @self))
|
271
300
|
end
|
@@ -290,7 +319,7 @@ module Teamlab
|
|
290
319
|
@request.get(['task', task_id.to_s, 'notify'])
|
291
320
|
end
|
292
321
|
|
293
|
-
def
|
322
|
+
def get_all_tasks(project_id)
|
294
323
|
@request.get([project_id.to_s, 'task', '@all'])
|
295
324
|
end
|
296
325
|
|
@@ -3,7 +3,7 @@ module Teamlab
|
|
3
3
|
class Settings
|
4
4
|
|
5
5
|
def initialize
|
6
|
-
@request = Teamlab::Request
|
6
|
+
@request = Teamlab::Request.new('settings')
|
7
7
|
end
|
8
8
|
|
9
9
|
def get_settings
|
@@ -11,23 +11,23 @@ module Teamlab
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def get_logo
|
14
|
-
@request.get(
|
14
|
+
@request.get(%w(logo))
|
15
15
|
end
|
16
16
|
|
17
17
|
def get_usage_quota
|
18
|
-
@request.get(
|
18
|
+
@request.get(%w('quota))
|
19
19
|
end
|
20
20
|
|
21
21
|
def get_version
|
22
|
-
@request.get(
|
22
|
+
@request.get(%w(version))
|
23
23
|
end
|
24
24
|
|
25
25
|
def get_security(ids = [])
|
26
|
-
@request.get(
|
26
|
+
@request.get(%w(security), ids: ids)
|
27
27
|
end
|
28
28
|
|
29
29
|
def get_admin_security(product_id, user_id)
|
30
|
-
@request.get(
|
30
|
+
@request.get(%w(security administrator), productid: product_id, userid: user_id)
|
31
31
|
end
|
32
32
|
|
33
33
|
def get_product_admin(product_id)
|
@@ -35,19 +35,19 @@ module Teamlab
|
|
35
35
|
end
|
36
36
|
|
37
37
|
def set_version(version_id)
|
38
|
-
@request.put(
|
38
|
+
@request.put(%w(version), versionId: version_id)
|
39
39
|
end
|
40
40
|
|
41
41
|
def set_security(id, options = {})
|
42
|
-
@request.put(
|
42
|
+
@request.put(%w(security), { id: id }.merge(options))
|
43
43
|
end
|
44
44
|
|
45
45
|
def set_access(id, enabled = true)
|
46
|
-
@request.put(
|
46
|
+
@request.put(%w(access), items: [id, enabled])
|
47
47
|
end
|
48
48
|
|
49
49
|
def set_product_admin(product_id, user_id, administrator = true)
|
50
|
-
@request.put(
|
50
|
+
@request.put(%w(security administrator), productid: product_id, userid: user_id, administrator: administrator)
|
51
51
|
end
|
52
52
|
end
|
53
53
|
end
|
data/lib/teamlab/Request.rb
CHANGED
@@ -9,25 +9,29 @@ module Teamlab
|
|
9
9
|
#include HTTParty
|
10
10
|
include HTTMultiParty
|
11
11
|
|
12
|
-
def
|
12
|
+
def initialize(api_additive)
|
13
|
+
@api_additive = api_additive.to_s
|
14
|
+
end
|
15
|
+
|
16
|
+
def post(*args)
|
13
17
|
request(:post, args)
|
14
18
|
end
|
15
19
|
|
16
|
-
def
|
20
|
+
def get(*args)
|
17
21
|
request(:get, args)
|
18
22
|
end
|
19
23
|
|
20
|
-
def
|
24
|
+
def put(*args)
|
21
25
|
request(:put, args)
|
22
26
|
end
|
23
27
|
|
24
|
-
def
|
28
|
+
def delete(*args)
|
25
29
|
request(:delete, args)
|
26
30
|
end
|
27
31
|
|
28
32
|
private
|
29
33
|
|
30
|
-
def
|
34
|
+
def request(type, args)
|
31
35
|
command, opts = parse_args(args)
|
32
36
|
url = generate_request_url(command)
|
33
37
|
attempts = 0
|
@@ -44,11 +48,11 @@ module Teamlab
|
|
44
48
|
response
|
45
49
|
end
|
46
50
|
|
47
|
-
def
|
48
|
-
Teamlab.config.server + Teamlab.config.api_path +
|
51
|
+
def generate_request_url(command)
|
52
|
+
Teamlab.config.server + Teamlab.config.api_path + @api_additive + command
|
49
53
|
end
|
50
54
|
|
51
|
-
def
|
55
|
+
def parse_args(args)
|
52
56
|
command = args.first.instance_of?(Array) ? '/' + args.shift.join('/') : args.shift.to_s
|
53
57
|
opts = {}
|
54
58
|
opts[:body] = args.last.instance_of?(Hash) ? args.pop : {}
|
data/lib/teamlab/version.rb
CHANGED
data/lib/teamlab.rb
CHANGED
@@ -15,47 +15,38 @@ require_relative 'teamlab/Modules/Mail'
|
|
15
15
|
module Teamlab
|
16
16
|
|
17
17
|
def self.people
|
18
|
-
Teamlab.config.api_additive = 'people'
|
19
18
|
@people ||= Teamlab::People.new
|
20
19
|
end
|
21
20
|
|
22
21
|
def self.group
|
23
|
-
Teamlab.config.api_additive = 'group'
|
24
22
|
@group ||= Teamlab::Group.new
|
25
23
|
end
|
26
24
|
|
27
25
|
def self.settings
|
28
|
-
Teamlab.config.api_additive = 'settings'
|
29
26
|
@settings ||= Teamlab::Settings.new
|
30
27
|
end
|
31
28
|
|
32
29
|
def self.files
|
33
|
-
Teamlab.config.api_additive = 'files'
|
34
30
|
@files ||= Teamlab::Files.new
|
35
31
|
end
|
36
32
|
|
37
33
|
def self.project
|
38
|
-
Teamlab.config.api_additive = 'project'
|
39
34
|
@project ||= Teamlab::Project.new
|
40
35
|
end
|
41
36
|
|
42
37
|
def self.crm
|
43
|
-
Teamlab.config.api_additive = 'crm'
|
44
38
|
@crm ||= Teamlab::Crm.new
|
45
39
|
end
|
46
40
|
|
47
41
|
def self.community
|
48
|
-
Teamlab.config.api_additive = 'community'
|
49
42
|
@community ||= Teamlab::Community.new
|
50
43
|
end
|
51
44
|
|
52
45
|
def self.calendar
|
53
|
-
Teamlab.config.api_additive = 'calendar'
|
54
46
|
@calendar ||= Teamlab::Calendar.new
|
55
47
|
end
|
56
48
|
|
57
49
|
def self.mail
|
58
|
-
Teamlab.config.api_additive = 'mail'
|
59
50
|
@mail ||= Teamlab::Mail.new
|
60
51
|
end
|
61
52
|
end
|