Beispiel #1
0
def get_generator_status_message(generator_class, job):
    message = safe_dom.NodeList()

    generator_description = generator_class.get_description()
    if job is None:
        message.append(
            safe_dom.Text('Statistics for %s have not been calculated yet' %
                          generator_description))
    elif job.status_code == jobs.STATUS_CODE_COMPLETED:
        message.append(
            safe_dom.Text(
                'Statistics for %s were last updated at %s in about %s sec.' %
                (generator_description,
                 job.updated_on.strftime(utils.HUMAN_READABLE_DATETIME_FORMAT),
                 job.execution_time_sec)))
    elif job.status_code == jobs.STATUS_CODE_FAILED:
        message.append(
            safe_dom.Text('There was an error updating %s ' %
                          generator_description + 'statistics.  Error msg:'))
        message.append(safe_dom.Element('br'))
        if issubclass(generator_class, jobs.MapReduceJob):
            error_message = jobs.MapReduceJob.get_error_message(job)
        else:
            error_message = job.output
        message.append(
            safe_dom.Element('div', className='gcb-message').add_child(
                safe_dom.Element('pre').add_text(error_message)))
    else:
        message.append(
            safe_dom.Text(
                'Job for %s statistics started at %s and is running now.' %
                (generator_description,
                 job.updated_on.strftime(
                     utils.HUMAN_READABLE_DATETIME_FORMAT))))
    return message
Beispiel #2
0
def get_student_profile_sub_unsub_link(handler, student, unused_course):
    email = student.email
    is_unsubscribed = unsubscribe.has_unsubscribed(email)

    # I18N: Control allowing user to subscribe/unsubscribe from email invitation
    sub_unsub_title = handler.gettext('Subscribe/Unsubscribe')
    sub_unsub_message = safe_dom.NodeList()

    if is_unsubscribed:
        resubscribe_url = unsubscribe.get_resubscribe_url(handler, email)
        sub_unsub_message.append(
            safe_dom.Text(
                # I18N: Message - user has unsubscribed from email invitations.
                handler.gettext(
                    'You are currently unsubscribed from course-related emails.'
                )))
        sub_unsub_message.append(
            safe_dom.A(resubscribe_url).add_text(
                # I18N: Control allowing user to re-subscribe to email invitations.
                handler.gettext('Click here to re-subscribe.')))
    else:
        unsubscribe_url = unsubscribe.get_unsubscribe_url(handler, email)
        sub_unsub_message.append(
            safe_dom.Text(
                # I18N: Text indicating user has opted in to email invitations.
                handler.gettext(
                    'You are currently receiving course-related emails. ')))
        sub_unsub_message.append(
            safe_dom.A(unsubscribe_url).add_text(
                # I18N: Control allowing user to unsubscribe from email invitations.
                handler.gettext('Click here to unsubscribe.')))

    return (sub_unsub_title, sub_unsub_message)
Beispiel #3
0
def get_certificate_table_entry(handler, student, course):
    # I18N: Title of section on page showing certificates for course completion.
    title = handler.gettext('Certificate')

    explanations = []
    if student_is_qualified(student, course, explanations=explanations):
        nl = safe_dom.NodeList()
        nl.append(
            safe_dom.A(CERTIFICATE_HANDLER_PATH).add_text(
                # I18N: Label on control to navigate to page showing certificate
                handler.gettext('Click for certificate'))).append(
                    safe_dom.Text(' | ')).append(
                        safe_dom.A(CERTIFICATE_PDF_HANDLER_PATH).add_text(
                            # I18N: Link for a PDF.
                            handler.gettext('Download PDF')))
        return (title, nl)
    else:
        nl = safe_dom.NodeList()
        nl.append(
            safe_dom.Text(
                # I18N: Text indicating student has not yet completed a course.
                handler.gettext(
                    'You have not yet met the course requirements for a '
                    'certificate of completion.')))
        if explanations:
            ul = safe_dom.Element('ul', className='certificate-explanations')
            for expl in explanations:
                ul.append(safe_dom.Element('li').add_text(expl))
            nl.append(ul)
        return (title, nl)
 def format_title(self, text):
     """Formats standard title."""
     return safe_dom.NodeList().append(
         safe_dom.Text('Course Builder ')).append(
             safe_dom.Entity('>')).append(
                 safe_dom.Text(' Admin ')).append(
                     safe_dom.Entity('>')).append(
                         safe_dom.Text(' %s' % text))
