mangoapps-ex-sdk-ruby 0.15.2
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 +7 -0
- data/CHANGELOG.md +506 -0
- data/LICENSE +201 -0
- data/README.md +2040 -0
- data/lib/mangoapps/client.rb +219 -0
- data/lib/mangoapps/config.rb +98 -0
- data/lib/mangoapps/errors.rb +45 -0
- data/lib/mangoapps/modules/attachments/get_folder_files.rb +14 -0
- data/lib/mangoapps/modules/attachments/get_folders.rb +14 -0
- data/lib/mangoapps/modules/attachments.rb +14 -0
- data/lib/mangoapps/modules/feeds/feeds.rb +14 -0
- data/lib/mangoapps/modules/feeds.rb +12 -0
- data/lib/mangoapps/modules/learn/course_catalog.rb +16 -0
- data/lib/mangoapps/modules/learn/course_categories.rb +16 -0
- data/lib/mangoapps/modules/learn/course_details.rb +13 -0
- data/lib/mangoapps/modules/learn/my_learning.rb +13 -0
- data/lib/mangoapps/modules/learn.rb +18 -0
- data/lib/mangoapps/modules/libraries/get_libraries.rb +14 -0
- data/lib/mangoapps/modules/libraries/get_library_categories.rb +14 -0
- data/lib/mangoapps/modules/libraries/get_library_items.rb +14 -0
- data/lib/mangoapps/modules/libraries.rb +16 -0
- data/lib/mangoapps/modules/notifications/my_priority_items.rb +13 -0
- data/lib/mangoapps/modules/notifications/notifications.rb +14 -0
- data/lib/mangoapps/modules/notifications.rb +14 -0
- data/lib/mangoapps/modules/posts/get_all_posts.rb +14 -0
- data/lib/mangoapps/modules/posts/get_post_by_id.rb +13 -0
- data/lib/mangoapps/modules/posts.rb +14 -0
- data/lib/mangoapps/modules/recognitions/award_categories.rb +14 -0
- data/lib/mangoapps/modules/recognitions/core_value_tags.rb +13 -0
- data/lib/mangoapps/modules/recognitions/get_award_feeds.rb +14 -0
- data/lib/mangoapps/modules/recognitions/get_awards_list.rb +14 -0
- data/lib/mangoapps/modules/recognitions/get_profile_awards.rb +13 -0
- data/lib/mangoapps/modules/recognitions/get_team_awards.rb +13 -0
- data/lib/mangoapps/modules/recognitions/gift_cards.rb +13 -0
- data/lib/mangoapps/modules/recognitions/leaderboard_info.rb +13 -0
- data/lib/mangoapps/modules/recognitions.rb +26 -0
- data/lib/mangoapps/modules/tasks/get_task_details.rb +13 -0
- data/lib/mangoapps/modules/tasks/get_tasks.rb +14 -0
- data/lib/mangoapps/modules/tasks.rb +14 -0
- data/lib/mangoapps/modules/trackers/get_trackers.rb +14 -0
- data/lib/mangoapps/modules/trackers.rb +12 -0
- data/lib/mangoapps/modules/users.rb +11 -0
- data/lib/mangoapps/modules/wikis/get_wiki_details.rb +13 -0
- data/lib/mangoapps/modules/wikis/get_wikis.rb +14 -0
- data/lib/mangoapps/modules/wikis.rb +14 -0
- data/lib/mangoapps/oauth.rb +187 -0
- data/lib/mangoapps/response.rb +92 -0
- data/lib/mangoapps/version.rb +5 -0
- data/lib/mangoapps.rb +34 -0
- metadata +181 -0
data/README.md
ADDED
@@ -0,0 +1,2040 @@
|
|
1
|
+
# MangoApps Ruby SDK
|
2
|
+
|
3
|
+
A clean, **real TDD** Ruby SDK for MangoApps APIs with OAuth2/OpenID Connect authentication. Features intuitive dot notation access, automatic response wrapping, and comprehensive real-world testing with actual MangoApps credentials.
|
4
|
+
|
5
|
+
## Features
|
6
|
+
|
7
|
+
- ๐ **OAuth2/OpenID Connect** authentication with automatic token refresh and userinfo endpoint
|
8
|
+
- ๐ **Internal API Authentication** - Alternative authentication using API keys for server-to-server communication
|
9
|
+
- ๐ค **Automatic Authentication Detection** - Automatically detects and prioritizes Internal API over OAuth credentials
|
10
|
+
- ๐ **Pagination Support** - All list APIs support optional page and limit parameters for efficient data retrieval
|
11
|
+
- ๐ **Simple API** with intuitive method names and clean dot notation
|
12
|
+
- ๐งช **Real TDD** - no mocking, only actual OAuth testing
|
13
|
+
- ๐ **Automatic retries** with exponential backoff
|
14
|
+
- ๐ **Comprehensive error handling** with specific exception types
|
15
|
+
- ๐ก๏ธ **Security-first** design with PKCE support and HTTPS enforcement
|
16
|
+
- ๐ง **Environment variable configuration** for secure credentials
|
17
|
+
- ๐ **Well-documented** with examples and guides
|
18
|
+
- โจ **Clean Response API** - Automatic response wrapping with intuitive dot notation access
|
19
|
+
- ๐ **Notifications Module** - User priority items including requests, events, quizzes, surveys, tasks, and todos
|
20
|
+
- ๐ฐ **Feeds Module** - User activity feeds with unread counts and feed details
|
21
|
+
- ๐ **Posts Module** - Get all posts with filtering options and post management
|
22
|
+
- ๐ **HTTPS Always** - All OAuth endpoints use HTTPS with automatic redirect handling
|
23
|
+
|
24
|
+
## Installation
|
25
|
+
|
26
|
+
Add this line to your application's Gemfile:
|
27
|
+
|
28
|
+
```ruby
|
29
|
+
gem "mangoapps-ex-sdk-ruby"
|
30
|
+
```
|
31
|
+
|
32
|
+
And then execute:
|
33
|
+
|
34
|
+
```bash
|
35
|
+
bundle install
|
36
|
+
```
|
37
|
+
|
38
|
+
Or install it directly:
|
39
|
+
|
40
|
+
```bash
|
41
|
+
gem install mangoapps-ex-sdk-ruby
|
42
|
+
```
|
43
|
+
|
44
|
+
**Current Version**: 0.15.2 (includes OAuth userinfo endpoint, HTTPS security enhancements, Internal API authentication, automatic authentication detection, and pagination support)
|
45
|
+
|
46
|
+
## Quick Start
|
47
|
+
|
48
|
+
### 1. Environment Setup
|
49
|
+
|
50
|
+
For testing purposes, create a `.env` file with your MangoApps credentials:
|
51
|
+
|
52
|
+
```bash
|
53
|
+
# .env (for testing only)
|
54
|
+
MANGOAPPS_DOMAIN=yourdomain.mangoapps.com
|
55
|
+
|
56
|
+
# OAuth2 Authentication (Option 1)
|
57
|
+
MANGOAPPS_CLIENT_ID=your_client_id_here
|
58
|
+
MANGOAPPS_CLIENT_SECRET=your_client_secret_here
|
59
|
+
MANGOAPPS_REDIRECT_URI=https://localhost:3000/oauth/callback
|
60
|
+
MANGOAPPS_SCOPE=openid profile email
|
61
|
+
|
62
|
+
# Internal API Authentication (Option 2 - Alternative to OAuth)
|
63
|
+
# Contact MangoApps support team to get your Internal API Key and Secret
|
64
|
+
MANGOAPPS_INTERNAL_API_KEY=824938b1a5ea1c29d472ba79254d68b62ce8e5df
|
65
|
+
MANGOAPPS_INTERNAL_API_SECRET=387103e2c91779d3bafb1a713bfa99a5
|
66
|
+
MANGOAPPS_TEST_HEADER=test1111
|
67
|
+
```
|
68
|
+
|
69
|
+
**Note**: The `.env` file is only used for testing. In production, you should handle token storage and management according to your application's security requirements.
|
70
|
+
|
71
|
+
### 2. Rails Integration
|
72
|
+
|
73
|
+
For Rails applications, see our comprehensive [Rails OAuth Guide](RAILS_OAUTH_GUIDE.md) which includes:
|
74
|
+
|
75
|
+
- Simple OAuth 2.0 flow implementation
|
76
|
+
- Token storage and management
|
77
|
+
- OAuth userinfo endpoint integration
|
78
|
+
- HTTPS security enforcement
|
79
|
+
- Complete callback handling
|
80
|
+
|
81
|
+
### 3. Configuration
|
82
|
+
|
83
|
+
```ruby
|
84
|
+
require "mangoapps"
|
85
|
+
|
86
|
+
# For testing - automatically loads from .env file and detects authentication method
|
87
|
+
config = MangoApps::Config.new
|
88
|
+
# Output: ๐ Using Internal API authentication (if internal API credentials found)
|
89
|
+
# Output: ๐ Using OAuth2 authentication (if OAuth credentials found)
|
90
|
+
|
91
|
+
# For production - OAuth2 configuration
|
92
|
+
config = MangoApps::Config.new(
|
93
|
+
domain: "yourdomain.mangoapps.com",
|
94
|
+
client_id: "your_client_id",
|
95
|
+
client_secret: "your_client_secret",
|
96
|
+
redirect_uri: "https://localhost:3000/oauth/callback",
|
97
|
+
scope: "openid profile email"
|
98
|
+
)
|
99
|
+
client = MangoApps::Client.new(config)
|
100
|
+
|
101
|
+
# For production - Internal API configuration (Alternative to OAuth)
|
102
|
+
# Note: Contact MangoApps support team to get your Internal API Key and Secret
|
103
|
+
config = MangoApps::Config.new(
|
104
|
+
domain: "yourdomain.mangoapps.com",
|
105
|
+
internal_api_key: "824938b1a5ea1c29d472ba79254d68b62ce8e5df",
|
106
|
+
internal_api_secret: "387103e2c91779d3bafb1a713bfa99a5",
|
107
|
+
test_header: "test1111" # Optional
|
108
|
+
)
|
109
|
+
client = MangoApps::Client.new(config)
|
110
|
+
```
|
111
|
+
|
112
|
+
### 3. OAuth Authentication
|
113
|
+
|
114
|
+
#### Quick Start (Recommended)
|
115
|
+
```bash
|
116
|
+
# Get OAuth token (interactive)
|
117
|
+
./run_auth.sh
|
118
|
+
|
119
|
+
# Run tests to verify everything works
|
120
|
+
./run_tests.sh
|
121
|
+
```
|
122
|
+
|
123
|
+
#### Basic Usage Example
|
124
|
+
```ruby
|
125
|
+
require 'mangoapps-ex-sdk-ruby'
|
126
|
+
|
127
|
+
# Initialize client
|
128
|
+
client = MangoApps::Client.new
|
129
|
+
|
130
|
+
# Get user profile
|
131
|
+
user = client.me
|
132
|
+
puts "Hello, #{user.name}!"
|
133
|
+
|
134
|
+
# Get OAuth user info (from OAuth userinfo endpoint)
|
135
|
+
userinfo = client.get_userinfo
|
136
|
+
puts "OAuth User: #{userinfo.name} (#{userinfo.email})"
|
137
|
+
puts "Username: #{userinfo.preferred_username}"
|
138
|
+
puts "Subject ID: #{userinfo.sub}"
|
139
|
+
|
140
|
+
# Get priority items
|
141
|
+
priority_items = client.my_priority_items
|
142
|
+
puts "You have #{priority_items.data.length} priority items:"
|
143
|
+
priority_items.data.each do |item|
|
144
|
+
puts " โข #{item.title}: #{item.count} pending"
|
145
|
+
end
|
146
|
+
|
147
|
+
# Get available courses
|
148
|
+
courses = client.course_catalog
|
149
|
+
puts "Available courses: #{courses.courses.length}"
|
150
|
+
|
151
|
+
# Get activity feeds
|
152
|
+
feeds = client.feeds
|
153
|
+
puts "Activity feeds: #{feeds.feeds.length} (unread: #{feeds.unread_counts.unread_feeds_count})"
|
154
|
+
|
155
|
+
# Get all posts
|
156
|
+
posts = client.get_all_posts(filter_by: "all")
|
157
|
+
puts "All posts: #{posts.feeds.length}"
|
158
|
+
|
159
|
+
# Get post details by ID
|
160
|
+
if posts.feeds.any?
|
161
|
+
post_id = posts.feeds.first.post_id
|
162
|
+
post_details = client.get_post_by_id(post_id, full_description: "Y")
|
163
|
+
puts "Post details: #{post_details.post.title}"
|
164
|
+
end
|
165
|
+
|
166
|
+
# Get user libraries
|
167
|
+
libraries = client.get_libraries
|
168
|
+
puts "User libraries: #{libraries.libraries.length}"
|
169
|
+
|
170
|
+
# Get library categories by ID
|
171
|
+
if libraries.libraries.any?
|
172
|
+
library_id = libraries.libraries.first.id
|
173
|
+
library_details = client.get_library_categories(library_id)
|
174
|
+
puts "Library details: #{library_details.library.name}"
|
175
|
+
|
176
|
+
# Get library items from first category
|
177
|
+
if library_details.library.categories.any?
|
178
|
+
category_id = library_details.library.categories.first.id
|
179
|
+
library_items = client.get_library_items(library_id, category_id)
|
180
|
+
puts "Library items: #{library_items.library_items.length} items in #{library_items.category_name}"
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
# Get user trackers
|
185
|
+
trackers = client.get_trackers
|
186
|
+
puts "User trackers: #{trackers.trackers.length}"
|
187
|
+
|
188
|
+
# Get user folders
|
189
|
+
folders = client.get_folders
|
190
|
+
puts "User folders: #{folders.folders.length}"
|
191
|
+
|
192
|
+
# Get files from first folder with content
|
193
|
+
if folders.folders.any?
|
194
|
+
folder_with_content = folders.folders.find { |f| f.child_count.to_i > 0 }
|
195
|
+
if folder_with_content
|
196
|
+
folder_files = client.get_folder_files(folder_with_content.id, include_folders: "Y")
|
197
|
+
puts "Folder files: #{folder_files.files.length} items in #{folder_files.name}"
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
# Get user tasks
|
202
|
+
tasks = client.get_tasks(filter: "Pending_Tasks", page: 1, limit: 3)
|
203
|
+
puts "User tasks: #{tasks.tasks.task.length}"
|
204
|
+
|
205
|
+
# Get detailed information for a specific task
|
206
|
+
if tasks.tasks.task.any?
|
207
|
+
first_task = tasks.tasks.task.first
|
208
|
+
task_id = first_task.is_a?(Array) ? first_task[1] : first_task.id
|
209
|
+
task_details = client.get_task_details(task_id)
|
210
|
+
puts "Task details: #{task_details.task.task_title} (Status: #{task_details.task.status})"
|
211
|
+
end
|
212
|
+
|
213
|
+
# Get user wikis
|
214
|
+
wikis = client.get_wikis(mode: "my", limit: 5, offset: 0)
|
215
|
+
puts "User wikis: #{wikis.wikis.length}"
|
216
|
+
|
217
|
+
# Get detailed information for the first wiki
|
218
|
+
if wikis.wikis.any?
|
219
|
+
first_wiki = wikis.wikis.first
|
220
|
+
wiki_details = client.get_wiki_details(first_wiki.id)
|
221
|
+
puts "Wiki details: #{wiki_details.wiki.details.title} (Read count: #{wiki_details.wiki.details.total_read_count})"
|
222
|
+
end
|
223
|
+
```
|
224
|
+
|
225
|
+
#### Manual OAuth Flow
|
226
|
+
```ruby
|
227
|
+
# Generate authorization URL
|
228
|
+
state = SecureRandom.hex(16)
|
229
|
+
auth_url = client.authorization_url(state: state)
|
230
|
+
puts "Open this URL to authorize: #{auth_url}"
|
231
|
+
|
232
|
+
# After user authorizes, exchange code for tokens
|
233
|
+
tokens = client.authenticate!(authorization_code: params[:code])
|
234
|
+
|
235
|
+
# Store tokens securely in your application
|
236
|
+
# (implementation depends on your storage solution)
|
237
|
+
store_tokens(tokens.access_token, tokens.refresh_token)
|
238
|
+
|
239
|
+
# Now you can make API calls with clean dot notation
|
240
|
+
user = client.me
|
241
|
+
puts "Welcome, #{user.user_profile.minimal_profile.name}!"
|
242
|
+
|
243
|
+
# Get OAuth user info from userinfo endpoint
|
244
|
+
userinfo = client.get_userinfo
|
245
|
+
puts "OAuth User: #{userinfo.name} (#{userinfo.email})"
|
246
|
+
puts "Subject ID: #{userinfo.sub}"
|
247
|
+
puts "Username: #{userinfo.preferred_username}"
|
248
|
+
```
|
249
|
+
|
250
|
+
#### OAuth Userinfo Endpoint
|
251
|
+
|
252
|
+
The SDK provides access to the OAuth userinfo endpoint for getting authenticated user information:
|
253
|
+
|
254
|
+
```ruby
|
255
|
+
# Get user info from OAuth userinfo endpoint
|
256
|
+
userinfo = client.get_userinfo
|
257
|
+
|
258
|
+
# Access OAuth user data with clean dot notation
|
259
|
+
puts "Name: #{userinfo.name}"
|
260
|
+
puts "Email: #{userinfo.email}"
|
261
|
+
puts "Subject ID: #{userinfo.sub}"
|
262
|
+
puts "Username: #{userinfo.preferred_username}"
|
263
|
+
|
264
|
+
# Available OAuth userinfo fields:
|
265
|
+
# - sub: Subject identifier (unique user ID)
|
266
|
+
# - name: Full name
|
267
|
+
# - email: Email address
|
268
|
+
# - preferred_username: Username
|
269
|
+
# - email_verified: Email verification status
|
270
|
+
# - locale: User locale
|
271
|
+
# - zoneinfo: Timezone information
|
272
|
+
```
|
273
|
+
|
274
|
+
#### HTTPS Security Features
|
275
|
+
|
276
|
+
The SDK enforces HTTPS for all OAuth operations:
|
277
|
+
|
278
|
+
```ruby
|
279
|
+
# Automatic HTTPS enforcement
|
280
|
+
# - Discovery endpoints always use HTTPS
|
281
|
+
# - Userinfo endpoints always use HTTPS
|
282
|
+
# - Automatic redirect handling (301/302)
|
283
|
+
# - SSL certificate verification
|
284
|
+
|
285
|
+
# Example: Even if discovery returns HTTP URLs, they're converted to HTTPS
|
286
|
+
config = MangoApps::Config.new(domain: "example.mangoapps.com")
|
287
|
+
client = MangoApps::Client.new(config)
|
288
|
+
|
289
|
+
# This will automatically use HTTPS
|
290
|
+
userinfo = client.get_userinfo
|
291
|
+
```
|
292
|
+
|
293
|
+
### 4. Automatic Authentication Detection
|
294
|
+
|
295
|
+
The SDK automatically detects and prioritizes authentication methods:
|
296
|
+
|
297
|
+
1. **Internal API Credentials** (highest priority) - If `MANGOAPPS_INTERNAL_API_KEY` and `MANGOAPPS_INTERNAL_API_SECRET` are found
|
298
|
+
2. **OAuth Credentials** (fallback) - If `MANGOAPPS_CLIENT_ID` and `MANGOAPPS_CLIENT_SECRET` are found
|
299
|
+
|
300
|
+
```ruby
|
301
|
+
# Automatic detection - no configuration needed
|
302
|
+
config = MangoApps::Config.new
|
303
|
+
# Shows: ๐ Using Internal API authentication (if internal API found)
|
304
|
+
# Shows: ๐ Using OAuth2 authentication (if OAuth found)
|
305
|
+
|
306
|
+
client = MangoApps::Client.new(config)
|
307
|
+
# All API calls work automatically with detected authentication method
|
308
|
+
```
|
309
|
+
|
310
|
+
### 5. Pagination Support
|
311
|
+
|
312
|
+
All list APIs support optional pagination parameters for efficient data retrieval:
|
313
|
+
|
314
|
+
```ruby
|
315
|
+
# Basic usage with default pagination
|
316
|
+
posts = client.get_all_posts
|
317
|
+
courses = client.course_catalog
|
318
|
+
|
319
|
+
# Pagination with custom page and limit
|
320
|
+
posts = client.get_all_posts(page: 2, limit: 10)
|
321
|
+
courses = client.course_catalog(page: 1, limit: 5)
|
322
|
+
|
323
|
+
# Filtering with pagination
|
324
|
+
posts = client.get_all_posts(filter_by: "all", page: 1, limit: 20)
|
325
|
+
tasks = client.get_tasks(filter: "Pending_Tasks", page: 1, limit: 10)
|
326
|
+
|
327
|
+
# Library items with pagination
|
328
|
+
items = client.get_library_items(library_id, category_id, page: 1, limit: 15)
|
329
|
+
```
|
330
|
+
|
331
|
+
**Default Pagination Values:**
|
332
|
+
- Most APIs: `page: 1, limit: 20`
|
333
|
+
- Tasks: `page: 1, limit: 5` (smaller default for task management)
|
334
|
+
- Posts: `page: 1, limit: 20` with `filter_by: "all"`
|
335
|
+
|
336
|
+
### 6. Internal API Authentication (Alternative to OAuth)
|
337
|
+
|
338
|
+
For applications that need direct API access without OAuth flow, you can use internal API authentication:
|
339
|
+
|
340
|
+
> **๐ Getting API Credentials**: Contact the MangoApps support team to obtain your Internal API Key and Secret for server-to-server authentication.
|
341
|
+
|
342
|
+
```ruby
|
343
|
+
# Configure with internal API credentials
|
344
|
+
config = MangoApps::Config.new(
|
345
|
+
domain: "yourdomain.mangoapps.com",
|
346
|
+
internal_api_key: "824938b1a5ea1c29d472ba79254d68b62ce8e5df",
|
347
|
+
internal_api_secret: "387103e2c91779d3bafb1a713bfa99a5",
|
348
|
+
)
|
349
|
+
client = MangoApps::Client.new(config)
|
350
|
+
|
351
|
+
# Use the SDK normally - authentication is handled automatically
|
352
|
+
user = client.me
|
353
|
+
puts "Hello, #{user.user_profile.minimal_profile.name}!"
|
354
|
+
|
355
|
+
# Get user info (uses /me endpoint for internal API)
|
356
|
+
userinfo = client.get_userinfo
|
357
|
+
puts "User: #{userinfo.name} (#{userinfo.email})"
|
358
|
+
|
359
|
+
# All other API calls work the same way
|
360
|
+
posts = client.get_all_posts
|
361
|
+
notifications = client.notifications
|
362
|
+
```
|
363
|
+
|
364
|
+
#### Internal API Headers
|
365
|
+
|
366
|
+
The SDK automatically adds the required headers for internal API authentication:
|
367
|
+
|
368
|
+
```ruby
|
369
|
+
# These headers are automatically added to all requests:
|
370
|
+
# - Internal-Api-Key: your_api_key
|
371
|
+
# - Internal-Api-Secret: your_api_secret
|
372
|
+
# - Test: your_test_header (if provided)
|
373
|
+
```
|
374
|
+
|
375
|
+
#### When to Use Internal API vs OAuth
|
376
|
+
|
377
|
+
- **OAuth2**: Use for user-facing applications where users need to authenticate
|
378
|
+
- **Internal API**: Use for server-to-server communication, automation, or internal tools
|
379
|
+
|
380
|
+
## Response Format
|
381
|
+
|
382
|
+
The SDK automatically wraps all API responses in a `MangoApps::Response` object that provides clean dot notation access:
|
383
|
+
|
384
|
+
```ruby
|
385
|
+
# Clean dot notation access (automatic response wrapping):
|
386
|
+
user = client.me
|
387
|
+
name = user.user_profile.minimal_profile.name
|
388
|
+
email = user.user_profile.minimal_profile.email
|
389
|
+
```
|
390
|
+
|
391
|
+
### Response Features
|
392
|
+
|
393
|
+
- **๐ฏ Dot Notation Access**: `response.user.name` for clean, intuitive API access
|
394
|
+
- **๐ Automatic Wrapping**: All responses are automatically wrapped in `MangoApps::Response`
|
395
|
+
- **๐ Hash Compatibility**: Still supports `[]` access if needed
|
396
|
+
- **๐ Enumerable Support**: Arrays and hashes work as expected
|
397
|
+
- **๐ Raw Data Access**: Use `response.raw_data` for original response
|
398
|
+
- **โก Type Safety**: Better IDE support and autocomplete
|
399
|
+
- **๐จ Clean Code**: No more verbose nested hash access
|
400
|
+
|
401
|
+
## API Resources
|
402
|
+
|
403
|
+
### Users Module
|
404
|
+
|
405
|
+
```ruby
|
406
|
+
# Get current user profile
|
407
|
+
user = client.me
|
408
|
+
|
409
|
+
# Access user data with clean dot notation
|
410
|
+
puts "User: #{user.user_profile.minimal_profile.name}"
|
411
|
+
puts "Email: #{user.user_profile.minimal_profile.email}"
|
412
|
+
puts "Points: #{user.user_profile.gamification.total_points}"
|
413
|
+
puts "Followers: #{user.user_profile.user_data.followers}"
|
414
|
+
```
|
415
|
+
|
416
|
+
### Learn Module
|
417
|
+
|
418
|
+
#### Course Catalog
|
419
|
+
```ruby
|
420
|
+
# Get course catalog
|
421
|
+
courses = client.course_catalog
|
422
|
+
|
423
|
+
# Access course data with clean dot notation
|
424
|
+
courses.courses.each do |course|
|
425
|
+
puts "#{course.name} - #{course.course_type}"
|
426
|
+
end
|
427
|
+
```
|
428
|
+
|
429
|
+
#### Course Categories
|
430
|
+
```ruby
|
431
|
+
# Get all course categories
|
432
|
+
categories = client.course_categories
|
433
|
+
|
434
|
+
# Access category data with clean dot notation
|
435
|
+
categories.all_categories.each do |category|
|
436
|
+
puts "#{category.name} - Position: #{category.position}"
|
437
|
+
end
|
438
|
+
|
439
|
+
# Get specific category details
|
440
|
+
category = client.course_category(category_id)
|
441
|
+
```
|
442
|
+
|
443
|
+
#### Course Details
|
444
|
+
```ruby
|
445
|
+
# Get detailed course information by course ID
|
446
|
+
course_id = 604
|
447
|
+
course = client.course_details(course_id)
|
448
|
+
|
449
|
+
# Access course data with clean dot notation
|
450
|
+
course_data = course.course
|
451
|
+
puts "Course: #{course_data.name} (ID: #{course_data.id})"
|
452
|
+
puts "Description: #{course_data.description}"
|
453
|
+
puts "Type: #{course_data.course_type}"
|
454
|
+
puts "Delivery Mode: #{course_data.delivery_mode}"
|
455
|
+
puts "Instructors: #{course_data.instructors.length}"
|
456
|
+
puts "Fields: #{course_data.fields.length}"
|
457
|
+
|
458
|
+
# Access course URLs
|
459
|
+
puts "Start Course URL: #{course_data.start_course_url}"
|
460
|
+
puts "Go to Course URL: #{course_data.goto_course_url}"
|
461
|
+
|
462
|
+
# Access course fields (details, certification, etc.)
|
463
|
+
course_data.fields.each do |field|
|
464
|
+
puts "Field: #{field.field_name}"
|
465
|
+
field.course_sub_fields.each do |sub_field|
|
466
|
+
puts " #{sub_field.field_name}: #{sub_field.field_value}"
|
467
|
+
end
|
468
|
+
end
|
469
|
+
```
|
470
|
+
|
471
|
+
#### My Learning
|
472
|
+
```ruby
|
473
|
+
# Get user's learning progress and courses
|
474
|
+
learning = client.my_learning
|
475
|
+
|
476
|
+
# Access user learning data with clean dot notation
|
477
|
+
puts "User: #{learning.user_name} (ID: #{learning.user_id})"
|
478
|
+
puts "Total training time: #{learning.total_training_time}"
|
479
|
+
puts "Ongoing courses: #{learning.ongoing_course_count}"
|
480
|
+
puts "Completed courses: #{learning.completed_course_count}"
|
481
|
+
puts "Registered courses: #{learning.registered_course_count}"
|
482
|
+
|
483
|
+
# Access learning sections
|
484
|
+
learning.section.each do |section|
|
485
|
+
puts "#{section.label} - #{section.count} courses"
|
486
|
+
|
487
|
+
# Access courses in each section
|
488
|
+
section.courses.each do |course|
|
489
|
+
puts " ๐ #{course.name} - #{course.course_progress}% progress"
|
490
|
+
end
|
491
|
+
end
|
492
|
+
```
|
493
|
+
|
494
|
+
### Recognitions Module
|
495
|
+
|
496
|
+
#### Award Categories
|
497
|
+
```ruby
|
498
|
+
# Get award categories
|
499
|
+
categories = client.award_categories
|
500
|
+
|
501
|
+
# Access award category data with clean dot notation
|
502
|
+
categories.award_categories.each do |category|
|
503
|
+
puts "#{category.name} (ID: #{category.id}) - Permission: #{category.recipient_permission}"
|
504
|
+
end
|
505
|
+
```
|
506
|
+
|
507
|
+
#### Core Value Tags
|
508
|
+
```ruby
|
509
|
+
# Get core value tags
|
510
|
+
tags = client.core_value_tags
|
511
|
+
|
512
|
+
# Access core value tag data with clean dot notation
|
513
|
+
tags.core_value_tags.each do |tag|
|
514
|
+
puts "#{tag.name} (ID: #{tag.id}) - Color: ##{tag.color}"
|
515
|
+
end
|
516
|
+
```
|
517
|
+
|
518
|
+
#### Leaderboard Info
|
519
|
+
```ruby
|
520
|
+
# Get leaderboard information
|
521
|
+
leaderboard = client.leaderboard_info
|
522
|
+
|
523
|
+
# Check if leaderboard data is available
|
524
|
+
if leaderboard.leaderboard_info
|
525
|
+
# Access user leaderboard with clean dot notation
|
526
|
+
leaderboard.leaderboard_info.user_info.each do |user|
|
527
|
+
puts "๐
#{user.name} (Rank: #{user.rank}) - Awards: #{user.award_count}"
|
528
|
+
end
|
529
|
+
|
530
|
+
# Access team leaderboard with clean dot notation
|
531
|
+
leaderboard.leaderboard_info.team_info.each do |team|
|
532
|
+
puts "๐ #{team.name} (Rank: #{team.rank}) - Awards: #{team.award_count}"
|
533
|
+
end
|
534
|
+
else
|
535
|
+
puts "No leaderboard data configured"
|
536
|
+
end
|
537
|
+
```
|
538
|
+
|
539
|
+
#### Tango Gift Cards
|
540
|
+
```ruby
|
541
|
+
# Get tango gift cards information
|
542
|
+
gift_cards = client.tango_gift_cards
|
543
|
+
|
544
|
+
# Access gift card data with clean dot notation
|
545
|
+
puts "Available points: #{gift_cards.tango_cards.available_points}"
|
546
|
+
puts "Terms: #{gift_cards.tango_cards.terms}"
|
547
|
+
```
|
548
|
+
|
549
|
+
#### Gift Cards
|
550
|
+
```ruby
|
551
|
+
# Get gift cards information
|
552
|
+
gift_cards = client.gift_cards
|
553
|
+
|
554
|
+
# Access gift card data with clean dot notation
|
555
|
+
gift_cards.cards.each do |card|
|
556
|
+
puts "#{card.brand_name} (Key: #{card.brand_key}) - Enabled: #{card.enabled}"
|
557
|
+
end
|
558
|
+
```
|
559
|
+
|
560
|
+
#### Get Awards List
|
561
|
+
```ruby
|
562
|
+
# Get awards list for a specific category
|
563
|
+
response = client.get_awards_list(category_id: 4303)
|
564
|
+
|
565
|
+
# Access award data with clean dot notation
|
566
|
+
response.get_awards_list.each do |award|
|
567
|
+
puts "#{award.name} (ID: #{award.id})"
|
568
|
+
puts " Description: #{award.description}"
|
569
|
+
puts " Points: #{award.points}"
|
570
|
+
puts " Reward Points: #{award.reward_points}"
|
571
|
+
puts " Image: #{award.attachment_url}"
|
572
|
+
end
|
573
|
+
```
|
574
|
+
|
575
|
+
#### Get Profile Awards
|
576
|
+
```ruby
|
577
|
+
# Get user profile awards
|
578
|
+
response = client.get_profile_awards
|
579
|
+
|
580
|
+
# Access core value tags with counts
|
581
|
+
response.core_value_tags.each do |tag|
|
582
|
+
puts "#{tag.name} (ID: #{tag.id}) - Count: #{tag.count}"
|
583
|
+
end
|
584
|
+
|
585
|
+
# Access award feeds
|
586
|
+
response.feeds.each do |feed|
|
587
|
+
puts "#{feed.feed_property.title} - Points: #{feed.recognition_points}"
|
588
|
+
puts "From: #{feed.from_user.name}"
|
589
|
+
puts "Body: #{feed.body}"
|
590
|
+
end
|
591
|
+
```
|
592
|
+
|
593
|
+
#### Get Team Awards
|
594
|
+
```ruby
|
595
|
+
# Get team awards for a specific project/team
|
596
|
+
response = client.get_team_awards(project_id: 117747)
|
597
|
+
|
598
|
+
# Access team core value tags with counts
|
599
|
+
response.core_value_tags.each do |tag|
|
600
|
+
puts "#{tag.name} (ID: #{tag.id}) - Count: #{tag.count}"
|
601
|
+
end
|
602
|
+
|
603
|
+
# Access team award feeds
|
604
|
+
response.feeds.each do |feed|
|
605
|
+
puts "#{feed.feed_property.title} - Points: #{feed.recognition_points}"
|
606
|
+
puts "From: #{feed.from_user.name}"
|
607
|
+
puts "Team: #{feed.group_name} (ID: #{feed.group_id})"
|
608
|
+
puts "Body: #{feed.body}"
|
609
|
+
end
|
610
|
+
```
|
611
|
+
|
612
|
+
#### My Priority Items
|
613
|
+
```ruby
|
614
|
+
# Get user's priority items
|
615
|
+
response = client.my_priority_items
|
616
|
+
|
617
|
+
# Access priority items data
|
618
|
+
response.data.each do |item|
|
619
|
+
puts "#{item.title} (ID: #{item.id}) - Count: #{item.count}"
|
620
|
+
puts " Action Type: #{item.action_type}"
|
621
|
+
puts " Icon: #{item.icon} (#{item.icon_color})"
|
622
|
+
puts " Details: #{item.info_details}"
|
623
|
+
end
|
624
|
+
|
625
|
+
# Check response status
|
626
|
+
puts "Success: #{response.success}"
|
627
|
+
puts "Display Type: #{response.display_type}"
|
628
|
+
```
|
629
|
+
|
630
|
+
#### Feeds
|
631
|
+
```ruby
|
632
|
+
# Get user's activity feeds
|
633
|
+
response = client.feeds
|
634
|
+
|
635
|
+
# Access feeds data
|
636
|
+
response.feeds.each do |feed|
|
637
|
+
puts "#{feed.feed_property.title} (ID: #{feed.id})"
|
638
|
+
puts " From: #{feed.from_user.name} | Group: #{feed.group_name}"
|
639
|
+
puts " Type: #{feed.feed_type} | Category: #{feed.category}"
|
640
|
+
puts " Created: #{Time.at(feed.created_at.to_i).strftime('%Y-%m-%d %H:%M:%S')}"
|
641
|
+
puts " Unread: #{feed.unread}"
|
642
|
+
puts " Body: #{feed.body[0..100]}..."
|
643
|
+
end
|
644
|
+
|
645
|
+
# Access unread counts
|
646
|
+
puts "Unread feeds: #{response.unread_counts.unread_feeds_count}"
|
647
|
+
puts "Direct messages: #{response.unread_counts.direct_messages_count}"
|
648
|
+
puts "What's new: #{response.unread_counts.whats_new_count}"
|
649
|
+
|
650
|
+
# Check response metadata
|
651
|
+
puts "Limit: #{response.limit} | Version: #{response.mangoapps_version}"
|
652
|
+
```
|
653
|
+
|
654
|
+
#### Get All Posts
|
655
|
+
```ruby
|
656
|
+
# Get all posts with filtering
|
657
|
+
response = client.get_all_posts(filter_by: "all")
|
658
|
+
|
659
|
+
# Access posts data
|
660
|
+
response.feeds.each do |post|
|
661
|
+
puts "#{post.tile.tile_name} (ID: #{post.id})"
|
662
|
+
puts " From: #{post.from_user.name} | Group: #{post.group_name}"
|
663
|
+
puts " Post ID: #{post.post_id} | View count: #{post.total_view_count}"
|
664
|
+
puts " Created: #{Time.at(post.created_at.to_i).strftime('%Y-%m-%d %H:%M:%S')}"
|
665
|
+
puts " Comments: #{post.comments.length} | Likes: #{post.like_count}"
|
666
|
+
puts " Content: #{post.tile.tile_content[0..100]}..."
|
667
|
+
end
|
668
|
+
|
669
|
+
# Access post configuration
|
670
|
+
puts "Post view count visibility: #{response.post_view_count_visibility}"
|
671
|
+
puts "Post view count link config: #{response.post_view_count_link_config}"
|
672
|
+
```
|
673
|
+
|
674
|
+
#### Get Post By ID
|
675
|
+
```ruby
|
676
|
+
# Get detailed post information by ID
|
677
|
+
post_id = 59101
|
678
|
+
response = client.get_post_by_id(post_id, full_description: "Y")
|
679
|
+
|
680
|
+
# Access post details
|
681
|
+
post = response.post
|
682
|
+
puts "#{post.title} (ID: #{post.id})"
|
683
|
+
puts " Created by: #{post.created_name} (ID: #{post.creator_by})"
|
684
|
+
puts " Created: #{Time.at(post.created_at.to_i).strftime('%Y-%m-%d %H:%M:%S')}"
|
685
|
+
puts " Conversation: #{post.conversation_name}"
|
686
|
+
puts " View count: #{post.total_view_count} | Likes: #{post.like_count} | Comments: #{post.comment_count}"
|
687
|
+
|
688
|
+
# Access tile information
|
689
|
+
if post.tile
|
690
|
+
puts " Tile: #{post.tile.tile_name}"
|
691
|
+
puts " Full description: #{post.tile.tile_full_description[0..200]}..."
|
692
|
+
puts " Image: #{post.tile.tile_image}"
|
693
|
+
end
|
694
|
+
|
695
|
+
# Check post permissions
|
696
|
+
puts " Can edit: #{post.can_edit} | Can comment: #{post.can_comment} | Can delete: #{post.can_delete}"
|
697
|
+
puts " Is draft: #{post.is_draft} | Archived: #{post.archived}"
|
698
|
+
```
|
699
|
+
|
700
|
+
#### Libraries Management
|
701
|
+
```ruby
|
702
|
+
# Get user's document libraries
|
703
|
+
libraries = client.get_libraries
|
704
|
+
|
705
|
+
# Access libraries data
|
706
|
+
puts "๐ User Libraries:"
|
707
|
+
libraries.libraries.each do |library|
|
708
|
+
puts " โข #{library.name} (ID: #{library.id})"
|
709
|
+
puts " Type: #{library.library_type} | View: #{library.view_mode}"
|
710
|
+
puts " Items: #{library.total_items_count} | Categories: #{library.categories.length}"
|
711
|
+
puts " Edit access: #{library.edit_access} | Position: #{library.position}"
|
712
|
+
puts " Banner: #{library.banner_color} | Icon: #{library.icon_properties.color}"
|
713
|
+
|
714
|
+
# Access library categories
|
715
|
+
if library.categories.any?
|
716
|
+
puts " Categories:"
|
717
|
+
library.categories.first(3).each do |category|
|
718
|
+
puts " - #{category.name} (#{category.library_items_count} items)"
|
719
|
+
end
|
720
|
+
end
|
721
|
+
puts ""
|
722
|
+
end
|
723
|
+
```
|
724
|
+
|
725
|
+
#### Get Library Categories
|
726
|
+
```ruby
|
727
|
+
# Get detailed library information and categories by library ID
|
728
|
+
library_id = 9776
|
729
|
+
response = client.get_library_categories(library_id)
|
730
|
+
|
731
|
+
# Access library details
|
732
|
+
library = response.library
|
733
|
+
puts "#{library.name} (ID: #{library.id})"
|
734
|
+
puts " Type: #{library.library_type} | View: #{library.view_mode}"
|
735
|
+
puts " Description: #{library.description}"
|
736
|
+
puts " Total items: #{library.total_items_count} | Categories: #{library.categories.length}"
|
737
|
+
puts " Edit access: #{library.edit_access} | Position: #{library.position}"
|
738
|
+
|
739
|
+
# Access library properties
|
740
|
+
puts " Banner color: #{library.banner_color} | Icon color enabled: #{library.enable_icon_color}"
|
741
|
+
puts " Created: #{Time.at(library.created_at.to_i).strftime('%Y-%m-%d %H:%M:%S')}"
|
742
|
+
puts " Updated: #{Time.at(library.updated_at.to_i).strftime('%Y-%m-%d %H:%M:%S')}"
|
743
|
+
|
744
|
+
# Access icon properties
|
745
|
+
if library.icon_properties
|
746
|
+
puts " Icon color: #{library.icon_properties.color} | Icon class: #{library.icon_properties.class}"
|
747
|
+
end
|
748
|
+
|
749
|
+
# Access categories
|
750
|
+
if library.categories.any?
|
751
|
+
puts " Categories:"
|
752
|
+
library.categories.each do |category|
|
753
|
+
puts " โข #{category.name} (ID: #{category.id})"
|
754
|
+
puts " Items: #{category.library_items_count} | Rank: #{category.rank}"
|
755
|
+
puts " Is system: #{category.is_system} | Icon: #{category.icon || 'None'}"
|
756
|
+
if category.description
|
757
|
+
puts " Description: #{category.description[0..100]}..."
|
758
|
+
end
|
759
|
+
end
|
760
|
+
end
|
761
|
+
```
|
762
|
+
|
763
|
+
#### Get Library Items
|
764
|
+
```ruby
|
765
|
+
# Get library items by library ID and category ID
|
766
|
+
library_id = 9776
|
767
|
+
category_id = 50114
|
768
|
+
response = client.get_library_items(library_id, category_id)
|
769
|
+
|
770
|
+
# Access library items data
|
771
|
+
puts "Category: #{response.category_name}"
|
772
|
+
puts "View mode: #{response.view_mode} | Library type: #{response.library_type}"
|
773
|
+
puts "Library ID: #{response.library_id} | Can add: #{response.can_add}"
|
774
|
+
puts "Icon color: #{response.enable_icon_color}"
|
775
|
+
|
776
|
+
# Access library items
|
777
|
+
if response.library_items.any?
|
778
|
+
puts "Library Items:"
|
779
|
+
response.library_items.each do |item|
|
780
|
+
puts " โข #{item.name} (ID: #{item.id})"
|
781
|
+
puts " Link type: #{item.link_type} | Link: #{item.link[0..50]}..."
|
782
|
+
|
783
|
+
# Handle different link types
|
784
|
+
if item.link_type == "ExternalLink"
|
785
|
+
if item.icon_properties
|
786
|
+
puts " Icon: #{item.icon_properties.color} | Class: #{item.icon_properties.class}"
|
787
|
+
end
|
788
|
+
elsif item.link_type == "Attachment"
|
789
|
+
puts " Attachment ID: #{item.attachment_id} | File type: #{item.file_type}"
|
790
|
+
puts " Likes: #{item.likes_count} | Is liked: #{item.is_liked}"
|
791
|
+
puts " Image: #{item.image_url}"
|
792
|
+
puts " Short URL: #{item.short_url[0..50]}..."
|
793
|
+
end
|
794
|
+
end
|
795
|
+
else
|
796
|
+
puts "No library items found"
|
797
|
+
end
|
798
|
+
```
|
799
|
+
|
800
|
+
#### Trackers Management
|
801
|
+
```ruby
|
802
|
+
# Get user's trackers
|
803
|
+
trackers = client.get_trackers
|
804
|
+
|
805
|
+
# Access trackers data
|
806
|
+
puts "๐ User Trackers:"
|
807
|
+
puts " Total trackers: #{trackers.trackers.length}"
|
808
|
+
puts " Transaction ID: #{trackers.transaction_id || 'None'}"
|
809
|
+
puts ""
|
810
|
+
|
811
|
+
# Display recent trackers
|
812
|
+
puts "๐ Recent Trackers:"
|
813
|
+
trackers.trackers.first(5).each do |tracker|
|
814
|
+
puts " โข #{tracker.name} (ID: #{tracker.id})"
|
815
|
+
puts " Last submission: #{Time.at(tracker.last_submission_date.to_i).strftime('%Y-%m-%d %H:%M:%S')}"
|
816
|
+
puts " Conversation: #{tracker.conversation_name} (ID: #{tracker.conversation_id})"
|
817
|
+
puts " Pinned: #{tracker.is_pinned} | Can share: #{tracker.can_share}"
|
818
|
+
|
819
|
+
# Access tracker icon info
|
820
|
+
if tracker.tracker_icon_info
|
821
|
+
puts " Icon: #{tracker.tracker_icon_info.color_code} | Class: #{tracker.tracker_icon_info.icon_url}"
|
822
|
+
end
|
823
|
+
|
824
|
+
puts " MLink: #{tracker.mlink[0..50]}..."
|
825
|
+
puts ""
|
826
|
+
end
|
827
|
+
```
|
828
|
+
|
829
|
+
#### Attachments Management
|
830
|
+
```ruby
|
831
|
+
# Get user's folders
|
832
|
+
folders = client.get_folders
|
833
|
+
|
834
|
+
# Access folders data
|
835
|
+
puts "๐ User Folders:"
|
836
|
+
puts " Total folders: #{folders.folders.length}"
|
837
|
+
puts " Transaction ID: #{folders.transaction_id || 'None'}"
|
838
|
+
puts ""
|
839
|
+
|
840
|
+
# Display folders
|
841
|
+
puts "๐ Available Folders:"
|
842
|
+
folders.folders.each do |folder|
|
843
|
+
puts " โข #{folder.name} (ID: #{folder.id})"
|
844
|
+
puts " Path: #{folder.relativePath}"
|
845
|
+
puts " Child count: #{folder.child_count} | Can save: #{folder.can_save}"
|
846
|
+
puts " Pinned: #{folder.is_pinned} | Virtual: #{folder.is_virtual_folder}"
|
847
|
+
puts " Folder rel: #{folder.folder_rel} | Type: #{folder.folder_type_from_db || 'None'}"
|
848
|
+
puts " Show in upload: #{folder.show_in_upload} | Show in move: #{folder.show_in_move}"
|
849
|
+
puts " Filter: #{folder.filter} | Show permissions: #{folder.show_permission_options}"
|
850
|
+
|
851
|
+
# Show conversation and user IDs if available
|
852
|
+
if folder.conversation_id
|
853
|
+
puts " Conversation ID: #{folder.conversation_id}"
|
854
|
+
end
|
855
|
+
if folder.user_id
|
856
|
+
puts " User ID: #{folder.user_id}"
|
857
|
+
end
|
858
|
+
|
859
|
+
puts ""
|
860
|
+
end
|
861
|
+
```
|
862
|
+
|
863
|
+
#### File and Folder Management
|
864
|
+
```ruby
|
865
|
+
# Get user's folders first
|
866
|
+
folders = client.get_folders
|
867
|
+
|
868
|
+
# Find a folder with content
|
869
|
+
if folders.folders.any?
|
870
|
+
folder = folders.folders.find { |f| f.child_count.to_i > 0 }
|
871
|
+
|
872
|
+
if folder
|
873
|
+
puts "๐ Exploring folder: #{folder.name} (ID: #{folder.id})"
|
874
|
+
|
875
|
+
# Get files and folders inside this folder
|
876
|
+
folder_contents = client.get_folder_files(folder.id, include_folders: "Y")
|
877
|
+
|
878
|
+
puts "๐ Folder Contents:"
|
879
|
+
puts " Folder name: #{folder_contents.name}"
|
880
|
+
puts " Total count: #{folder_contents.total_count}"
|
881
|
+
puts " Role: #{folder_contents.role_name}"
|
882
|
+
puts " Domain suspended: #{folder_contents.is_domain_suspended}"
|
883
|
+
puts " Show in upload: #{folder_contents.show_in_upload}"
|
884
|
+
puts ""
|
885
|
+
|
886
|
+
# Display files and folders
|
887
|
+
puts "๐ Files and Folders:"
|
888
|
+
folder_contents.files.first(10).each do |item|
|
889
|
+
puts " โข #{item.filename} (ID: #{item.id})"
|
890
|
+
puts " Type: #{item.is_folder ? 'Folder' : 'File'}"
|
891
|
+
puts " Size: #{item.size} bytes"
|
892
|
+
puts " Uploader: #{item.uploader_name} (ID: #{item.user_id})"
|
893
|
+
puts " Updated: #{Time.at(item.updated_at.to_i).strftime('%Y-%m-%d %H:%M:%S')}"
|
894
|
+
puts " Visibility: #{item.visibility} | Privacy: #{item.privacy_type}"
|
895
|
+
puts " Pinned: #{item.is_pinned} | Liked: #{item.is_liked}"
|
896
|
+
puts " Can save: #{item.can_save} | Show permissions: #{item.show_permission_options}"
|
897
|
+
|
898
|
+
# Show role permissions
|
899
|
+
if item.role
|
900
|
+
puts " Permissions: Edit: #{item.role.can_edit} | Share: #{item.role.can_share} | Restore: #{item.role.can_restore}"
|
901
|
+
end
|
902
|
+
|
903
|
+
# Show links
|
904
|
+
if item.mLink
|
905
|
+
puts " MLink: #{item.mLink[0..50]}..."
|
906
|
+
end
|
907
|
+
|
908
|
+
puts ""
|
909
|
+
end
|
910
|
+
else
|
911
|
+
puts "No folders with content found"
|
912
|
+
end
|
913
|
+
else
|
914
|
+
puts "No folders found"
|
915
|
+
end
|
916
|
+
```
|
917
|
+
|
918
|
+
#### Task Management
|
919
|
+
```ruby
|
920
|
+
# Get user's tasks with filtering and pagination
|
921
|
+
tasks = client.get_tasks(filter: "Pending_Tasks", page: 1, limit: 5)
|
922
|
+
|
923
|
+
# Access tasks data
|
924
|
+
puts "๐ User Tasks:"
|
925
|
+
puts " Total tasks: #{tasks.tasks.task.length}"
|
926
|
+
puts " Transaction ID: #{tasks.transaction_id || 'None'}"
|
927
|
+
puts ""
|
928
|
+
|
929
|
+
# Display tasks
|
930
|
+
puts "๐ Task List:"
|
931
|
+
tasks.tasks.task.each do |task|
|
932
|
+
puts " โข #{task.task_title} (ID: #{task.id})"
|
933
|
+
puts " Status: #{task.status} | Bucket: #{task.bucket}"
|
934
|
+
puts " Assigned to: #{task.assigned_to_name} (ID: #{task.assigned_to})"
|
935
|
+
puts " Created by: #{task.creator_name} (ID: #{task.creator_id})"
|
936
|
+
puts " Created: #{Time.at(task.created_at.to_i).strftime('%Y-%m-%d %H:%M:%S')}"
|
937
|
+
puts " Assigned: #{Time.at(task.assigned_on.to_i).strftime('%Y-%m-%d %H:%M:%S')}"
|
938
|
+
puts " Due: #{task.due} | Due on: #{task.due_on ? Time.at(task.due_on.to_i).strftime('%Y-%m-%d %H:%M:%S') : 'None'}"
|
939
|
+
puts " Is overdue: #{task.is_overdue} | Can be started: #{task.task_can_be_started}"
|
940
|
+
puts " Milestone: #{task.milestone_name || 'None'} (ID: #{task.milestone_id || 'None'})"
|
941
|
+
puts " Project: #{task.conversation_name} (ID: #{task.project_id})"
|
942
|
+
puts " Visibility: #{task.visibility} | Priority: #{task.personal_priority}"
|
943
|
+
|
944
|
+
# Show reviewers
|
945
|
+
if task.reviewers && task.reviewers.reviewer
|
946
|
+
reviewers = task.reviewers.reviewer
|
947
|
+
puts " Reviewers: #{reviewers.length} reviewers"
|
948
|
+
reviewers.first(3).each do |reviewer|
|
949
|
+
puts " - #{reviewer.user_name} (Status: #{reviewer.status})"
|
950
|
+
end
|
951
|
+
end
|
952
|
+
|
953
|
+
# Show next actions
|
954
|
+
if task.next_actions && task.next_actions.action
|
955
|
+
actions = task.next_actions.action
|
956
|
+
puts " Available actions: #{actions.join(', ')}"
|
957
|
+
end
|
958
|
+
|
959
|
+
# Show links
|
960
|
+
if task.mlink
|
961
|
+
puts " MLink: #{task.mlink[0..50]}..."
|
962
|
+
end
|
963
|
+
|
964
|
+
puts ""
|
965
|
+
end
|
966
|
+
```
|
967
|
+
|
968
|
+
#### Task Details Management
|
969
|
+
```ruby
|
970
|
+
# Get detailed information for a specific task
|
971
|
+
task_details = client.get_task_details("394153")
|
972
|
+
|
973
|
+
# Access task details data
|
974
|
+
puts "๐ Task Details:"
|
975
|
+
puts " Task ID: #{task_details.task.id}"
|
976
|
+
puts " Title: #{task_details.task.task_title}"
|
977
|
+
puts " Status: #{task_details.task.status} | Bucket: #{task_details.task.bucket}"
|
978
|
+
puts " Assigned to: #{task_details.task.assigned_to_name} (ID: #{task_details.task.assigned_to})"
|
979
|
+
puts " Created by: #{task_details.task.creator_name} (ID: #{task_details.task.creator_id})"
|
980
|
+
puts " Created: #{Time.at(task_details.task.created_at.to_i).strftime('%Y-%m-%d %H:%M:%S')}"
|
981
|
+
puts " Assigned: #{Time.at(task_details.task.assigned_on.to_i).strftime('%Y-%m-%d %H:%M:%S')}"
|
982
|
+
puts " Due: #{task_details.task.due} | Due on: #{task_details.task.due_on ? Time.at(task_details.task.due_on.to_i).strftime('%Y-%m-%d %H:%M:%S') : 'None'}"
|
983
|
+
puts " Is overdue: #{task_details.task.is_overdue} | Can be started: #{task_details.task.task_can_be_started}"
|
984
|
+
puts " Milestone: #{task_details.task.milestone_name || 'None'} (ID: #{task_details.task.milestone_id || 'None'})"
|
985
|
+
puts " Project: #{task_details.task.conversation_name} (ID: #{task_details.task.project_id})"
|
986
|
+
puts " Visibility: #{task_details.task.visibility} | Priority: #{task_details.task.personal_priority}"
|
987
|
+
puts " Transaction ID: #{task_details.transaction_id || 'None'}"
|
988
|
+
puts ""
|
989
|
+
|
990
|
+
# Show task timeline
|
991
|
+
if task_details.task.started_on
|
992
|
+
puts "๐
Started: #{Time.at(task_details.task.started_on.to_i).strftime('%Y-%m-%d %H:%M:%S')}"
|
993
|
+
end
|
994
|
+
if task_details.task.finished_on
|
995
|
+
puts "๐
Finished: #{Time.at(task_details.task.finished_on.to_i).strftime('%Y-%m-%d %H:%M:%S')}"
|
996
|
+
end
|
997
|
+
if task_details.task.delivered_on
|
998
|
+
puts "๐
Delivered: #{Time.at(task_details.task.delivered_on.to_i).strftime('%Y-%m-%d %H:%M:%S')}"
|
999
|
+
end
|
1000
|
+
|
1001
|
+
# Show task history
|
1002
|
+
if task_details.task.reopened_on
|
1003
|
+
puts "๐
Reopened: #{Time.at(task_details.task.reopened_on.to_i).strftime('%Y-%m-%d %H:%M:%S')}"
|
1004
|
+
end
|
1005
|
+
if task_details.task.restarted_on
|
1006
|
+
puts "๐
Restarted: #{Time.at(task_details.task.restarted_on.to_i).strftime('%Y-%m-%d %H:%M:%S')}"
|
1007
|
+
end
|
1008
|
+
|
1009
|
+
# Show reviewers
|
1010
|
+
if task_details.task.reviewers && task_details.task.reviewers.reviewer
|
1011
|
+
reviewers = task_details.task.reviewers.reviewer
|
1012
|
+
puts "๐ฅ Reviewers: #{reviewers.length} reviewers"
|
1013
|
+
reviewers.first(5).each do |reviewer|
|
1014
|
+
puts " - #{reviewer.user_name} (Status: #{reviewer.status})"
|
1015
|
+
end
|
1016
|
+
end
|
1017
|
+
|
1018
|
+
# Show next actions
|
1019
|
+
if task_details.task.next_actions && task_details.task.next_actions.action
|
1020
|
+
actions = task_details.task.next_actions.action
|
1021
|
+
puts "โก Available actions: #{actions.join(', ')}"
|
1022
|
+
end
|
1023
|
+
|
1024
|
+
# Show task content
|
1025
|
+
if task_details.task.name
|
1026
|
+
puts "๐ Task content: #{task_details.task.name[0..200]}..."
|
1027
|
+
end
|
1028
|
+
if task_details.task.notes
|
1029
|
+
puts "๐ Notes: #{task_details.task.notes[0..200]}..."
|
1030
|
+
end
|
1031
|
+
|
1032
|
+
# Show links
|
1033
|
+
if task_details.task.mlink
|
1034
|
+
puts "๐ MLink: #{task_details.task.mlink}"
|
1035
|
+
end
|
1036
|
+
|
1037
|
+
# Show attachments
|
1038
|
+
if task_details.task.attachments
|
1039
|
+
puts "๐ Attachments: #{task_details.task.attachments.length} attachments"
|
1040
|
+
end
|
1041
|
+
if task_details.task.attachment_references
|
1042
|
+
puts "๐ Attachment references: #{task_details.task.attachment_references.length} references"
|
1043
|
+
end
|
1044
|
+
```
|
1045
|
+
|
1046
|
+
#### Wiki Management
|
1047
|
+
```ruby
|
1048
|
+
# Get user's wikis with filtering and pagination
|
1049
|
+
wikis = client.get_wikis(mode: "my", limit: 20, offset: 0)
|
1050
|
+
|
1051
|
+
# Access wikis data
|
1052
|
+
puts "๐ User Wikis:"
|
1053
|
+
puts " Total wikis: #{wikis.wikis.length}"
|
1054
|
+
puts " Transaction ID: #{wikis.transaction_id || 'None'}"
|
1055
|
+
puts ""
|
1056
|
+
|
1057
|
+
# Display wikis
|
1058
|
+
puts "๐ Wiki List:"
|
1059
|
+
wikis.wikis.each do |wiki|
|
1060
|
+
puts " โข #{wiki.title} (ID: #{wiki.id})"
|
1061
|
+
puts " Updated: #{Time.at(wiki.updated_at.to_i).strftime('%Y-%m-%d %H:%M:%S')}"
|
1062
|
+
puts " Children: #{wiki.children_count} | Can edit: #{wiki.can_edit}"
|
1063
|
+
puts " Conversation: #{wiki.conversation_name || 'None'} (ID: #{wiki.conversation_id})"
|
1064
|
+
puts " Is draft: #{wiki.is_draft} | PDF access: #{wiki.generate_pdf_access}"
|
1065
|
+
puts " User: #{wiki.user_name || 'None'} | Status: #{wiki.status || 'None'}"
|
1066
|
+
puts " Governance enabled: #{wiki.governance_enabled} | Governance date: #{wiki.governance_date || 'None'}"
|
1067
|
+
|
1068
|
+
# Show icon properties
|
1069
|
+
if wiki.icon_properties
|
1070
|
+
background_color = wiki.icon_properties.respond_to?(:'background-color') ? wiki.icon_properties.send(:'background-color') : nil
|
1071
|
+
puts " Icon: #{wiki.icon_properties.class} | Color: #{background_color || 'None'}"
|
1072
|
+
end
|
1073
|
+
|
1074
|
+
# Show user image URL
|
1075
|
+
if wiki.user_image_url
|
1076
|
+
puts " User image: #{wiki.user_image_url[0..50]}..."
|
1077
|
+
end
|
1078
|
+
|
1079
|
+
puts ""
|
1080
|
+
end
|
1081
|
+
```
|
1082
|
+
|
1083
|
+
#### Wiki Details Management
|
1084
|
+
```ruby
|
1085
|
+
# Get detailed information for a specific wiki
|
1086
|
+
wiki_details = client.get_wiki_details("7212")
|
1087
|
+
|
1088
|
+
# Access wiki details data
|
1089
|
+
puts "๐ Wiki Details:"
|
1090
|
+
puts " Wiki ID: #{wiki_details.wiki.details.id}"
|
1091
|
+
puts " Title: #{wiki_details.wiki.details.title}"
|
1092
|
+
puts " Status: #{wiki_details.wiki.details.status} | Platform: #{wiki_details.wiki.details.platform}"
|
1093
|
+
puts " Created: #{Time.at(wiki_details.wiki.details.created_at.to_i).strftime('%Y-%m-%d %H:%M:%S')}"
|
1094
|
+
puts " Updated: #{Time.at(wiki_details.wiki.details.updated_at.to_i).strftime('%Y-%m-%d %H:%M:%S')}"
|
1095
|
+
puts " Modified: #{wiki_details.wiki.details.modified_on}"
|
1096
|
+
puts " Created by: #{wiki_details.wiki.details.created_by_name} (ID: #{wiki_details.wiki.details.user_id})"
|
1097
|
+
puts " Updated by: #{wiki_details.wiki.details.updated_by_name} (ID: #{wiki_details.wiki.details.last_updated_by})"
|
1098
|
+
puts " Conversation: #{wiki_details.wiki.details.conversation_name} (ID: #{wiki_details.wiki.details.conversation_id})"
|
1099
|
+
puts " Read count: #{wiki_details.wiki.details.total_read_count} | Children: #{wiki_details.wiki.details.children_count}"
|
1100
|
+
puts " Edit permissions: #{wiki_details.wiki.details.edit_permissions} | Commentable: #{wiki_details.wiki.details.is_commentable}"
|
1101
|
+
puts " Generate PDF access: #{wiki_details.wiki.details.generate_pdf_access} | Show TOC: #{wiki_details.wiki.details.show_toc}"
|
1102
|
+
puts " Has TOC: #{wiki_details.wiki.details.has_toc} | Archived: #{wiki_details.wiki.details.archived}"
|
1103
|
+
puts " Domain ID: #{wiki_details.wiki.details.domain_id} | Feed ID: #{wiki_details.wiki.details.feed_id}"
|
1104
|
+
puts ""
|
1105
|
+
|
1106
|
+
# Show wiki content
|
1107
|
+
if wiki_details.wiki.details.description
|
1108
|
+
puts "๐ Description: #{wiki_details.wiki.details.description[0..300]}..."
|
1109
|
+
end
|
1110
|
+
|
1111
|
+
# Show banner URL
|
1112
|
+
if wiki_details.wiki.details.banner_url
|
1113
|
+
puts "๐ผ๏ธ Banner URL: #{wiki_details.wiki.details.banner_url}"
|
1114
|
+
end
|
1115
|
+
|
1116
|
+
# Show wiki permissions
|
1117
|
+
puts "๐ Wiki Permissions:"
|
1118
|
+
puts " Can comment: #{wiki_details.wiki.can_comment}"
|
1119
|
+
puts " Can edit: #{wiki_details.wiki.can_edit}"
|
1120
|
+
puts " Can delete: #{wiki_details.wiki.can_delete}"
|
1121
|
+
puts " Can rename: #{wiki_details.wiki.can_rename}"
|
1122
|
+
puts " Can move: #{wiki_details.wiki.can_move}"
|
1123
|
+
puts " Can duplicate: #{wiki_details.wiki.can_duplicate}"
|
1124
|
+
|
1125
|
+
# Show wiki links
|
1126
|
+
if wiki_details.wiki.mlink
|
1127
|
+
puts "๐ MLink: #{wiki_details.wiki.mlink}"
|
1128
|
+
end
|
1129
|
+
|
1130
|
+
# Show attachments
|
1131
|
+
if wiki_details.wiki.attachments
|
1132
|
+
puts "๐ Attachments: #{wiki_details.wiki.attachments.length} attachments"
|
1133
|
+
end
|
1134
|
+
if wiki_details.wiki.attachment_references
|
1135
|
+
puts "๐ Attachment references: #{wiki_details.wiki.attachment_references.length} references"
|
1136
|
+
end
|
1137
|
+
|
1138
|
+
# Show reactions
|
1139
|
+
if wiki_details.wiki.reactions
|
1140
|
+
reactions = wiki_details.wiki.reactions
|
1141
|
+
puts "๐ Reactions: Like: #{reactions.like_count}, Superlike: #{reactions.superlike_count}"
|
1142
|
+
puts "๐ Reactions: Haha: #{reactions.haha_count}, Yay: #{reactions.yay_count}, Wow: #{reactions.wow_count}, Sad: #{reactions.sad_count}"
|
1143
|
+
puts "๐ค User reactions: Liked: #{reactions.liked}, Superliked: #{reactions.superliked}"
|
1144
|
+
end
|
1145
|
+
|
1146
|
+
# Show reaction data
|
1147
|
+
if wiki_details.wiki.reaction_data
|
1148
|
+
reaction_data = wiki_details.wiki.reaction_data
|
1149
|
+
puts "๐ Reaction data: #{reaction_data.length} reaction types"
|
1150
|
+
reaction_data.each do |reaction|
|
1151
|
+
puts " - #{reaction.label}: #{reaction.count} (Reacted: #{reaction.reacted})"
|
1152
|
+
end
|
1153
|
+
end
|
1154
|
+
|
1155
|
+
# Show comment count
|
1156
|
+
puts "๐ฌ Comment count: #{wiki_details.wiki.comment_count}"
|
1157
|
+
|
1158
|
+
# Show wiki status
|
1159
|
+
puts "๐ Is pinned: #{wiki_details.wiki.is_pinned}"
|
1160
|
+
puts "๐ Is draft: #{wiki_details.wiki.is_draft}"
|
1161
|
+
puts "๐ Governance enabled: #{wiki_details.wiki.governance_enabled}"
|
1162
|
+
|
1163
|
+
# Show hashtags
|
1164
|
+
if wiki_details.wiki.hashtags
|
1165
|
+
hashtags = wiki_details.wiki.hashtags
|
1166
|
+
puts "๐ท๏ธ Hashtags: #{hashtags.length} hashtags"
|
1167
|
+
hashtags.each do |hashtag|
|
1168
|
+
puts " - #{hashtag}"
|
1169
|
+
end
|
1170
|
+
end
|
1171
|
+
```
|
1172
|
+
|
1173
|
+
#### Award Feeds Management
|
1174
|
+
```ruby
|
1175
|
+
# Get award feeds with comprehensive recognition data
|
1176
|
+
award_feeds = client.get_award_feeds
|
1177
|
+
|
1178
|
+
# Access award feeds data
|
1179
|
+
puts "๐ Award Feeds:"
|
1180
|
+
puts " Transaction ID: #{award_feeds.transaction_id || 'None'}"
|
1181
|
+
puts " Limit: #{award_feeds.limit || 'None'}"
|
1182
|
+
puts " Current priority: #{award_feeds.current_priority || 'None'}"
|
1183
|
+
puts " Enable mobile pin: #{award_feeds.enable_mobile_pin}"
|
1184
|
+
puts " MangoApps version: #{award_feeds.mangoapps_version}"
|
1185
|
+
puts " Comments order: #{award_feeds.comments_order}"
|
1186
|
+
puts " Private message reply order: #{award_feeds.private_message_reply_order || 'None'}"
|
1187
|
+
puts " Photo shape: #{award_feeds.photo_shape || 'None'}"
|
1188
|
+
puts " Moderation feed IDs: #{award_feeds.moderation_feed_ids || 'None'}"
|
1189
|
+
puts " Moderation HTML: #{award_feeds.moderation_html || 'None'}"
|
1190
|
+
puts ""
|
1191
|
+
|
1192
|
+
# Show unread counts
|
1193
|
+
if award_feeds.unread_counts
|
1194
|
+
unread_counts = award_feeds.unread_counts
|
1195
|
+
puts "๐ Unread Counts:"
|
1196
|
+
puts " Direct messages: #{unread_counts.direct_messages_count}"
|
1197
|
+
puts " What's new: #{unread_counts.whats_new_count}"
|
1198
|
+
puts " Unread feeds: #{unread_counts.unread_feeds_count}"
|
1199
|
+
puts " Mentions: #{unread_counts.mention_count}"
|
1200
|
+
puts " Primary unread: #{unread_counts.primary_unread_count}"
|
1201
|
+
puts " Secondary unread: #{unread_counts.secondary_unread_count}"
|
1202
|
+
puts " Unread notifications: #{unread_counts.unread_notification_count}"
|
1203
|
+
puts ""
|
1204
|
+
end
|
1205
|
+
|
1206
|
+
# Display award feeds
|
1207
|
+
puts "๐ Award Feed List:"
|
1208
|
+
award_feeds.feeds.each do |feed|
|
1209
|
+
puts " โข Feed ID: #{feed.id} | Type: #{feed.feed_type}"
|
1210
|
+
puts " Category: #{feed.category} | Sub-category: #{feed.sub_category}"
|
1211
|
+
puts " Recognition points: #{feed.recognition_points}"
|
1212
|
+
puts " From: #{feed.from_user.name if feed.from_user} | To: #{feed.to_users.length if feed.to_users} users"
|
1213
|
+
puts " Reactions: Like: #{feed.like_count}, Superlike: #{feed.superlike_count}"
|
1214
|
+
puts " Comments: #{feed.comment_count} | Attachments: #{feed.attachment_count}"
|
1215
|
+
puts " Created: #{Time.at(feed.created_at.to_i).strftime('%Y-%m-%d %H:%M:%S')}"
|
1216
|
+
puts " Updated: #{Time.at(feed.updated_at.to_i).strftime('%Y-%m-%d %H:%M:%S')}"
|
1217
|
+
|
1218
|
+
# Show award details
|
1219
|
+
if feed.feed_property
|
1220
|
+
puts " Award: #{feed.feed_property.title}"
|
1221
|
+
puts " Labels: #{feed.feed_property.label_1}, #{feed.feed_property.label_2}"
|
1222
|
+
puts " Image URL: #{feed.feed_property.image_url[0..50]}..." if feed.feed_property.image_url
|
1223
|
+
puts " Status: #{feed.feed_property.status} | Result format: #{feed.feed_property.result_format}"
|
1224
|
+
end
|
1225
|
+
|
1226
|
+
# Show from user
|
1227
|
+
if feed.from_user
|
1228
|
+
puts " From user: #{feed.from_user.name} (ID: #{feed.from_user.id})"
|
1229
|
+
puts " Email: #{feed.from_user.email}"
|
1230
|
+
puts " Photo: #{feed.from_user.photo[0..50]}..." if feed.from_user.photo
|
1231
|
+
end
|
1232
|
+
|
1233
|
+
# Show to users
|
1234
|
+
if feed.to_users
|
1235
|
+
puts " To users: #{feed.to_users.length} users"
|
1236
|
+
feed.to_users.each do |user|
|
1237
|
+
puts " - #{user.name} (ID: #{user.id})"
|
1238
|
+
end
|
1239
|
+
end
|
1240
|
+
|
1241
|
+
# Show feed story users
|
1242
|
+
if feed.feed_story_users
|
1243
|
+
puts " Story users: #{feed.feed_story_users.length} users"
|
1244
|
+
feed.feed_story_users.each do |user|
|
1245
|
+
puts " - #{user.name} (ID: #{user.id})"
|
1246
|
+
end
|
1247
|
+
end
|
1248
|
+
|
1249
|
+
# Show core value tags
|
1250
|
+
if feed.core_value_tags
|
1251
|
+
puts " Core value tags: #{feed.core_value_tags.length} tags"
|
1252
|
+
feed.core_value_tags.each do |tag|
|
1253
|
+
puts " - #{tag.name} (ID: #{tag.id}, Color: #{tag.color})"
|
1254
|
+
end
|
1255
|
+
end
|
1256
|
+
|
1257
|
+
# Show reaction data
|
1258
|
+
if feed.reaction_data
|
1259
|
+
puts " Reaction data: #{feed.reaction_data.length} reaction types"
|
1260
|
+
feed.reaction_data.each do |reaction|
|
1261
|
+
puts " - #{reaction.label}: #{reaction.count} (Reacted: #{reaction.reacted})"
|
1262
|
+
end
|
1263
|
+
end
|
1264
|
+
|
1265
|
+
# Show comments
|
1266
|
+
if feed.comments
|
1267
|
+
puts " Comments: #{feed.comments.length} comments"
|
1268
|
+
feed.comments.first(3).each do |comment|
|
1269
|
+
puts " - #{comment.body[0..50]}... by #{comment.user.name if comment.user}"
|
1270
|
+
end
|
1271
|
+
end
|
1272
|
+
|
1273
|
+
puts ""
|
1274
|
+
end
|
1275
|
+
```
|
1276
|
+
|
1277
|
+
## Available Modules
|
1278
|
+
|
1279
|
+
### โ
Currently Implemented
|
1280
|
+
|
1281
|
+
#### Users Module
|
1282
|
+
- **User Profile**: `client.me` - Get current user information with clean dot notation access
|
1283
|
+
|
1284
|
+
#### Learn Module
|
1285
|
+
- **Course Catalog**: `client.course_catalog` - Get available courses
|
1286
|
+
- **Course Categories**: `client.course_categories` - Get course categories
|
1287
|
+
- **Course Details**: `client.course_details(course_id)` - Get detailed course information by ID
|
1288
|
+
- **My Learning**: `client.my_learning` - Get user's learning progress and courses
|
1289
|
+
|
1290
|
+
#### Recognitions Module
|
1291
|
+
- **Award Categories**: `client.award_categories` - Get recognition award categories
|
1292
|
+
- **Get Awards List**: `client.get_awards_list(category_id: id)` - Get awards for a specific category
|
1293
|
+
- **Get Profile Awards**: `client.get_profile_awards` - Get user's personal awards and activity
|
1294
|
+
- **Get Team Awards**: `client.get_team_awards(project_id: id)` - Get team awards and activity
|
1295
|
+
- **Get Award Feeds**: `client.get_award_feeds` - Get award feeds with comprehensive recognition data
|
1296
|
+
- **Core Value Tags**: `client.core_value_tags` - Get core value tags for recognition
|
1297
|
+
- **Leaderboard Info**: `client.leaderboard_info` - Get user and team leaderboard information
|
1298
|
+
- **Gift Cards**: `client.gift_cards` - Get available gift cards for recognition rewards
|
1299
|
+
|
1300
|
+
#### Notifications Module
|
1301
|
+
- **My Priority Items**: `client.my_priority_items` - Get user's priority items including requests, events, quizzes, surveys, tasks, and todos
|
1302
|
+
- **Notifications**: `client.notifications` - Get user's notifications with unread counts and detailed notification information
|
1303
|
+
|
1304
|
+
#### Feeds Module
|
1305
|
+
- **Feeds**: `client.feeds` - Get user's activity feeds with unread counts and feed details
|
1306
|
+
|
1307
|
+
#### Posts Module
|
1308
|
+
- **Get All Posts**: `client.get_all_posts(filter_by: "all")` - Get all posts with filtering options
|
1309
|
+
- **Get Post By ID**: `client.get_post_by_id(post_id, full_description: "Y")` - Get detailed post information by ID
|
1310
|
+
|
1311
|
+
#### Libraries Module
|
1312
|
+
- **Get Libraries**: `client.get_libraries` - Get user's document libraries with categories and items
|
1313
|
+
- **Get Library Categories**: `client.get_library_categories(library_id)` - Get detailed library information and categories by library ID
|
1314
|
+
- **Get Library Items**: `client.get_library_items(library_id, category_id)` - Get library items by library ID and category ID
|
1315
|
+
|
1316
|
+
#### Trackers Module
|
1317
|
+
- **Get Trackers**: `client.get_trackers` - Get user's trackers with submission dates and conversation details
|
1318
|
+
|
1319
|
+
#### Attachments Module
|
1320
|
+
- **Get Folders**: `client.get_folders` - Get user's file folders with permissions and metadata
|
1321
|
+
- **Get Folder Files**: `client.get_folder_files(folder_id, include_folders: "Y")` - Get files and folders inside a specific folder
|
1322
|
+
|
1323
|
+
#### Tasks Module
|
1324
|
+
- **Get Tasks**: `client.get_tasks(filter: "Pending_Tasks", page: 1, limit: 5)` - Get user's tasks with filtering, pagination, and detailed task information
|
1325
|
+
- **Get Task Details**: `client.get_task_details(task_id)` - Get detailed information for a specific task by ID
|
1326
|
+
|
1327
|
+
#### Wikis Module
|
1328
|
+
- **Get Wikis**: `client.get_wikis(mode: "my", limit: 20, offset: 0)` - Get user's wikis with filtering, pagination, and detailed wiki information
|
1329
|
+
- **Get Wiki Details**: `client.get_wiki_details(wiki_id)` - Get detailed information for a specific wiki by ID
|
1330
|
+
|
1331
|
+
## Complete Examples
|
1332
|
+
|
1333
|
+
### Notifications Management
|
1334
|
+
```ruby
|
1335
|
+
require 'mangoapps-ex-sdk-ruby'
|
1336
|
+
|
1337
|
+
# Initialize client
|
1338
|
+
client = MangoApps::Client.new
|
1339
|
+
|
1340
|
+
# Get user's priority items
|
1341
|
+
priority_items = client.my_priority_items
|
1342
|
+
|
1343
|
+
# Display all priority items with details
|
1344
|
+
puts "๐ User Priority Items Dashboard"
|
1345
|
+
puts "================================"
|
1346
|
+
puts "Success: #{priority_items.success}"
|
1347
|
+
puts "Display Type: #{priority_items.display_type}"
|
1348
|
+
puts ""
|
1349
|
+
|
1350
|
+
priority_items.data.each do |item|
|
1351
|
+
puts "๐ #{item.title} (ID: #{item.id})"
|
1352
|
+
puts " Count: #{item.count} pending items"
|
1353
|
+
puts " Action Type: #{item.action_type}"
|
1354
|
+
puts " Icon: #{item.icon} (#{item.icon_color})"
|
1355
|
+
puts " Background: #{item.icon_bg_color}"
|
1356
|
+
puts " Description: #{item.info_details.gsub(/<[^>]*>/, '').strip[0..100]}..."
|
1357
|
+
puts ""
|
1358
|
+
end
|
1359
|
+
|
1360
|
+
# Get user's notifications
|
1361
|
+
notifications = client.notifications
|
1362
|
+
|
1363
|
+
# Display notifications dashboard
|
1364
|
+
puts "๐ User Notifications Dashboard"
|
1365
|
+
puts "==============================="
|
1366
|
+
puts "What's new: #{notifications.whats_new_count}"
|
1367
|
+
puts "Unread feeds: #{notifications.unread_feeds_count}"
|
1368
|
+
puts "Mentions: #{notifications.mention_count}"
|
1369
|
+
puts "Direct messages: #{notifications.direct_messages_count}"
|
1370
|
+
puts "Unread notifications: #{notifications.unread_notification_count}"
|
1371
|
+
puts ""
|
1372
|
+
|
1373
|
+
notifications.notifications.first(5).each do |notification|
|
1374
|
+
puts "๐ข #{notification.sender_name} (ID: #{notification.id})"
|
1375
|
+
puts " Text: #{notification.text[0..100]}..."
|
1376
|
+
puts " Type: #{notification.notification_type || 'None'}"
|
1377
|
+
puts " Read: #{notification.is_read} | Updated: #{Time.at(notification.updated_at.to_i).strftime('%Y-%m-%d %H:%M:%S')}"
|
1378
|
+
puts " MLink: #{notification.mlink || 'None'}"
|
1379
|
+
if notification.mention_tags && notification.mention_tags.any?
|
1380
|
+
puts " Mentions: #{notification.mention_tags.map { |tag| tag.mention }.join(', ')}"
|
1381
|
+
end
|
1382
|
+
puts ""
|
1383
|
+
end
|
1384
|
+
|
1385
|
+
# Filter by specific action types
|
1386
|
+
approval_items = priority_items.data.select { |item| item.action_type == 'approval' }
|
1387
|
+
puts "๐ Approval Items: #{approval_items.length}"
|
1388
|
+
approval_items.each do |item|
|
1389
|
+
puts " โข #{item.title}: #{item.count} items"
|
1390
|
+
end
|
1391
|
+
|
1392
|
+
# Get high-priority items (count > 5)
|
1393
|
+
high_priority = priority_items.data.select { |item| item.count > 5 }
|
1394
|
+
puts "โ ๏ธ High Priority Items: #{high_priority.length}"
|
1395
|
+
high_priority.each do |item|
|
1396
|
+
puts " โข #{item.title}: #{item.count} items"
|
1397
|
+
end
|
1398
|
+
```
|
1399
|
+
|
1400
|
+
### User Profile Management
|
1401
|
+
```ruby
|
1402
|
+
# Get current user profile
|
1403
|
+
user = client.me
|
1404
|
+
|
1405
|
+
# Access user information with clean dot notation
|
1406
|
+
puts "Name: #{user.user_profile.minimal_profile.name}"
|
1407
|
+
puts "Email: #{user.user_profile.minimal_profile.email}"
|
1408
|
+
puts "User Type: #{user.user_profile.minimal_profile.user_type}"
|
1409
|
+
|
1410
|
+
# Access user statistics
|
1411
|
+
puts "Followers: #{user.user_profile.user_data.followers}"
|
1412
|
+
puts "Following: #{user.user_profile.user_data.following}"
|
1413
|
+
|
1414
|
+
# Access gamification data
|
1415
|
+
puts "Current Level: #{user.user_profile.gamification.current_level}"
|
1416
|
+
puts "Total Points: #{user.user_profile.gamification.total_points}"
|
1417
|
+
puts "Badges: #{user.user_profile.gamification.badges.length}"
|
1418
|
+
|
1419
|
+
# Access recognition data
|
1420
|
+
puts "Reward Points Received: #{user.user_profile.recognition.total_reward_points_received}"
|
1421
|
+
```
|
1422
|
+
|
1423
|
+
### Learning Management
|
1424
|
+
```ruby
|
1425
|
+
# Get course catalog
|
1426
|
+
courses = client.course_catalog
|
1427
|
+
|
1428
|
+
# Browse available courses
|
1429
|
+
courses.courses.each do |course|
|
1430
|
+
puts "๐ #{course.name}"
|
1431
|
+
puts " Type: #{course.course_type}"
|
1432
|
+
puts " Delivery: #{course.delivery_mode}"
|
1433
|
+
puts " URL: #{course.start_course_url}"
|
1434
|
+
puts ""
|
1435
|
+
|
1436
|
+
# Get detailed course information
|
1437
|
+
course_details = client.course_details(course.id)
|
1438
|
+
detailed_course = course_details.course
|
1439
|
+
puts " ๐ Detailed Info:"
|
1440
|
+
puts " Description: #{detailed_course.description}"
|
1441
|
+
puts " Instructors: #{detailed_course.instructors.length}"
|
1442
|
+
puts " Fields: #{detailed_course.fields.length}"
|
1443
|
+
puts ""
|
1444
|
+
end
|
1445
|
+
|
1446
|
+
# Get course categories
|
1447
|
+
categories = client.course_categories
|
1448
|
+
|
1449
|
+
# Browse course categories
|
1450
|
+
categories.all_categories.each do |category|
|
1451
|
+
puts "๐ #{category.name}"
|
1452
|
+
puts " Position: #{category.position}"
|
1453
|
+
puts " Icon: #{category.icon_properties}"
|
1454
|
+
puts ""
|
1455
|
+
end
|
1456
|
+
|
1457
|
+
# Get user's learning progress
|
1458
|
+
learning = client.my_learning
|
1459
|
+
|
1460
|
+
# Display learning summary
|
1461
|
+
puts "๐ Learning Summary for #{learning.user_name}"
|
1462
|
+
puts "โฑ๏ธ Total training time: #{learning.total_training_time}"
|
1463
|
+
puts "๐ Ongoing: #{learning.ongoing_course_count} | โ
Completed: #{learning.completed_course_count} | ๐ Registered: #{learning.registered_course_count}"
|
1464
|
+
puts ""
|
1465
|
+
|
1466
|
+
# Browse learning sections
|
1467
|
+
learning.section.each do |section|
|
1468
|
+
puts "๐ #{section.label} (#{section.count} courses)"
|
1469
|
+
|
1470
|
+
section.courses.each do |course|
|
1471
|
+
puts " ๐ #{course.name}"
|
1472
|
+
puts " Progress: #{course.course_progress}%"
|
1473
|
+
puts " Type: #{course.course_type}"
|
1474
|
+
puts " URL: #{course.start_course_url}"
|
1475
|
+
puts ""
|
1476
|
+
end
|
1477
|
+
end
|
1478
|
+
```
|
1479
|
+
|
1480
|
+
### Recognition Management
|
1481
|
+
```ruby
|
1482
|
+
# Get award categories
|
1483
|
+
categories = client.award_categories
|
1484
|
+
|
1485
|
+
# Display available award categories
|
1486
|
+
puts "๐ Available Award Categories:"
|
1487
|
+
categories.award_categories.each do |category|
|
1488
|
+
puts " โข #{category.name} (ID: #{category.id})"
|
1489
|
+
puts " Permission: #{category.recipient_permission}"
|
1490
|
+
end
|
1491
|
+
puts ""
|
1492
|
+
|
1493
|
+
# Get awards for a specific category
|
1494
|
+
category_id = 4303 # Safety & Quality category
|
1495
|
+
awards = client.get_awards_list(category_id: category_id)
|
1496
|
+
|
1497
|
+
# Display awards in the category
|
1498
|
+
puts "๐ Awards in Category #{category_id}:"
|
1499
|
+
awards.get_awards_list.each do |award|
|
1500
|
+
puts " โข #{award.name} (ID: #{award.id})"
|
1501
|
+
puts " Points: #{award.points} | Reward Points: #{award.reward_points || 'None'}"
|
1502
|
+
puts " Description: #{award.description}"
|
1503
|
+
end
|
1504
|
+
puts ""
|
1505
|
+
|
1506
|
+
# Get user profile awards
|
1507
|
+
profile_awards = client.get_profile_awards
|
1508
|
+
|
1509
|
+
# Display user's personal awards
|
1510
|
+
puts "๐ User Profile Awards:"
|
1511
|
+
puts " Core Value Tags:"
|
1512
|
+
profile_awards.core_value_tags.each do |tag|
|
1513
|
+
puts " โข #{tag.name} (ID: #{tag.id}) - Count: #{tag.count}"
|
1514
|
+
end
|
1515
|
+
puts " Recent Awards:"
|
1516
|
+
profile_awards.feeds.each do |feed|
|
1517
|
+
puts " โข #{feed.feed_property.title} - Points: #{feed.recognition_points}"
|
1518
|
+
puts " From: #{feed.from_user.name}"
|
1519
|
+
end
|
1520
|
+
puts ""
|
1521
|
+
|
1522
|
+
# Get team awards
|
1523
|
+
team_id = 117747 # All Users team
|
1524
|
+
team_awards = client.get_team_awards(project_id: team_id)
|
1525
|
+
|
1526
|
+
# Display team awards
|
1527
|
+
puts "๐ Team Awards (Team ID: #{team_id}):"
|
1528
|
+
puts " Team Core Value Tags:"
|
1529
|
+
team_awards.core_value_tags.each do |tag|
|
1530
|
+
puts " โข #{tag.name} (ID: #{tag.id}) - Count: #{tag.count}"
|
1531
|
+
end
|
1532
|
+
puts " Team Recent Awards:"
|
1533
|
+
team_awards.feeds.each do |feed|
|
1534
|
+
puts " โข #{feed.feed_property.title} - Points: #{feed.recognition_points}"
|
1535
|
+
puts " From: #{feed.from_user.name} | Team: #{feed.group_name}"
|
1536
|
+
end
|
1537
|
+
puts ""
|
1538
|
+
|
1539
|
+
# Get user priority items
|
1540
|
+
priority_items = client.my_priority_items
|
1541
|
+
|
1542
|
+
# Display priority items
|
1543
|
+
puts "๐ User Priority Items:"
|
1544
|
+
priority_items.data.each do |item|
|
1545
|
+
puts " โข #{item.title} (ID: #{item.id}) - Count: #{item.count}"
|
1546
|
+
puts " Action Type: #{item.action_type} | Icon: #{item.icon}"
|
1547
|
+
end
|
1548
|
+
puts ""
|
1549
|
+
|
1550
|
+
# Get user activity feeds
|
1551
|
+
feeds = client.feeds
|
1552
|
+
|
1553
|
+
# Display feeds
|
1554
|
+
puts "๐ฐ User Activity Feeds:"
|
1555
|
+
puts " Total feeds: #{feeds.feeds.length}"
|
1556
|
+
puts " Unread feeds: #{feeds.unread_counts.unread_feeds_count}"
|
1557
|
+
puts " Direct messages: #{feeds.unread_counts.direct_messages_count}"
|
1558
|
+
puts " What's new: #{feeds.unread_counts.whats_new_count}"
|
1559
|
+
puts ""
|
1560
|
+
|
1561
|
+
# Display recent feeds
|
1562
|
+
puts "๐ฐ Recent Feeds:"
|
1563
|
+
feeds.feeds.first(3).each do |feed|
|
1564
|
+
puts " โข #{feed.feed_property.title} (ID: #{feed.id})"
|
1565
|
+
puts " From: #{feed.from_user.name} | Group: #{feed.group_name}"
|
1566
|
+
puts " Type: #{feed.feed_type} | Unread: #{feed.unread}"
|
1567
|
+
end
|
1568
|
+
puts ""
|
1569
|
+
|
1570
|
+
# Get all posts
|
1571
|
+
posts = client.get_all_posts(filter_by: "all")
|
1572
|
+
|
1573
|
+
# Display posts
|
1574
|
+
puts "๐ All Posts:"
|
1575
|
+
puts " Total posts: #{posts.feeds.length}"
|
1576
|
+
puts " Post view count visibility: #{posts.post_view_count_visibility}"
|
1577
|
+
puts ""
|
1578
|
+
|
1579
|
+
# Display recent posts
|
1580
|
+
puts "๐ Recent Posts:"
|
1581
|
+
posts.feeds.first(3).each do |post|
|
1582
|
+
puts " โข #{post.tile.tile_name} (ID: #{post.id})"
|
1583
|
+
puts " From: #{post.from_user.name} | Group: #{post.group_name}"
|
1584
|
+
puts " Views: #{post.total_view_count} | Comments: #{post.comments.length}"
|
1585
|
+
end
|
1586
|
+
puts ""
|
1587
|
+
|
1588
|
+
# Get detailed post information
|
1589
|
+
if posts.feeds.any?
|
1590
|
+
first_post_id = posts.feeds.first.post_id
|
1591
|
+
post_details = client.get_post_by_id(first_post_id, full_description: "Y")
|
1592
|
+
|
1593
|
+
puts "๐ Post Details (ID: #{first_post_id}):"
|
1594
|
+
puts " Title: #{post_details.post.title}"
|
1595
|
+
puts " Created by: #{post_details.post.created_name}"
|
1596
|
+
puts " View count: #{post_details.post.total_view_count}"
|
1597
|
+
puts " Can edit: #{post_details.post.can_edit} | Can comment: #{post_details.post.can_comment}"
|
1598
|
+
puts " Full description available: #{post_details.post.tile.tile_full_description.length > 0 ? 'Yes' : 'No'}"
|
1599
|
+
end
|
1600
|
+
puts ""
|
1601
|
+
|
1602
|
+
# Get user libraries
|
1603
|
+
libraries = client.get_libraries
|
1604
|
+
|
1605
|
+
puts "๐ User Libraries:"
|
1606
|
+
puts " Total libraries: #{libraries.libraries.length}"
|
1607
|
+
puts ""
|
1608
|
+
|
1609
|
+
# Display recent libraries
|
1610
|
+
puts "๐ Recent Libraries:"
|
1611
|
+
libraries.libraries.first(3).each do |library|
|
1612
|
+
puts " โข #{library.name} (ID: #{library.id})"
|
1613
|
+
puts " Type: #{library.library_type} | Items: #{library.total_items_count}"
|
1614
|
+
puts " Categories: #{library.categories.length} | Edit access: #{library.edit_access}"
|
1615
|
+
end
|
1616
|
+
puts ""
|
1617
|
+
|
1618
|
+
# Get detailed library information
|
1619
|
+
if libraries.libraries.any?
|
1620
|
+
first_library_id = libraries.libraries.first.id
|
1621
|
+
library_details = client.get_library_categories(first_library_id)
|
1622
|
+
|
1623
|
+
puts "๐ Library Details (ID: #{first_library_id}):"
|
1624
|
+
puts " Name: #{library_details.library.name}"
|
1625
|
+
puts " Type: #{library_details.library.library_type} | View: #{library_details.library.view_mode}"
|
1626
|
+
puts " Total items: #{library_details.library.total_items_count}"
|
1627
|
+
puts " Categories: #{library_details.library.categories.length}"
|
1628
|
+
puts " Edit access: #{library_details.library.edit_access}"
|
1629
|
+
|
1630
|
+
# Get library items from first category
|
1631
|
+
if library_details.library.categories.any?
|
1632
|
+
first_category_id = library_details.library.categories.first.id
|
1633
|
+
library_items = client.get_library_items(first_library_id, first_category_id)
|
1634
|
+
|
1635
|
+
puts "๐ Library Items (Category: #{library_items.category_name}):"
|
1636
|
+
puts " View mode: #{library_items.view_mode} | Library type: #{library_items.library_type}"
|
1637
|
+
puts " Items count: #{library_items.library_items.length}"
|
1638
|
+
puts " Can add: #{library_items.can_add}"
|
1639
|
+
end
|
1640
|
+
end
|
1641
|
+
puts ""
|
1642
|
+
|
1643
|
+
# Get user trackers
|
1644
|
+
trackers = client.get_trackers
|
1645
|
+
|
1646
|
+
puts "๐ User Trackers:"
|
1647
|
+
puts " Total trackers: #{trackers.trackers.length}"
|
1648
|
+
puts ""
|
1649
|
+
|
1650
|
+
# Display recent trackers
|
1651
|
+
puts "๐ Recent Trackers:"
|
1652
|
+
trackers.trackers.first(3).each do |tracker|
|
1653
|
+
puts " โข #{tracker.name} (ID: #{tracker.id})"
|
1654
|
+
puts " Last submission: #{Time.at(tracker.last_submission_date.to_i).strftime('%Y-%m-%d %H:%M:%S')}"
|
1655
|
+
puts " Conversation: #{tracker.conversation_name}"
|
1656
|
+
puts " Pinned: #{tracker.is_pinned} | Can share: #{tracker.can_share}"
|
1657
|
+
end
|
1658
|
+
puts ""
|
1659
|
+
|
1660
|
+
# Get user folders
|
1661
|
+
folders = client.get_folders
|
1662
|
+
|
1663
|
+
puts "๐ User Folders:"
|
1664
|
+
puts " Total folders: #{folders.folders.length}"
|
1665
|
+
puts ""
|
1666
|
+
|
1667
|
+
# Display first few folders
|
1668
|
+
puts "๐ Available Folders:"
|
1669
|
+
folders.folders.first(3).each do |folder|
|
1670
|
+
puts " โข #{folder.name} (ID: #{folder.id})"
|
1671
|
+
puts " Path: #{folder.relativePath} | Child count: #{folder.child_count}"
|
1672
|
+
puts " Can save: #{folder.can_save} | Pinned: #{folder.is_pinned}"
|
1673
|
+
end
|
1674
|
+
puts ""
|
1675
|
+
|
1676
|
+
# Get files from first folder with content
|
1677
|
+
if folders.folders.any?
|
1678
|
+
folder_with_content = folders.folders.find { |f| f.child_count.to_i > 0 }
|
1679
|
+
if folder_with_content
|
1680
|
+
folder_files = client.get_folder_files(folder_with_content.id, include_folders: "Y")
|
1681
|
+
puts "๐ Folder Files:"
|
1682
|
+
puts " Folder: #{folder_files.name} | Total: #{folder_files.total_count}"
|
1683
|
+
puts " Role: #{folder_files.role_name} | Upload enabled: #{folder_files.show_in_upload}"
|
1684
|
+
end
|
1685
|
+
end
|
1686
|
+
puts ""
|
1687
|
+
|
1688
|
+
# Get user tasks
|
1689
|
+
tasks = client.get_tasks(filter: "Pending_Tasks", page: 1, limit: 3)
|
1690
|
+
|
1691
|
+
puts "๐ User Tasks:"
|
1692
|
+
puts " Total tasks: #{tasks.tasks.task.length}"
|
1693
|
+
puts ""
|
1694
|
+
|
1695
|
+
# Display first few tasks
|
1696
|
+
puts "๐ Recent Tasks:"
|
1697
|
+
tasks.tasks.task.first(3).each do |task|
|
1698
|
+
puts " โข #{task.task_title} (ID: #{task.id})"
|
1699
|
+
puts " Status: #{task.status} | Assigned to: #{task.assigned_to_name}"
|
1700
|
+
puts " Due: #{task.due_on ? Time.at(task.due_on.to_i).strftime('%Y-%m-%d') : 'None'}"
|
1701
|
+
puts " Is overdue: #{task.is_overdue} | Priority: #{task.personal_priority}"
|
1702
|
+
end
|
1703
|
+
puts ""
|
1704
|
+
|
1705
|
+
# Get detailed information for the first task
|
1706
|
+
if tasks.tasks.task.any?
|
1707
|
+
first_task = tasks.tasks.task.first
|
1708
|
+
task_id = first_task.is_a?(Array) ? first_task[1] : first_task.id
|
1709
|
+
task_details = client.get_task_details(task_id)
|
1710
|
+
|
1711
|
+
puts "๐ Task Details:"
|
1712
|
+
puts " Task: #{task_details.task.task_title} (ID: #{task_details.task.id})"
|
1713
|
+
puts " Status: #{task_details.task.status} | Bucket: #{task_details.task.bucket}"
|
1714
|
+
puts " Assigned to: #{task_details.task.assigned_to_name} | Created by: #{task_details.task.creator_name}"
|
1715
|
+
puts " Due: #{task_details.task.due_on ? Time.at(task_details.task.due_on.to_i).strftime('%Y-%m-%d') : 'None'}"
|
1716
|
+
puts " Is overdue: #{task_details.task.is_overdue} | Priority: #{task_details.task.personal_priority}"
|
1717
|
+
puts " Milestone: #{task_details.task.milestone_name || 'None'}"
|
1718
|
+
puts " Project: #{task_details.task.conversation_name}"
|
1719
|
+
puts " Visibility: #{task_details.task.visibility}"
|
1720
|
+
|
1721
|
+
# Show reviewers
|
1722
|
+
if task_details.task.reviewers && task_details.task.reviewers.reviewer
|
1723
|
+
reviewers = task_details.task.reviewers.reviewer
|
1724
|
+
puts " Reviewers: #{reviewers.length} reviewers"
|
1725
|
+
end
|
1726
|
+
|
1727
|
+
# Show next actions
|
1728
|
+
if task_details.task.next_actions && task_details.task.next_actions.action
|
1729
|
+
actions = task_details.task.next_actions.action
|
1730
|
+
puts " Available actions: #{actions.join(', ')}"
|
1731
|
+
end
|
1732
|
+
end
|
1733
|
+
puts ""
|
1734
|
+
|
1735
|
+
# Get user wikis
|
1736
|
+
wikis = client.get_wikis(mode: "my", limit: 5, offset: 0)
|
1737
|
+
|
1738
|
+
puts "๐ User Wikis:"
|
1739
|
+
puts " Total wikis: #{wikis.wikis.length}"
|
1740
|
+
puts ""
|
1741
|
+
|
1742
|
+
# Display first few wikis
|
1743
|
+
puts "๐ Recent Wikis:"
|
1744
|
+
wikis.wikis.first(3).each do |wiki|
|
1745
|
+
puts " โข #{wiki.title} (ID: #{wiki.id})"
|
1746
|
+
puts " Updated: #{Time.at(wiki.updated_at.to_i).strftime('%Y-%m-%d')}"
|
1747
|
+
puts " Children: #{wiki.children_count} | Can edit: #{wiki.can_edit}"
|
1748
|
+
puts " Conversation: #{wiki.conversation_name || 'None'} (ID: #{wiki.conversation_id})"
|
1749
|
+
puts " Is draft: #{wiki.is_draft} | PDF access: #{wiki.generate_pdf_access}"
|
1750
|
+
end
|
1751
|
+
puts ""
|
1752
|
+
|
1753
|
+
# Get detailed information for the first wiki
|
1754
|
+
if wikis.wikis.any?
|
1755
|
+
first_wiki = wikis.wikis.first
|
1756
|
+
wiki_details = client.get_wiki_details(first_wiki.id)
|
1757
|
+
|
1758
|
+
puts "๐ Wiki Details:"
|
1759
|
+
puts " Wiki: #{wiki_details.wiki.details.title} (ID: #{wiki_details.wiki.details.id})"
|
1760
|
+
puts " Status: #{wiki_details.wiki.details.status} | Platform: #{wiki_details.wiki.details.platform}"
|
1761
|
+
puts " Created by: #{wiki_details.wiki.details.created_by_name} | Updated by: #{wiki_details.wiki.details.updated_by_name}"
|
1762
|
+
puts " Read count: #{wiki_details.wiki.details.total_read_count} | Children: #{wiki_details.wiki.details.children_count}"
|
1763
|
+
puts " Conversation: #{wiki_details.wiki.details.conversation_name}"
|
1764
|
+
puts " Edit permissions: #{wiki_details.wiki.details.edit_permissions} | Commentable: #{wiki_details.wiki.details.is_commentable}"
|
1765
|
+
puts " Generate PDF access: #{wiki_details.wiki.details.generate_pdf_access} | Show TOC: #{wiki_details.wiki.details.show_toc}"
|
1766
|
+
puts " Archived: #{wiki_details.wiki.details.archived} | Is draft: #{wiki_details.wiki.is_draft}"
|
1767
|
+
|
1768
|
+
# Show permissions
|
1769
|
+
puts " Permissions: Comment: #{wiki_details.wiki.can_comment}, Edit: #{wiki_details.wiki.can_edit}, Delete: #{wiki_details.wiki.can_delete}"
|
1770
|
+
|
1771
|
+
# Show reactions
|
1772
|
+
if wiki_details.wiki.reactions
|
1773
|
+
reactions = wiki_details.wiki.reactions
|
1774
|
+
puts " Reactions: Like: #{reactions.like_count}, Superlike: #{reactions.superlike_count}"
|
1775
|
+
end
|
1776
|
+
|
1777
|
+
# Show comment count
|
1778
|
+
puts " Comment count: #{wiki_details.wiki.comment_count}"
|
1779
|
+
end
|
1780
|
+
puts ""
|
1781
|
+
|
1782
|
+
# Get award feeds
|
1783
|
+
award_feeds = client.get_award_feeds
|
1784
|
+
|
1785
|
+
# Display award feeds
|
1786
|
+
puts "๐ Award Feeds:"
|
1787
|
+
puts " Unread counts:"
|
1788
|
+
if award_feeds.unread_counts
|
1789
|
+
puts " Direct messages: #{award_feeds.unread_counts.direct_messages_count}"
|
1790
|
+
puts " What's new: #{award_feeds.unread_counts.whats_new_count}"
|
1791
|
+
puts " Unread feeds: #{award_feeds.unread_counts.unread_feeds_count}"
|
1792
|
+
puts " Mentions: #{award_feeds.unread_counts.mention_count}"
|
1793
|
+
puts " Primary unread: #{award_feeds.unread_counts.primary_unread_count}"
|
1794
|
+
puts " Secondary unread: #{award_feeds.unread_counts.secondary_unread_count}"
|
1795
|
+
puts " Unread notifications: #{award_feeds.unread_counts.unread_notification_count}"
|
1796
|
+
end
|
1797
|
+
puts " Recent Award Feeds:"
|
1798
|
+
award_feeds.feeds.first(3).each do |feed|
|
1799
|
+
puts " โข #{feed.feed_property.title if feed.feed_property} - Points: #{feed.recognition_points}"
|
1800
|
+
puts " From: #{feed.from_user.name if feed.from_user} | To: #{feed.to_users.length if feed.to_users} users"
|
1801
|
+
puts " Reactions: Like: #{feed.like_count}, Superlike: #{feed.superlike_count}"
|
1802
|
+
puts " Comments: #{feed.comment_count} | Created: #{Time.at(feed.created_at.to_i).strftime('%Y-%m-%d')}"
|
1803
|
+
end
|
1804
|
+
puts ""
|
1805
|
+
|
1806
|
+
# Get core value tags
|
1807
|
+
tags = client.core_value_tags
|
1808
|
+
|
1809
|
+
# Display core value tags
|
1810
|
+
puts "๐ฏ Core Value Tags:"
|
1811
|
+
tags.core_value_tags.each do |tag|
|
1812
|
+
puts " โข #{tag.name} (ID: #{tag.id})"
|
1813
|
+
puts " Color: ##{tag.color}"
|
1814
|
+
end
|
1815
|
+
puts ""
|
1816
|
+
|
1817
|
+
# Get leaderboard information
|
1818
|
+
leaderboard = client.leaderboard_info
|
1819
|
+
|
1820
|
+
# Display leaderboard if available
|
1821
|
+
if leaderboard.leaderboard_info
|
1822
|
+
puts "๐
User Leaderboard:"
|
1823
|
+
leaderboard.leaderboard_info.user_info.each do |user|
|
1824
|
+
puts " #{user.rank}. #{user.name} - #{user.award_count} awards"
|
1825
|
+
end
|
1826
|
+
puts ""
|
1827
|
+
|
1828
|
+
puts "๐ Team Leaderboard:"
|
1829
|
+
leaderboard.leaderboard_info.team_info.each do |team|
|
1830
|
+
puts " #{team.rank}. #{team.name} - #{team.award_count} awards"
|
1831
|
+
end
|
1832
|
+
else
|
1833
|
+
puts "๐ No leaderboard data configured"
|
1834
|
+
end
|
1835
|
+
|
1836
|
+
# Get tango gift cards information
|
1837
|
+
tango_gift_cards = client.tango_gift_cards
|
1838
|
+
|
1839
|
+
# Display tango gift card information
|
1840
|
+
puts "๐ Tango Gift Cards:"
|
1841
|
+
puts " Available points: #{tango_gift_cards.tango_cards.available_points}"
|
1842
|
+
puts " Terms: #{tango_gift_cards.tango_cards.terms[0..100]}..." if tango_gift_cards.tango_cards.terms
|
1843
|
+
puts ""
|
1844
|
+
|
1845
|
+
# Get gift cards information
|
1846
|
+
gift_cards = client.gift_cards
|
1847
|
+
|
1848
|
+
# Display available gift cards
|
1849
|
+
puts "๐ Available Gift Cards:"
|
1850
|
+
gift_cards.cards.each do |card|
|
1851
|
+
puts " โข #{card.brand_name} (Key: #{card.brand_key}) - Enabled: #{card.enabled}"
|
1852
|
+
end
|
1853
|
+
```
|
1854
|
+
|
1855
|
+
### Error Handling with Clean Responses
|
1856
|
+
```ruby
|
1857
|
+
begin
|
1858
|
+
user = client.me
|
1859
|
+
|
1860
|
+
# Clean dot notation access
|
1861
|
+
puts "Welcome, #{user.user_profile.minimal_profile.name}!"
|
1862
|
+
|
1863
|
+
rescue MangoApps::AuthenticationError => e
|
1864
|
+
puts "Authentication failed: #{e.message}"
|
1865
|
+
# Redirect to OAuth flow
|
1866
|
+
|
1867
|
+
rescue MangoApps::APIError => e
|
1868
|
+
puts "API error: #{e.message}"
|
1869
|
+
puts "Status: #{e.status_code}"
|
1870
|
+
|
1871
|
+
rescue MangoApps::RateLimitError => e
|
1872
|
+
puts "Rate limited: #{e.message}"
|
1873
|
+
# Implement backoff strategy
|
1874
|
+
end
|
1875
|
+
```
|
1876
|
+
|
1877
|
+
|
1878
|
+
## Error Handling
|
1879
|
+
|
1880
|
+
The SDK provides specific exception types for different error scenarios:
|
1881
|
+
|
1882
|
+
```ruby
|
1883
|
+
begin
|
1884
|
+
posts = client.posts_list
|
1885
|
+
rescue MangoApps::AuthenticationError => e
|
1886
|
+
puts "Authentication failed: #{e.message}"
|
1887
|
+
rescue MangoApps::APIError => e
|
1888
|
+
puts "API error: #{e.message}"
|
1889
|
+
rescue MangoApps::RateLimitError => e
|
1890
|
+
puts "Rate limited: #{e.message}"
|
1891
|
+
end
|
1892
|
+
|
1893
|
+
# OAuth-specific error handling
|
1894
|
+
begin
|
1895
|
+
userinfo = client.get_userinfo
|
1896
|
+
rescue MangoApps::TokenExpiredError => e
|
1897
|
+
puts "OAuth token expired: #{e.message}"
|
1898
|
+
# Refresh token or redirect to OAuth flow
|
1899
|
+
rescue MangoApps::APIError => e
|
1900
|
+
puts "OAuth userinfo error: #{e.message}"
|
1901
|
+
end
|
1902
|
+
```
|
1903
|
+
|
1904
|
+
### Available Exception Types
|
1905
|
+
|
1906
|
+
- `MangoApps::Error` - Base error class
|
1907
|
+
- `MangoApps::APIError` - General API errors
|
1908
|
+
- `MangoApps::AuthenticationError` - Authentication failures
|
1909
|
+
- `MangoApps::TokenExpiredError` - Token expiration
|
1910
|
+
- `MangoApps::DiscoveryError` - OAuth discovery endpoint errors
|
1911
|
+
- `MangoApps::TokenExchangeError` - OAuth token exchange errors
|
1912
|
+
- `MangoApps::BadRequestError` - 400 errors
|
1913
|
+
- `MangoApps::UnauthorizedError` - 401 errors
|
1914
|
+
- `MangoApps::ForbiddenError` - 403 errors
|
1915
|
+
- `MangoApps::NotFoundError` - 404 errors
|
1916
|
+
- `MangoApps::RateLimitError` - 429 errors
|
1917
|
+
- `MangoApps::ServerError` - 5xx errors
|
1918
|
+
|
1919
|
+
## Configuration Options
|
1920
|
+
|
1921
|
+
```ruby
|
1922
|
+
config = MangoApps::Config.new(
|
1923
|
+
domain: "yourdomain.mangoapps.com",
|
1924
|
+
client_id: "your_client_id",
|
1925
|
+
client_secret: "your_client_secret",
|
1926
|
+
redirect_uri: "https://localhost:3000/oauth/callback",
|
1927
|
+
scope: "openid profile email",
|
1928
|
+
timeout: 30,
|
1929
|
+
open_timeout: 10,
|
1930
|
+
logger: Logger.new(STDOUT)
|
1931
|
+
)
|
1932
|
+
|
1933
|
+
# OAuth-specific configuration
|
1934
|
+
# - All OAuth endpoints automatically use HTTPS
|
1935
|
+
# - Automatic redirect handling for 301/302 responses
|
1936
|
+
# - SSL certificate verification enabled
|
1937
|
+
```
|
1938
|
+
|
1939
|
+
|
1940
|
+
## Development
|
1941
|
+
|
1942
|
+
### For SDK Users
|
1943
|
+
|
1944
|
+
If you're using this SDK in your application, you only need:
|
1945
|
+
|
1946
|
+
1. **Install the gem**: `gem install mangoapps-ex-sdk-ruby`
|
1947
|
+
2. **Configure OAuth**: Set up your MangoApps OAuth credentials
|
1948
|
+
3. **Start coding**: Use the examples above
|
1949
|
+
|
1950
|
+
### For SDK Developers
|
1951
|
+
|
1952
|
+
If you're contributing to or extending this SDK, see our comprehensive developer documentation:
|
1953
|
+
|
1954
|
+
๐ **[DEVELOPER.md](DEVELOPER.md)** - Complete guide for SDK development including:
|
1955
|
+
- Adding new APIs and modules
|
1956
|
+
- Testing guidelines (real TDD approach)
|
1957
|
+
- Development workflow
|
1958
|
+
- Code style and standards
|
1959
|
+
- Module architecture
|
1960
|
+
- Error handling
|
1961
|
+
- Documentation standards
|
1962
|
+
- Release process
|
1963
|
+
|
1964
|
+
### Quick Development Setup
|
1965
|
+
|
1966
|
+
```bash
|
1967
|
+
git clone https://github.com/MangoAppsInc/mangoapps-ex-sdk-ruby.git
|
1968
|
+
cd mangoapps-ex-sdk-ruby
|
1969
|
+
cp .env.example .env
|
1970
|
+
# Edit .env with your MangoApps credentials (for testing only)
|
1971
|
+
bundle install
|
1972
|
+
```
|
1973
|
+
|
1974
|
+
### Testing the SDK
|
1975
|
+
|
1976
|
+
This SDK uses **real TDD** - no mocking, only actual OAuth testing:
|
1977
|
+
|
1978
|
+
```bash
|
1979
|
+
# Get OAuth token (first time or when expired)
|
1980
|
+
./run_auth.sh
|
1981
|
+
|
1982
|
+
# Run tests
|
1983
|
+
./run_tests.sh
|
1984
|
+
|
1985
|
+
# Run specific module tests
|
1986
|
+
./run_tests.sh learn
|
1987
|
+
./run_tests.sh users
|
1988
|
+
./run_tests.sh recognitions
|
1989
|
+
./run_tests.sh notifications
|
1990
|
+
./run_tests.sh feeds
|
1991
|
+
./run_tests.sh posts
|
1992
|
+
|
1993
|
+
# Interactive testing
|
1994
|
+
./run_irb.sh
|
1995
|
+
```
|
1996
|
+
|
1997
|
+
### Current API Coverage
|
1998
|
+
|
1999
|
+
- โ
**Learn Module**: Course catalog, categories, course details, and my learning (4 endpoints)
|
2000
|
+
- โ
**Users Module**: User profile and authentication (1 endpoint)
|
2001
|
+
- โ
**Recognitions Module**: Award categories, get awards list, get profile awards, get team awards, get award feeds, core value tags, leaderboard info, and gift cards (8 endpoints)
|
2002
|
+
- โ
**Notifications Module**: My priority items for requests, events, quizzes, surveys, tasks, and todos, and user notifications with unread counts (2 endpoints)
|
2003
|
+
- โ
**Feeds Module**: User activity feeds with unread counts and feed details (1 endpoint)
|
2004
|
+
- โ
**Posts Module**: Get all posts with filtering options and get post by ID (2 endpoints)
|
2005
|
+
- โ
**Libraries Module**: Get user's document libraries with categories and items, get library categories by ID, and get library items by library and category ID (3 endpoints)
|
2006
|
+
- โ
**Trackers Module**: Get user's trackers with submission dates and conversation details (1 endpoint)
|
2007
|
+
- โ
**Attachments Module**: Get user's file folders with permissions and metadata, and get files and folders inside specific folders (2 endpoints)
|
2008
|
+
- โ
**Tasks Module**: Get user's tasks with filtering, pagination, and detailed task information, and get detailed information for specific tasks (2 endpoints)
|
2009
|
+
- โ
**Wikis Module**: Get user's wikis with filtering, pagination, and detailed wiki information, and get detailed information for specific wikis (2 endpoints)
|
2010
|
+
- โ
**Error Handling**: Comprehensive error logging and testing
|
2011
|
+
- โ
**OAuth Flow**: Token management, refresh, and userinfo endpoint
|
2012
|
+
- โ
**Internal API Auth**: Alternative authentication using API keys
|
2013
|
+
- โ
**Auto Detection**: Automatic authentication method detection and prioritization
|
2014
|
+
- โ
**Pagination Support**: Optional page and limit parameters for all list APIs
|
2015
|
+
- โ
**HTTPS Security**: Automatic HTTPS enforcement with redirect handling
|
2016
|
+
|
2017
|
+
**Total: 29 API endpoints across 11 modules + OAuth + Internal API + Auto Detection + Pagination**
|
2018
|
+
|
2019
|
+
## Contributing
|
2020
|
+
|
2021
|
+
1. Fork the repository
|
2022
|
+
2. Create a feature branch
|
2023
|
+
3. Write real tests first (no mocking)
|
2024
|
+
4. Implement the feature
|
2025
|
+
5. Ensure all tests pass
|
2026
|
+
6. Submit a pull request
|
2027
|
+
|
2028
|
+
## License
|
2029
|
+
|
2030
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
2031
|
+
|
2032
|
+
## Support
|
2033
|
+
|
2034
|
+
- **Documentation**: [RubyDoc](https://rubydoc.info/gems/mangoapps-ex-sdk-ruby)
|
2035
|
+
- **Issues**: [GitHub Issues](https://github.com/MangoAppsInc/mangoapps-ex-sdk-ruby/issues)
|
2036
|
+
- **MangoApps**: [Official Website](https://www.mangoapps.com)
|
2037
|
+
|
2038
|
+
## Changelog
|
2039
|
+
|
2040
|
+
See [CHANGELOG.md](CHANGELOG.md) for a list of changes and version history.
|