示例#1
0
    def get_context(self, request, assets, notes):
        # Allow the logged in user to add assets to his composition
        citable = request.GET.get('citable', '') == 'true'

        # Include annotation metadata. (makes response much larger)
        include_annotations = request.GET.get('annotations', '') == 'true'

        # Initialize the context
        ures = UserResource()
        ctx = {
            'space_viewer': ures.render_one(request, self.record_viewer),
            'is_faculty': self.is_viewer_faculty
        }

        if self.record_owner:
            ctx['space_owner'] = ures.render_one(request, self.record_owner)

        ctx['active_filters'] = {}
        for key, val in request.GET.items():
            if (key in self.valid_filters or key.startswith('vocabulary-')):
                ctx['active_filters'][key] = val

        ctx['editable'] = self.viewing_own_records
        ctx['citable'] = citable

        # render the assets
        ares = AssetResource(include_annotations=include_annotations,
                             extras={
                                 'editable': self.viewing_own_records,
                                 'citable': citable
                             })
        ctx['assets'] = ares.render_list(request, self.record_viewer, assets,
                                         notes)

        return ctx
def all_projects(request):
    """
    An ajax-only request to retrieve a course's projects,
    assignment responses and selections
    """

    if not request.is_ajax():
        raise Http404()

    if not request.user.is_staff:
        in_course_or_404(request.user.username, request.course)

    course = request.course
    logged_in_user = request.user

    projects = Project.objects.visible_by_course(request, course)

    # Assemble the context
    user_rez = UserResource()
    course_rez = CourseSummaryResource()
    data = {'projects': homepage_project_json(request, projects, False),
            'space_viewer': user_rez.render_one(request, logged_in_user),
            'course': course_rez.render_one(request, course),
            'compositions': len(projects) > 0,
            'is_faculty': course.is_faculty(logged_in_user)}

    json_stream = simplejson.dumps(data, indent=2)
    return HttpResponse(json_stream, mimetype='application/json')
示例#3
0
    def get_context(self, request, assets, notes):
        # Allow the logged in user to add assets to his composition
        citable = request.GET.get('citable', '') == 'true'

        # Include annotation metadata. (makes response much larger)
        include_annotations = request.GET.get('annotations', '') == 'true'

        # Initialize the context
        ures = UserResource()
        ctx = {
            'space_viewer': ures.render_one(request, self.record_viewer),
            'is_faculty': self.is_viewer_faculty
        }

        if self.record_owner:
            ctx['space_owner'] = ures.render_one(request, self.record_owner)

        ctx['active_filters'] = {}
        for key, val in request.GET.items():
            if (key in self.valid_filters or key.startswith('vocabulary-')):
                ctx['active_filters'][key] = val

        ctx['editable'] = self.viewing_own_records
        ctx['citable'] = citable

        # render the assets
        ares = AssetResource(include_annotations=include_annotations,
                             extras={'editable': self.viewing_own_records,
                                     'citable': citable})
        ctx['assets'] = ares.render_list(request,
                                         self.record_viewer,
                                         assets, notes)

        return ctx
示例#4
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')
示例#5
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)
示例#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', '')
        }

        return self.render_to_response(data)
示例#7
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)
示例#8
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)
示例#9
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)
示例#10
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')
示例#11
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')
示例#12
0
    def test_render_list(self):
        u = UserFactory(username='******',
                        first_name='Student',
                        last_name='One')

        self.assertTrue(self.client.login(username=u.username,
                                          password="******"))

        g1 = GroupFactory(name="group1")
        g2 = GroupFactory(name="group2")
        CourseFactory(title="Sample Course", faculty_group=g1, group=g2)
        u.groups.add(g2)
        UserFactory(username='******',
                    first_name='Instructor',
                    last_name='One').groups.add(g2)
        UserFactory(username='******').groups.add(g2)
        UserFactory(username='******').groups.add(g2)
        UserFactory(username='******',
                    first_name='Student',
                    last_name='Two').groups.add(g2)
        UserFactory(username='******',
                    first_name="Teacher's",
                    last_name="Assistant").groups.add(g2)

        sample_course = Course.objects.get(title="Sample Course")

        members = UserResource().render_list(None, sample_course.members)

        self.assertEquals(len(members), 6)
        self.assertEquals(members[0]['public_name'], "test_instructor_two")
        self.assertEquals(members[1]['public_name'], "test_student_three")
        self.assertEquals(members[2]['public_name'], "Assistant, Teacher's")
        self.assertEquals(members[3]['public_name'], "One, Instructor")
        self.assertEquals(members[4]['public_name'], "One, Student")
        self.assertEquals(members[5]['public_name'], "Two, Student")
