Esempio n. 1
0
    def get(self, request, *args, **kwargs):
        """Show a threadedcomments discussion of an arbitrary object.
        discussion_id is the pk of the root comment."""

        discussion_id = kwargs.get('discussion_id', None)
        root_comment = get_object_or_404(ThreadedComment, pk=discussion_id)
        if not root_comment.content_object.permission_to(
                'read', request.course, request.user):
            return HttpResponseForbidden('You do not have permission \
                                         to view this discussion.')

        try:
            my_course = root_comment.content_object.context.content_object
        except:
            # legacy: for when contexts weren't being set in new()
            my_course = request.course
            root_comment.content_object.context = \
                Collaboration.objects.get_for_object(my_course)
            root_comment.content_object.save()

        data = {'space_owner': request.user.username}

        if not request.is_ajax():
            data['discussion'] = root_comment
            return render_to_response('discussions/discussion.html', data,
                                      context_instance=RequestContext(request))
        else:
            vocabulary = VocabularyResource().render_list(
                request, Vocabulary.objects.filter(course=request.course))

            user_resource = UserResource()
            owners = user_resource.render_list(request, request.course.members)

            data['panels'] = [{
                'panel_state': 'open',
                'subpanel_state': 'open',
                'panel_state_label': "Discussion",
                'template': 'discussion',
                'owners': owners,
                'vocabulary': vocabulary,
                'title': root_comment.title,
                'can_edit_title': my_course.is_faculty(request.user),
                'root_comment_id': root_comment.id,
                'context': threaded_comment_json(request, root_comment)
            }]

            # Create a place for asset editing
            panel = {'panel_state': 'closed',
                     'panel_state_label': "Item Details",
                     'template': 'asset_quick_edit',
                     'update_history': False,
                     'show_collection': False,
                     'owners': owners,
                     'vocabulary': vocabulary,
                     'context': {'type': 'asset'}}

            data['panels'].append(panel)

            return HttpResponse(json.dumps(data),
                                content_type='application/json')
Esempio n. 2
0
    def get(self, request, asset_id=None, annot_id=None):
        if asset_id:
            try:
                asset = Asset.objects.get(pk=asset_id, course=request.course)
                asset.primary
            except Asset.DoesNotExist:
                return asset_switch_course(request, asset_id)
            except Source.DoesNotExist:
                ctx = RequestContext(request)
                return render_to_response('500.html', {}, context_instance=ctx)

        data = {'asset_id': asset_id, 'annotation_id': annot_id}

        if not request.is_ajax():
            return render_to_response('assetmgr/asset_workspace.html',
                                      data,
                                      context_instance=RequestContext(request))
        ctx = {'type': 'asset'}
        if asset_id:
            # @todo - refactor this context out of the mix
            # ideally, the client would simply request the json
            # the mixin is expecting a queryset, so this becomes awkward here
            assets = Asset.objects.filter(pk=asset_id)
            (assets, notes) = self.visible_assets_and_notes(request, assets)

            # only return original author's global annotations
            notes = notes.exclude(~Q(author=request.user), range1__isnull=True)

            ares = AssetResource()
            ctx.update(ares.render_one_context(request, asset, notes))

            help_setting = UserSetting.get_setting(request.user,
                                                   "help_item_detail_view",
                                                   True)
            ctx['user_settings'] = {'help_item_detail_view': help_setting}

        vocabulary = VocabularyResource().render_list(
            request, Vocabulary.objects.get_for_object(request.course))

        user_resource = UserResource()
        owners = user_resource.render_list(request, request.course.members)

        update_history = True
        show_collection = True
        template = 'asset_workspace'

        data['panels'] = [{
            'panel_state': 'open',
            'panel_state_label': "Annotate Media",
            'context': ctx,
            'owners': owners,
            'vocabulary': vocabulary,
            'template': template,
            'current_asset': asset_id,
            'current_annotation': annot_id,
            'update_history': update_history,
            'show_collection': show_collection}]

        return self.render_to_json_response(data)
Esempio n. 3
0
    def get(self, request):
        user_resource = UserResource()
        owners = user_resource.render_list(request, request.course.members)

        data = {
            'owners': json.dumps(owners),
            'return_url': request.GET.get('return_url', '')
        }

        return self.render_to_response(data)
