PageRenderTime 43ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/kalite/distributed/static/js/distributed/content/models.js

https://gitlab.com/gregtyka/ka-lite
JavaScript | 171 lines | 132 code | 28 blank | 11 comment | 13 complexity | c27229373c952391809cafb2bdcbab2d MD5 | raw file
  1. var _ = require("underscore");
  2. var Backbone = require("base/backbone");
  3. var get_params = require("utils/get_params");
  4. var setGetParamDict = get_params.setGetParamDict;
  5. var sprintf = require("sprintf-js").sprintf;
  6. var ExtraFieldsBaseModel = Backbone.Model.extend({
  7. initialize: function() {
  8. _.bindAll(this, "parse", "toJSON");
  9. },
  10. parse: function(response) {
  11. if (response!==undefined) {
  12. var extra_fields = response.extra_fields;
  13. delete response.extra_fields;
  14. this.database_attrs = Object.keys(response);
  15. if(extra_fields!==undefined) {
  16. extra_fields = JSON.parse(extra_fields);
  17. response = _.extend(response, extra_fields);
  18. }
  19. }
  20. return response;
  21. },
  22. toJSON: function() {
  23. var attributes = _.clone(this.attributes);
  24. var extra_fields = {};
  25. for (var property in attributes) {
  26. if (!_.contains(this.database_attrs, property)) {
  27. extra_fields[property] = attributes[property];
  28. delete attributes.property;
  29. }
  30. }
  31. attributes.extra_fields = JSON.stringify(extra_fields);
  32. return attributes;
  33. }
  34. });
  35. var ContentDataModel = ExtraFieldsBaseModel.extend({
  36. /*
  37. Contains data about a content resource itself, with no user-specific data.
  38. */
  39. defaults: {
  40. description: "",
  41. title: "",
  42. author_name: "",
  43. path: ""
  44. },
  45. url: function () {
  46. return sprintf("/api/content/%s/%s/", this.get("channel"), this.get("id"));
  47. }
  48. });
  49. var ContentLogModel = ExtraFieldsBaseModel.extend({
  50. /*
  51. Contains summary data about the user's history of interaction with the current exercise.
  52. */
  53. defaults: {
  54. complete: false,
  55. points: 0,
  56. views: 0,
  57. progress: 0,
  58. time_spent: 0
  59. },
  60. // Set this here, as models created on the client side do not have it set by parse.
  61. database_attrs: [
  62. "user",
  63. "content_id",
  64. "points",
  65. "language",
  66. "complete",
  67. "completion_timestamp",
  68. "completion_counter",
  69. "time_spent",
  70. "content_source",
  71. "content_kind",
  72. "progress",
  73. "views",
  74. "latest_activity_timestamp"
  75. ],
  76. initialize: function() {
  77. _.bindAll(this, "urlRoot", "save", "saveNow", "set_complete");
  78. },
  79. urlRoot: function() {
  80. return window.sessionModel.get("GET_CONTENT_LOGS_URL");
  81. },
  82. // We let the view call save whenever it feels like on this model - essentially on every
  83. // change event that we can register on the content viewer (video playback updating, etc.)
  84. // However, in order not to overwhelm the server with unnecessary saves, we throttle the save
  85. // call here. On page exit, 'saveNow' is called to prevent data loss.
  86. save: _.throttle(function(key, val, options){this.saveNow(key, val, options);}, 30000),
  87. saveNow: function (key, val, options){
  88. this.set("latest_activity_timestamp", window.statusModel.get_server_time(), {silent: true});
  89. Backbone.Model.prototype.save.call(this, key, val, options);
  90. },
  91. set_complete: function() {
  92. var already_complete = this.get("complete");
  93. this.set({
  94. progress: 1,
  95. complete: true,
  96. completion_counter: (this.get("completion_counter") || 0) + 1
  97. });
  98. if (!already_complete) {
  99. this.set({
  100. completion_timestamp: window.statusModel.get_server_time()
  101. });
  102. }
  103. }
  104. });
  105. var ContentLogCollection = Backbone.Collection.extend({
  106. model: ContentLogModel,
  107. model_id_key: "content_id",
  108. initialize: function(models, options) {
  109. options = typeof options !== "undefined" && options !== null ? options : {};
  110. this.content_model = options.content_model;
  111. this.content_ids = options.content_ids;
  112. },
  113. url: function() {
  114. data = {
  115. "user": window.statusModel.get("user_id")
  116. };
  117. if (typeof this.content_model !== "undefined") {
  118. data[this.model_id_key] = this.content_model.get("id");
  119. } else if (typeof this.content_ids !== "undefined") {
  120. data[this.model_id_key + "__in"] = this.content_ids;
  121. }
  122. return setGetParamDict(this.model.prototype.urlRoot(), data);
  123. },
  124. get_first_log_or_new_log: function() {
  125. if (this.length > 0) {
  126. return this.at(0);
  127. } else {
  128. var data = {
  129. "content_source": this.content_model.get("source") || "",
  130. "content_kind": this.content_model.get("kind"),
  131. "user": window.statusModel.get("user_uri")
  132. };
  133. data[this.model_id_key] = this.content_model.get("id");
  134. return new this.model(data);
  135. }
  136. }
  137. });
  138. module.exports = {
  139. ExtraFieldsBaseModel: ExtraFieldsBaseModel,
  140. ContentDataModel: ContentDataModel,
  141. ContentLogModel: ContentLogModel,
  142. ContentLogCollection: ContentLogCollection
  143. };