{"action":"created","comment":{"url":"https://api.github.com/repos/open-craft/problem-builder/pulls/comments/34553909","id":34553909,"diff_hunk":"@@ -66,23 +74,122 @@ class MentoringTableBlock(StudioEditableXBlockMixin, StudioContainerXBlockMixin,\n             {\"display_name\": \"Immunity Map\", \"value\": \"immunity-map\"},\n         ],\n     )\n-    editable_fields = (\"type\", )\n+    editable_fields = (\"type\", \"allow_download\")\n+    allow_download = Boolean(\n+        display_name=_(\"Allow Download\"),\n+        help=_(\"Allow students to download a copy of the table for themselves.\"),\n+        default=False,\n+        scope=Scope.content\n+    )\n+    allow_sharing = Boolean(\n+        display_name=_(\"Allow Sharing\"),\n+        help=_(\"Allow students to share their results with other students.\"),\n+        default=True,\n+        scope=Scope.content\n+    )\n+    # Stores who a user has allowed to see their table.\n+    shared_with = Dict(scope=Scope.user_state_summary)\n+    # Stores whose tables a user is allowed to view. This needs to be kept in sync with the previous field.\n+    view_options = Dict(scope=Scope.user_state_summary)\n     has_children = True\n \n-    def student_view(self, context):\n-        context = context.copy() if context else {}\n-        fragment = Fragment()\n+    css_path = 'public/css/mentoring-table.css'\n+    js_path = 'public/js/review_blocks.js'\n+\n+    @XBlock.json_handler\n+    def table_render(self, data, suffix=''):\n+        context = {}\n         header_values = []\n         content_values = []\n+        user_service = self.runtime.service(self, 'user')\n+        target_username = data.get('target_username')\n+        if user_service and target_username:\n+            username = user_service.get_current_user().opt_attrs['edx-platform.username'].lower()\n+            permitted = self.view_options.get(username)\n+            if target_username in permitted:\n+                context['student_submissions_key'] = user_service.get_anonymous_user_id(\n+                    target_username, unicode(self.runtime.course_id)\n+                )\n+            elif target_username == username:\n+                # Use default settings.\n+                pass\n+            else:\n+                raise JsonHandlerError(403, _(\"You are not permitted to view this student's table.\"))\n+\n         for child_id in self.children:\n             child = self.runtime.get_block(child_id)\n             # Child should be an instance of MentoringTableColumn\n             header_values.append(child.header)\n             child_frag = child.render('mentoring_view', context)\n             content_values.append(child_frag.content)\n-            fragment.add_frag_resources(child_frag)\n         context['header_values'] = header_values if any(header_values) else None\n         context['content_values'] = content_values\n+        html = loader.render_template('templates/html/mentoring-table.html', context)\n+        return {'content': html}\n+\n+    @property\n+    def current_user_key(self):\n+        user = self.runtime.service(self, 'user').get_current_user()\n+        # We may be in the SDK, in which case the username may not really be available.\n+        return user.opt_attrs.get('edx-platform.username', 'username').lower()\n+\n+    @XBlock.json_handler\n+    def get_shared_list(self, data, suffix=''):\n+        context = {'shared_with': self.shared_with.get(self.current_user_key, [])}\n+        return {\n+            'content': loader.render_template('templates/html/mentoring-table-shared-list.html', context)\n+        }\n+\n+    @XBlock.json_handler\n+    def share_results(self, data, suffix=''):\n+        target_usernames = data.get('usernames')\n+        target_usernames = [username.strip().lower() for username in target_usernames if username.strip()]\n+        current_username = self.current_user_key\n+        if not target_usernames:\n+            raise JsonHandlerError(400, _('Usernames not provided.'))\n+        shared_with = self.shared_with.get(current_username, [])","path":"problem_builder/table.py","position":114,"original_position":114,"commit_id":"dc931522bcbda30ce64410425b4c3793a8e81f4f","original_commit_id":"dc931522bcbda30ce64410425b4c3793a8e81f4f","user":{"login":"e-kolpakov","id":3330048,"avatar_url":"https://avatars.githubusercontent.com/u/3330048?v=3","gravatar_id":"","url":"https://api.github.com/users/e-kolpakov","html_url":"https://github.com/e-kolpakov","followers_url":"https://api.github.com/users/e-kolpakov/followers","following_url":"https://api.github.com/users/e-kolpakov/following{/other_user}","gists_url":"https://api.github.com/users/e-kolpakov/gists{/gist_id}","starred_url":"https://api.github.com/users/e-kolpakov/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/e-kolpakov/subscriptions","organizations_url":"https://api.github.com/users/e-kolpakov/orgs","repos_url":"https://api.github.com/users/e-kolpakov/repos","events_url":"https://api.github.com/users/e-kolpakov/events{/privacy}","received_events_url":"https://api.github.com/users/e-kolpakov/received_events","type":"User","site_admin":false},"body":"@Kelketek shared_with and view_options could be sets - in such case it wouldn't be necessary to check if it's already there - just add to a set.","created_at":"2015-07-14T10:15:30Z","updated_at":"2015-07-14T10:15:30Z","html_url":"https://github.com/open-craft/problem-builder/pull/43#discussion_r34553909","pull_request_url":"https://api.github.com/repos/open-craft/problem-builder/pulls/43","_links":{"self":{"href":"https://api.github.com/repos/open-craft/problem-builder/pulls/comments/34553909"},"html":{"href":"https://github.com/open-craft/problem-builder/pull/43#discussion_r34553909"},"pull_request":{"href":"https://api.github.com/repos/open-craft/problem-builder/pulls/43"}}},"pull_request":{"url":"https://api.github.com/repos/open-craft/problem-builder/pulls/43","id":39525570,"html_url":"https://github.com/open-craft/problem-builder/pull/43","diff_url":"https://github.com/open-craft/problem-builder/pull/43.diff","patch_url":"https://github.com/open-craft/problem-builder/pull/43.patch","issue_url":"https://api.github.com/repos/open-craft/problem-builder/issues/43","number":43,"state":"open","locked":false,"title":"Allow students to download a copy of their answer table.","user":{"login":"Kelketek","id":1099483,"avatar_url":"https://avatars.githubusercontent.com/u/1099483?v=3","gravatar_id":"","url":"https://api.github.com/users/Kelketek","html_url":"https://github.com/Kelketek","followers_url":"https://api.github.com/users/Kelketek/followers","following_url":"https://api.github.com/users/Kelketek/following{/other_user}","gists_url":"https://api.github.com/users/Kelketek/gists{/gist_id}","starred_url":"https://api.github.com/users/Kelketek/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Kelketek/subscriptions","organizations_url":"https://api.github.com/users/Kelketek/orgs","repos_url":"https://api.github.com/users/Kelketek/repos","events_url":"https://api.github.com/users/Kelketek/events{/privacy}","received_events_url":"https://api.github.com/users/Kelketek/received_events","type":"User","site_admin":false},"body":"","created_at":"2015-07-08T21:28:44Z","updated_at":"2015-07-14T10:15:30Z","closed_at":null,"merged_at":null,"merge_commit_sha":"4a7228923dab34ca657cf444eedca5b76f1c1690","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/open-craft/problem-builder/pulls/43/commits","review_comments_url":"https://api.github.com/repos/open-craft/problem-builder/pulls/43/comments","review_comment_url":"https://api.github.com/repos/open-craft/problem-builder/pulls/comments{/number}","comments_url":"https://api.github.com/repos/open-craft/problem-builder/issues/43/comments","statuses_url":"https://api.github.com/repos/open-craft/problem-builder/statuses/dc931522bcbda30ce64410425b4c3793a8e81f4f","head":{"label":"open-craft:download-table","ref":"download-table","sha":"dc931522bcbda30ce64410425b4c3793a8e81f4f","user":{"login":"open-craft","id":7414786,"avatar_url":"https://avatars.githubusercontent.com/u/7414786?v=3","gravatar_id":"","url":"https://api.github.com/users/open-craft","html_url":"https://github.com/open-craft","followers_url":"https://api.github.com/users/open-craft/followers","following_url":"https://api.github.com/users/open-craft/following{/other_user}","gists_url":"https://api.github.com/users/open-craft/gists{/gist_id}","starred_url":"https://api.github.com/users/open-craft/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/open-craft/subscriptions","organizations_url":"https://api.github.com/users/open-craft/orgs","repos_url":"https://api.github.com/users/open-craft/repos","events_url":"https://api.github.com/users/open-craft/events{/privacy}","received_events_url":"https://api.github.com/users/open-craft/received_events","type":"Organization","site_admin":false},"repo":{"id":33264452,"name":"problem-builder","full_name":"open-craft/problem-builder","owner":{"login":"open-craft","id":7414786,"avatar_url":"https://avatars.githubusercontent.com/u/7414786?v=3","gravatar_id":"","url":"https://api.github.com/users/open-craft","html_url":"https://github.com/open-craft","followers_url":"https://api.github.com/users/open-craft/followers","following_url":"https://api.github.com/users/open-craft/following{/other_user}","gists_url":"https://api.github.com/users/open-craft/gists{/gist_id}","starred_url":"https://api.github.com/users/open-craft/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/open-craft/subscriptions","organizations_url":"https://api.github.com/users/open-craft/orgs","repos_url":"https://api.github.com/users/open-craft/repos","events_url":"https://api.github.com/users/open-craft/events{/privacy}","received_events_url":"https://api.github.com/users/open-craft/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/open-craft/problem-builder","description":"An XBlock for posing questions to students","fork":false,"url":"https://api.github.com/repos/open-craft/problem-builder","forks_url":"https://api.github.com/repos/open-craft/problem-builder/forks","keys_url":"https://api.github.com/repos/open-craft/problem-builder/keys{/key_id}","collaborators_url":"https://api.github.com/repos/open-craft/problem-builder/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/open-craft/problem-builder/teams","hooks_url":"https://api.github.com/repos/open-craft/problem-builder/hooks","issue_events_url":"https://api.github.com/repos/open-craft/problem-builder/issues/events{/number}","events_url":"https://api.github.com/repos/open-craft/problem-builder/events","assignees_url":"https://api.github.com/repos/open-craft/problem-builder/assignees{/user}","branches_url":"https://api.github.com/repos/open-craft/problem-builder/branches{/branch}","tags_url":"https://api.github.com/repos/open-craft/problem-builder/tags","blobs_url":"https://api.github.com/repos/open-craft/problem-builder/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/open-craft/problem-builder/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/open-craft/problem-builder/git/refs{/sha}","trees_url":"https://api.github.com/repos/open-craft/problem-builder/git/trees{/sha}","statuses_url":"https://api.github.com/repos/open-craft/problem-builder/statuses/{sha}","languages_url":"https://api.github.com/repos/open-craft/problem-builder/languages","stargazers_url":"https://api.github.com/repos/open-craft/problem-builder/stargazers","contributors_url":"https://api.github.com/repos/open-craft/problem-builder/contributors","subscribers_url":"https://api.github.com/repos/open-craft/problem-builder/subscribers","subscription_url":"https://api.github.com/repos/open-craft/problem-builder/subscription","commits_url":"https://api.github.com/repos/open-craft/problem-builder/commits{/sha}","git_commits_url":"https://api.github.com/repos/open-craft/problem-builder/git/commits{/sha}","comments_url":"https://api.github.com/repos/open-craft/problem-builder/comments{/number}","issue_comment_url":"https://api.github.com/repos/open-craft/problem-builder/issues/comments{/number}","contents_url":"https://api.github.com/repos/open-craft/problem-builder/contents/{+path}","compare_url":"https://api.github.com/repos/open-craft/problem-builder/compare/{base}...{head}","merges_url":"https://api.github.com/repos/open-craft/problem-builder/merges","archive_url":"https://api.github.com/repos/open-craft/problem-builder/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/open-craft/problem-builder/downloads","issues_url":"https://api.github.com/repos/open-craft/problem-builder/issues{/number}","pulls_url":"https://api.github.com/repos/open-craft/problem-builder/pulls{/number}","milestones_url":"https://api.github.com/repos/open-craft/problem-builder/milestones{/number}","notifications_url":"https://api.github.com/repos/open-craft/problem-builder/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/open-craft/problem-builder/labels{/name}","releases_url":"https://api.github.com/repos/open-craft/problem-builder/releases{/id}","created_at":"2015-04-01T18:18:42Z","updated_at":"2015-05-14T03:28:29Z","pushed_at":"2015-07-14T09:41:35Z","git_url":"git://github.com/open-craft/problem-builder.git","ssh_url":"git@github.com:open-craft/problem-builder.git","clone_url":"https://github.com/open-craft/problem-builder.git","svn_url":"https://github.com/open-craft/problem-builder","homepage":null,"size":4452,"stargazers_count":2,"watchers_count":2,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":6,"forks":0,"open_issues":6,"watchers":2,"default_branch":"master"}},"base":{"label":"open-craft:master","ref":"master","sha":"472a3130ab90397396affcfc95347047c46b4414","user":{"login":"open-craft","id":7414786,"avatar_url":"https://avatars.githubusercontent.com/u/7414786?v=3","gravatar_id":"","url":"https://api.github.com/users/open-craft","html_url":"https://github.com/open-craft","followers_url":"https://api.github.com/users/open-craft/followers","following_url":"https://api.github.com/users/open-craft/following{/other_user}","gists_url":"https://api.github.com/users/open-craft/gists{/gist_id}","starred_url":"https://api.github.com/users/open-craft/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/open-craft/subscriptions","organizations_url":"https://api.github.com/users/open-craft/orgs","repos_url":"https://api.github.com/users/open-craft/repos","events_url":"https://api.github.com/users/open-craft/events{/privacy}","received_events_url":"https://api.github.com/users/open-craft/received_events","type":"Organization","site_admin":false},"repo":{"id":33264452,"name":"problem-builder","full_name":"open-craft/problem-builder","owner":{"login":"open-craft","id":7414786,"avatar_url":"https://avatars.githubusercontent.com/u/7414786?v=3","gravatar_id":"","url":"https://api.github.com/users/open-craft","html_url":"https://github.com/open-craft","followers_url":"https://api.github.com/users/open-craft/followers","following_url":"https://api.github.com/users/open-craft/following{/other_user}","gists_url":"https://api.github.com/users/open-craft/gists{/gist_id}","starred_url":"https://api.github.com/users/open-craft/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/open-craft/subscriptions","organizations_url":"https://api.github.com/users/open-craft/orgs","repos_url":"https://api.github.com/users/open-craft/repos","events_url":"https://api.github.com/users/open-craft/events{/privacy}","received_events_url":"https://api.github.com/users/open-craft/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/open-craft/problem-builder","description":"An XBlock for posing questions to students","fork":false,"url":"https://api.github.com/repos/open-craft/problem-builder","forks_url":"https://api.github.com/repos/open-craft/problem-builder/forks","keys_url":"https://api.github.com/repos/open-craft/problem-builder/keys{/key_id}","collaborators_url":"https://api.github.com/repos/open-craft/problem-builder/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/open-craft/problem-builder/teams","hooks_url":"https://api.github.com/repos/open-craft/problem-builder/hooks","issue_events_url":"https://api.github.com/repos/open-craft/problem-builder/issues/events{/number}","events_url":"https://api.github.com/repos/open-craft/problem-builder/events","assignees_url":"https://api.github.com/repos/open-craft/problem-builder/assignees{/user}","branches_url":"https://api.github.com/repos/open-craft/problem-builder/branches{/branch}","tags_url":"https://api.github.com/repos/open-craft/problem-builder/tags","blobs_url":"https://api.github.com/repos/open-craft/problem-builder/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/open-craft/problem-builder/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/open-craft/problem-builder/git/refs{/sha}","trees_url":"https://api.github.com/repos/open-craft/problem-builder/git/trees{/sha}","statuses_url":"https://api.github.com/repos/open-craft/problem-builder/statuses/{sha}","languages_url":"https://api.github.com/repos/open-craft/problem-builder/languages","stargazers_url":"https://api.github.com/repos/open-craft/problem-builder/stargazers","contributors_url":"https://api.github.com/repos/open-craft/problem-builder/contributors","subscribers_url":"https://api.github.com/repos/open-craft/problem-builder/subscribers","subscription_url":"https://api.github.com/repos/open-craft/problem-builder/subscription","commits_url":"https://api.github.com/repos/open-craft/problem-builder/commits{/sha}","git_commits_url":"https://api.github.com/repos/open-craft/problem-builder/git/commits{/sha}","comments_url":"https://api.github.com/repos/open-craft/problem-builder/comments{/number}","issue_comment_url":"https://api.github.com/repos/open-craft/problem-builder/issues/comments{/number}","contents_url":"https://api.github.com/repos/open-craft/problem-builder/contents/{+path}","compare_url":"https://api.github.com/repos/open-craft/problem-builder/compare/{base}...{head}","merges_url":"https://api.github.com/repos/open-craft/problem-builder/merges","archive_url":"https://api.github.com/repos/open-craft/problem-builder/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/open-craft/problem-builder/downloads","issues_url":"https://api.github.com/repos/open-craft/problem-builder/issues{/number}","pulls_url":"https://api.github.com/repos/open-craft/problem-builder/pulls{/number}","milestones_url":"https://api.github.com/repos/open-craft/problem-builder/milestones{/number}","notifications_url":"https://api.github.com/repos/open-craft/problem-builder/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/open-craft/problem-builder/labels{/name}","releases_url":"https://api.github.com/repos/open-craft/problem-builder/releases{/id}","created_at":"2015-04-01T18:18:42Z","updated_at":"2015-05-14T03:28:29Z","pushed_at":"2015-07-14T09:41:35Z","git_url":"git://github.com/open-craft/problem-builder.git","ssh_url":"git@github.com:open-craft/problem-builder.git","clone_url":"https://github.com/open-craft/problem-builder.git","svn_url":"https://github.com/open-craft/problem-builder","homepage":null,"size":4452,"stargazers_count":2,"watchers_count":2,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":6,"forks":0,"open_issues":6,"watchers":2,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/open-craft/problem-builder/pulls/43"},"html":{"href":"https://github.com/open-craft/problem-builder/pull/43"},"issue":{"href":"https://api.github.com/repos/open-craft/problem-builder/issues/43"},"comments":{"href":"https://api.github.com/repos/open-craft/problem-builder/issues/43/comments"},"review_comments":{"href":"https://api.github.com/repos/open-craft/problem-builder/pulls/43/comments"},"review_comment":{"href":"https://api.github.com/repos/open-craft/problem-builder/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/open-craft/problem-builder/pulls/43/commits"},"statuses":{"href":"https://api.github.com/repos/open-craft/problem-builder/statuses/dc931522bcbda30ce64410425b4c3793a8e81f4f"}}}}