Beispiel #5
0
 def format_title(self, text):
     """Formats standard title."""
     title = self.app_context.get_environ()['course']['title']
     return safe_dom.NodeList().append(safe_dom.Text('U-MOOC ')).append(
         safe_dom.Entity('>')).append(safe_dom.Text(
             ' %s ' % title)).append(safe_dom.Entity('>')).append(
                 safe_dom.Text(' Dashboard ')).append(
                     safe_dom.Entity('>')).append(
                         safe_dom.Text(' %s' % text))
Beispiel #6
0
 def _get_availability(self, resource):
     if not hasattr(resource, 'now_available'):
         return safe_dom.Text('')
     if resource.now_available:
         return safe_dom.Text('')
     else:
         return safe_dom.NodeList().append(safe_dom.Text(' ')).append(
             safe_dom.Element('span', className='draft-label').add_text(
                 '(%s)' % unit_lesson_editor.DRAFT_TEXT))
Beispiel #7
0
    def get_markup(self, job):
        """Returns Jinja markup for question stats analytics."""

        errors = []
        stats_calculated = False
        update_message = safe_dom.Text('')

        accumulated_question_answers = None
        accumulated_assessment_answers = None

        if not job:
            update_message = safe_dom.Text(
                'Multiple-choice question statistics have not been calculated '
                'yet.')
        else:
            if job.status_code == jobs.STATUS_CODE_COMPLETED:
                accumulated_question_answers, accumulated_assessment_answers = (
                    transforms.loads(job.output))
                stats_calculated = True
                update_message = safe_dom.Text(
                    """
                    Multiple-choice question statistics were last updated at
                    %s in about %s second(s).""" %
                    (job.updated_on.strftime(HUMAN_READABLE_TIME_FORMAT),
                     job.execution_time_sec))
            elif job.status_code == jobs.STATUS_CODE_FAILED:
                update_message = safe_dom.NodeList().append(
                    safe_dom.Text("""
                        There was an error updating multiple-choice question
                        statistics. Here is the message:""")).append(
                        safe_dom.Element('br')).append(
                            safe_dom.Element('blockquote').add_child(
                                safe_dom.Element('pre').add_text('\n%s' %
                                                                 job.output)))
            else:
                update_message = safe_dom.Text(
                    """
                    Multiple-choice question statistics update started at %s
                    and is running now. Please come back shortly.""" %
                    (job.updated_on.strftime(HUMAN_READABLE_TIME_FORMAT)))

        return jinja2.utils.Markup(
            self.get_template(
                'question_stats.html', [os.path.dirname(__file__)]).render(
                    {
                        'errors':
                        errors,
                        'accumulated_question_answers':
                        transforms.dumps(accumulated_question_answers),
                        'accumulated_assessment_answers':
                        transforms.dumps(accumulated_assessment_answers),
                        'stats_calculated':
                        stats_calculated,
                        'update_message':
                        update_message,
                    },
                    autoescape=True))
Beispiel #8
0
    def _get_user_nav(self):
        current_action = self.request.get('action')
        nav_mappings = [('welcome', 'Welcome'), ('courses', 'Courses'),
                        ('settings', 'Settings'), ('perf', 'Metrics'),
                        ('deployment', 'Deployment')]
        if DIRECT_CODE_EXECUTION_UI_ENABLED:
            nav_mappings.append(('console', 'Console'))
        nav = safe_dom.NodeList()
        for action, title in nav_mappings:
            if action == current_action:
                elt = safe_dom.Element('a',
                                       href='/admin?action=%s' % action,
                                       className='selected')
            else:
                elt = safe_dom.Element('a', href='/admin?action=%s' % action)
            elt.add_text(title)
            nav.append(elt).append(safe_dom.Text(' '))

        if appengine_config.gcb_appstats_enabled():
            nav.append(
                safe_dom.Element(
                    'a', target='_blank',
                    href='/admin/stats/').add_text('Appstats')).append(
                        safe_dom.Text(' '))

        if appengine_config.PRODUCTION_MODE:
            app_id = app.get_application_id()
            nav.append(
                safe_dom.Element('a',
                                 target='_blank',
                                 href=('https://appengine.google.com/'
                                       'dashboard?app_id=s~%s' %
                                       app_id)).add_text('Google App Engine'))
        else:
            nav.append(
                safe_dom.Element('a',
                                 target='_blank',
                                 href='http://localhost:8000/').add_text(
                                     'Google App Engine')).append(
                                         safe_dom.Text(' '))

        nav.append(
            safe_dom.Element(
                'a',
                target='_blank',
                href='https://code.google.com/p/course-builder/wiki/AdminPage'
            ).add_text('Help'))

        nav.append(
            safe_dom.Element(
                'a',
                href=('https://groups.google.com/forum/'
                      '?fromgroups#!forum/course-builder-announce'),
                target='_blank').add_text('News'))

        return nav
