{"action":"created","comment":{"url":"https://api.github.com/repos/learningequality/kolibri/pulls/comments/74623181","id":74623181,"diff_hunk":"@@ -54,9 +126,214 @@ function togglemodal(store, bool) {\n   }\n }\n \n+\n+/**\n+ * Create models to store logging information\n+ * To be called on page load for content renderers\n+ */\n+function initContentSession(store, Kolibri, channelId, contentId, contentKind) {\n+  const ContentSessionLogResource = Kolibri.resources.ContentSessionLogResource;\n+  const ContentSummaryLogResource = Kolibri.resources.ContentSummaryLogResource;\n+\n+  /* Create summary log iff user exists */\n+  if (store.state.core.session.user_id) {\n+     /* Fetch collection matching content and user */\n+    const summaryCollection = ContentSummaryLogResource.getCollection({\n+      content_id: contentId,\n+      user: store.state.core.session.user_id,\n+    });\n+    summaryCollection.fetch().then(summary => {\n+      /* If a summary model exists, map that to the state */\n+      if (summary.length > 0) {\n+        store.dispatch('SET_LOGGING_SUMMARY_STATE', _contentSummaryLoggingState(summary[0]));\n+      } else {\n+        /* If a summary model does not exist, create default state */\n+        store.dispatch('SET_LOGGING_SUMMARY_STATE', _contentSummaryLoggingState({\n+          pk: null,\n+          start_timestamp: new Date(),\n+          completion_timestamp: null,\n+          end_timestamp: null,\n+          progress: 0,\n+          time_spent: 0,\n+          extra_fields: '{}',\n+          time_spent_before_current_session: 0,\n+          progress_before_current_session: 0,\n+        }));\n+\n+        const summaryData = Object.assign({\n+          channel_id: channelId,\n+          content_id: contentId,\n+          kind: contentKind,\n+        }, _contentSummaryModel(store));\n+\n+        /* Save a new summary model and set id on state */\n+        const summaryModel = ContentSummaryLogResource.createModel(summaryData);\n+        summaryModel.save().then((newSummary) => {\n+          store.dispatch('SET_LOGGING_SUMMARY_ID', newSummary.pk);\n+        });\n+      }\n+    });\n+  }\n+\n+  /* Set session log state to default */\n+  store.dispatch('SET_LOGGING_SESSION_STATE', _contentSessionLoggingState({\n+    pk: null,\n+    start_timestamp: new Date(),\n+    end_timestamp: null,\n+    time_spent: 0,\n+    progress: 0,\n+    extra_fields: '{}',\n+  }));\n+\n+  const sessionData = Object.assign({\n+    channel_id: channelId,\n+    content_id: contentId,\n+    kind: contentKind,\n+  }, _contentSessionModel(store));\n+\n+  /* Save a new session model and set id on state */\n+  const sessionModel = ContentSessionLogResource.createModel(sessionData);\n+  sessionModel.save().then((newSession) => {\n+    store.dispatch('SET_LOGGING_SESSION_ID', newSession.pk);\n+  });\n+}\n+\n+\n+/**\n+ * Update the progress percentage\n+ * To be called periodically by content renderers on interval or on pause\n+ * Must be called after initContentSession\n+ * @param {float} progressPercent\n+ * @param {boolean} forceSave\n+ */\n+function updateProgress(store, Kolibri, progressPercent, forceSave = false) {\n+  /* Create aliases for logs */\n+  const summaryLog = store.state.core.logging.summary;\n+  const sessionLog = store.state.core.logging.session;\n+\n+  /* Store original value to check if 100% reached this iteration */\n+  const originalProgress = summaryLog.progress;\n+\n+  /* Calculate progress based on progressPercent */\n+  const sessionProgress = sessionLog.progress + progressPercent;\n+  const summaryProgress = (summaryLog.id) ?\n+    Math.min(1, summaryLog.progress_before_current_session + sessionProgress) : 0;\n+\n+  /* Update the logging state with new progress information */\n+  store.dispatch('SET_LOGGING_PROGRESS', sessionProgress, summaryProgress);\n+\n+  /* Determine if progress threshold has been met */\n+  const progressThresholdMet = sessionProgress -\n+    sessionLog.progress_at_last_save >= progressThreshold;\n+\n+  /* Mark completion time if 100% progress reached */\n+  const completedContent = originalProgress < 1 && summaryProgress === 1;\n+  if (completedContent) {\n+    store.dispatch('SET_LOGGING_COMPLETION_TIME', new Date());\n+  }\n+\n+  /* Save models if needed */\n+  if (forceSave || completedContent || progressThresholdMet) {\n+    this.saveLogs(Kolibri);\n+  }\n+}\n+\n+\n+/**\n+ * Update the total time spent and end time stamps\n+ * To be called periodically by interval timer\n+ * Must be called after initContentSession\n+ * @param {boolean} forceSave\n+ */\n+function updateTimeSpent(store, Kolibri, forceSave = false) {\n+  /* Create aliases for logs */\n+  const summaryLog = store.state.core.logging.summary;\n+  const sessionLog = store.state.core.logging.session;\n+\n+  /* Calculate new times based on how much time has passed since last save */\n+  const sessionTime = intervalTimer.getNewTimeElapsed() + sessionLog.time_spent;\n+  const summaryTime = (summaryLog.id) ?\n+    sessionTime + summaryLog.time_spent_before_current_session : 0;\n+\n+  /* Update the logging state with new timing information */\n+  store.dispatch('SET_LOGGING_TIME', sessionTime, summaryTime, new Date());\n+\n+  /* Determine if time threshold has been met */\n+  const timeThresholdMet = sessionLog.time_spent -\n+    sessionLog.total_time_at_last_save >= timeThreshold;\n+\n+  /* Save models if needed */\n+  if (forceSave || timeThresholdMet) {\n+    this.saveLogs(Kolibri);\n+  }\n+}\n+\n+\n+/**\n+ * Do a PATCH to update existing logging models\n+ * Must be called after initContentSession\n+ */\n+function saveLogs(store, Kolibri) {\n+  const ContentSessionLogResource = Kolibri.resources.ContentSessionLogResource;\n+  const ContentSummaryLogResource = Kolibri.resources.ContentSummaryLogResource;\n+  /* Create aliases for logs */\n+  const summaryLog = store.state.core.logging.summary;\n+  const sessionLog = store.state.core.logging.session;\n+\n+  /* If a session model exists, save it with updated values */\n+  if (sessionLog.id) {\n+    const sessionModel = ContentSessionLogResource.getModel(sessionLog.id);\n+    sessionModel.save(_contentSessionModel(store)).then((model) => {","path":"kolibri/core/assets/src/core-actions.js","position":237,"original_position":237,"commit_id":"23d8dd816afc896d2ac7749ad579a71065617088","original_commit_id":"23d8dd816afc896d2ac7749ad579a71065617088","user":{"login":"jamalex","id":618416,"avatar_url":"https://avatars.githubusercontent.com/u/618416?v=3","gravatar_id":"","url":"https://api.github.com/users/jamalex","html_url":"https://github.com/jamalex","followers_url":"https://api.github.com/users/jamalex/followers","following_url":"https://api.github.com/users/jamalex/following{/other_user}","gists_url":"https://api.github.com/users/jamalex/gists{/gist_id}","starred_url":"https://api.github.com/users/jamalex/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jamalex/subscriptions","organizations_url":"https://api.github.com/users/jamalex/orgs","repos_url":"https://api.github.com/users/jamalex/repos","events_url":"https://api.github.com/users/jamalex/events{/privacy}","received_events_url":"https://api.github.com/users/jamalex/received_events","type":"User","site_admin":false},"body":"I think the value passed to this callback is just a raw object, not a model (right, @rtibbles?), so perhaps call it `data` here, instead of `model`.","created_at":"2016-08-12T16:50:20Z","updated_at":"2016-08-12T16:50:20Z","html_url":"https://github.com/learningequality/kolibri/pull/374#discussion_r74623181","pull_request_url":"https://api.github.com/repos/learningequality/kolibri/pulls/374","_links":{"self":{"href":"https://api.github.com/repos/learningequality/kolibri/pulls/comments/74623181"},"html":{"href":"https://github.com/learningequality/kolibri/pull/374#discussion_r74623181"},"pull_request":{"href":"https://api.github.com/repos/learningequality/kolibri/pulls/374"}}},"pull_request":{"url":"https://api.github.com/repos/learningequality/kolibri/pulls/374","id":81000567,"html_url":"https://github.com/learningequality/kolibri/pull/374","diff_url":"https://github.com/learningequality/kolibri/pull/374.diff","patch_url":"https://github.com/learningequality/kolibri/pull/374.patch","issue_url":"https://api.github.com/repos/learningequality/kolibri/issues/374","number":374,"state":"open","locked":false,"title":"Content logging","user":{"login":"jayoshih","id":7447496,"avatar_url":"https://avatars.githubusercontent.com/u/7447496?v=3","gravatar_id":"","url":"https://api.github.com/users/jayoshih","html_url":"https://github.com/jayoshih","followers_url":"https://api.github.com/users/jayoshih/followers","following_url":"https://api.github.com/users/jayoshih/following{/other_user}","gists_url":"https://api.github.com/users/jayoshih/gists{/gist_id}","starred_url":"https://api.github.com/users/jayoshih/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jayoshih/subscriptions","organizations_url":"https://api.github.com/users/jayoshih/orgs","repos_url":"https://api.github.com/users/jayoshih/repos","events_url":"https://api.github.com/users/jayoshih/events{/privacy}","received_events_url":"https://api.github.com/users/jayoshih/received_events","type":"User","site_admin":false},"body":"## Summary\r\nNew code logs users' interactions with content. The session logs record users' interaction each time they navigate to a piece of content. The summary log records users' cumulative interactions with each content item. There is a timer that updates how much time is spent (only counts when user is watching to a video, listening to audio, or has a document open). There is also a progress tracker that records how much time of video/audio content has been played or is automatically set to 100% after 15 seconds of viewing a pdf document. If the user is anonymous, only a content session log is created, not a summary log.\r\n\r\n\r\n## TODO\r\n\r\n- [ ] Have tests been written for the new code?\r\n- [ ] Has documentation been written/updated?\r\n- [ ] New dependencies (if any) added to requirements file\r\n- [ ] Add an entry to CHANGELOG.rst\r\n- [ ] Add yourself it AUTHORS.rst if you don't appear there\r\n\r\n## Reviewer guidance\r\nAdded ability to track users' progress on content (how much time was spent and how much progress was made)\r\n\r\n## Issues addressed\r\n- Added in progress tracking\r\n\r\n## Documentation\r\n(none)\r\n\r\n## Screenshots (if appropriate)","created_at":"2016-08-11T17:50:15Z","updated_at":"2016-08-12T16:50:20Z","closed_at":null,"merged_at":null,"merge_commit_sha":"135f96a640308683ea668c96d083b31f73df488f","assignee":{"login":"jamalex","id":618416,"avatar_url":"https://avatars.githubusercontent.com/u/618416?v=3","gravatar_id":"","url":"https://api.github.com/users/jamalex","html_url":"https://github.com/jamalex","followers_url":"https://api.github.com/users/jamalex/followers","following_url":"https://api.github.com/users/jamalex/following{/other_user}","gists_url":"https://api.github.com/users/jamalex/gists{/gist_id}","starred_url":"https://api.github.com/users/jamalex/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jamalex/subscriptions","organizations_url":"https://api.github.com/users/jamalex/orgs","repos_url":"https://api.github.com/users/jamalex/repos","events_url":"https://api.github.com/users/jamalex/events{/privacy}","received_events_url":"https://api.github.com/users/jamalex/received_events","type":"User","site_admin":false},"assignees":[{"login":"jamalex","id":618416,"avatar_url":"https://avatars.githubusercontent.com/u/618416?v=3","gravatar_id":"","url":"https://api.github.com/users/jamalex","html_url":"https://github.com/jamalex","followers_url":"https://api.github.com/users/jamalex/followers","following_url":"https://api.github.com/users/jamalex/following{/other_user}","gists_url":"https://api.github.com/users/jamalex/gists{/gist_id}","starred_url":"https://api.github.com/users/jamalex/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jamalex/subscriptions","organizations_url":"https://api.github.com/users/jamalex/orgs","repos_url":"https://api.github.com/users/jamalex/repos","events_url":"https://api.github.com/users/jamalex/events{/privacy}","received_events_url":"https://api.github.com/users/jamalex/received_events","type":"User","site_admin":false}],"milestone":null,"commits_url":"https://api.github.com/repos/learningequality/kolibri/pulls/374/commits","review_comments_url":"https://api.github.com/repos/learningequality/kolibri/pulls/374/comments","review_comment_url":"https://api.github.com/repos/learningequality/kolibri/pulls/comments{/number}","comments_url":"https://api.github.com/repos/learningequality/kolibri/issues/374/comments","statuses_url":"https://api.github.com/repos/learningequality/kolibri/statuses/23d8dd816afc896d2ac7749ad579a71065617088","head":{"label":"jayoshih:content-logging","ref":"content-logging","sha":"23d8dd816afc896d2ac7749ad579a71065617088","user":{"login":"jayoshih","id":7447496,"avatar_url":"https://avatars.githubusercontent.com/u/7447496?v=3","gravatar_id":"","url":"https://api.github.com/users/jayoshih","html_url":"https://github.com/jayoshih","followers_url":"https://api.github.com/users/jayoshih/followers","following_url":"https://api.github.com/users/jayoshih/following{/other_user}","gists_url":"https://api.github.com/users/jayoshih/gists{/gist_id}","starred_url":"https://api.github.com/users/jayoshih/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jayoshih/subscriptions","organizations_url":"https://api.github.com/users/jayoshih/orgs","repos_url":"https://api.github.com/users/jayoshih/repos","events_url":"https://api.github.com/users/jayoshih/events{/privacy}","received_events_url":"https://api.github.com/users/jayoshih/received_events","type":"User","site_admin":false},"repo":{"id":52636211,"name":"kolibri","full_name":"jayoshih/kolibri","owner":{"login":"jayoshih","id":7447496,"avatar_url":"https://avatars.githubusercontent.com/u/7447496?v=3","gravatar_id":"","url":"https://api.github.com/users/jayoshih","html_url":"https://github.com/jayoshih","followers_url":"https://api.github.com/users/jayoshih/followers","following_url":"https://api.github.com/users/jayoshih/following{/other_user}","gists_url":"https://api.github.com/users/jayoshih/gists{/gist_id}","starred_url":"https://api.github.com/users/jayoshih/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jayoshih/subscriptions","organizations_url":"https://api.github.com/users/jayoshih/orgs","repos_url":"https://api.github.com/users/jayoshih/repos","events_url":"https://api.github.com/users/jayoshih/events{/privacy}","received_events_url":"https://api.github.com/users/jayoshih/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/jayoshih/kolibri","description":"This is where Kolibri shall be born, watch and participate!","fork":true,"url":"https://api.github.com/repos/jayoshih/kolibri","forks_url":"https://api.github.com/repos/jayoshih/kolibri/forks","keys_url":"https://api.github.com/repos/jayoshih/kolibri/keys{/key_id}","collaborators_url":"https://api.github.com/repos/jayoshih/kolibri/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/jayoshih/kolibri/teams","hooks_url":"https://api.github.com/repos/jayoshih/kolibri/hooks","issue_events_url":"https://api.github.com/repos/jayoshih/kolibri/issues/events{/number}","events_url":"https://api.github.com/repos/jayoshih/kolibri/events","assignees_url":"https://api.github.com/repos/jayoshih/kolibri/assignees{/user}","branches_url":"https://api.github.com/repos/jayoshih/kolibri/branches{/branch}","tags_url":"https://api.github.com/repos/jayoshih/kolibri/tags","blobs_url":"https://api.github.com/repos/jayoshih/kolibri/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/jayoshih/kolibri/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/jayoshih/kolibri/git/refs{/sha}","trees_url":"https://api.github.com/repos/jayoshih/kolibri/git/trees{/sha}","statuses_url":"https://api.github.com/repos/jayoshih/kolibri/statuses/{sha}","languages_url":"https://api.github.com/repos/jayoshih/kolibri/languages","stargazers_url":"https://api.github.com/repos/jayoshih/kolibri/stargazers","contributors_url":"https://api.github.com/repos/jayoshih/kolibri/contributors","subscribers_url":"https://api.github.com/repos/jayoshih/kolibri/subscribers","subscription_url":"https://api.github.com/repos/jayoshih/kolibri/subscription","commits_url":"https://api.github.com/repos/jayoshih/kolibri/commits{/sha}","git_commits_url":"https://api.github.com/repos/jayoshih/kolibri/git/commits{/sha}","comments_url":"https://api.github.com/repos/jayoshih/kolibri/comments{/number}","issue_comment_url":"https://api.github.com/repos/jayoshih/kolibri/issues/comments{/number}","contents_url":"https://api.github.com/repos/jayoshih/kolibri/contents/{+path}","compare_url":"https://api.github.com/repos/jayoshih/kolibri/compare/{base}...{head}","merges_url":"https://api.github.com/repos/jayoshih/kolibri/merges","archive_url":"https://api.github.com/repos/jayoshih/kolibri/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/jayoshih/kolibri/downloads","issues_url":"https://api.github.com/repos/jayoshih/kolibri/issues{/number}","pulls_url":"https://api.github.com/repos/jayoshih/kolibri/pulls{/number}","milestones_url":"https://api.github.com/repos/jayoshih/kolibri/milestones{/number}","notifications_url":"https://api.github.com/repos/jayoshih/kolibri/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/jayoshih/kolibri/labels{/name}","releases_url":"https://api.github.com/repos/jayoshih/kolibri/releases{/id}","deployments_url":"https://api.github.com/repos/jayoshih/kolibri/deployments","created_at":"2016-02-26T22:12:13Z","updated_at":"2016-02-26T22:12:14Z","pushed_at":"2016-08-11T20:49:55Z","git_url":"git://github.com/jayoshih/kolibri.git","ssh_url":"git@github.com:jayoshih/kolibri.git","clone_url":"https://github.com/jayoshih/kolibri.git","svn_url":"https://github.com/jayoshih/kolibri","homepage":"http://learningequality.org/kolibri/","size":7352,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"learningequality:master","ref":"master","sha":"8d3e387159660794afdfb8342c81da239d9907b0","user":{"login":"learningequality","id":3926525,"avatar_url":"https://avatars.githubusercontent.com/u/3926525?v=3","gravatar_id":"","url":"https://api.github.com/users/learningequality","html_url":"https://github.com/learningequality","followers_url":"https://api.github.com/users/learningequality/followers","following_url":"https://api.github.com/users/learningequality/following{/other_user}","gists_url":"https://api.github.com/users/learningequality/gists{/gist_id}","starred_url":"https://api.github.com/users/learningequality/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/learningequality/subscriptions","organizations_url":"https://api.github.com/users/learningequality/orgs","repos_url":"https://api.github.com/users/learningequality/repos","events_url":"https://api.github.com/users/learningequality/events{/privacy}","received_events_url":"https://api.github.com/users/learningequality/received_events","type":"Organization","site_admin":false},"repo":{"id":49976939,"name":"kolibri","full_name":"learningequality/kolibri","owner":{"login":"learningequality","id":3926525,"avatar_url":"https://avatars.githubusercontent.com/u/3926525?v=3","gravatar_id":"","url":"https://api.github.com/users/learningequality","html_url":"https://github.com/learningequality","followers_url":"https://api.github.com/users/learningequality/followers","following_url":"https://api.github.com/users/learningequality/following{/other_user}","gists_url":"https://api.github.com/users/learningequality/gists{/gist_id}","starred_url":"https://api.github.com/users/learningequality/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/learningequality/subscriptions","organizations_url":"https://api.github.com/users/learningequality/orgs","repos_url":"https://api.github.com/users/learningequality/repos","events_url":"https://api.github.com/users/learningequality/events{/privacy}","received_events_url":"https://api.github.com/users/learningequality/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/learningequality/kolibri","description":"This is where Kolibri shall be born, watch and participate!","fork":false,"url":"https://api.github.com/repos/learningequality/kolibri","forks_url":"https://api.github.com/repos/learningequality/kolibri/forks","keys_url":"https://api.github.com/repos/learningequality/kolibri/keys{/key_id}","collaborators_url":"https://api.github.com/repos/learningequality/kolibri/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/learningequality/kolibri/teams","hooks_url":"https://api.github.com/repos/learningequality/kolibri/hooks","issue_events_url":"https://api.github.com/repos/learningequality/kolibri/issues/events{/number}","events_url":"https://api.github.com/repos/learningequality/kolibri/events","assignees_url":"https://api.github.com/repos/learningequality/kolibri/assignees{/user}","branches_url":"https://api.github.com/repos/learningequality/kolibri/branches{/branch}","tags_url":"https://api.github.com/repos/learningequality/kolibri/tags","blobs_url":"https://api.github.com/repos/learningequality/kolibri/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/learningequality/kolibri/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/learningequality/kolibri/git/refs{/sha}","trees_url":"https://api.github.com/repos/learningequality/kolibri/git/trees{/sha}","statuses_url":"https://api.github.com/repos/learningequality/kolibri/statuses/{sha}","languages_url":"https://api.github.com/repos/learningequality/kolibri/languages","stargazers_url":"https://api.github.com/repos/learningequality/kolibri/stargazers","contributors_url":"https://api.github.com/repos/learningequality/kolibri/contributors","subscribers_url":"https://api.github.com/repos/learningequality/kolibri/subscribers","subscription_url":"https://api.github.com/repos/learningequality/kolibri/subscription","commits_url":"https://api.github.com/repos/learningequality/kolibri/commits{/sha}","git_commits_url":"https://api.github.com/repos/learningequality/kolibri/git/commits{/sha}","comments_url":"https://api.github.com/repos/learningequality/kolibri/comments{/number}","issue_comment_url":"https://api.github.com/repos/learningequality/kolibri/issues/comments{/number}","contents_url":"https://api.github.com/repos/learningequality/kolibri/contents/{+path}","compare_url":"https://api.github.com/repos/learningequality/kolibri/compare/{base}...{head}","merges_url":"https://api.github.com/repos/learningequality/kolibri/merges","archive_url":"https://api.github.com/repos/learningequality/kolibri/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/learningequality/kolibri/downloads","issues_url":"https://api.github.com/repos/learningequality/kolibri/issues{/number}","pulls_url":"https://api.github.com/repos/learningequality/kolibri/pulls{/number}","milestones_url":"https://api.github.com/repos/learningequality/kolibri/milestones{/number}","notifications_url":"https://api.github.com/repos/learningequality/kolibri/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/learningequality/kolibri/labels{/name}","releases_url":"https://api.github.com/repos/learningequality/kolibri/releases{/id}","deployments_url":"https://api.github.com/repos/learningequality/kolibri/deployments","created_at":"2016-01-19T19:22:07Z","updated_at":"2016-07-15T21:33:22Z","pushed_at":"2016-08-12T15:54:43Z","git_url":"git://github.com/learningequality/kolibri.git","ssh_url":"git@github.com:learningequality/kolibri.git","clone_url":"https://github.com/learningequality/kolibri.git","svn_url":"https://github.com/learningequality/kolibri","homepage":"http://learningequality.org/kolibri/","size":7940,"stargazers_count":25,"watchers_count":25,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":31,"mirror_url":null,"open_issues_count":35,"forks":31,"open_issues":35,"watchers":25,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/learningequality/kolibri/pulls/374"},"html":{"href":"https://github.com/learningequality/kolibri/pull/374"},"issue":{"href":"https://api.github.com/repos/learningequality/kolibri/issues/374"},"comments":{"href":"https://api.github.com/repos/learningequality/kolibri/issues/374/comments"},"review_comments":{"href":"https://api.github.com/repos/learningequality/kolibri/pulls/374/comments"},"review_comment":{"href":"https://api.github.com/repos/learningequality/kolibri/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/learningequality/kolibri/pulls/374/commits"},"statuses":{"href":"https://api.github.com/repos/learningequality/kolibri/statuses/23d8dd816afc896d2ac7749ad579a71065617088"}}}}
{"actor":{"display_login":"jamalex"}}