Esempio n. 4
0
    def get(self, request, asset_id=None, annot_id=None):

        if asset_id:
            try:
                asset = Asset.objects.get(pk=asset_id, course=request.course)
                asset.primary
            except Asset.DoesNotExist:
                return asset_switch_course(request, asset_id)
            except Source.DoesNotExist:
                ctx = RequestContext(request)
                return render_to_response('500.html', {}, context_instance=ctx)

        data = {'asset_id': asset_id, 'annotation_id': annot_id}

        if not request.is_ajax():
            return render_to_response('assetmgr/asset_workspace.html',
                                      data,
                                      context_instance=RequestContext(request))
        context = {'type': 'asset'}
        if asset_id:
            # @todo - refactor this context out of the mix
            # ideally, the client would simply request the json
            # the mixin is expecting a queryset, so this becomes awkward here
            self.record_owner = request.user
            assets = Asset.objects.filter(pk=asset_id)
            (assets, notes) = self.visible_assets_and_notes(request, assets)
            context['assets'] = {
                asset.pk: AssetResource().render_one(request, asset, notes)
            }

            help_setting = UserSetting.get_setting(request.user,
                                                   "help_item_detail_view",
                                                   True)
            context['user_settings'] = {'help_item_detail_view': help_setting}

        vocabulary = VocabularyResource().render_list(
            request, Vocabulary.objects.get_for_object(request.course))

        user_resource = UserResource()
        owners = user_resource.render_list(request, request.course.members)

        data['panels'] = [{
            'panel_state': 'open',
            'panel_state_label': "Annotate Media",
            'context': context,
            'owners': owners,
            'vocabulary': vocabulary,
            'template': 'asset_workspace',
            'current_asset': asset_id,
            'current_annotation': annot_id,
            'update_history': True,
            'show_collection': True
        }]

        return self.render_to_json_response(data)
Esempio n. 5
0
    def get(self, request):
        user_resource = UserResource()
        owners = user_resource.render_list(request, request.course.members)

        data = {
            'owners': json.dumps(owners),
            'return_url': request.GET.get('return_url', ''),
            'width': EMBED_WIDTH,
            'height': EMBED_HEIGHT
        }

        return self.render_to_response(data)
Esempio n. 6
0
    def get(self, request):
        user_resource = UserResource()
        owners = user_resource.render_list(request, request.course.members)

        data = {
            'owners': json.dumps(owners),
            'return_url': request.GET.get('return_url', ''),
            'width': EMBED_WIDTH,
            'height': EMBED_HEIGHT
        }

        return self.render_to_response(data)
Esempio n. 7
0
def asset_workspace(request, asset_id=None, annot_id=None):
    if not request.user.is_staff:
        in_course_or_404(request.user.username, request.course)

    if asset_id:
        try:
            asset = Asset.objects.get(pk=asset_id, course=request.course)
            asset.primary
        except Asset.DoesNotExist:
            return asset_switch_course(request, asset_id)
        except Source.DoesNotExist:
            response = direct_to_template(request, "500.html", {})
            response.status_code = 500
            return response

    data = {
        'space_owner': request.user.username,
        'asset_id': asset_id,
        'annotation_id': annot_id
    }

    if not request.is_ajax():
        return render_to_response('assetmgr/asset_workspace.html',
                                  data,
                                  context_instance=RequestContext(request))
    elif asset_id:
        # @todo - refactor this context out of the mix
        # ideally, the client would simply request the json
        context = detail_asset_json(request, asset)
    else:
        context = {'type': 'asset'}

    vocabulary = VocabularyResource().render_list(
        request, Vocabulary.objects.get_for_object(request.course))

    user_resource = UserResource()
    owners = user_resource.render_list(request, request.course.members)

    data['panels'] = [{
        'panel_state': 'open',
        'panel_state_label': "Annotate Media",
        'context': context,
        'owners': owners,
        'vocabulary': vocabulary,
        'template': 'asset_workspace',
        'current_asset': asset_id,
        'current_annotation': annot_id,
        'update_history': True,
        'show_collection': True,
    }]

    return HttpResponse(simplejson.dumps(data, indent=2),
                        mimetype='application/json')
