comprodls-sdk 2.83.0-alpha → 2.84.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -139,6 +139,7 @@ exports.AUTH_API_URLS = {
139
139
  getParticularShadowClassAPI: '/org/{orgId}/shadow/classes/{extClassId}',
140
140
  classProductAssociation: '/org/{orgId}/classes/{classId}/associate-product/{productcode}',
141
141
  multiClassProductAssociations: '/org/{orgId}/classes/{classId}/associate-product/multi',
142
+ classMaterialAssociation: '/org/{orgId}/classes/{classId}/associate-materials/multi',
142
143
  enrollUsertoClass: '/org/{orgId}/classes/{classId}/enroll-user/{userId}',
143
144
  enrollSelftoClass: '/org/{orgId}/classes/{classId}/enroll-self',
144
145
  enrollMultiUserstoClass: '/org/{orgId}/classes/{classId}/enroll-user/multi',
@@ -321,8 +322,7 @@ exports.PRODUCT_API_URLS = {
321
322
 
322
323
  exports.XAPI_API_URLS = {
323
324
  postMultiStatements: '/{orgId}/statements/multi',
324
- postExternalMultiStatements: '/{orgId}/external/statements/multi',
325
- resetUserProductProgress: '/accounts/{accountId}/progress/user/product/reset'
325
+ postExternalMultiStatements: '/{orgId}/external/statements/multi'
326
326
  };
327
327
 
328
328
  exports.ATTEMPTS_API_URLS = {
@@ -26,7 +26,9 @@
26
26
  var ERROR_TYPES = {
27
27
  "API_ERROR": "API_ERROR",
28
28
  "SDK_ERROR": "SDK_ERROR",
29
- "CHANNEL_SUBSCRIPTION": "CHANNEL_SUBSCRIPTION"
29
+ "CHANNEL_SUBSCRIPTION": "CHANNEL_SUBSCRIPTION",
30
+ "UNEXPECTED_ERROR": "UNEXPECTED_ERROR",
31
+ "POLLING_INITIATION": "POLLING_INITIATION"
30
32
  };
31
33
 
32
34
  var ERROR_CATEGORY = {
@@ -79,6 +79,8 @@ function auth() {
79
79
  createClassProductAssociation: createClassProductAssociation.bind(this),
80
80
  removeClassProductAssociation: removeClassProductAssociation.bind(this),
81
81
  createMultiClassProductAssociations: createMultiClassProductAssociations.bind(this),
82
+ associateMaterialsWithClass: associateMaterialsWithClass.bind(this),
83
+ unassociateMaterialsWithClass: unassociateMaterialsWithClass.bind(this),
82
84
  addItemsToShowcaseOfAClass: addItemsToShowcaseOfAClass.bind(this),
83
85
  deleteItemsFromShowcaseOfAClass: deleteItemsFromShowcaseOfAClass.bind(this),
84
86
 
@@ -1397,6 +1399,111 @@ function createClassProductAssociation(options) {
1397
1399
  return dfd.promise;
1398
1400
  }
1399
1401
 
1402
+ /**
1403
+ * @param {
1404
+ * *classId: 'string',
1405
+ * *body: {
1406
+ * productcodes: ['string'],
1407
+ * bundlecodes: ['string'],
1408
+ * }
1409
+ * } options
1410
+ */
1411
+ function associateMaterialsWithClass(options) {
1412
+ var self = this;
1413
+ // Initializing promise
1414
+ var dfd = q.defer();
1415
+ // Validations
1416
+ var err = helpers.validations.isAuthenticated(self.orgId, self.token);
1417
+ if(err) { dfd.reject(err); }
1418
+ else {
1419
+ if(options && options.classId && options.body && (options.body.productcodes
1420
+ || options.body.bundlecodes)) {
1421
+ // Passed all validations, Contruct API url
1422
+ var url = self.config.DEFAULT_HOSTS.AUTH +
1423
+ self.config.AUTH_API_URLS.classMaterialAssociation;
1424
+ url = helpers.api.constructAPIUrl(url, {
1425
+ orgId: self.orgId, classId: options.classId
1426
+ });
1427
+ // Setup request with URL and Params
1428
+ var requestAPI = request.post(url)
1429
+ .set('Content-Type', 'application/json')
1430
+ .set('Accept', 'application/json');
1431
+ if(self.traceid) { requestAPI.set('X-Amzn-Trace-Id', self.traceid); }
1432
+
1433
+ // Setup token in Authorization header
1434
+ requestAPI = helpers.api.setupAPIToken(requestAPI, self.token);
1435
+
1436
+ requestAPI.agent(keepaliveAgent).end(function(err, response) {
1437
+ if(err) {
1438
+ err = new DLSError(helpers.errors.ERROR_TYPES.API_ERROR, err);
1439
+ dfd.reject(err);
1440
+ }
1441
+ else { dfd.resolve(response.body); }
1442
+ });
1443
+ } else {
1444
+ err = {};
1445
+ err.message = err.description = 'classId or productcodes or bundlecodes not found in'
1446
+ + 'request options.';
1447
+ err = new DLSError(helpers.errors.ERROR_TYPES.SDK_ERROR, err);
1448
+ dfd.reject(err);
1449
+ }
1450
+ }
1451
+ return dfd.promise;
1452
+ }
1453
+
1454
+ /**
1455
+ * @param {
1456
+ * *classId: string,
1457
+ * *body: {
1458
+ * 'productcodes' :['string'],
1459
+ * 'bundlecodes' : ['string']
1460
+ * }
1461
+ * } options
1462
+ */
1463
+ function unassociateMaterialsWithClass(options) {
1464
+ var self = this;
1465
+ // Initializing promise
1466
+ var dfd = q.defer();
1467
+ // Validations
1468
+ var err = helpers.validations.isAuthenticated(self.orgId, self.token);
1469
+ if(err) { dfd.reject(err); }
1470
+ else {
1471
+ if(options && options.classId && options.body &&
1472
+ (options.body.productcodes || options.body.bundlecodes)) {
1473
+ // Passed all validations, Contruct API url
1474
+ var url= self.config.DEFAULT_HOSTS.AUTH + self.config.AUTH_API_URLS.classMaterialAssociation;
1475
+ url = helpers.api.constructAPIUrl(url, {
1476
+ orgId: self.orgId, classId: options.classId
1477
+ });
1478
+ // Setup request with URL and Params
1479
+ var requestAPI = request.delete(url)
1480
+ .set('Content-Type', 'application/json')
1481
+ .set('Accept', 'application/json');
1482
+
1483
+ if(self.traceid) { requestAPI.set('X-Amzn-Trace-Id', self.traceid); }
1484
+
1485
+ // Setup token in Authorization header
1486
+ requestAPI = helpers.api.setupAPIToken(requestAPI, self.token);
1487
+
1488
+ requestAPI.agent(keepaliveAgent).end(function(err, response) {
1489
+ if(err) {
1490
+ err = new DLSError(helpers.errors.ERROR_TYPES.API_ERROR, err);
1491
+ dfd.reject(err);
1492
+ }
1493
+ else { dfd.resolve(response.body); }
1494
+ });
1495
+ } else {
1496
+ err = {};
1497
+ const msg = 'classId or productcodes or bundlecodes not found in request options.';
1498
+ err.message = msg;
1499
+ err.description = msg;
1500
+ err = new DLSError(helpers.errors.ERROR_TYPES.SDK_ERROR, err);
1501
+ dfd.reject(err);
1502
+ }
1503
+ }
1504
+ return dfd.promise;
1505
+ }
1506
+
1400
1507
  //options = {
1401
1508
  // classId: 'class uuid',
1402
1509
  // productcode: 'product code'
@@ -2088,6 +2195,14 @@ function updateClass(options) {
2088
2195
  "productcode": "string", //mandatory
2089
2196
  "title": ""
2090
2197
  }
2198
+ ],
2199
+ "bundles": [ // optional
2200
+ {
2201
+ "bundlecode": "string", //mandatory
2202
+ },
2203
+ {
2204
+ "bundlecode": "string", //mandatory
2205
+ }
2091
2206
  ]
2092
2207
  }
2093
2208
  ],
@@ -2103,6 +2218,7 @@ function updateClass(options) {
2103
2218
  "students": true,
2104
2219
  "teachers": true,
2105
2220
  "products": true,
2221
+ "bundles": true,
2106
2222
  "groups": true,
2107
2223
  "assigned_paths": true,
2108
2224
  "tags": true,
@@ -2143,6 +2259,7 @@ function updateClass(options) {
2143
2259
  }
2144
2260
  ],
2145
2261
  "products": [ { "productcode": "string" } ],
2262
+ "bundles": [ { "bundlecode": "string" } ],
2146
2263
  "analyticsharingmodel": "string" // Valid values: ['NOINHERIT_SYNCBACK']
2147
2264
  "analytics_score_aggregation_type": "string", // Valid values: ['best', 'first', 'last']
2148
2265
  "limits": {los: number, students: number} // Optional field
@@ -2369,7 +2486,12 @@ function deleteAssignedPath(options) {
2369
2486
  item_type: 'string', //mandatory, ['dls-internal','external']
2370
2487
  dls_product_code: 'string' //mandatory only if item_type is 'dls-internal'
2371
2488
  }
2372
- ]
2489
+ ],
2490
+ "rules": {}, // Optional
2491
+ "context": { // Optional (Needed for system event only)
2492
+ "bundle-code": "string",
2493
+ "space_key": "string"
2494
+ }
2373
2495
  }