示例#13
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)
def your_projects(request, record_owner_name):
    """
    An ajax-only request to retrieve a specified user's projects,
    assignment responses and selections
    """
    if not request.is_ajax():
        raise Http404()

    course = request.course
    in_course_or_404(record_owner_name, course)

    logged_in_user = request.user
    is_faculty = course.is_faculty(logged_in_user)
    record_owner = get_object_or_404(User, username=record_owner_name)
    viewing_own_work = record_owner == logged_in_user

    # Record Owner's Visible Work,
    # sorted by modified date & feedback (if applicable)
    projects = Project.objects.visible_by_course_and_user(request,
                                                          course,
                                                          record_owner)

    # Show unresponded assignments if viewing self & self is a student
    assignments = []
    if not is_faculty and viewing_own_work:
        assignments = Project.objects.unresponded_assignments(request,
                                                              logged_in_user)

    # Assemble the context
    user_rez = UserResource()
    course_rez = CourseSummaryResource()
    data = {
        'assignments': homepage_assignment_json(assignments, is_faculty),
        'projects': homepage_project_json(request, projects, viewing_own_work),
        'space_viewer': user_rez.render_one(request, logged_in_user),
        'space_owner': user_rez.render_one(request, record_owner),
        'editable': viewing_own_work,
        'course': course_rez.render_one(request, course),
        'compositions': len(projects) > 0 or len(assignments) > 0,
        'is_faculty': is_faculty}

    json_stream = simplejson.dumps(data, indent=2)
    return HttpResponse(json_stream, mimetype='application/json')
示例#15
0
    def test_render_one(self):
        self.assertTrue(
            self.api_client.client.login(username="******",
                                         password="******"))

        student_one = User.objects.get(username='******')

        member = UserResource().render_one(None, student_one)

        self.assertEquals(member['public_name'], "Student One")
示例#16
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)
示例#17
0
    def test_render_one(self):
        u = UserFactory(username='******',
                        first_name='Student', last_name='One')
        self.assertTrue(
            self.client.login(username=u.username, password="******"))

        student_one = User.objects.get(username='******')

        member = UserResource().render_one(None, student_one)

        self.assertEquals(member['public_name'], "Student One")
示例#18
0
def your_projects(request, record_owner_name):
    """
    An ajax-only request to retrieve a specified user's projects,
    assignment responses and selections
    """
    course = request.course
    in_course_or_404(record_owner_name, course)

    logged_in_user = request.user
    is_faculty = course.is_faculty(logged_in_user)
    record_owner = get_object_or_404(User, username=record_owner_name)
    viewing_own_work = record_owner == logged_in_user

    # Record Owner's Visible Work,
    # sorted by modified date & feedback (if applicable)
    projects = Project.objects.visible_by_course_and_user(request,
                                                          course,
                                                          record_owner)

    # Show unresponded assignments if viewing self & self is a student
    assignments = []
    if not is_faculty and viewing_own_work:
        assignments = Project.objects.unresponded_assignments(request,
                                                              logged_in_user)

    # Assemble the context
    user_rez = UserResource()
    course_rez = CourseSummaryResource()
    data = {
        'assignments': homepage_assignment_json(assignments, is_faculty),
        'projects': homepage_project_json(request, projects, viewing_own_work),
        'space_viewer': user_rez.render_one(request, logged_in_user),
        'space_owner': user_rez.render_one(request, record_owner),
        'editable': viewing_own_work,
        'course': course_rez.render_one(request, course),
        'compositions': len(projects) > 0 or len(assignments) > 0,
        'is_faculty': is_faculty}

    json_stream = simplejson.dumps(data, indent=2)
    return HttpResponse(json_stream, mimetype='application/json')