Esempio n. 8
0
def asset_workspace(request, asset_id=None, annot_id=None):
    if not request.user.is_staff:
        in_course_or_404(request.user.username, request.course)

    if asset_id:
        try:
            asset = Asset.objects.get(pk=asset_id, course=request.course)
            asset.primary
        except Asset.DoesNotExist:
            return asset_switch_course(request, asset_id)
        except Source.DoesNotExist:
            response = direct_to_template(request, "500.html", {})
            response.status_code = 500
            return response

    data = {'space_owner': request.user.username,
            'asset_id': asset_id,
            'annotation_id': annot_id}

    if not request.is_ajax():
        return render_to_response('assetmgr/asset_workspace.html',
                                  data,
                                  context_instance=RequestContext(request))
    elif asset_id:
        # @todo - refactor this context out of the mix
        # ideally, the client would simply request the json
        context = detail_asset_json(request, asset)
    else:
        context = {'type': 'asset'}

    vocabulary = VocabularyResource().render_list(
        request, Vocabulary.objects.get_for_object(request.course))

    user_resource = UserResource()
    owners = user_resource.render_list(request, request.course.members)

    data['panels'] = [{'panel_state': 'open',
                       'panel_state_label': "Annotate Media",
                       'context': context,
                       'owners': owners,
                       'vocabulary': vocabulary,
                       'template': 'asset_workspace',
                       'current_asset': asset_id,
                       'current_annotation': annot_id,
                       'update_history': True,
                       'show_collection': True, }]

    return HttpResponse(simplejson.dumps(data, indent=2),
                        mimetype='application/json')
Esempio n. 9
0
    def get(self, request, course_pk=None, asset_id=None, annot_id=None):
        if asset_id:
            try:
                asset = Asset.objects.get(pk=asset_id, course=request.course)
                asset.primary
            except Asset.DoesNotExist:
                return asset_switch_course(request, asset_id)
            except Source.DoesNotExist:
                return render(request, '500.html', {})

        if not request.is_ajax():
            return self.redirect_to_react_views(request.course.id, asset_id,
                                                annot_id)

        ctx = {'asset_id': asset_id, 'annotation_id': annot_id}

        qs = Vocabulary.objects.filter(course=request.course)
        vocabulary = VocabularyResource().render_list(request, qs)

        user_resource = UserResource()
        owners = user_resource.render_list(request, request.course.members)

        ctx['panels'] = [{
            'panel_state': 'open',
            'panel_state_label': "Annotate Media",
            'context': {
                'type':
                'asset',
                'is_faculty':
                self.is_viewer_faculty,
                'allow_item_download':
                self.is_viewer_faculty
                and course_details.allow_item_download(request.course)
            },
            'owners': owners,
            'vocabulary': vocabulary,
            'template': 'asset_workspace',
            'current_asset': asset_id,
            'current_annotation': annot_id,
            'update_history': True,
            'show_collection': True
        }]

        return self.render_to_json_response(ctx)
Esempio n. 10
0
    def get(self, request, asset_id=None, annot_id=None):
        if asset_id:
            try:
                asset = Asset.objects.get(pk=asset_id, course=request.course)
                asset.primary
            except Asset.DoesNotExist:
                return asset_switch_course(request, asset_id)
            except Source.DoesNotExist:
                ctx = RequestContext(request)
                return render_to_response('500.html', {}, context_instance=ctx)

        ctx = {'asset_id': asset_id, 'annotation_id': annot_id}

        if not request.is_ajax():
            return render_to_response('assetmgr/asset_workspace.html',
                                      ctx,
                                      context_instance=RequestContext(request))

        qs = Vocabulary.objects.filter(course=request.course)
        vocabulary = VocabularyResource().render_list(request, qs)

        user_resource = UserResource()
        owners = user_resource.render_list(request, request.course.members)

        ctx['panels'] = [{
            'panel_state': 'open',
            'panel_state_label': "Annotate Media",
            'context': {
                'type': 'asset',
                'is_faculty': self.is_viewer_faculty,
                'allow_item_download': self.is_viewer_faculty and
                allow_item_download(request.course)
            },
            'owners': owners,
            'vocabulary': vocabulary,
            'template': 'asset_workspace',
            'current_asset': asset_id,
            'current_annotation': annot_id,
            'update_history': True,
            'show_collection': True}]

        return self.render_to_json_response(ctx)