2374
2496
  }
2375
2497
  */
@@ -3134,6 +3256,7 @@ function deleteItemsFromShowcaseOfAClass(options){
3134
3256
  * "students": true,
3135
3257
  * "teachers": true,
3136
3258
  * "products": true,
3259
+ * "bundles": true,
3137
3260
  * "groups": true,
3138
3261
  * "assigned_paths": true,
3139
3262
  * "skip_assigned_path_create_notification": true,
@@ -3170,6 +3293,11 @@ function deleteItemsFromShowcaseOfAClass(options){
3170
3293
  * "productcode": "string"
3171
3294
  * }
3172
3295
  * ],
3296
+ * "bundles": [
3297
+ * {
3298
+ * "bundlecode": "string"
3299
+ * }
3300
+ * ],
3173
3301
  * "analyticsharingmodel": "NOINHERIT_SYNCBACK",
3174
3302
  * "analytics_score_aggregation_type": "best",
3175
3303
  * "limits": {
@@ -80,11 +80,8 @@ function _connect(pubnubCW, options) {
80
80
  'publishKey': options.publishKey,
81
81
  'subscribeKey': options.subscribeKey,
82
82
  'ssl': true
83
- },
84
- 'pollingEndpoint': options.pollingEndpoint,
85
- 'pollingIterations': options.pollingIterations || 10, // Default polling iterations is 10
86
- 'pollingInterval': options.pollingInterval, // Default polling interval is exponential backoff
87
- });
83
+ }
84
+ });
88
85
  }