示例#19
0
    def get(self, request):
        ures = UserResource()
        course_res = CourseResource()
        pres = ProjectResource(editable=self.viewing_own_records,
                               record_viewer=self.record_viewer,
                               is_viewer_faculty=self.is_viewer_faculty)
        assignments = []

        ctx = {
            'space_viewer': ures.render_one(request, self.record_viewer),
            'editable': self.viewing_own_records,
            'course': course_res.render_one(request, request.course),
            'is_faculty': self.is_viewer_faculty,
            'is_superuser': request.user.is_superuser,
        }

        if self.record_owner:
            ctx['space_owner'] = ures.render_one(request, self.record_owner)

            if not request.course.is_true_member(self.record_owner):
                return self.render_to_json_response(ctx)

            projects = Project.objects.visible_by_course_and_user(
                request.course, request.user, self.record_owner,
                self.viewing_faculty_records)

            # Show unresponded assignments if viewing self & self is a student
            if not self.is_viewer_faculty and self.viewing_own_records:
                assignments = list(
                    Project.objects.unresponded_assignments(
                        request.course, request.user))
        else:
            projects = Project.objects.visible_by_course(
                request.course, request.user)

        # update counts and paginate
        ctx['compositions'] = len(projects) > 0 or len(assignments) > 0
        ctx.update(self.paginate(pres, assignments, projects))
        return self.render_to_json_response(ctx)
示例#20
0
def deprecated_course_detail_view(request, course_pk):
    try:
        course = get_object_or_404(Course, pk=course_pk)
        request.course = course
        request.session[SESSION_KEY] = course
    except Course.DoesNotExist:
        return HttpResponseRedirect('/accounts/login/')

    logged_in_user = request.user
    classwork_owner = request.user  # Viewing your own work by default
    if 'username' in request.GET:
        user_name = request.GET['username']
        in_course_or_404(user_name, request.course)
        classwork_owner = get_object_or_404(User, username=user_name)

    qs = ExternalCollection.objects.filter(course=request.course)
    collections = qs.filter(uploader=False).order_by('title')
    uploader = qs.filter(uploader=True).first()

    owners = []
    if (request.course.is_member(logged_in_user)
            and (logged_in_user.is_staff
                 or logged_in_user.has_perm('assetmgr.can_upload_for'))):
        owners = UserResource().render_list(request, request.course.members)

    context = {
        'classwork_owner':
        classwork_owner,
        'information_title':
        course_information_title(course),
        'faculty_feed':
        Project.objects.faculty_compositions(course, logged_in_user),
        'is_faculty':
        cached_course_is_faculty(course, logged_in_user),
        'discussions':
        get_course_discussions(course),
        'msg':
        request.GET.get('msg', ''),
        'view':
        request.GET.get('view', ''),
        'collections':
        collections,
        'uploader':
        uploader,
        'can_upload':
        course_details.can_upload(request.user, request.course),
        'owners':
        owners
    }

    return context
