def initialize(self, record_owner_name=None): # initialize a few helpful variables here self.record_viewer = self.request.user self.record_owner = None if record_owner_name: self.record_owner = get_object_or_404(User, username=record_owner_name) # Is the current user faculty or a CCNMTL staff member self.is_viewer_faculty = cached_course_is_faculty(self.request.course, self.record_viewer) # Can the record_owner edit the records self.viewing_own_records = (self.record_owner == self.record_viewer) self.viewing_faculty_records = ( self.record_owner and cached_course_is_faculty(self.request.course, self.record_owner)) # Does the course allow viewing other user selections? # The viewer can always view their own records + faculty records # If the viewer is faculty, they can view all records self.all_selections_are_visible = \ all_selections_are_visible(self.request.course) self.all_items_are_visible = \ all_items_are_visible(self.request.course) self.visible_authors = [] if (not self.is_viewer_faculty and (not self.all_selections_are_visible or not self.all_items_are_visible)): self.visible_authors = [self.record_viewer.id] # me for user in self.request.course.faculty.all(): self.visible_authors.append(user.id)
def dispatch(self, *args, **kwargs): # initialize a few helpful variables here self.record_viewer = self.request.user self.record_owner = None record_owner_name = kwargs.pop("record_owner_name", None) if record_owner_name: self.record_owner = get_object_or_404(User, username=record_owner_name) # Is the current user faculty or a CCNMTL staff member self.is_viewer_faculty = cached_course_is_faculty(self.request.course, self.record_viewer) # Can the record_owner edit the records self.viewing_own_records = self.record_owner == self.record_viewer self.viewing_faculty_records = self.record_owner and cached_course_is_faculty( self.request.course, self.record_owner ) # Does the course allow viewing other user selections? # The viewer can always view their own records + faculty records # If the viewer is faculty, they can view all records self.all_selections_are_visible = all_selections_are_visible(self.request.course) self.visible_authors = [] if not self.all_selections_are_visible and not self.is_viewer_faculty: self.visible_authors = [self.record_viewer.id] # me for user in self.request.course.faculty.all(): self.visible_authors.append(user.id) return super(RestrictedMaterialsMixin, self).dispatch(*args, **kwargs)
def dispatch(self, *args, **kwargs): # initialize a few helpful variables here self.record_viewer = self.request.user self.record_owner = None record_owner_name = kwargs.pop('record_owner_name', None) if record_owner_name: self.record_owner = get_object_or_404(User, username=record_owner_name) # Is the current user faculty or a CCNMTL staff member self.is_viewer_faculty = cached_course_is_faculty( self.request.course, self.record_viewer) # Can the record_owner edit the records self.viewing_own_records = (self.record_owner == self.record_viewer) self.viewing_faculty_records = (self.record_owner and cached_course_is_faculty( self.request.course, self.record_owner)) # Does the course allow viewing other user selections? # The viewer can always view their own records + faculty records # If the viewer is faculty, they can view all records self.all_selections_are_visible = \ all_selections_are_visible(self.request.course) self.visible_authors = [] if not self.all_selections_are_visible and not self.is_viewer_faculty: self.visible_authors = [self.record_viewer.id] # me for user in self.request.course.faculty.all(): self.visible_authors.append(user.id) return super(RestrictedMaterialsMixin, self).dispatch(*args, **kwargs)
def apply_authorization_limits(self, request, object_list): course = self.course or request.course if (all_selections_are_visible(course) or cached_course_is_faculty(course, request.user)): return self.get_unrestricted(request, object_list, course) else: return self.get_restricted(request, object_list, course)
def __init__(self, *args, **kwargs): r = super(DashboardSettingsForm, self).__init__(*args, **kwargs) self.fields['publish_to_world'].initial = \ allow_public_compositions(self.instance) self.fields['see_eachothers_items'].initial = \ all_items_are_visible(self.instance) self.fields['see_eachothers_selections'].initial = \ all_selections_are_visible(self.instance) self.fields['allow_item_download'].initial = \ allow_item_download(self.instance) self.fields['allow_roster_changes'].initial = \ allow_roster_changes(self.instance) return r
def __init__(self, *args, **kwargs): r = super(DashboardSettingsForm, self).__init__(*args, **kwargs) self.fields['publish_to_world'].initial = \ allow_public_compositions(self.instance) self.fields['homepage_title'].initial = \ course_information_title(self.instance) self.fields['see_eachothers_items'].initial = \ all_items_are_visible(self.instance) self.fields['see_eachothers_selections'].initial = \ all_selections_are_visible(self.instance) self.fields['allow_item_download'].initial = \ allow_item_download(self.instance) self.fields['allow_roster_changes'].initial = \ allow_roster_changes(self.instance) return r
def test_post_disabled_selection_visibility(self): self.client.login(username=self.instructor_one.username, password='******') data = {course_details.ITEM_VISIBILITY_KEY: 0} response = self.client.post('/dashboard/settings/', data) self.assertEquals(response.status_code, 302) # unchanged from defaults self.assertEquals(course_information_title(self.sample_course), 'From Your Instructor') self.assertFalse(allow_public_compositions(self.sample_course)) # updated self.assertFalse(all_items_are_visible(self.sample_course)) self.assertFalse(all_selections_are_visible(self.sample_course))
def test_post(self): self.assertTrue( self.client.login(username=self.instructor_one.username, password='******')) data = { course_details.COURSE_INFORMATION_TITLE_KEY: "Foo", course_details.SELECTION_VISIBILITY_KEY: 0, course_details.ITEM_VISIBILITY_KEY: 0, course_details.ALLOW_PUBLIC_COMPOSITIONS_KEY: 1 } response = self.client.post('/dashboard/settings/', data) self.assertEquals(response.status_code, 302) self.assertEquals(course_information_title(self.sample_course), "Foo") self.assertTrue(allow_public_compositions(self.sample_course)) self.assertFalse(all_items_are_visible(self.sample_course)) self.assertFalse(all_selections_are_visible(self.sample_course))
def __init__(self, *args, **kwargs): r = super(DashboardSettingsForm, self).__init__(*args, **kwargs) self.fields['publish_to_world'].initial = \ allow_public_compositions(self.instance) self.fields['homepage_title'].initial = \ course_information_title(self.instance) self.fields['see_eachothers_items'].initial = \ all_items_are_visible(self.instance) self.fields['see_eachothers_selections'].initial = \ all_selections_are_visible(self.instance) self.fields['allow_item_download'].initial = \ allow_item_download(self.instance) lti_context = LTICourseContext.objects.filter( group=self.instance.group.id, faculty_group=self.instance.faculty_group.id).first() self.fields['lti_integration'].initial = \ (lti_context and lti_context.enable) return r
def __init__(self, request, *args, **kwargs): super(ProjectForm, self).__init__(*args, **kwargs) lst = [(u.id, get_public_name(u, request)) for u in request.course.user_set.all()] self.fields['participants'].choices = sorted( lst, key=lambda participant: participant[1]) self.fields['participants'].widget.attrs = { 'id': "id_participants_%s" % self.instance.id } project = kwargs['instance'] if project: # set initial publish value col = project.get_collaboration() if col: self.initial['publish'] = col.policy_record.policy_name else: self.instance = None choices = self.get_choices(request, project) self.fields['publish'].choices = choices # response view policy. limit choices if there is no project # or the project is a selection assignment if (not project or not ( project.is_composition() or project.is_sequence())): choices = [RESPONSE_VIEW_NEVER] if all_selections_are_visible(request.course): choices.append(RESPONSE_VIEW_SUBMITTED) choices.append(RESPONSE_VIEW_ALWAYS) self.fields['response_view_policy'].choices = choices self.fields['participants'].required = False self.fields['body'].required = False self.fields['submit'].required = False self.fields['publish'].required = False # for structured collaboration self.fields['title'].widget.attrs['maxlength'] = 80
def __init__(self, request, *args, **kwargs): super(ProjectForm, self).__init__(*args, **kwargs) lst = [(u.id, get_public_name(u, request)) for u in request.course.user_set.all()] self.fields['participants'].choices = sorted( lst, key=lambda participant: participant[1]) self.fields['participants'].widget.attrs = { 'id': "id_participants_%s" % self.instance.id } project = kwargs['instance'] if project: # set initial publish value col = project.get_collaboration() if col: self.initial['publish'] = col.policy_record.policy_name else: self.instance = None choices = self.get_choices(request, project) self.fields['publish'].choices = choices # response view policy. limit choices if there is no project # or the project is a selection assignment if (not project or not (project.is_composition() or project.is_sequence())): choices = [RESPONSE_VIEW_NEVER] if all_selections_are_visible(request.course): choices.append(RESPONSE_VIEW_SUBMITTED) choices.append(RESPONSE_VIEW_ALWAYS) self.fields['response_view_policy'].choices = choices self.fields['participants'].required = False self.fields['body'].required = False self.fields['submit'].required = False self.fields['publish'].required = False # for structured collaboration self.fields['title'].widget.attrs['maxlength'] = 80
def apply_limits(self, request, object_list, exclude_global=True): if request.user.is_authenticated(): if exclude_global: # only request user's global annotations object_list = object_list.exclude(~Q(author=request.user), range1__isnull=True) # Make sure the requesting user is allowed to see this note invisible = [] courses = {} for note in object_list.select_related('asset__course'): course = note.asset.course # Cache this out per course/user. It's just too slow otherwise if not course.id in courses.keys(): courses[course.id] = {'whitelist': None} is_faculty = cached_course_is_faculty(course, request.user) if (not course_details.all_selections_are_visible(course) and not is_faculty): courses[course.id]['whitelist'] = list(course.faculty) courses[course.id]['whitelist'].append(request.user) if not cached_course_is_member(course, request.user): invisible.append(note.id) elif (courses[course.id]['whitelist'] and not note.author in courses[course.id]['whitelist']): # apply per course limitations # the user or a faculty member must be the selection author invisible.append(note.id) return object_list.exclude(id__in=invisible).order_by('id') elif request.public: # attribute "public" set on request when requesting a # public_to_world essay. all notes are public by default return object_list.order_by('id') else: return []
def mediathread_activity_by_course(request): """STAFF ONLY reporting of entire application activity """ if not request.user.is_staff: return HttpResponseForbidden("forbidden") response = HttpResponse(mimetype='text/csv') response['Content-Disposition'] = \ 'attachment; filename=mediathread_activity_by_course.csv' writer = csv.writer(response) headers = ['Id', 'Title', 'Instructor', 'Course String', 'Term', 'Year', 'Section', 'Course Number', 'School', 'Students', 'Items', 'Selections', 'Compositions', 'Assignments', 'Discussions', 'Public To World Compositions', 'All Selections Visible'] writer.writerow(headers) rows = [] for c in Course.objects.all().order_by('-id'): if (c.faculty_group is None or (not (c.faculty_group.name.startswith('t1') or c.faculty_group.name.startswith('t2') or c.faculty_group.name.startswith('t3')))): continue row = [] row.append(c.id) row.append(c.title) if 'instructor' in c.details(): row.append(c.details()['instructor'].value) else: row.append('') course_string = c.faculty_group.name row.append(course_string) bits = c.faculty_group.name.split('.') row.append(bits[0]) # term row.append(bits[1][1:]) # year row.append(bits[2]) # section row.append(bits[3]) # courseNo row.append(bits[4]) # school row.append(len(c.students)) items = Asset.objects.filter(course=c) row.append(len(items)) selections = SherdNote.objects.filter(asset__course=c) row.append(len(selections)) compositions = 0 assignments = 0 projects = Project.objects.filter(course=c) for p in projects: if p.visibility_short() == 'Assignment': assignments += 1 else: compositions += 1 row.append(compositions) row.append(assignments) try: row.append(len(get_course_discussions(c))) except Collaboration.DoesNotExist: row.append(0) row.append(course_details.allow_public_compositions(c)) row.append(course_details.all_selections_are_visible(c)) rows.append(row) for row in rows: try: writer.writerow(row) except: pass return response
def get(self, request, *args, **kwargs): headers = [ 'Id', 'Created', 'Title', 'Instructor', 'Course String', 'Term', 'Year', 'Section', 'Course Number', 'School', 'Students', '% Active Students', 'Total Items', 'Student Items', 'Student Selections', 'Compositions', 'Assignments', 'Responses', 'Discussions', 'Public To World Compositions', 'All Selections Visible', '# of Active Tags', '% Using Tags', '% Items Tagged', '% Selections Tagged', '# of Active Vocabulary Terms', '% Using Vocabulary', '% Items Classified', '% Selections Classified' ] rows = [] # Hard-coding date until we have time to code a proper ui qs = Course.objects.filter(created_at__year__gte='2019', created_at__month__gte='6') for the_course in qs.order_by('-id'): row = [] row.append(the_course.id) row.append(the_course.created_at.strftime(self.date_fmt)) row.append(the_course.title) if 'instructor' in the_course.details(): row.append(the_course.details()['instructor'].value) else: row.append('') course_string = the_course.faculty_group.name row.append(course_string) bits = the_course.faculty_group.name.split('.') if len(bits) >= 5: row.append(bits[0]) # term row.append(bits[1][1:]) # year row.append(bits[2]) # section row.append(bits[3]) # courseNo row.append(bits[4]) # school else: row.append('') row.append('') row.append('') row.append('') row.append('') students = self.all_students(the_course) row.append(len(students)) row.append(self.active_students(students)) items = Asset.objects.filter(course=the_course) row.append(len(items)) # student work only student_ids = students.values('id') items = Asset.objects.filter(course=the_course, author__id__in=student_ids) row.append(len(items)) selections = SherdNote.objects.filter(asset__course=the_course, author__id__in=student_ids) row.append(len(selections)) compositions, assignments, responses = \ self.project_count(the_course) row.append(compositions) row.append(assignments) row.append(responses) row.append(self.discussion_count(the_course)) row.append(course_details.allow_public_compositions(the_course)) row.append(course_details.all_selections_are_visible(the_course)) # Breakdown tags & vocabulary terms by item & selection if len(selections) > 0: item_notes = selections.filter(range1=None, range2=None) sel_notes = selections.exclude(range1=None, range2=None) tags = Tag.objects.usage_for_queryset(selections) row.append(len(tags)) # # of Active Tags', tagged = selections.filter(tags__isnull=False).values('author') tag_users = tagged.distinct().count() if len(students) > 0: # % users using tags row.append(float(tag_users) / len(students) * 100) else: row.append(0) # '% Items Tagged', '% Selections Tagged' t = item_notes.filter(tags__isnull=False).exclude( tags__exact='') row.append(float(len(t)) / len(selections) * 100) t = sel_notes.filter(tags__isnull=False).exclude( tags__exact='') row.append(float(len(t)) / len(selections) * 100) # Vocabulary related = TermRelationship.objects.filter( term__vocabulary__course=the_course, sherdnote__id__in=selections.values_list('id', flat=True)) # '# of Active Vocabulary Terms' q = related.aggregate(Count('term', distinct=True)) active_terms = q['term__count'] q = related.aggregate(Count('sherdnote__author', distinct=True)) vocab_users = q['sherdnote__author__count'] row.append(active_terms) if len(students) > 0: # % users row.append(float(vocab_users) / len(students) * 100) else: row.append(0) related_ids = related.values_list('sherdnote__id', flat=True) items = len( SherdNote.objects.filter(id__in=related_ids, range1=None, range2=None)) row.append(float(items) / len(selections) * 100) # % Items sel = len( SherdNote.objects.filter(id__in=related_ids).exclude( range1=None, range2=None)) row.append(float(sel) / len(selections) * 100) # % Selections rows.append(row) return self.render_csv_response('mediathread_activity_by_course', headers, rows)
def mediathread_activity_by_course(request): """STAFF ONLY reporting of entire application activity """ if not request.user.is_staff: return HttpResponseForbidden("forbidden") response = HttpResponse(mimetype='text/csv') response['Content-Disposition'] = \ 'attachment; filename=mediathread_activity_by_course.csv' writer = csv.writer(response) headers = [ 'Id', 'Title', 'Instructor', 'Course String', 'Term', 'Year', 'Section', 'Course Number', 'School', 'Students', '% Active Students', 'Items', 'Selections', 'Compositions', 'Assignments', 'Discussions', 'Public To World Compositions', 'All Selections Visible', '# of Active Tags', '% Using Tags', '% Items Tagged', '% Selections Tagged', '# of Active Vocabulary Terms', '% Using Vocabulary', '% Items Classified', '% Selections Classified' ] writer.writerow(headers) rows = [] for the_course in Course.objects.all().order_by('-id'): if (the_course.faculty_group is None or (not (the_course.faculty_group.name.startswith('t1') or the_course.faculty_group.name.startswith('t2') or the_course.faculty_group.name.startswith('t3')))): continue row = [] row.append(the_course.id) row.append(the_course.title) if 'instructor' in the_course.details(): row.append(the_course.details()['instructor'].value) else: row.append('') course_string = the_course.faculty_group.name row.append(course_string) bits = the_course.faculty_group.name.split('.') row.append(bits[0]) # term row.append(bits[1][1:]) # year row.append(bits[2]) # section row.append(bits[3]) # courseNo row.append(bits[4]) # school students = the_course.group.user_set.all() if the_course.faculty_group: ids = the_course.faculty_group.user_set.values('id') students = students.exclude(id__in=ids) row.append(len(students)) if len(students) > 0: active = students.filter( Q(projects__isnull=False) | Q(sherdnote__isnull=False)).distinct() row.append(float(len(active)) / len(students) * 100) else: row.append(0) items = Asset.objects.filter(course=the_course) row.append(len(items)) selections = SherdNote.objects.filter(asset__course=the_course) row.append(len(selections)) compositions = 0 assignments = 0 projects = Project.objects.filter(course=the_course) for project in projects: if project.visibility_short() == 'Assignment': assignments += 1 else: compositions += 1 row.append(compositions) row.append(assignments) try: discussions = get_course_discussions(the_course) row.append(len(discussions)) '# of Discussion Items', '% participating in Discussions', except Collaboration.DoesNotExist: row.append(0) row.append(course_details.allow_public_compositions(the_course)) row.append(course_details.all_selections_are_visible(the_course)) # Breakdown tags & vocabulary terms by item & selection if len(selections) > 0: item_notes = selections.filter(range1=None, range2=None) sel_notes = selections.exclude(range1=None, range2=None) tags = Tag.objects.usage_for_queryset(selections) row.append(len(tags)) # # of Active Tags', tag_users = len( selections.filter(tags__isnull=False).distinct('author')) if len(students) > 0: # % users using tags row.append(float(tag_users) / len(students) * 100) else: row.append(0) # '% Items Tagged', '% Selections Tagged' t = item_notes.filter(tags__isnull=False).exclude(tags__exact='') row.append(float(len(t)) / len(selections) * 100) t = sel_notes.filter(tags__isnull=False).exclude(tags__exact='') row.append(float(len(t)) / len(selections) * 100) # Vocabulary vocab = Vocabulary.objects.get_for_object(the_course) content_type = ContentType.objects.get_for_model(SherdNote) related = TermRelationship.objects.filter( term__vocabulary__in=vocab, content_type=content_type, object_id__in=selections.values_list('id')) # '# of Active Vocabulary Terms' q = related.aggregate(Count('term', distinct=True)) active_terms = q['term__count'] vocab_users = len( SherdNote.objects.filter(id__in=related.values_list( 'object_id')).distinct('author')) row.append(active_terms) if len(students) > 0: row.append(float(vocab_users) / len(students) * 100) # % users else: row.append(0) related_ids = related.values_list('object_id') items = len( SherdNote.objects.filter(id__in=related_ids, range1=None, range2=None)) row.append(float(items) / len(selections) * 100) # % Items sel = len( SherdNote.objects.filter(id__in=related_ids).exclude( range1=None, range2=None)) row.append(float(sel) / len(selections) * 100) # % Selections rows.append(row) for row in rows: try: writer.writerow(row) except: pass return response
def get(self, request, *args, **kwargs): headers = ['Id', 'Title', 'Instructor', 'Course String', 'Term', 'Year', 'Section', 'Course Number', 'School', 'Students', '% Active Students', 'Items', 'Selections', 'Compositions', 'Assignments', 'Discussions', 'Public To World Compositions', 'All Selections Visible', '# of Active Tags', '% Using Tags', '% Items Tagged', '% Selections Tagged', '# of Active Vocabulary Terms', '% Using Vocabulary', '% Items Classified', '% Selections Classified'] rows = [] for the_course in Course.objects.all().order_by('-id'): if not self.include_course(the_course): continue row = [] row.append(the_course.id) row.append(the_course.title) if 'instructor' in the_course.details(): row.append(the_course.details()['instructor'].value) else: row.append('') course_string = the_course.faculty_group.name row.append(course_string) bits = the_course.faculty_group.name.split('.') row.append(bits[0]) # term row.append(bits[1][1:]) # year row.append(bits[2]) # section row.append(bits[3]) # courseNo row.append(bits[4]) # school students = self.all_students(the_course) row.append(len(students)) row.append(self.active_students(students)) items = Asset.objects.filter(course=the_course) row.append(len(items)) selections = SherdNote.objects.filter(asset__course=the_course) row.append(len(selections)) compositions, assignments = self.project_count(the_course) row.append(compositions) row.append(assignments) row.append(self.discussion_count(the_course)) row.append(course_details.allow_public_compositions(the_course)) row.append(course_details.all_selections_are_visible(the_course)) # Breakdown tags & vocabulary terms by item & selection if len(selections) > 0: item_notes = selections.filter(range1=None, range2=None) sel_notes = selections.exclude(range1=None, range2=None) tags = Tag.objects.usage_for_queryset(selections) row.append(len(tags)) # # of Active Tags', tagged = selections.filter(tags__isnull=False).values('author') tag_users = tagged.distinct().count() if len(students) > 0: # % users using tags row.append(float(tag_users) / len(students) * 100) else: row.append(0) # '% Items Tagged', '% Selections Tagged' t = item_notes.filter(tags__isnull=False).exclude( tags__exact='') row.append(float(len(t)) / len(selections) * 100) t = sel_notes.filter(tags__isnull=False).exclude( tags__exact='') row.append(float(len(t)) / len(selections) * 100) # Vocabulary vocab = Vocabulary.objects.get_for_object(the_course) content_type = ContentType.objects.get_for_model(SherdNote) related = TermRelationship.objects.filter( term__vocabulary__in=vocab, content_type=content_type, object_id__in=selections.values_list('id')) # '# of Active Vocabulary Terms' q = related.aggregate(Count('term', distinct=True)) active_terms = q['term__count'] termed = SherdNote.objects.filter( id__in=related.values_list('object_id')).values('author') vocab_users = termed.distinct().count() row.append(active_terms) if len(students) > 0: # % users row.append(float(vocab_users) / len(students) * 100) else: row.append(0) related_ids = related.values_list('object_id') items = len(SherdNote.objects.filter(id__in=related_ids, range1=None, range2=None)) row.append(float(items) / len(selections) * 100) # % Items sel = len(SherdNote.objects.filter(id__in=related_ids).exclude( range1=None, range2=None)) row.append(float(sel) / len(selections) * 100) # % Selections rows.append(row) return self.render_csv_response( 'mediathread_activity_by_course', headers, rows)
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 k, val in request.GET.items(): if (k == 'tag' or k == 'modified' or k.startswith('vocabulary-')): active_filters[k] = 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 v in Vocabulary.objects.get_for_object(request.course): vocabulary = { 'id': v.id, 'display_name': v.display_name, 'term_set': [] } related = TermRelationship.objects.filter(term__vocabulary=v, content_type=content_type, object_id__in=note_ids) terms = [] for r in related: if r.term.display_name not in terms: the_term = term_resource.render_one(request, r.term) vocabulary['term_set'].append(the_term) terms.append(r.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')
def mediathread_activity_by_course(request): """STAFF ONLY reporting of entire application activity """ if not request.user.is_staff: return HttpResponseForbidden("forbidden") response = HttpResponse(mimetype='text/csv') response['Content-Disposition'] = \ 'attachment; filename=mediathread_activity_by_course.csv' writer = csv.writer(response) headers = ['Id', 'Title', 'Instructor', 'Course String', 'Term', 'Year', 'Section', 'Course Number', 'School', 'Students', '% Active Students', 'Items', 'Selections', 'Compositions', 'Assignments', 'Discussions', 'Public To World Compositions', 'All Selections Visible', '# of Active Tags', '% Using Tags', '% Items Tagged', '% Selections Tagged', '# of Active Vocabulary Terms', '% Using Vocabulary', '% Items Classified', '% Selections Classified'] writer.writerow(headers) rows = [] for the_course in Course.objects.all().order_by('-id'): if (the_course.faculty_group is None or (not (the_course.faculty_group.name.startswith('t1') or the_course.faculty_group.name.startswith('t2') or the_course.faculty_group.name.startswith('t3')))): continue row = [] row.append(the_course.id) row.append(the_course.title) if 'instructor' in the_course.details(): row.append(the_course.details()['instructor'].value) else: row.append('') course_string = the_course.faculty_group.name row.append(course_string) bits = the_course.faculty_group.name.split('.') row.append(bits[0]) # term row.append(bits[1][1:]) # year row.append(bits[2]) # section row.append(bits[3]) # courseNo row.append(bits[4]) # school students = the_course.group.user_set.all() if the_course.faculty_group: ids = the_course.faculty_group.user_set.values('id') students = students.exclude(id__in=ids) row.append(len(students)) if len(students) > 0: active = students.filter(Q(projects__isnull=False) | Q(sherdnote__isnull=False)).distinct() row.append(float(len(active)) / len(students) * 100) else: row.append(0) items = Asset.objects.filter(course=the_course) row.append(len(items)) selections = SherdNote.objects.filter(asset__course=the_course) row.append(len(selections)) compositions = 0 assignments = 0 projects = Project.objects.filter(course=the_course) for project in projects: if project.visibility_short() == 'Assignment': assignments += 1 else: compositions += 1 row.append(compositions) row.append(assignments) try: discussions = get_course_discussions(the_course) row.append(len(discussions)) '# of Discussion Items', '% participating in Discussions', except Collaboration.DoesNotExist: row.append(0) row.append(course_details.allow_public_compositions(the_course)) row.append(course_details.all_selections_are_visible(the_course)) # Breakdown tags & vocabulary terms by item & selection if len(selections) > 0: item_notes = selections.filter(range1=None, range2=None) sel_notes = selections.exclude(range1=None, range2=None) tags = Tag.objects.usage_for_queryset(selections) row.append(len(tags)) # # of Active Tags', tag_users = len( selections.filter(tags__isnull=False).distinct('author')) if len(students) > 0: # % users using tags row.append(float(tag_users) / len(students) * 100) else: row.append(0) # '% Items Tagged', '% Selections Tagged' t = item_notes.filter(tags__isnull=False).exclude(tags__exact='') row.append(float(len(t)) / len(selections) * 100) t = sel_notes.filter(tags__isnull=False).exclude(tags__exact='') row.append(float(len(t)) / len(selections) * 100) # Vocabulary vocab = Vocabulary.objects.get_for_object(the_course) content_type = ContentType.objects.get_for_model(SherdNote) related = TermRelationship.objects.filter( term__vocabulary__in=vocab, content_type=content_type, object_id__in=selections.values_list('id')) # '# of Active Vocabulary Terms' q = related.aggregate(Count('term', distinct=True)) active_terms = q['term__count'] vocab_users = len(SherdNote.objects.filter( id__in=related.values_list('object_id')).distinct( 'author')) row.append(active_terms) if len(students) > 0: row.append(float(vocab_users) / len(students) * 100) # % users else: row.append(0) related_ids = related.values_list('object_id') items = len(SherdNote.objects.filter(id__in=related_ids, range1=None, range2=None)) row.append(float(items) / len(selections) * 100) # % Items sel = len(SherdNote.objects.filter(id__in=related_ids).exclude( range1=None, range2=None)) row.append(float(sel) / len(selections) * 100) # % Selections rows.append(row) for row in rows: try: writer.writerow(row) except: pass return response
def get(self, request, *args, **kwargs): headers = ['Id', 'Created', 'Title', 'Instructor', 'Course String', 'Term', 'Year', 'Section', 'Course Number', 'School', 'Students', '% Active Students', 'Total Items', 'Student Items', 'Student Selections', 'Compositions', 'Assignments', 'Responses', 'Discussions', 'Public To World Compositions', 'All Selections Visible', '# of Active Tags', '% Using Tags', '% Items Tagged', '% Selections Tagged', '# of Active Vocabulary Terms', '% Using Vocabulary', '% Items Classified', '% Selections Classified'] rows = [] # Hard-coding date until we have time to code a proper ui qs = Course.objects.filter(created_at__year__gte='2018') for the_course in qs.order_by('-id'): row = [] row.append(the_course.id) row.append(the_course.created_at.strftime(self.date_fmt)) row.append(the_course.title) if 'instructor' in the_course.details(): row.append(the_course.details()['instructor'].value) else: row.append('') course_string = the_course.faculty_group.name row.append(course_string) bits = the_course.faculty_group.name.split('.') if len(bits) >= 5: row.append(bits[0]) # term row.append(bits[1][1:]) # year row.append(bits[2]) # section row.append(bits[3]) # courseNo row.append(bits[4]) # school else: row.append('') row.append('') row.append('') row.append('') row.append('') students = self.all_students(the_course) row.append(len(students)) row.append(self.active_students(students)) items = Asset.objects.filter(course=the_course) row.append(len(items)) # student work only student_ids = students.values('id') items = Asset.objects.filter( course=the_course, author__id__in=student_ids) row.append(len(items)) selections = SherdNote.objects.filter( asset__course=the_course, author__id__in=student_ids) row.append(len(selections)) compositions, assignments, responses = \ self.project_count(the_course) row.append(compositions) row.append(assignments) row.append(responses) row.append(self.discussion_count(the_course)) row.append(course_details.allow_public_compositions(the_course)) row.append(course_details.all_selections_are_visible(the_course)) # Breakdown tags & vocabulary terms by item & selection if len(selections) > 0: item_notes = selections.filter(range1=None, range2=None) sel_notes = selections.exclude(range1=None, range2=None) tags = Tag.objects.usage_for_queryset(selections) row.append(len(tags)) # # of Active Tags', tagged = selections.filter(tags__isnull=False).values('author') tag_users = tagged.distinct().count() if len(students) > 0: # % users using tags row.append(float(tag_users) / len(students) * 100) else: row.append(0) # '% Items Tagged', '% Selections Tagged' t = item_notes.filter(tags__isnull=False).exclude( tags__exact='') row.append(float(len(t)) / len(selections) * 100) t = sel_notes.filter(tags__isnull=False).exclude( tags__exact='') row.append(float(len(t)) / len(selections) * 100) # Vocabulary related = TermRelationship.objects.filter( term__vocabulary__course=the_course, sherdnote__id__in=selections.values_list('id', flat=True)) # '# of Active Vocabulary Terms' q = related.aggregate(Count('term', distinct=True)) active_terms = q['term__count'] q = related.aggregate( Count('sherdnote__author', distinct=True)) vocab_users = q['sherdnote__author__count'] row.append(active_terms) if len(students) > 0: # % users row.append(float(vocab_users) / len(students) * 100) else: row.append(0) related_ids = related.values_list('sherdnote__id', flat=True) items = len(SherdNote.objects.filter(id__in=related_ids, range1=None, range2=None)) row.append(float(items) / len(selections) * 100) # % Items sel = len(SherdNote.objects.filter(id__in=related_ids).exclude( range1=None, range2=None)) row.append(float(sel) / len(selections) * 100) # % Selections rows.append(row) return self.render_csv_response( 'mediathread_activity_by_course', headers, rows)
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')
def test_all_selections_are_visible(self): # default self.assertTrue(all_selections_are_visible(self.sample_course))
def mediathread_activity_by_course(request): """STAFF ONLY reporting of entire application activity """ if not request.user.is_staff: return HttpResponseForbidden("forbidden") response = HttpResponse(mimetype='text/csv') response['Content-Disposition'] = \ 'attachment; filename=mediathread_activity_by_course.csv' writer = csv.writer(response) headers = [ 'Id', 'Title', 'Instructor', 'Course String', 'Term', 'Year', 'Section', 'Course Number', 'School', 'Students', 'Items', 'Selections', 'Compositions', 'Assignments', 'Discussions', 'Public To World Compositions', 'All Selections Visible' ] writer.writerow(headers) rows = [] for the_course in Course.objects.all().order_by('-id'): if (the_course.faculty_group is None or (not (the_course.faculty_group.name.startswith('t1') or the_course.faculty_group.name.startswith('t2') or the_course.faculty_group.name.startswith('t3')))): continue row = [] row.append(the_course.id) row.append(the_course.title) if 'instructor' in the_course.details(): row.append(the_course.details()['instructor'].value) else: row.append('') course_string = the_course.faculty_group.name row.append(course_string) bits = the_course.faculty_group.name.split('.') row.append(bits[0]) # term row.append(bits[1][1:]) # year row.append(bits[2]) # section row.append(bits[3]) # courseNo row.append(bits[4]) # school row.append(len(the_course.students)) items = Asset.objects.filter(course=the_course) row.append(len(items)) selections = SherdNote.objects.filter(asset__course=the_course) row.append(len(selections)) compositions = 0 assignments = 0 projects = Project.objects.filter(course=the_course) for project in projects: if project.visibility_short() == 'Assignment': assignments += 1 else: compositions += 1 row.append(compositions) row.append(assignments) try: row.append(len(get_course_discussions(the_course))) except Collaboration.DoesNotExist: row.append(0) row.append(course_details.allow_public_compositions(the_course)) row.append(course_details.all_selections_are_visible(the_course)) rows.append(row) for row in rows: try: writer.writerow(row) except: pass return response