Beispiel #1
0
def move_to_verified_cohort(sender, instance, **kwargs):  # pylint: disable=unused-argument
    """
    If the learner has changed modes, update assigned cohort iff the course is using
    the Automatic Verified Track Cohorting MVP feature.
    """
    course_key = instance.course_id
    verified_cohort_enabled = VerifiedTrackCohortedCourse.is_verified_track_cohort_enabled(course_key)
    verified_cohort_name = VerifiedTrackCohortedCourse.verified_cohort_name_for_course(course_key)

    if verified_cohort_enabled and (instance.mode != instance._old_mode):  # pylint: disable=protected-access
        if not is_course_cohorted(course_key):
            log.error("Automatic verified cohorting enabled for course '%s', but course is not cohorted", course_key)
        else:
            existing_cohorts = get_course_cohorts(get_course_by_id(course_key), CourseCohort.MANUAL)
            if any(cohort.name == verified_cohort_name for cohort in existing_cohorts):
                args = {
                    'course_id': unicode(course_key),
                    'user_id': instance.user.id,
                    'verified_cohort_name': verified_cohort_name
                }
                # Do the update with a 3-second delay in hopes that the CourseEnrollment transaction has been
                # completed before the celery task runs. We want a reasonably short delay in case the learner
                # immediately goes to the courseware.
                sync_cohort_with_mode.apply_async(kwargs=args, countdown=3)

                # In case the transaction actually was not committed before the celery task runs,
                # run it again after 5 minutes. If the first completed successfully, this task will be a no-op.
                sync_cohort_with_mode.apply_async(kwargs=args, countdown=300)
            else:
                log.error(
                    "Automatic verified cohorting enabled for course '%s', but cohort named '%s' does not exist.",
                    course_key,
                    verified_cohort_name,
                )
Beispiel #2
0
def make_course_settings(course, user):
    """
    Generate a JSON-serializable model for course settings, which will be used to initialize a
    DiscussionCourseSettings object on the client.
    """
    return {
        'is_cohorted': is_course_cohorted(course.id),
        'allow_anonymous': course.allow_anonymous,
        'allow_anonymous_to_peers': course.allow_anonymous_to_peers,
        'cohorts': [{"id": str(g.id), "name": g.name} for g in get_course_cohorts(course)],
        'category_map': utils.get_discussion_category_map(course, user)
    }
def _section_send_email(course, access):
    """ Provide data for the corresponding bulk email section """
    course_key = course.id

    # Monkey-patch applicable_aside_types to return no asides for the duration of this render
    with patch.object(course.runtime, 'applicable_aside_types', null_applicable_aside_types):
        # This HtmlDescriptor is only being used to generate a nice text editor.
        html_module = HtmlDescriptor(
            course.system,
            DictFieldData({'data': ''}),
            ScopeIds(None, None, None, course_key.make_usage_key('html', 'fake'))
        )
        fragment = course.system.render(html_module, 'studio_view')
    fragment = wrap_xblock(
        'LmsRuntime', html_module, 'studio_view', fragment, None,
        extra_data={"course-id": unicode(course_key)},
        usage_id_serializer=lambda usage_id: quote_slashes(unicode(usage_id)),
        # Generate a new request_token here at random, because this module isn't connected to any other
        # xblock rendering.
        request_token=uuid.uuid1().get_hex()
    )
    cohorts = []
    if is_course_cohorted(course_key):
        cohorts = get_course_cohorts(course)
    course_modes = []
    if not VerifiedTrackCohortedCourse.is_verified_track_cohort_enabled(course_key):
        course_modes = CourseMode.modes_for_course(course_key, include_expired=True, only_selectable=False)
    email_editor = fragment.content
    section_data = {
        'section_key': 'send_email',
        'section_display_name': _('Email'),
        'access': access,
        'send_email': reverse('send_email', kwargs={'course_id': unicode(course_key)}),
        'editor': email_editor,
        'cohorts': cohorts,
        'course_modes': course_modes,
        'default_cohort_name': DEFAULT_COHORT_NAME,
        'list_instructor_tasks_url': reverse(
            'list_instructor_tasks', kwargs={'course_id': unicode(course_key)}
        ),
        'email_background_tasks_url': reverse(
            'list_background_email_tasks', kwargs={'course_id': unicode(course_key)}
        ),
        'email_content_history_url': reverse(
            'list_email_content', kwargs={'course_id': unicode(course_key)}
        ),
    }
    from openedx.stanford.lms.djangoapps.instructor.views.instructor_dashboard import send_email_section_data
    section_data.update(send_email_section_data())
    return section_data