示例#21
0
    def get(self, request):
        ures = UserResource()
        course_rez = CourseResource()
        pres = ProjectResource(editable=self.viewing_own_records,
                               record_viewer=self.record_viewer,
                               is_viewer_faculty=self.is_viewer_faculty)
        assignments = []

        ctx = {
            'space_viewer': ures.render_one(request, self.record_viewer),
            'editable': self.viewing_own_records,
            'course': course_rez.render_one(request, request.course),
            'is_faculty': self.is_viewer_faculty
        }

        if (self.record_owner):
            in_course_or_404(self.record_owner.username, request.course)

            projects = Project.objects.visible_by_course_and_user(
                request, request.course, self.record_owner,
                self.viewing_faculty_records)

            # Show unresponded assignments if viewing self & self is a student
            if not self.is_viewer_faculty and self.viewing_own_records:
                assignments = Project.objects.unresponded_assignments(
                    request, self.record_viewer)

            ctx['space_owner'] = ures.render_one(request, self.record_owner)
            ctx['assignments'] = pres.render_assignments(request, assignments)
        else:
            projects = Project.objects.visible_by_course(
                request, request.course)

        ctx['projects'] = pres.render_projects(request, projects)
        ctx['compositions'] = len(projects) > 0 or len(assignments) > 0

        return self.render_to_json_response(ctx)
示例#22
0
def all_projects(request):
    """
    An ajax-only request to retrieve a course's projects,
    assignment responses and selections
    """
    if not request.user.is_staff:
        in_course_or_404(request.user.username, request.course)

    course = request.course
    logged_in_user = request.user

    projects = Project.objects.visible_by_course(request, course)

    # Assemble the context
    user_rez = UserResource()
    course_rez = CourseSummaryResource()
    data = {'projects': homepage_project_json(request, projects, False),
            'space_viewer': user_rez.render_one(request, logged_in_user),
            'course': course_rez.render_one(request, course),
            'compositions': len(projects) > 0,
            'is_faculty': course.is_faculty(logged_in_user)}

    json_stream = simplejson.dumps(data, indent=2)
    return HttpResponse(json_stream, mimetype='application/json')
示例#23
0
    def test_render_list(self):
        self.assertTrue(
            self.api_client.client.login(username="******",
                                         password="******"))

        sample_course = Course.objects.get(title="Sample Course")

        members = UserResource().render_list(None, sample_course.members)

        self.assertEquals(len(members), 6)
        self.assertEquals(members[0]['public_name'], "test_instructor_two")
        self.assertEquals(members[1]['public_name'], "test_student_three")
        self.assertEquals(members[2]['public_name'], "Instructor One")
        self.assertEquals(members[3]['public_name'], "Student One")
        self.assertEquals(members[4]['public_name'], "Student Two")
        self.assertEquals(members[5]['public_name'], "Teacher's  Assistant")
示例#24
0
    def get(self, request, *args, **kwargs):
        course = get_object_or_404(Course, id=kwargs.pop('course_id', None))
        faculty = [user.id for user in course.faculty.all()]
        faculty_ctx = UserResource().render_list(request, course.faculty.all())

        # filter assets & notes by the faculty set
        assets = Asset.objects.by_course(course)
        if settings.SURELINK_URL:
            assets = assets.exclude(
                source__url__startswith=settings.SURELINK_URL)
        assets = assets.filter(sherdnote_set__author__id__in=faculty).exclude(
            source__label='flv_pseudo')

        notes = SherdNote.objects.get_related_notes(
            assets, None, faculty, True).exclude_primary_types(['flv_pseudo'])

        ares = AssetResource(include_annotations=False)
        asset_ctx = ares.render_list(request, None, None, assets, notes)

        projects = Project.objects.by_course_and_users(course, faculty)

        # filter private projects
        if projects.count() > 0:
            collabs = Collaboration.objects.get_for_object_list(projects)
            collabs = collabs.exclude(
                policy_record__policy_name='PrivateEditorsAreOwners')
            ids = collabs.values_list('object_pk', flat=True)
            projects = projects.filter(id__in=ids)

        info_ctx = CourseInfoResource().render_one(request, course)

        ctx = {
            'course': {
                'id': course.id,
                'title': course.title,
                'faculty': faculty_ctx,
                'info': info_ctx
            },
            'assets': asset_ctx,
            'projects': ProjectResource().render_list(request, projects)
        }

        return self.render_to_json_response(ctx)