Esempio n. 11
0
def discussion_create(request):

    """Start a discussion of an arbitrary model instance."""
    title = request.POST['comment_html']

    # Find the object we're discussing.
    the_content_type = ContentType.objects.get(
        app_label=request.POST['app_label'], model=request.POST['model'])
    assert the_content_type is not None

    the_object = the_content_type.get_object_for_this_type(
        pk=request.POST['obj_pk'])
    assert the_object is not None

    try:
        obj_sc = Collaboration.objects.get_for_object(the_object)
    except Collaboration.DoesNotExist:
        obj_sc = Collaboration()
        # TODO: populate this collab with sensible auth defaults.
        obj_sc.content_object = the_object
        obj_sc.save()

    # sky: I think what I want to do is have the ThreadedComment
    # point to the_object
    # and the collaboration will point to the threaded root comment
    # that way, whereas, if we live in Collaboration-land,
    # we can get to ThreadedComments
    # threaded comments can also live in it's own world without 'knowing'
    # about SC OTOH, threaded comment shouldn't be able
    # to point to the regular object
    # until Collaboration says it's OK (i.e. has permissions)
    # ISSUE: how to migrate? (see models.py)

    # now create the CHILD collaboration object for the discussion to point at.
    # This represents the auth for the discussion itself.
    disc_sc = Collaboration(_parent=obj_sc,
                            title=title,
                            # or we could point it at the root
                            # threadedcomments object.
                            # content_object=None,
                            context=request.collaboration_context,
                            )
    disc_sc.set_policy(request.POST.get('publish', None))
    disc_sc.save()

    # finally create the root discussion object, pointing it at the CHILD.
    new_threaded_comment = ThreadedComment(parent=None,
                                           title=title,
                                           comment='',
                                           user=request.user,
                                           content_object=disc_sc)

    # TODO: find the default site_id
    new_threaded_comment.site_id = 1
    new_threaded_comment.save()

    disc_sc.content_object = new_threaded_comment
    disc_sc.save()

    if not request.is_ajax():
        return HttpResponseRedirect("/discussion/%d/" %
                                    new_threaded_comment.id)
    else:
        vocabulary = VocabularyResource().render_list(
            request, Vocabulary.objects.get_for_object(request.course))

        user_resource = UserResource()
        owners = user_resource.render_list(request, request.course.members)

        data = {'panel_state': 'open',
                'panel_state_label': "Instructor Feedback",
                'template': 'discussion',
                'owners': owners,
                'vocabulary': vocabulary,
                'context': threaded_comment_json(request,
                                                 new_threaded_comment)}

        return HttpResponse(json.dumps(data, indent=2),
                            content_type='application/json')
Esempio n. 12
0
def discussion_create(request):
    """Start a discussion of an arbitrary model instance."""
    title = request.POST['comment_html']

    # Find the object we're discussing.
    the_content_type = ContentType.objects.get(
        app_label=request.POST['app_label'], model=request.POST['model'])
    assert the_content_type is not None

    the_object = the_content_type.get_object_for_this_type(
        pk=request.POST['obj_pk'])
    assert the_object is not None

    try:
        obj_sc = Collaboration.get_associated_collab(the_object)
    except Collaboration.DoesNotExist:
        obj_sc = Collaboration()
        # TODO: populate this collab with sensible auth defaults.
        obj_sc.content_object = the_object
        obj_sc.save()

    # sky: I think what I want to do is have the ThreadedComment
    # point to the_object
    # and the collaboration will point to the threaded root comment
    # that way, whereas, if we live in Collaboration-land,
    # we can get to ThreadedComments
    # threaded comments can also live in it's own world without 'knowing'
    # about SC OTOH, threaded comment shouldn't be able
    # to point to the regular object
    # until Collaboration says it's OK (i.e. has permissions)
    # ISSUE: how to migrate? (see models.py)

    # now create the CHILD collaboration object for the discussion to point at.
    # This represents the auth for the discussion itself.
    disc_sc = Collaboration(
        _parent=obj_sc,
        title=title,
        # or we could point it at the root
        # threadedcomments object.
        # content_object=None,
        context=request.collaboration_context,
    )
    disc_sc.policy = request.POST.get('publish', None)
    if request.POST.get('inherit', None) == 'true':
        disc_sc.group_id = obj_sc.group_id
        disc_sc.user_id = obj_sc.user_id
    disc_sc.save()

    # finally create the root discussion object, pointing it at the CHILD.
    new_threaded_comment = ThreadedComment(parent=None,
                                           title=title,
                                           comment='',
                                           user=request.user,
                                           content_object=disc_sc)

    # TODO: find the default site_id
    new_threaded_comment.site_id = 1
    new_threaded_comment.save()

    disc_sc.content_object = new_threaded_comment
    disc_sc.save()

    if not request.is_ajax():
        return HttpResponseRedirect("/discussion/%d/" %
                                    new_threaded_comment.id)
    else:
        vocabulary = VocabularyResource().render_list(
            request, Vocabulary.objects.get_for_object(request.course))

        user_resource = UserResource()
        owners = user_resource.render_list(request, request.course.members)

        data = {
            'panel_state': 'open',
            'panel_state_label': "Instructor Feedback",
            'template': 'discussion',
            'owners': owners,
            'vocabulary': vocabulary,
            'context': threaded_comment_json(request, new_threaded_comment)
        }

        return HttpResponse(simplejson.dumps(data, indent=2),
                            mimetype='application/json')