Beispiel #9
0
 def describe(cls, entity_class):
     for fn in models_data_removal.Registry.get_user_id_removers():
         if fn.im_self == entity_class:
             return safe_dom.Text('By user_id')
     for fn in models_data_removal.Registry.get_email_removers():
         if fn.im_self == entity_class:
             return safe_dom.Text('By email')
     if (entity_class.kind() in
         models_data_removal.Registry.get_unindexed_classes()):
         return safe_dom.Text('Map/Reduce job')
Beispiel #10
0
 def get_doc_string(item, default_value):
     """Formats an item documentation string for display."""
     doc_string = item.doc_string
     if not doc_string:
         doc_string = 'No documentation available.'
     if isinstance(doc_string, safe_dom.SafeDom):
         return safe_dom.NodeList().append(doc_string).append(
             safe_dom.Text(' Default: \'%s\'.' % default_value))
     doc_string = ' %s Default: \'%s\'.' % (doc_string, default_value)
     return safe_dom.Text(doc_string)
Beispiel #11
0
 def format_title(self, text):
     """Formats standard title with or without course picker."""
     ret = safe_dom.NodeList()
     cb_text = 'Course Builder '
     ret.append(safe_dom.Text(cb_text))
     ret.append(safe_dom.Entity('>'))
     ret.append(safe_dom.Text(' %s ' % self.app_context.get_title()))
     ret.append(safe_dom.Entity('>'))
     dashboard_text = ' Dashboard '
     ret.append(safe_dom.Text(dashboard_text))
     ret.append(safe_dom.Entity('>'))
     ret.append(safe_dom.Text(' %s' % text))
     return ret
Beispiel #12
0
    def render_page(self, template_values, in_action=None):
        page_title = template_values['page_title']
        template_values['header_title'] = page_title
        template_values['page_headers'] = [
            hook(self) for hook in self.PAGE_HEADER_HOOKS]
        template_values['breadcrumbs'] = page_title

        current_action = (in_action or self.request.get('action')
            or self.default_action_for_current_permissions())
        current_menu_item = self.actions_to_menu_items.get(current_action)
        template_values['root_menu_group'] = self.root_menu_group
        template_values['current_menu_item'] = current_menu_item
        template_values['is_global_admin'] = True
        template_values['course_app_contexts'] = dashboard.get_visible_courses()

        template_values['gcb_course_base'] = '/'
        template_values['user_nav'] = safe_dom.NodeList().append(
            safe_dom.Text('%s | ' % users.get_current_user().email())
        ).append(
            safe_dom.Element(
                'a', href=users.create_logout_url(self.request.uri)
            ).add_text('Logout'))
        template_values[
            'page_footer'] = 'Page created on: %s' % datetime.datetime.now()
        template_values['coursebuilder_version'] = (
            os.environ['GCB_PRODUCT_VERSION'])
        template_values['application_id'] = app.get_application_id()
        template_values['application_version'] = (
            os.environ['CURRENT_VERSION_ID'])
        if not template_values.get('sections'):
            template_values['sections'] = []

        self.response.write(
            self.get_template('view.html', []).render(template_values))
Beispiel #13
0
 def get_lines(value):
     """Convert \\n line breaks into <br> and escape the lines."""
     escaped_value = safe_dom.NodeList()
     for line in str(value).split('\n'):
         escaped_value.append(safe_dom.Text(line)).append(
             safe_dom.Element('br'))
     return escaped_value