示例#25
0
    def get_context_data(self, **kwargs):
        context = super(CourseDetailView, self).get_context_data(**kwargs)
        course = context.get('object')

        qs = ExternalCollection.objects.filter(course=self.request.course)
        collections = qs.filter(uploader=False).order_by('title')
        uploader = qs.filter(uploader=True).first()

        owners = []
        if (self.request.course.is_member(self.request.user) and
            (self.request.user.is_staff
             or self.request.user.has_perm('assetmgr.can_upload_for'))):
            owners = UserResource().render_list(self.request, course.members)

        context.update({
            'course':
            course,
            'classwork_owner':
            self.request.user,
            'information_title':
            course_information_title(course),
            'faculty_feed':
            Project.objects.faculty_compositions(course, self.request.user),
            'is_faculty':
            cached_course_is_faculty(course, self.request.user),
            'owners':
            owners,
            'collections':
            collections,
            'uploader':
            uploader,
            'msg':
            self.request.GET.get('msg', ''),
            'can_upload':
            course_details.can_upload(self.request.user, self.request.course),
        })
        return context
示例#26
0
    def get(self, request, *args, **kwargs):
        course = get_object_or_404(Course, id=kwargs.pop('course_id', None))
        faculty = [user.id for user in course.faculty.all()]
        faculty_ctx = UserResource().render_list(request, course.faculty.all())

        # filter assets & notes by the faculty set
        assets = Asset.objects.by_course(course)
        assets = assets.filter(sherdnote_set__author__id__in=faculty)
        notes = SherdNote.objects.get_related_notes(assets, None, faculty)

        ares = AssetResource(include_annotations=False)
        asset_ctx = ares.render_list(request, None, assets, notes)

        projects = Project.objects.by_course_and_users(course, faculty)

        # filter private projects
        collabs = Collaboration.objects.get_for_object_list(projects)
        collabs = collabs.exclude(
            _policy__policy_name='PrivateEditorsAreOwners')
        ids = [int(c.object_pk) for c in collabs]
        projects = projects.filter(id__in=ids)

        info_ctx = CourseInfoResource().render_one(request, course)

        ctx = {
            'course': {
                'id': course.id,
                'title': course.title,
                'faculty': faculty_ctx,
                'info': info_ctx
            },
            'assets': asset_ctx,
            'projects': ProjectResource().render_list(request, projects)
        }

        return self.render_to_json_response(ctx)
示例#27
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')
示例#28
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')
示例#29
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))

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

        is_faculty = request.course.is_faculty(request.user)
        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:
            resource = ProjectResource(
                record_viewer=request.user,
                is_viewer_faculty=is_faculty,
                editable=parent_assignment.can_edit(request))
            assignment_ctx = resource.render_one(request, parent_assignment)

            panel = {
                'is_faculty':
                is_faculty,
                'panel_state':
                "open" if (project.title == "Untitled"
                           and len(project.body) == 0) else "closed",
                'subpanel_state':
                'closed',
                'context':
                assignment_ctx,
                'owners':
                owners,
                'vocabulary':
                vocabulary,
                'template':
                'project'
            }
            panels.append(panel)

        # Requested project, can be either an assignment or composition
        resource = ProjectResource(record_viewer=request.user,
                                   is_viewer_faculty=is_faculty,
                                   editable=can_edit)
        project_context = resource.render_one(request, project)

        # 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 project.is_assignment(request):
            responses = project.responses_by(request, request.user)
            if len(responses) > 0:
                response = responses[0]
                response_can_edit = response.can_edit(request)
                resource = ProjectResource(record_viewer=request.user,
                                           is_viewer_faculty=is_faculty,
                                           editable=response_can_edit)
                response_context = resource.render_one(request, response)

                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(json.dumps(data, indent=2),
                            mimetype='application/json')