89
86
 
90
87
  function _cleanup(pubnubCW) { pubnubCW.cleanup(); }
@@ -1,5 +1,4 @@
1
1
  var pubNub = require("pubnub");
2
- var request = require('superagent');
3
2
  var EventEmitter = require("events").EventEmitter;
4
3
  var helpers = require('../../helpers');
5
4
 
@@ -22,13 +21,6 @@ module.exports = function () {
22
21
  var _globalSubscription = [];
23
22
  var _globalSubscriptionStatus = {};
24
23
  var bStatusSubscribed = false;
25
- /** ID of the setTimeout - used for Polling events when PubNub fails */
26
- var _setTimeoutIDForPolling;
27
- /** Timestamp from when the events need to be fetched */
28
- var _startTimestampForPolling;
29
- /** Counter for polling */
30
- var _pollingCounter;
31
- var bPollingInitiated = false;
32
24
 
33
25
  /** ###### END OF MODULE GLOBALS */
34
26
 
@@ -44,9 +36,6 @@ module.exports = function () {
44
36
  //Returning the adaptor (Plain Javascript object)
45
37
  return {
46
38
  "on": function (channelObj, handler) {
47
- // If PubNub fails, we will fetch the events from this timestamp
48
- _startTimestampForPolling = Date.now();
49
-
50
39
  var pubNubChannel;
51
40
  var channelContext = [];
52
41
 
@@ -75,9 +64,6 @@ module.exports = function () {
75
64
  _eventEmitter.on(channelObj.channel, handler);
76
65
  bStatusSubscribed = true;
77
66
  }
78
-
79
- // Clean up the old events
80
- _checkOldBubbledEvents();
81
67
  },
82
68
  "getMySubscriptionStatus": __getMySubscriptionStatus
83
69
  };
@@ -91,10 +77,6 @@ module.exports = function () {
91
77
 
92
78
  var _translatePubnubStatus = function(status, options) {
93
79
  var channels = [], error, successObj;
94
-
95
- // If polling has been initiated, ignore all punnub status
96
- if (bPollingInitiated) return;
97
-
98
80
  switch (status.category) {
99
81
  case "PNConnectedCategory":
100
82
  if(status.operation === "PNSubscribeOperation") {
@@ -156,10 +138,11 @@ module.exports = function () {
156
138
  break;
157
139
  case "PNNetworkIssuesCategory":
158
140
  if(status.operation === 'PNSubscribeOperation') {
159
- if(!options.accountId || !_userOptions.pollingEndpoint) {
141
+ if(!options.accountId) {
160
142
  error = {
161
- message: "Polling initiation error: Missing mandatory parameters to initiate polling operation - [accountId, pollingEndpoint]",
162
- status: status.statusCode
143
+ message: "Missing mandatory parameters to initiate polling operation - accountId",
144
+ status: status.statusCode,
145
+ type: helpers.errors.ERROR_TYPES.POLLING_INITIATION,
163
146
  };
164
147
  error = new PUSHXError(helpers.errors.ERROR_CATEGORY.PUSHX, error);
165
148
  _eventEmitter.emit('pushx_status', error);
@@ -173,9 +156,6 @@ module.exports = function () {
173
156
  * The wrapper supports multiple channels, but the APP currently uses a single channel only.
174
157
  * Polling will also limited to a single channel.
175
158
  */
176
- _pollingCounter = 0;
177
- _pollForEvents();
178
- bPollingInitiated = true;
179
159
  }
180
160
  }
181
161
  else {
@@ -188,8 +168,9 @@ module.exports = function () {
188
168
  default:
189
169
  // Emit error for other status-category received from pubnub
190
170
  error = {
191
- message: "PushX Error: unexpected error",
171
+ message: "PushX Error",
192
172
  status: status.statusCode,
173
+ type: helpers.errors.ERROR_TYPES.UNEXPECTED_ERROR,
193
174
  pushXError: status
194
175
  };
195
176
  error = new PUSHXError(helpers.errors.ERROR_CATEGORY.PUSHX, error);
@@ -226,7 +207,6 @@ module.exports = function () {
226
207
  * @returns PROMISE.
227
208
  */
228
209
  var __setup = function (userOptions) {
229
-
230
210
  var pubnubConfig = userOptions.pubnub;
231
211
  pubnubConfig.uuid = userOptions.userid;
232
212
  var accountId = userOptions.accountid;
@@ -265,169 +245,8 @@ module.exports = function () {
265
245
  _globalSubscription = [];
266
246
  bStatusSubscribed = false;
267
247
  _globalSubscriptionStatus = {};
268
- bPollingInitiated = false;
269
248
  }
270
249
  _pubnubClient = undefined;
271
-
272
- // Clear the Polling
273
- if (_setTimeoutIDForPolling) {
274
- clearTimeout(_setTimeoutIDForPolling);
275
- // Setting the start time to now to clear the old events
276
- _startTimestampForPolling = Date.now();
277
- _checkOldBubbledEvents();
278
- _setTimeoutIDForPolling = undefined;
279
- _pollingCounter = undefined;
280
- _startTimestampForPolling = undefined;
281
- }
282
- };
283
-
284
- /**
285
- * Polling function
286
- */
287
- var _pollForEvents = function () {
288
- // Setup request params
289
- var params = {
290
- accountid: _userOptions.accountid,
291
- channelname: _globalSubscription[0],
292
- starttime: _startTimestampForPolling,
293
- endtime: Date.now()
294
- };
295
-
296
- // Safe check to avoid poll for events if the channel name or start time is not set
297
- // This handles an edge condition where the clearTimeout doesn't work as expected
298
- if (!params.channelname || !params.starttime) {
299
- return;
300
- }
301
-
302
- var requestAPI = request.get(_userOptions.pollingEndpoint).query(params);
303
-
304
- requestAPI
305
- .end(function(error, response) {
306
-
307
- if (!error) {
308
- // Bubble the connected status
309
- if (_pollingCounter === 0) {
310
- // Set the status of the channel to subscribed
311
- if(_globalSubscriptionStatus[_globalSubscription[0]]) {
312
- _globalSubscriptionStatus[_globalSubscription[0]].status = 'subscribed';
313
- }
314
-
315
- var successObj = {
316
- category: 'PUSHX',
317
- type: 'CHANNEL_SUBSCRIPTION',
318
- status: 'SUCCESS',
319
- message: 'Success: Subscribed successfully.',
320
- httpcode: 200,
321
- data: {
322
- payload: {
323
- channels: _globalSubscription
324
- },
325
- message: 'Success: Subscribed successfully.'
326
- }
327
- };
328
- _eventEmitter.emit('pushx_status', successObj);
329
- }
330
-
331
- // Bubble the received events
332
- _bubblePolledEvents(response.body);
333
-
334
- // Increase the counter
335
- _pollingCounter++;
336
- }
337
-
338
- // Polling will be done only for specific number of times
339
- if (_pollingCounter > _userOptions.pollingIterations) {
340
- var error = {
341
- message: "Polling error: Polling limit exceeded",
342
- status: 429
343
- };
344
- error = new PUSHXError(helpers.errors.ERROR_CATEGORY.PUSHX, error);
345
- _eventEmitter.emit('pushx_status', error);
346
- } else {
347
- var timeoutDelay;
348
-
349
- // If the polling interval is provided, use that
350
- if (_userOptions.pollingInterval) {
351
- timeoutDelay = _userOptions.pollingInterval * 60 * 1000;
352
- } else {
353
- // Else, use exponential backoff
354
- timeoutDelay = parseInt(Math.pow(1.3, _pollingCounter) * 10 * 1000, 10);
355
- }
356
-
357
- // Set timeout for next poll
358
- if (timeoutDelay) {
359
- _setTimeoutIDForPolling = setTimeout(_pollForEvents, timeoutDelay);
360
- }
361
- }
362
- });
363
- };
364
-
365
- /**
366
- * Bubble the polled events to the FE APP
367
- * @param {*} events - Events recieved from the polling endpoint
368
- */
369
- var _bubblePolledEvents = function (events) {
370
- // Load the old events from the session storage
371
- var oldEventData = _checkOldBubbledEvents();
372
-
373
- var oldEvents = oldEventData.events;
374
- var sessionStorageKey = oldEventData.key;
375
-
376
- for (var i = 0; i < events.entities.length; i++) {
377
- var event = events.entities[i];
378
- var eventId = event.pk + '_' + event.sk;
379
-
380
- // Check if the event is already emitted
381
- if (!oldEvents[eventId]) {
382
- oldEvents[eventId] = event.context.start_time;
383
-
384
- // Emit the event
385
- _eventEmitter.emit(_globalSubscription[0], event);
386
- }
387
- }
388
-
389
- // Save the bubbled events to session storage
390
- sessionStorage.setItem(sessionStorageKey, JSON.stringify(oldEvents));
391
- };
392
-
393
- /**
394
- * Check the old bubbled events and remove the events that are older than the start timestamp
395
- * @returns {object} - Object containing the key and the events
396
- */
397
- var _checkOldBubbledEvents = function () {
398
- var sessionStorageKey = 'comprodls.old_pushx_events.' + _userOptions.userid + '.' + _globalSubscription[0];
399
- var oldEvents = sessionStorage.getItem(sessionStorageKey);
400
-
401
- if (oldEvents) {
402
- try {
403
- oldEvents = JSON.parse(oldEvents);
404
- } catch (e) {
405
- oldEvents = {};
406
- }
407
-
408
- var oldEventIds = Object.keys(oldEvents);
409
-
410
- // Remove the events that are older than the start timestamp
411
- for (var i = 0; i < oldEventIds.length; i++) {
412
- var oldEventId = oldEventIds[i];
413
-
414
- if (oldEvents[oldEventId] < _startTimestampForPolling) {
415
- delete oldEvents[oldEventId];
416
- }
417
- }
418
-
419
- // If the number of events has changed, save the events
420
- if (oldEventIds.length !== Object.keys(oldEvents).length) {
421
- sessionStorage.setItem(sessionStorageKey, JSON.stringify(oldEvents));
422
- }
423
- } else {
424
- oldEvents = {};
425
- }
426
-
427
- return {
428
- key: sessionStorageKey,
429
- events: oldEvents
430
- };
431
250
  };
432
251
 
433
252
  return { // Return public methods for the wrapper
@@ -538,6 +538,7 @@ function provisionBulkSpaces(options) {
538
538
  * clone_settings: {
539
539
  * *src_ext_classid: 'string',
540
540
  * products: boolean,
541
+ * bundles: boolean,
541
542
  * assigned_paths: boolean,
542
543
  * ext_assigned_path_id_rule: 'string' //enum: ['SRC_ID']
543
544
  * advanced: {
@@ -551,6 +552,9 @@ function provisionBulkSpaces(options) {
551
552
  * ],
552
553
  * products: [
553
554
  * { *productcode: 'string' },
555
+ * ],
556
+ * bundles: [
557
+ * { *bundlecode: 'string' },
554
558
  * ]
555
559
  * }
556
560
  * }
@@ -42,8 +42,7 @@ function xapi(accountId) {
42
42
  this.accountId = accountId;
43
43
  return {
44
44
  postStatement: postStatements.bind(this),
45
- postExternalStatements: postExternalStatements.bind(this),
46
- resetUserProductProgress: resetUserProductProgress.bind(this)
45
+ postExternalStatements: postExternalStatements.bind(this)
47
46
  };
48
47
  }
49
48
 
@@ -232,44 +231,3 @@ function postExternalStatements(options) {
232
231
  });
233
232
  return dfd.promise;
234
233
  }
235
-
236
- /*options = {
237
- userid: 'string',
238
- productcode: 'string',
239
- actorid: 'string'
240
- }*/
241
- function resetUserProductProgress(options) {
242
- var self = this;
243
- // Initializing promise
244
- var dfd = q.defer();
245
- var err = {};
246
- if(options && options.userid && options.productcode && options.actorid) {
247
-
248
- // Passed all validations, Contruct API url
249
- var url = self.config.DEFAULT_HOSTS.XAPI + self.config.XAPI_API_URLS.resetUserProductProgress;
250
- url = helpers.api.constructAPIUrl(url, { accountId : self.accountId });
251
-
252
- // Setup request with URL and Params
253
- var requestAPI = request.delete(url)
254
- .set('Content-Type', 'application/json')
255
- .set('Accept', 'application/json')
256
- .send(options);
257
-
258
- if(self.traceid) { requestAPI.set('X-Amzn-Trace-Id', self.traceid); }
259
-
260
- requestAPI.end(function(error, response) {
261
- if(error) {
262
- err = new DLSError(helpers.errors.ERROR_TYPES.API_ERROR, error);
263
- dfd.reject(err);
264
- }
265
- else { dfd.resolve(response.body); }
266
- });
267
- }
268
- else {
269
- err.message = err.description = 'userid, productcode or actorid not found in request options.';
270
- err = new DLSError(helpers.errors.ERROR_TYPES.SDK_ERROR, err);
271
- dfd.reject(err);
272
- }
273
-
274
- return dfd.promise;
275
- }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "comprodls-sdk",
3
3
  "description": "comproDLS SDK for JavaScript",
4
- "version": "2.83.0-alpha",
4
+ "version": "2.84.0",
5
5
  "author": {
6
6
  "name": "Compro Technologies Private Limited",
7
7
  "url": "http://www.comprotechnologies.com/"