Beispiel #14
0
def _get_assets_contrib(handler, items, name, all_paths):
    if not contrib_asset_listers:
        items.append(safe_dom.Text(
            'No assets extensions have been registered'))
    else:
        for asset_lister in contrib_asset_listers:
            items.append(asset_lister(handler))
    def render_page(self, template_values, in_action=None, in_tab=None):
        """Renders a page using provided template values."""
        template_values['header_title'] = template_values['page_title']
        template_values['page_headers'] = [
            hook(self) for hook in self.PAGE_HEADER_HOOKS
        ]
        template_values['course_picker'] = self.get_course_picker()
        template_values['course_title'] = self.app_context.get_title()
        template_values['top_nav'] = self._get_top_nav(in_action, in_tab)
        template_values['gcb_course_base'] = self.get_base_href(self)
        template_values['user_nav'] = safe_dom.NodeList().append(
            safe_dom.Text('%s | ' % users.get_current_user().email())).append(
                safe_dom.Element('a',
                                 href=users.create_logout_url(
                                     self.request.uri)).add_text('Logout'))
        template_values[
            'page_footer'] = 'Page created on: %s' % datetime.datetime.now()
        template_values['coursebuilder_version'] = (
            os.environ['GCB_PRODUCT_VERSION'])
        template_values['application_id'] = app_identity.get_application_id()
        template_values['application_version'] = (
            os.environ['CURRENT_VERSION_ID'])
        template_values[
            'can_highlight_code'] = oeditor.CAN_HIGHLIGHT_CODE.value
        template_values['extra_css_href_list'] = self.EXTRA_CSS_HREF_LIST
        template_values['extra_js_href_list'] = self.EXTRA_JS_HREF_LIST
        if not template_values.get('sections'):
            template_values['sections'] = []

        self.response.write(
            self.get_template('view.html', []).render(template_values))
Beispiel #16
0
    def render_page(self, template_values, in_action=None, in_tab=None):
        page_title = template_values['page_title']
        template_values['header_title'] = page_title
        template_values['page_headers'] = [
            hook(self) for hook in self.PAGE_HEADER_HOOKS
        ]
        template_values['breadcrumbs'] = page_title

        template_values['top_nav'] = self._get_top_nav(in_action, in_tab)
        template_values['gcb_course_base'] = '/'
        template_values['user_nav'] = safe_dom.NodeList().append(
            safe_dom.Text('%s | ' % users.get_current_user().email())).append(
                safe_dom.Element('a',
                                 href=users.create_logout_url(
                                     self.request.uri)).add_text('Logout'))
        template_values[
            'page_footer'] = 'Page created on: %s' % datetime.datetime.now()
        template_values['coursebuilder_version'] = (
            os.environ['GCB_PRODUCT_VERSION'])
        template_values['application_id'] = app.get_application_id()
        template_values['application_version'] = (
            os.environ['CURRENT_VERSION_ID'])
        template_values[
            'can_highlight_code'] = oeditor.CAN_HIGHLIGHT_CODE.value
        if not template_values.get('sections'):
            template_values['sections'] = []

        self.response.write(
            self.get_template('view.html', []).render(template_values))
Beispiel #17
0
def get_pipeline_link(xsrf, app_context, generator_class, job):
    ret = safe_dom.NodeList()
    if (not issubclass(generator_class, jobs.MapReduceJob) or
            # Don't give access to the pipeline details UI unless someone
            # has actively intended to provide access.  The UI allows you to
            # kill jobs, and we don't want naive users stumbling around in
            # there without adult supervision.
            not mapreduce_module.GCB_ENABLE_MAPREDUCE_DETAIL_ACCESS.value or

            # Status URL may not be available immediately after job is launched;
            # pipeline setup is done w/ 'yield', and happens a bit later.
            not job or not jobs.MapReduceJob.has_status_url(job)):
        return ret

    if job.has_finished:
        link_text = 'View completed job run details'
    else:
        link_text = 'Check status of job'

    status_url = jobs.MapReduceJob.get_status_url(
        job, app_context.get_namespace_name(),
        xsrf.create_xsrf_token(mapreduce_module.XSRF_ACTION_NAME))
    ret.append(safe_dom.Text('    '))
    ret.append(safe_dom.A(status_url, target='_blank').add_text(link_text))
    return ret
Beispiel #18
0
def assemble_sanitized_message(text, link):
    node_list = safe_dom.NodeList()
    if text:
        node_list.append(safe_dom.Text(text))
    if link:
        node_list.append(safe_dom.Element(
            'a', href=link, target='_blank').add_text('Learn more...'))
    return node_list