Esempio n. 13
0
def discussion_view(request, discussion_id):
    """Show a threadedcomments discussion of an arbitrary object.
    discussion_id is the pk of the root comment."""

    root_comment = get_object_or_404(ThreadedComment, pk=discussion_id)
    if not root_comment.content_object.permission_to('read', request):
        return HttpResponseForbidden('You do not have permission \
                                     to view this discussion.')

    try:
        my_course = root_comment.content_object.context.content_object
    except:
        # legacy: for when contexts weren't being set in new()
        my_course = request.course
        root_comment.content_object.context = \
            Collaboration.get_associated_collab(my_course)
        root_comment.content_object.save()

    data = {'space_owner': request.user.username}

    if not request.is_ajax():
        data['discussion'] = root_comment
        return render_to_response('discussions/discussion.html',
                                  data,
                                  context_instance=RequestContext(request))
    else:
        vocabulary = VocabularyResource().render_list(
            request, Vocabulary.objects.get_for_object(request.course))

        user_resource = UserResource()
        owners = user_resource.render_list(request, request.course.members)

        data['panels'] = [{
            'panel_state':
            'open',
            'subpanel_state':
            'open',
            'panel_state_label':
            "Discussion",
            'template':
            'discussion',
            'owners':
            owners,
            'vocabulary':
            vocabulary,
            'title':
            root_comment.title,
            'can_edit_title':
            my_course.is_faculty(request.user),
            'root_comment_id':
            root_comment.id,
            'context':
            threaded_comment_json(request, root_comment)
        }]

        # Create a place for asset editing
        panel = {
            'panel_state': 'closed',
            'panel_state_label': "Item Details",
            'template': 'asset_quick_edit',
            'update_history': False,
            'show_collection': False,
            'owners': owners,
            'vocabulary': vocabulary,
            'context': {
                'type': 'asset'
            }
        }

        data['panels'].append(panel)

        return HttpResponse(simplejson.dumps(data, indent=2),
                            mimetype='application/json')