Beispiel #4
0
def move_to_verified_cohort(sender, instance, **kwargs):  # pylint: disable=unused-argument
    """
    If the learner has changed modes, update assigned cohort iff the course is using
    the Automatic Verified Track Cohorting MVP feature.
    """
    course_key = instance.course_id
    verified_cohort_enabled = VerifiedTrackCohortedCourse.is_verified_track_cohort_enabled(course_key)
    verified_cohort_name = VerifiedTrackCohortedCourse.verified_cohort_name_for_course(course_key)

    if verified_cohort_enabled and (instance.mode != instance._old_mode):  # pylint: disable=protected-access
        if not is_course_cohorted(course_key):
            log.error("Automatic verified cohorting enabled for course '%s', but course is not cohorted.", course_key)
        else:
            course = get_course_by_id(course_key)
            existing_manual_cohorts = get_course_cohorts(course, CourseCohort.MANUAL)
            if any(cohort.name == verified_cohort_name for cohort in existing_manual_cohorts):
                # Get a random cohort to use as the default cohort (for audit learners).
                # Note that calling this method will create a "Default Group" random cohort if no random
                # cohort yet exist.
                random_cohort = get_random_cohort(course_key)
                args = {
                    'course_id': unicode(course_key),
                    'user_id': instance.user.id,
                    'verified_cohort_name': verified_cohort_name,
                    'default_cohort_name': random_cohort.name
                }
                log.info(
                    "Queuing automatic cohorting for user '%s' in course '%s' "
                    "due to change in enrollment mode from '%s' to '%s'.",
                    instance.user.id, course_key, instance._old_mode, instance.mode  # pylint: disable=protected-access
                )

                # Do the update with a 3-second delay in hopes that the CourseEnrollment transaction has been
                # completed before the celery task runs. We want a reasonably short delay in case the learner
                # immediately goes to the courseware.
                sync_cohort_with_mode.apply_async(kwargs=args, countdown=3)

                # In case the transaction actually was not committed before the celery task runs,
                # run it again after 5 minutes. If the first completed successfully, this task will be a no-op.
                sync_cohort_with_mode.apply_async(kwargs=args, countdown=300)
            else:
                log.error(
                    "Automatic verified cohorting enabled for course '%s', "
                    "but verified cohort named '%s' does not exist.",
                    course_key,
                    verified_cohort_name,
                )
Beispiel #5
0
 def val_cohorts(self):
     """Проверка наличия в курсе когорт, для каждой вывод их численности либо сообщение об их отсутствии"""
     course = self.course
     cohorts = get_course_cohorts(course)
     names = [getattr(x, "name") for x in cohorts]
     users = [getattr(x, "users").all() for x in cohorts]
     report = []
     cohort_strs = []
     for num, x in enumerate(names):
         cohort_strs.append([x, str(len(users[num]))])
     is_cohorted = get_course_cohort_settings(self.course_key).is_cohorted
     if not is_cohorted:
         cohort_strs = []
         report.append(_("Cohorts are disabled"))
     result = Report(name=self.scenarios_names["cohorts"],
                     head=[_(" Cohorts "), _("Population")],
                     body=cohort_strs,
                     warnings=report,
                     )
     return result