Beispiel #19
0
def get_schema_fields():
    enabled_name = (
        GUIDE_SETTINGS_SCHEMA_SECTION + ':' + GUIDE_ENABLED_FOR_THIS_COURSE)
    enabled = schema_fields.SchemaField(
        enabled_name, 'Enable Guides', 'boolean',
        optional=True, i18n=False, editable=True,
        description=str(safe_dom.NodeList(
        ).append(safe_dom.Text(
            'If checked, this course will be included in the guides '
            'experience accessible at ')
        ).append(safe_dom.assemble_link(
            '/modules/guides', '/modules/guides', target="_blank")
        ).append(safe_dom.Text('. Course must not be Private. ')
        ).append(safe_dom.assemble_link(
            services.help_urls.get(enabled_name), 'Learn more...',
            target="_blank"))))
    color = schema_fields.SchemaField(
        GUIDE_SETTINGS_SCHEMA_SECTION + ':' + GUIDE_COLOR,
        'Color', 'string',
        optional=True, i18n=False, editable=True,
        description='The color scheme for this course\'s guides must '
            'be expressed as a web color hex triplet, beginning with '
            'a "#". If blank, #00838F will be used.')
    duration = schema_fields.SchemaField(
        GUIDE_SETTINGS_SCHEMA_SECTION + ':' + GUIDE_DURATION,
        'Duration', 'integer',
        optional=True, i18n=False, editable=True, default_value=0,
        description=(
            'Specify the average length of each lesson in the course in '
            'minutes and it will be used to estimate the duration of each '
            'guide. If blank or set to 0, duration will not be shown.'))
    availabiliy_name = GUIDE_SETTINGS_SCHEMA_SECTION + ':' + GUIDE_AVAILABILITY
    availability = schema_fields.SchemaField(
        availabiliy_name, 'Availability', 'boolean', optional=True, i18n=False,
        select_data=AVAILABILITY_SELECT_DATA,
        default_value=courses.AVAILABILITY_COURSE,
        description=str(safe_dom.NodeList(
        ).append(safe_dom.Text(
            'Guides default to the availability of the course, '
            'but may also be restricted to admins (Private). ')
        ).append(safe_dom.assemble_link(
            services.help_urls.get(availabiliy_name), 'Learn more...',
            target="_blank"))))

    return (lambda _: enabled, lambda _: color, lambda _: duration,
            lambda _: availability)
Beispiel #20
0
    def get_markup(self, job):
        template_values = {}
        template_values['stats_calculated'] = False
        if not job:
            message = ('%s statistics have not been calculated yet.' %
                       self.description.capitalize())
            template_values['update_message'] = safe_dom.Text(message)
        else:
            if job.status_code == jobs.STATUS_CODE_COMPLETED:
                template_values['stats_calculated'] = True
                default_message = (
                    '%s statistics were last updated at %s in about %s sec.' %
                    (self.description.capitalize(),
                     job.updated_on.strftime(utils.HUMAN_READABLE_TIME_FORMAT),
                     job.execution_time_sec))
                # This message can be overridden by _fill_completed_values()
                # as necessary and approprate.
                template_values['update_message'] = safe_dom.Text(
                    default_message)

                self._fill_completed_values(job, template_values)
            elif job.status_code == jobs.STATUS_CODE_FAILED:
                message = (
                    'There was an error updating %s statistics.  Error msg:' %
                    self.description)
                update_message = safe_dom.NodeList()
                update_message.append(safe_dom.Text(message))
                update_message.append(safe_dom.Element('br'))
                update_message.append(
                    safe_dom.Element('blockquote').add_child(
                        safe_dom.Element('pre').add_text(
                            '\n%s' % self._get_error_message(job))))
                template_values['update_message'] = update_message
            else:
                message = (
                    '%s statistics update started at %s and is running now.' %
                    (self.description.capitalize(),
                     job.updated_on.strftime(
                         utils.HUMAN_READABLE_TIME_FORMAT)))
                template_values['update_message'] = safe_dom.Text(message)
                self._fill_pending_values(job, template_values)
        return jinja2.utils.Markup(
            self.get_template(self.html_template_name,
                              [os.path.dirname(__file__)]).render(
                                  template_values, autoescape=True))