Esempio n. 14
0
def project_workspace(request, project_id, feedback=None):
    """
    A multi-panel editable view for the specified project
    Legacy note: Ideally, this function would be named project_view but
    StructuredCollaboration requires the view name
    to be  <class>-view to do a reverse lookup

    Panel 1: Parent Assignment (if applicable)
    Panel 2: Project
    Panel 3: Instructor Feedback (if applicable & exists)

    Keyword arguments:
    project_id -- the model id
    """
    project = get_object_or_404(Project, pk=project_id)

    if not project.can_read(request):
        return HttpResponseForbidden("forbidden")

    show_feedback = feedback == "feedback"
    data = {'space_owner': request.user.username,
            'show_feedback': show_feedback}

    if not request.is_ajax():
        data['project'] = project
        return render_to_response('projects/project.html',
                                  data,
                                  context_instance=RequestContext(request))
    else:
        panels = []

        vocabulary = VocabularyResource().render_list(
            request, Vocabulary.objects.get_for_object(request.course))

        user_resource = UserResource()
        owners = user_resource.render_list(request, request.course.members)

        course = request.course
        is_faculty = course.is_faculty(request.user)
        is_assignment = project.is_assignment(request)
        can_edit = project.can_edit(request)
        feedback_discussion = project.feedback_discussion() \
            if is_faculty or can_edit else None

        # Project Parent (assignment) if exists
        parent_assignment = project.assignment()
        if parent_assignment:
            assignment_context = composition_project_json(
                request,
                parent_assignment,
                parent_assignment.can_edit(request))

            assignment_context['create_selection'] = True

            display = "open" if (project.title == "Untitled" and
                                 len(project.body) == 0) else "closed"

            panel = {'is_faculty': is_faculty,
                     'panel_state': display,
                     'subpanel_state': 'closed',
                     'context': assignment_context,
                     'owners': owners,
                     'vocabulary': vocabulary,
                     'template': 'project'}
            panels.append(panel)

        # Requested project, can be either an assignment or composition
        project_context = composition_project_json(request, project, can_edit)

        # only editing if it's new
        project_context['editing'] = \
            True if can_edit and len(project.body) < 1 else False

        project_context['create_instructor_feedback'] = \
            is_faculty and parent_assignment and not feedback_discussion

        panel = {'is_faculty': is_faculty,
                 'panel_state': 'closed' if show_feedback else 'open',
                 'context': project_context,
                 'template': 'project',
                 'owners': owners,
                 'vocabulary': vocabulary}
        panels.append(panel)

        # Project Response -- if the requested project is an assignment
        # This is primarily a student view. The student's response should
        # pop up automatically when the parent assignment is viewed.
        if is_assignment:
            responses = project.responses_by(request, request.user)
            if len(responses) > 0:
                response = responses[0]
                response_can_edit = response.can_edit(request)
                response_context = composition_project_json(request,
                                                            response,
                                                            response_can_edit)

                panel = {'is_faculty': is_faculty,
                         'panel_state': 'closed',
                         'context': response_context,
                         'template': 'project',
                         'owners': owners,
                         'vocabulary': vocabulary}
                panels.append(panel)

                if not feedback_discussion and response_can_edit:
                    feedback_discussion = response.feedback_discussion()

        data['panels'] = panels

        # If feedback exists for the requested project
        if feedback_discussion:
            # 3rd pane is the instructor feedback, if it exists
            panel = {'panel_state': 'open' if show_feedback else 'closed',
                     'panel_state_label': "Instructor Feedback",
                     'template': 'discussion',
                     'owners': owners,
                     'vocabulary': vocabulary,
                     'context': threaded_comment_json(request,
                                                      feedback_discussion)}
            panels.append(panel)

        # Create a place for asset editing
        panel = {'panel_state': 'closed',
                 'panel_state_label': "Item Details",
                 'template': 'asset_quick_edit',
                 'update_history': False,
                 'owners': owners,
                 'vocabulary': vocabulary,
                 'context': {'type': 'asset'}}
        panels.append(panel)

        return HttpResponse(simplejson.dumps(data, indent=2),
                            mimetype='application/json')
Esempio n. 15
0
    def post(self, request, *args, **kwargs):
        """Start a discussion of an arbitrary model instance."""
        title = request.POST['comment_html']
        comment = request.POST.get('comment', '')

        # Find the object we're discussing.
        model = request.POST['model']
        the_content_type = ContentType.objects.get(
            app_label=request.POST['app_label'], model=model)
        assert the_content_type is not None

        the_object = the_content_type.get_object_for_this_type(
            pk=request.POST['obj_pk'])
        assert the_object is not None

        try:
            obj_sc = Collaboration.objects.get_for_object(the_object)
        except Collaboration.DoesNotExist:
            obj_sc = Collaboration()
            # TODO: populate this collab with sensible auth defaults.
            obj_sc.content_object = the_object
            obj_sc.save()

        # sky: I think what I want to do is have the ThreadedComment
        # point to the_object
        # and the collaboration will point to the threaded root comment
        # that way, whereas, if we live in Collaboration-land,
        # we can get to ThreadedComments
        # threaded comments can also live in it's own world without 'knowing'
        # about SC OTOH, threaded comment shouldn't be able
        # to point to the regular object
        # until Collaboration says it's OK (i.e. has permissions)
        # ISSUE: how to migrate? (see models.py)

        # now create the CHILD collaboration object for the
        # discussion to point at.
        # This represents the auth for the discussion itself.
        collaboration_context = cached_course_collaboration(request.course)
        disc_sc = Collaboration(
            _parent=obj_sc,
            title=title,
            context=collaboration_context,
        )
        disc_sc.set_policy(request.POST.get('publish', None))
        disc_sc.save()

        # finally create the root discussion object, pointing it at the CHILD.
        new_threaded_comment = ThreadedComment(parent=None,
                                               title=title,
                                               comment=comment,
                                               user=request.user,
                                               content_object=disc_sc)

        # TODO: find the default site_id
        new_threaded_comment.site_id = 1
        new_threaded_comment.save()

        disc_sc.content_object = new_threaded_comment
        disc_sc.save()

        DiscussionIndex.update_class_references(
            new_threaded_comment.comment, new_threaded_comment.user,
            new_threaded_comment, new_threaded_comment.content_object,
            new_threaded_comment.user)

        if not request.is_ajax():
            if model == 'project':
                discussion_url = reverse('project-workspace',
                                         args=(request.course.pk,
                                               the_object.pk))
            else:
                discussion_url = reverse('discussion-view',
                                         args=(request.course.pk,
                                               new_threaded_comment.id))

            return HttpResponseRedirect(discussion_url)
        else:
            vocabulary = VocabularyResource().render_list(
                request, Vocabulary.objects.filter(course=request.course))

            user_resource = UserResource()
            owners = user_resource.render_list(request, request.course.members)

            data = {
                'panel_state': 'open',
                'panel_state_label': "Instructor Feedback",
                'template': 'discussion',
                'owners': owners,
                'vocabulary': vocabulary,
                'context': threaded_comment_json(request, new_threaded_comment)
            }

            return HttpResponse(json.dumps(data, indent=2),
                                content_type='application/json')