Beispiel #6
0
def _section_send_email(course, access):
    """ Provide data for the corresponding bulk email section """
    course_key = course.id

    # Monkey-patch applicable_aside_types to return no asides for the duration of this render
    with patch.object(course.runtime, 'applicable_aside_types',
                      null_applicable_aside_types):
        # This HtmlDescriptor is only being used to generate a nice text editor.
        html_module = HtmlDescriptor(
            course.system, DictFieldData({'data': ''}),
            ScopeIds(None, None, None,
                     course_key.make_usage_key('html', 'fake')))
        fragment = course.system.render(html_module, 'studio_view')
    fragment = wrap_xblock(
        'LmsRuntime',
        html_module,
        'studio_view',
        fragment,
        None,
        extra_data={"course-id": unicode(course_key)},
        usage_id_serializer=lambda usage_id: quote_slashes(unicode(usage_id)),
        # Generate a new request_token here at random, because this module isn't connected to any other
        # xblock rendering.
        request_token=uuid.uuid1().get_hex())
    cohorts = []
    if is_course_cohorted(course_key):
        cohorts = get_course_cohorts(course)
    course_modes = []
    if not VerifiedTrackCohortedCourse.is_verified_track_cohort_enabled(
            course_key):
        course_modes = CourseMode.modes_for_course(course_key,
                                                   include_expired=True,
                                                   only_selectable=False)
    email_editor = fragment.content
    section_data = {
        'section_key':
        'send_email',
        'section_display_name':
        _('Email'),
        'access':
        access,
        'send_email':
        reverse('send_email', kwargs={'course_id': unicode(course_key)}),
        'editor':
        email_editor,
        'cohorts':
        cohorts,
        'course_modes':
        course_modes,
        'default_cohort_name':
        DEFAULT_COHORT_NAME,
        'list_instructor_tasks_url':
        reverse('list_instructor_tasks',
                kwargs={'course_id': unicode(course_key)}),
        'email_background_tasks_url':
        reverse('list_background_email_tasks',
                kwargs={'course_id': unicode(course_key)}),
        'email_content_history_url':
        reverse('list_email_content',
                kwargs={'course_id': unicode(course_key)}),
    }
    return section_data
    def student_view(self, context=None):
        """
        The primary view of the StaffGradedXBlock, shown to students
        when viewing courses.
        """
        frag = Fragment()
        frag.add_css(self.resource_string("static/css/staff_graded.css"))
        loader = ResourceLoader(__name__)
        _ = self.runtime.service(self, "i18n").ugettext

        # Add i18n js
        statici18n_js_url = self._get_statici18n_js_url()
        if statici18n_js_url:
            frag.add_javascript_url(
                self.runtime.local_resource_url(self, statici18n_js_url))

        frag.add_javascript(
            self.resource_string("static/js/src/staff_graded.js"))
        frag.initialize_js('StaffGradedXBlock')

        context['id'] = self.location.html_id()
        context['instructions'] = markdown.markdown(self.instructions)
        context['display_name'] = self.display_name
        context['is_staff'] = self.runtime.user_is_staff

        course_id = self.location.course_key
        context['available_cohorts'] = [
            cohort.name for cohort in get_course_cohorts(course_id=course_id)
        ]
        context['available_tracks'] = [
            (mode.slug, mode.name)
            for mode in modes_for_course(course_id, only_selectable=False)
        ]

        if context['is_staff']:
            from crum import get_current_request
            from django.middleware.csrf import get_token
            context['import_url'] = self.runtime.handler_url(
                self, "csv_import_handler")
            context['export_url'] = self.runtime.handler_url(
                self, "csv_export_handler")
            context['poll_url'] = self.runtime.handler_url(
                self, "get_results_handler")
            context['csrf_token'] = get_token(get_current_request())
            frag.add_javascript(
                loader.load_unicode('static/js/src/staff_graded.js'))
            frag.initialize_js('StaffGradedProblem',
                               json_args={
                                   k: context[k]
                                   for k in ('csrf_token', 'import_url',
                                             'export_url', 'poll_url', 'id')
                               })

        try:
            score = get_score(self.location, self.runtime.user_id) or {}
            context['grades_available'] = True
        except NoSuchServiceError:
            context['grades_available'] = False
        else:
            if score:
                grade = score['score']
                context['score_string'] = _('{score} / {total} points').format(
                    score=grade, total=self.weight)
            else:
                context['score_string'] = _('{total} points possible').format(
                    total=self.weight)
        frag.add_content(
            loader.render_django_template('static/html/staff_graded.html',
                                          context))
        return frag
Beispiel #8
0
def _section_send_email(course, access):
    """ Provide data for the corresponding bulk email section """
    course_key = course.id

    # Monkey-patch applicable_aside_types to return no asides for the duration of this render
    with patch.object(course.runtime, 'applicable_aside_types',
                      null_applicable_aside_types):
        # This HtmlBlock is only being used to generate a nice text editor.
        html_module = HtmlBlock(
            course.system, DictFieldData({'data': ''}),
            ScopeIds(None, None, None,
                     course_key.make_usage_key('html', 'fake')))
        fragment = course.system.render(html_module, 'studio_view')
    fragment = wrap_xblock(
        'LmsRuntime',
        html_module,
        'studio_view',
        fragment,
        None,
        extra_data={"course-id": str(course_key)},
        usage_id_serializer=lambda usage_id: quote_slashes(str(usage_id)),
        # Generate a new request_token here at random, because this module isn't connected to any other
        # xblock rendering.
        request_token=uuid.uuid1().hex)
    cohorts = []
    if is_course_cohorted(course_key):
        cohorts = get_course_cohorts(course)
    course_modes = CourseMode.modes_for_course(course_key,
                                               include_expired=True,
                                               only_selectable=False)
    email_editor = fragment.content
    section_data = {
        'section_key':
        'send_email',
        'section_display_name':
        _('Email'),
        'access':
        access,
        'send_email':
        reverse('send_email', kwargs={'course_id': str(course_key)}),
        'editor':
        email_editor,
        'cohorts':
        cohorts,
        'course_modes':
        course_modes,
        'default_cohort_name':
        DEFAULT_COHORT_NAME,
        'list_instructor_tasks_url':
        reverse('list_instructor_tasks', kwargs={'course_id':
                                                 str(course_key)}),
        'email_background_tasks_url':
        reverse('list_background_email_tasks',
                kwargs={'course_id': str(course_key)}),
        'email_content_history_url':
        reverse('list_email_content', kwargs={'course_id': str(course_key)}),
    }
    if settings.FEATURES.get("ENABLE_NEW_BULK_EMAIL_EXPERIENCE",
                             False) is not False:
        section_data[
            "communications_mfe_url"] = f"{settings.COMMUNICATIONS_MICROFRONTEND_URL}/courses/{str(course_key)}/bulk_email"
    return section_data