Beispiel #21
0
    def render_page(self, template_values, in_action=None):
        """Renders a page using provided template values."""
        template_values['header_title'] = template_values['page_title']
        template_values['page_headers'] = [
            hook(self) for hook in self.PAGE_HEADER_HOOKS
        ]
        template_values['course_title'] = self.app_context.get_title()

        current_action = in_action or self._get_current_menu_action()
        template_values['current_menu_item'] = self.actions_to_menu_items.get(
            current_action)
        template_values['courses_menu_item'] = self.actions_to_menu_items.get(
            'courses')
        template_values['root_menu_group'] = self.root_menu_group

        template_values['course_app_contexts'] = get_visible_courses()
        template_values['app_context'] = self.app_context
        template_values['current_course'] = self.get_course()
        template_values['gcb_course_base'] = self.get_base_href(self)
        template_values['user_nav'] = safe_dom.NodeList().append(
            safe_dom.Text('%s | ' % users.get_current_user().email())).append(
                safe_dom.Element('a',
                                 href=users.create_logout_url(
                                     self.request.uri)).add_text('Logout'))
        template_values[
            'page_footer'] = 'Page created on: %s' % datetime.datetime.now()
        template_values['coursebuilder_version'] = (
            os.environ['GCB_PRODUCT_VERSION'])
        template_values['application_id'] = app_identity.get_application_id()
        version = os.environ['CURRENT_VERSION_ID']
        if '.' not in version or not appengine_config.PRODUCTION_MODE:
            template_values['application_version'] = version
        else:
            version, deployed_at = version.split('.', 1)
            template_values['application_version'] = version
            template_values[
                'deployed_at'] = datetime.datetime.utcfromtimestamp(
                    int(deployed_at) >> 28)  # Yes, really.

        template_values['extra_css_href_list'] = self.EXTRA_CSS_HREF_LIST
        template_values['extra_js_href_list'] = self.EXTRA_JS_HREF_LIST
        template_values['powered_by_url'] = services.help_urls.get(
            'dashboard:powered_by')

        if not template_values.get('sections'):
            template_values['sections'] = []
        if not appengine_config.PRODUCTION_MODE:
            template_values['page_uuid'] = str(uuid.uuid1())

        self.response.write(
            self.get_template('view.html').render(template_values))
Beispiel #22
0
    def render_page(self, template_values, in_action=None):
        """Render page contents and write them into the response.

        NOTE: The resulting contents are *not* sent to the client (user's
        browser) as a result of calling render_page(). webapp2 does not
        forward the response and its contents to the client until the
        handler itself completes.
        """
        page_title = template_values['page_title']
        template_values['header_title'] = page_title
        template_values['page_headers'] = [
            hook(self) for hook in self.PAGE_HEADER_HOOKS]
        template_values['breadcrumbs'] = page_title

        # menu
        current_action = (in_action or self.request.get('action')
            or self.default_action_for_current_permissions())
        template_values['current_menu_item'] = self.actions_to_menu_items\
            .get(current_action)
        template_values['courses_menu_item'] = self.actions_to_menu_items.get(
            'courses')
        template_values['root_menu_group'] = self.root_menu_group

        template_values['course_app_contexts'] = dashboard.get_visible_courses()
        template_values['gcb_course_base'] = self.BASE_URL
        template_values['user_nav'] = safe_dom.NodeList().append(
            safe_dom.Text('%s | ' % users.get_current_user().email())
        ).append(
            safe_dom.Element(
                'a', href=users.create_logout_url(self.request.uri)
            ).add_text('Logout'))
        template_values[
            'page_footer'] = 'Page created on: %s' % datetime.datetime.now()
        template_values['coursebuilder_version'] = (
            os.environ['GCB_PRODUCT_VERSION'])
        template_values['application_id'] = app.get_application_id()
        version = os.environ['CURRENT_VERSION_ID']
        if '.' not in version or not appengine_config.PRODUCTION_MODE:
            template_values['application_version'] = version
        else:
            version, deployed_at = version.split('.', 1)
            template_values['application_version'] = version
            template_values['deployed_at'] = datetime.datetime.utcfromtimestamp(
                int(deployed_at) >> 28)  # Yes, really.
        if not template_values.get('sections'):
            template_values['sections'] = []
        if not appengine_config.PRODUCTION_MODE:
            template_values['page_uuid'] = str(uuid.uuid1())

        self.response.write(
            self.get_template('view.html').render(template_values))
Beispiel #23
0
    def render_page(self, template_values):
        """Renders a page using provided template values."""

        template_values['top_nav'] = self._get_user_nav()
        template_values['user_nav'] = safe_dom.NodeList().append(
            safe_dom.Text('%s | ' % users.get_current_user().email())).append(
                safe_dom.Element('a',
                                 href=users.create_logout_url(
                                     self.request.uri)).add_text('Logout'))
        template_values[
            'page_footer'] = 'Created on: %s' % datetime.datetime.now()

        self.response.write(
            self.get_template('view.html', []).render(template_values))