def get_records(request, record_owner, assets):
    course = request.course
    logged_in_user = request.user

    # Can the record_owner edit the records
    viewing_own_work = (record_owner == logged_in_user)
    viewing_faculty_records = record_owner and course.is_faculty(record_owner)

    # Allow the logged in user to add assets to his composition
    citable = ('citable' in request.GET and
               request.GET.get('citable') == 'true')

    # Is the current user faculty OR staff
    is_faculty = course.is_faculty(logged_in_user)

    # Does the course allow viewing other user selections?
    owner_selections_are_visible = (
        course_details.all_selections_are_visible(course) or
        viewing_own_work or viewing_faculty_records or is_faculty)

    # Filter the assets
    for fil in filter_by:
        filter_value = request.GET.get(fil)
        if filter_value:
            assets = [asset for asset in assets
                      if filter_by[fil](asset, filter_value, record_owner)]

    active_filters = get_active_filters(request, filter_by)

    # Spew out json for the assets
    asset_json = []
    options = {
        'owner_selections_are_visible': ('annotations' in request.GET and
                                         owner_selections_are_visible),
        'all_selections_are_visible':
        course_details.all_selections_are_visible(course) or is_faculty,
        'can_edit': viewing_own_work,
        'citable': citable
    }

    for asset in assets:
        asset_json.append(gallery_asset_json(request, asset, logged_in_user,
                                             record_owner, options))
    # Tags
    tags = []
    if record_owner:
        if owner_selections_are_visible:
            # Tags for selected user
            tags = Tag.objects.usage_for_queryset(
                record_owner.sherdnote_set.filter(asset__course=course),
                counts=True)
    else:
        if owner_selections_are_visible:
            # Tags for the whole class
            tags = Tag.objects.usage_for_queryset(
                SherdNote.objects.filter(asset__course=course),
                counts=True)
        else:
            # Tags for myself and faculty members
            tags = Tag.objects.usage_for_queryset(
                logged_in_user.sherdnote_set.filter(asset__course=course),
                counts=True)

            for f in course.faculty:
                tags.extend(Tag.objects.usage_for_queryset(
                            f.sherdnote_set.filter(asset__course=course),
                            counts=True))

    tags.sort(lambda a, b: cmp(a.name.lower(), b.name.lower()))

    user_resource = UserResource()
    owners = user_resource.render_list(request, request.course.members)

    # Assemble the context
    data = {'assets': asset_json,
            'tags': [{'name': tag.name} for tag in tags],
            'active_filters': active_filters,
            'space_viewer': user_resource.render_one(request, logged_in_user),
            'editable': viewing_own_work,
            'citable': citable,
            'owners': owners,
            'is_faculty': is_faculty, }

    if record_owner:
        data['space_owner'] = user_resource.render_one(request, record_owner)

    json_stream = simplejson.dumps(data, indent=2)
    return HttpResponse(json_stream, mimetype='application/json')