示例#30
0
def triple_homepage(request):
    if not request.course:
        return HttpResponseRedirect('/accounts/login/')

    logged_in_user = request.user
    classwork_owner = request.user  # Viewing your own work by default
    if 'username' in request.GET:
        user_name = request.GET['username']
        in_course_or_404(user_name, request.course)
        classwork_owner = get_object_or_404(User, username=user_name)

    course = request.course

    archives = []
    upload_archive = None
    for item in course.asset_set.archives().order_by('title'):
        archive = item.sources['archive']
        thumb = item.sources.get('thumb', None)
        description = item.metadata().get('description', '')
        uploader = item.metadata().get('upload', 0)

        archive_context = {
            "id": item.id,
            "title": item.title,
            "thumb": (None if not thumb else {"id": thumb.id,
                                              "url": thumb.url}),
            "archive": {"id": archive.id, "url": archive.url},
            "metadata": (description[0]
                         if hasattr(description, 'append') else description)
        }

        if (uploader[0] if hasattr(uploader, 'append') else uploader):
            upload_archive = archive_context
        else:
            archives.append(archive_context)

    archives.sort(key=operator.itemgetter('title'))

    owners = []
    if (in_course(logged_in_user.username, request.course) and
        (logged_in_user.is_staff or
         logged_in_user.has_perm('assetmgr.can_upload_for'))):
        owners = UserResource().render_list(request, request.course.members)

    context = {
        'classwork_owner': classwork_owner,
        'help_homepage_instructor_column': False,
        'help_homepage_classwork_column': False,
        'faculty_feed': get_prof_feed(course, request),
        'is_faculty': course.is_faculty(logged_in_user),
        'discussions': get_course_discussions(course),
        'msg': request.GET.get('msg', ''),
        'view': request.GET.get('view', ''),
        'archives': archives,
        'upload_archive': upload_archive,
        'can_upload': course_details.can_upload(request.user, request.course),
        'show_tour': should_show_tour(request, course, logged_in_user),
        'owners': owners
    }

    if getattr(settings, 'DJANGOSHERD_FLICKR_APIKEY', None):
        # MUST only contain string values for now!!
        # (see templates/assetmgr/bookmarklet.js to see why or fix)
        context['bookmarklet_vars'] = {
            'flickr_apikey': settings.DJANGOSHERD_FLICKR_APIKEY
        }

    return context