Beispiel #24
0
 def _add_pipeline_link(self, job, template_values, message):
     status_url = jobs.MapReduceJob.get_status_url(
         # app_context is forcibly injected into instances from
         # modules.dashboard.get_analytics()
         # pylint: disable=undefined-variable
         job,
         self.app_context.get_namespace_name(),
         utils.XsrfTokenManager.create_xsrf_token(
             mapreduce_module.XSRF_ACTION_NAME))
     update_message = safe_dom.NodeList()
     update_message.append(template_values['update_message'])
     update_message.append(safe_dom.Text('    '))
     update_message.append(
         safe_dom.A(status_url, target='_blank').add_text(message))
     template_values['update_message'] = update_message
Beispiel #25
0
    def _fill_completed_values(self, job, template_values):
        course = courses.Course(self)
        template_values['entity_codes'] = transforms.dumps(
            progress.UnitLessonCompletionTracker.EVENT_CODE_MAPPING.values())
        value = transforms.loads(job.output)
        if value:
            value = transforms.dumps(value)
        else:
            value = None
        template_values['progress'] = value

        try:
            template_values['content'] = transforms.dumps(
                progress.ProgressStats(course).compute_entity_dict(
                    'course', []))
        except IOError:
            template_values['update_message'] = safe_dom.Text(
                'This feature is supported by CB 1.3 and up.')
Beispiel #26
0
def get_student_profile_invitation_link(handler, unused_student,
                                        unused_course):
    env = handler.app_context.get_environ()
    email_env = env['course'].get(INVITATION_EMAIL_KEY, {})
    if not email_env.get('enabled'):
        return (None, None)

    # I18N: Title encouraging user to invite friends to join a course
    invitation_title = handler.gettext('Invite Friends')
    if InvitationEmail.is_available(handler):
        invitation_link = safe_dom.A(
            InvitationHandler.URL
            # I18N: Label on control asking user to invite friends to join.
        ).add_text(
            handler.gettext('Click to send invitations to family and friends'))
    else:
        # I18N: Inviting friends to join a course is not currently enabled.
        invitation_link = safe_dom.Text(
            handler.gettext('Invitations not currently available'))

    return (invitation_title, invitation_link)
Beispiel #27
0
    def render_page(self, template_values, in_action=None):
        """Renders a page using provided template values."""
        template_values['header_title'] = template_values['page_title']
        template_values['page_headers'] = [
            hook(self) for hook in self.PAGE_HEADER_HOOKS
        ]
        template_values['course_title'] = self.app_context.get_title()

        current_action = (in_action or self.request.get('action')
                          or self.default_action_for_current_permissions())
        current_menu_item = self.actions_to_menu_items.get(current_action)
        template_values['root_menu_group'] = self.root_menu_group
        template_values['current_menu_item'] = current_menu_item
        template_values['app_context'] = self.app_context
        template_values['course_app_contexts'] = get_visible_courses()
        template_values['current_course'] = self.get_course()

        template_values['gcb_course_base'] = self.get_base_href(self)
        template_values['user_nav'] = safe_dom.NodeList().append(
            safe_dom.Text('%s | ' % users.get_current_user().email())).append(
                safe_dom.Element('a',
                                 href=users.create_logout_url(
                                     self.request.uri)).add_text('Logout'))
        template_values[
            'page_footer'] = 'Page created on: %s' % datetime.datetime.now()
        template_values['coursebuilder_version'] = (
            os.environ['GCB_PRODUCT_VERSION'])
        template_values['application_id'] = app_identity.get_application_id()
        template_values['application_version'] = (
            os.environ['CURRENT_VERSION_ID'])
        template_values['extra_css_href_list'] = self.EXTRA_CSS_HREF_LIST
        template_values['extra_js_href_list'] = self.EXTRA_JS_HREF_LIST
        if not template_values.get('sections'):
            template_values['sections'] = []

        self.response.write(
            self.get_template('view.html', []).render(template_values))
Beispiel #28
0
    def get_markup(self, job):
        """Returns Jinja markup for peer review analytics."""

        errors = []
        stats_calculated = False
        update_message = safe_dom.Text('')

        course = courses.Course(self)
        serialized_units = []

        if not job:
            update_message = safe_dom.Text(
                'Peer review statistics have not been calculated yet.')
        else:
            if job.status_code == jobs.STATUS_CODE_COMPLETED:
                stats = transforms.loads(job.output)
                stats_calculated = True

                for unit in course.get_peer_reviewed_units():
                    if unit.unit_id in stats['counts_by_completed_reviews']:
                        unit_stats = (
                            stats['counts_by_completed_reviews'][unit.unit_id])
                        serialized_units.append({
                            'stats': unit_stats,
                            'title': unit.title,
                            'unit_id': unit.unit_id,
                        })
                update_message = safe_dom.Text(
                    """
                    Peer review statistics were last updated at
                    %s in about %s second(s).""" %
                    (job.updated_on.strftime(HUMAN_READABLE_TIME_FORMAT),
                     job.execution_time_sec))
            elif job.status_code == jobs.STATUS_CODE_FAILED:
                update_message = safe_dom.NodeList().append(
                    safe_dom.Text("""
                        There was an error updating peer review statistics.
                        Here is the message:""")).append(
                        safe_dom.Element('br')).append(
                            safe_dom.Element('blockquote').add_child(
                                safe_dom.Element('pre').add_text('\n%s' %
                                                                 job.output)))
            else:
                update_message = safe_dom.Text(
                    """
                    Peer review statistics update started at %s and is running
                    now. Please come back shortly.""" %
                    job.updated_on.strftime(HUMAN_READABLE_TIME_FORMAT))

        return jinja2.utils.Markup(
            self.get_template(
                'stats.html', [os.path.dirname(__file__)]).render(
                    {
                        'errors': errors,
                        'serialized_units': serialized_units,
                        'serialized_units_json':
                        transforms.dumps(serialized_units),
                        'stats_calculated': stats_calculated,
                        'update_message': update_message,
                    },
                    autoescape=True))
Beispiel #29
0
    safe_dom.Element('ol').add_child(
        safe_dom.Element('li').add_text(
            'The word \'course\', which is a required element.')).add_child(
                safe_dom.Element('li').add_text("""
A unique course URL prefix. Examples could be '/cs101' or '/art'.
Default: '/'""")).add_child(
                    safe_dom.Element('li').add_text("""
A file system location of course asset files. If location is left empty,
the course assets are stored in a datastore instead of the file system. A course
with assets in a datastore can be edited online. A course with assets on file
system must be re-deployed to Google App Engine manually.""")).add_child(
                        safe_dom.Element('li').add_text("""
A course datastore namespace where course data is stored in App Engine.
Note: this value cannot be changed after the course is created."""))
).append(
    safe_dom.Text('For example, consider the following two course entries:')
).append(safe_dom.Element('br')).append(
    safe_dom.Element(
        'div',
        className='gcb-message').add_text('course:/cs101::ns_cs101').add_child(
            safe_dom.Element('br')).add_text('course:/:/')).append(
                safe_dom.Element('div').add_text("""
Assuming you are hosting Course Builder on http://www.example.com, the first
entry defines a course on a http://www.example.com/cs101 and both its assets
and student data are stored in the datastore namespace 'ns_cs101'. The second
entry defines a course hosted on http://www.example.com/, with its assets
stored in the '/' folder of the installation and its data stored in the default
empty datastore namespace.""")).append(safe_dom.Element('br')).append(
                    safe_dom.Element('div').add_text("""
A line that starts with '#' is ignored. Course entries are applied in the
order they are defined."""))
from models import jobs
from models import services
from models import transforms
from modules.dashboard import dashboard

from google.appengine.api import namespace_manager
from google.appengine.api import search
from google.appengine.ext import db

MODULE_NAME = 'Full Text Search'

DEPRECATED = config.ConfigProperty(
    'gcb_can_index_automatically',
    bool,
    safe_dom.Text(
        'This property has been deprecated; it is retained so that we '
        'will not generate no-such-variable error messages for existing '
        'installations that have this property set.'),
    default_value=False,
    label='Automatically index search',
    deprecated=True)
SEARCH_QUERIES_MADE = counters.PerfCounter(
    'gcb-search-queries-made',
    'The number of student queries made to the search module.')
SEARCH_RESULTS_RETURNED = counters.PerfCounter(
    'gcb-search-results-returned',
    'The number of search results returned across all student queries.')
SEARCH_FAILURES = counters.PerfCounter(
    'gcb-search-failures',
    'The number of search failure messages returned across all student '
    'queries.')