示例#31
0
def render_assets(request, record_owner, assets):
    course = request.course
    logged_in_user = request.user

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

    # Can the record_owner edit the records
    viewing_own_records = (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 = request.GET.get('citable', '') == 'true'

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

    # Spew out json for the assets
    if request.GET.get('annotations', '') == 'true':
        resource = AssetResource(owner_selections_are_visible, record_owner, {
            'editable': viewing_own_records,
            'citable': citable
        })
    else:
        resource = AssetSummaryResource({
            'editable': viewing_own_records,
            'citable': citable
        })

    asset_json = resource.render_list(request, assets)

    active_filters = {}
    for key, val in request.GET.items():
        if (key == 'tag' or key == 'modified'
                or key.startswith('vocabulary-')):
            active_filters[key] = val

    user_resource = UserResource()

    # #todo -- figure out a cleaner way to do this. Ugli-ness
    # Collate tag set & vocabulary set for the result set.
    # Get all visible notes for the returned asset set
    # These notes may include global annotations for all users,
    # whereas the rendered set will not
    active_asset_ids = [a['id'] for a in asset_json]
    active_notes = []
    if record_owner:
        if owner_selections_are_visible:
            active_notes = SherdNote.objects.filter(
                asset__course=course,
                asset__id__in=active_asset_ids,
                author__id=record_owner.id)
    else:
        if all_selections_are_visible(course) or is_faculty:
            # Display all tags for the asset set including globals
            active_notes = SherdNote.objects.filter(
                asset__course=course, asset__id__in=active_asset_ids)
        else:
            whitelist = [f.id for f in course.faculty]
            whitelist.append(request.user.id)
            active_notes = SherdNote.objects.filter(
                asset__course=course,
                asset__id__in=active_asset_ids,
                author__id__in=whitelist)

    tags = []
    if len(active_notes) > 0:
        tags = Tag.objects.usage_for_queryset(active_notes)
        tags.sort(lambda a, b: cmp(a.name.lower(), b.name.lower()))

    active_vocabulary = []
    note_ids = [n.id for n in active_notes]
    content_type = ContentType.objects.get_for_model(SherdNote)
    term_resource = TermResource()
    for vocab in Vocabulary.objects.get_for_object(request.course):
        vocabulary = {
            'id': vocab.id,
            'display_name': vocab.display_name,
            'term_set': []
        }
        related = TermRelationship.objects.filter(term__vocabulary=vocab,
                                                  content_type=content_type,
                                                  object_id__in=note_ids)

        terms = []
        for rel in related:
            if rel.term.display_name not in terms:
                the_term = term_resource.render_one(request, rel.term)
                vocabulary['term_set'].append(the_term)
                terms.append(rel.term.display_name)

        active_vocabulary.append(vocabulary)

    # Assemble the context
    data = {
        'assets': asset_json,
        'active_tags': TagResource().render_list(request, tags),
        'active_filters': active_filters,
        'active_vocabulary': active_vocabulary,
        'space_viewer': user_resource.render_one(request, logged_in_user),
        'editable': viewing_own_records,
        'citable': citable,
        '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')
示例#32
0
    def get(self, request, *args, **kwargs):
        project = get_object_or_404(Project, pk=kwargs.get('project_id', None))
        data = {'space_owner': request.user.username}

        if not request.is_ajax():
            self.template_name = 'projects/composition.html'
            data['project'] = project
            return self.render_to_response(data)
        else:
            panels = []

            lst = Vocabulary.objects.filter(course=request.course)
            lst = lst.prefetch_related('term_set')
            vocabulary = VocabularyResource().render_list(request, lst)

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

            is_faculty = request.course.is_faculty(request.user)
            can_edit = project.can_edit(request.course, request.user)

            # Requested project, can be either an assignment or composition
            resource = ProjectResource(record_viewer=request.user,
                                       is_viewer_faculty=is_faculty,
                                       editable=can_edit)
            project_context = resource.render_one(request, project)

            # 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'] = False

            project_revisions_url = reverse(
                'project-revisions', args=[request.course.pk, project.id])

            panel = {
                'is_faculty': is_faculty,
                'context': project_context,
                'template': 'project',
                'owners': owners,
                'project_revisions_url': project_revisions_url,
                'vocabulary': vocabulary
            }
            panels.append(panel)

            data['panels'] = panels

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

            return self.render_to_json_response(data)
示例#33
0
    def get(self, request, *args, **kwargs):
        project = get_object_or_404(Project, pk=kwargs.get('project_id', None))
        assignment = project.assignment()
        if not assignment or not assignment.is_essay_assignment():
            return HttpResponseForbidden('')

        panels = []

        lst = Vocabulary.objects.filter(course=request.course)
        lst = lst.prefetch_related('term_set')
        vocabulary = VocabularyResource().render_list(request, lst)

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

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

        parent = project.assignment()

        # Requested project, can be either an assignment or composition
        resource = ProjectResource(record_viewer=request.user,
                                   is_viewer_faculty=is_faculty,
                                   editable=can_edit)
        project_context = resource.render_one(request, project)

        # 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 and not feedback_discussion

        project_revisions_url = reverse('project-revisions',
                                        args=[request.course.pk, project.id])

        panel = {
            'is_faculty':
            is_faculty,
            'show_feedback':
            feedback_discussion is not None,
            'create_feedback_url':
            reverse('discussion-create', args=[request.course.pk]),
            'project_revisions_url':
            project_revisions_url,
            'context':
            project_context,
            'template':
            'project_response',
            'owners':
            owners,
            'vocabulary':
            vocabulary
        }
        panels.append(panel)

        # If feedback exists for the requested project
        if feedback_discussion:
            # 3rd pane is the instructor feedback, if it exists
            panel = {
                'template': 'project_feedback',
                'owners': owners,
                'vocabulary': vocabulary,
                'context': threaded_comment_json(request, feedback_discussion)
            }
            panels.append(panel)

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

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

        return self.render_to_json_response(data)
示例#34
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')