def list_and_format_file_list(self, title, subfolder, links=False, upload=False, prefix=None, caption_if_empty='< none >', edit_url_template=None, sub_title=None): """Walks files in folders and renders their names in a section.""" items = safe_dom.NodeList() count = 0 for filename in self.list_files(subfolder): if prefix and not filename.startswith(prefix): continue li = safe_dom.Element('li') if links: li.add_child( safe_dom.Element( 'a', href=urllib.quote(filename)).add_text(filename)) if edit_url_template: edit_url = edit_url_template % urllib.quote(filename) li.add_child(safe_dom.Entity(' ')).add_child( safe_dom.Element('a', href=edit_url).add_text('[Edit]')) else: li.add_text(filename) count += 1 items.append(li) output = safe_dom.NodeList() if filer.is_editable_fs(self.app_context) and upload: output.append( safe_dom.Element( 'a', className='btn btn-primary pull-right', href='dashboard?%s' % urllib.urlencode({ 'action': 'add_asset', 'base': subfolder })).add_text('Upload')).append( safe_dom.Element( 'div', style='clear: both; padding-top: 2px;')) if title: h3 = safe_dom.Element('h3') if count: h3.add_text('%s (%s)' % (title, count)) else: h3.add_text(title) output.append(h3) if sub_title: output.append(safe_dom.Element('blockquote').add_text(sub_title)) if items: output.append(safe_dom.Element('ol').add_children(items)) else: if caption_if_empty: output.append( safe_dom.Element('blockquote').add_text(caption_if_empty)) return output
def list_question_groups(self): """Prepare a list of question groups.""" if not filer.is_editable_fs(self.app_context): return safe_dom.NodeList() all_questions = QuestionDAO.get_all() output = safe_dom.NodeList() if all_questions: output.append( safe_dom.Element('a', className='gcb-button gcb-pull-right', href='dashboard?action=add_question_group'). add_text('Add Question Group')).append( safe_dom.Element('div', style='clear: both; padding-top: 2px;')) output.append(safe_dom.Element('h3').add_text('Question Groups')) # TODO(jorr): Hook this into the datastore all_question_groups = QuestionGroupDAO.get_all() if all_question_groups: ol = safe_dom.Element('ol') for question_group in all_question_groups: edit_url = 'dashboard?action=edit_question_group&key=%s' % ( question_group.id) li = safe_dom.Element('li') li.add_text(question_group.description).add_child( safe_dom.Entity(' ')).add_child( safe_dom.Element('a', href=edit_url).add_text('[Edit]')) ol.add_child(li) output.append(ol) else: output.append(safe_dom.Element('blockquote').add_text('< none >')) return output
def list_questions(self): """Prepare a list of the question bank contents.""" if not filer.is_editable_fs(self.app_context): return safe_dom.NodeList() output = safe_dom.NodeList().append( safe_dom.Element('a', className='gcb-button gcb-pull-right', href='dashboard?action=add_mc_question'). add_text('Add Multiple Choice')).append( safe_dom.Element('a', className='gcb-button gcb-pull-right', href='dashboard?action=add_sa_question'). add_text('Add Short Answer')).append( safe_dom.Element( 'div', style='clear: both; padding-top: 2px;')).append( safe_dom.Element('h3').add_text('Question Bank')) all_questions = QuestionDAO.get_all() if all_questions: ol = safe_dom.Element('ol') for question in all_questions: edit_url = 'dashboard?action=edit_question&key=%s' % question.id li = safe_dom.Element('li') li.add_text(question.description).add_child( safe_dom.Entity(' ')).add_child( safe_dom.Element('a', href=edit_url).add_text('[Edit]')) ol.add_child(li) output.append(ol) else: output.append(safe_dom.Element('blockquote').add_text('< none >')) return output
def get_settings(self): """Renders course settings view.""" yaml_actions = [] # Basic course info. course_info = [('Course Title', self.app_context.get_environ()['course']['title']), ('Context Path', self.app_context.get_slug()), ('Datastore Namespace', self.app_context.get_namespace_name())] # Course file system. fs = self.app_context.fs.impl course_info.append(('File system', fs.__class__.__name__)) if fs.__class__ == vfs.LocalReadOnlyFileSystem: course_info.append( ('Home folder', sites.abspath(self.app_context.get_home_folder(), '/'))) # Enable editing if supported. if filer.is_editable_fs(self.app_context): yaml_actions.append({ 'id': 'edit_course_yaml', 'caption': 'Edit', 'action': self.get_action_url('create_or_edit_settings'), 'xsrf_token': self.create_xsrf_token('create_or_edit_settings') }) # Yaml file content. yaml_info = [] yaml_stream = self.app_context.fs.open( self.app_context.get_config_filename()) if yaml_stream: yaml_lines = yaml_stream.read().decode('utf-8') for line in yaml_lines.split('\n'): yaml_info.append(line) else: yaml_info.append('< empty file >') # Prepare template values. template_values = {} template_values['page_title'] = self.format_title('Settings') template_values['page_description'] = messages.SETTINGS_DESCRIPTION template_values['sections'] = [{ 'title': 'About the Course', 'description': messages.ABOUT_THE_COURSE_DESCRIPTION, 'children': course_info }, { 'title': 'Contents of course.yaml file', 'description': messages.CONTENTS_OF_THE_COURSE_DESCRIPTION, 'actions': yaml_actions, 'children': yaml_info }] self.render_page(template_values)
def list_and_format_file_list( self, title, subfolder, links=False, upload=False, prefix=None, caption_if_empty='< none >', edit_url_template=None, merge_local_files=False, sub_title=None): """Walks files in folders and renders their names in a section.""" items = safe_dom.NodeList() count = 0 for filename in self.list_files( subfolder, merge_local_files=merge_local_files): if prefix and not filename.startswith(prefix): continue li = safe_dom.Element('li') if links: li.add_child(safe_dom.Element( 'a', href=urllib.quote(filename)).add_text(filename)) else: li.add_text(filename) if (edit_url_template and self.app_context.fs.impl.is_read_write()): edit_url = edit_url_template % urllib.quote(filename) li.add_child( safe_dom.Entity(' ') ).add_child( safe_dom.Element('a', href=edit_url).add_text('[Edit]')) count += 1 items.append(li) output = safe_dom.NodeList() if filer.is_editable_fs(self.app_context) and upload: output.append( safe_dom.Element( 'a', className='gcb-button gcb-pull-right', href='dashboard?%s' % urllib.urlencode( {'action': 'add_asset', 'base': subfolder}) ).add_text( 'Upload to ' + filer.strip_leading_and_trailing_slashes(subfolder)) ).append( safe_dom.Element('div', style='clear: both; padding-top: 2px;')) if title: h3 = safe_dom.Element('h3') if count: h3.add_text('%s (%s)' % (title, count)) else: h3.add_text(title) output.append(h3) if sub_title: output.append(safe_dom.Element('blockquote').add_text(sub_title)) if items: output.append(safe_dom.Element('ol').add_children(items)) else: if caption_if_empty: output.append( safe_dom.Element('blockquote').add_text(caption_if_empty)) return output
def get_settings(self): """Renders course settings view.""" yaml_actions = [] # Basic course info. course_info = [ ('Course Title', self.app_context.get_environ()['course']['title']), ('Context Path', self.app_context.get_slug()), ('Datastore Namespace', self.app_context.get_namespace_name())] # Course file system. fs = self.app_context.fs.impl course_info.append(('File system', fs.__class__.__name__)) if fs.__class__ == vfs.LocalReadOnlyFileSystem: course_info.append(('Home folder', sites.abspath( self.app_context.get_home_folder(), '/'))) # Enable editing if supported. if filer.is_editable_fs(self.app_context): yaml_actions.append({ 'id': 'edit_course_yaml', 'caption': 'Edit', 'action': self.get_action_url('create_or_edit_settings'), 'xsrf_token': self.create_xsrf_token( 'create_or_edit_settings')}) # Yaml file content. yaml_info = [] yaml_stream = self.app_context.fs.open( self.app_context.get_config_filename()) if yaml_stream: yaml_lines = yaml_stream.read().decode('utf-8') for line in yaml_lines.split('\n'): yaml_info.append(line) else: yaml_info.append('< empty file >') # Prepare template values. template_values = {} template_values['page_title'] = self.format_title('Settings') template_values['page_description'] = messages.SETTINGS_DESCRIPTION template_values['sections'] = [ { 'title': 'About the Course', 'description': messages.ABOUT_THE_COURSE_DESCRIPTION, 'children': course_info}, { 'title': 'Contents of course.yaml file', 'description': messages.CONTENTS_OF_THE_COURSE_DESCRIPTION, 'actions': yaml_actions, 'children': yaml_info}] self.render_page(template_values)
def list_and_format_file_list(self, title, subfolder, links=False, upload=False, prefix=None, caption_if_empty='< none >', edit_url_template=None, sub_title=None): """Walks files in folders and renders their names in a section.""" lines = [] count = 0 for filename in self.list_files(subfolder): if prefix and not filename.startswith(prefix): continue if links: lines.append('<li><a href="%s">%s</a>' % (urllib.quote(filename), cgi.escape(filename))) if edit_url_template: edit_url = edit_url_template % urllib.quote(filename) lines.append(' <a href="%s">[Edit]</a>' % edit_url) lines.append('</li>\n') else: lines.append('<li>%s</li>\n' % cgi.escape(filename)) count += 1 output = [] if filer.is_editable_fs(self.app_context) and upload: output.append( '<a class="gcb-button pull-right" href="dashboard?%s">' 'Upload</a>' % urllib.urlencode({ 'action': 'add_asset', 'base': subfolder })) output.append('<div style=\"clear: both; padding-top: 2px;\" />') if title: output.append('<h3>%s' % cgi.escape(title)) if count: output.append(' (%s)' % count) output.append('</h3>') if sub_title: output.append('<blockquote>%s</blockquote>' % cgi.escape(sub_title)) if lines: output.append('<ol>') output += lines output.append('</ol>') else: if caption_if_empty: output.append('<blockquote>%s</blockquote>' % cgi.escape(caption_if_empty)) return output
def list_and_format_file_list( self, title, subfolder, links=False, upload=False, prefix=None, caption_if_empty='< none >', edit_url_template=None, sub_title=None): """Walks files in folders and renders their names in a section.""" lines = [] count = 0 for filename in self.list_files(subfolder): if prefix and not filename.startswith(prefix): continue if links: lines.append( '<li><a href="%s">%s</a>' % ( urllib.quote(filename), cgi.escape(filename))) if edit_url_template: edit_url = edit_url_template % urllib.quote(filename) lines.append(' <a href="%s">[Edit]</a>' % edit_url) lines.append('</li>\n') else: lines.append('<li>%s</li>\n' % cgi.escape(filename)) count += 1 output = [] if filer.is_editable_fs(self.app_context) and upload: output.append( '<a class="gcb-button pull-right" href="dashboard?%s">' 'Upload</a>' % urllib.urlencode( {'action': 'add_asset', 'base': subfolder})) output.append('<div style=\"clear: both; padding-top: 2px;\" />') if title: output.append('<h3>%s' % cgi.escape(title)) if count: output.append(' (%s)' % count) output.append('</h3>') if sub_title: output.append('<blockquote>%s</blockquote>' % cgi.escape(sub_title)) if lines: output.append('<ol>') output += lines output.append('</ol>') else: if caption_if_empty: output.append( '<blockquote>%s</blockquote>' % cgi.escape( caption_if_empty)) return output
def _render_edit_form_for(self, rest_handler_cls, title, annotations_dict=None, delete_xsrf_token='delete-unit', page_description=None): """Renders an editor form for a given REST handler class.""" if not annotations_dict: annotations_dict = rest_handler_cls.SCHEMA_ANNOTATIONS_DICT key = self.request.get('key') extra_args = {} if self.request.get('is_newly_created'): extra_args['is_newly_created'] = 1 exit_url = self.canonicalize_url('/dashboard') rest_url = self.canonicalize_url(rest_handler_cls.URI) delete_url = '%s?%s' % ( self.canonicalize_url(rest_handler_cls.URI), urllib.urlencode({ 'key': key, 'xsrf_token': cgi.escape(self.create_xsrf_token(delete_xsrf_token)) })) form_html = oeditor.ObjectEditor.get_html_for( self, rest_handler_cls.SCHEMA_JSON, annotations_dict, key, rest_url, exit_url, extra_args=extra_args, delete_url=delete_url, delete_method='delete', read_only=not filer.is_editable_fs(self.app_context), required_modules=rest_handler_cls.REQUIRED_MODULES) template_values = {} template_values['page_title'] = self.format_title('Edit %s' % title) if page_description: template_values['page_description'] = page_description template_values['main_content'] = form_html self.render_page(template_values)
def list_question_groups(self): """Prepare a list of question groups.""" if not filer.is_editable_fs(self.app_context): return safe_dom.NodeList() all_questions = QuestionDAO.get_all() output = safe_dom.NodeList() if all_questions: output.append( safe_dom.Element( 'a', className='gcb-button gcb-pull-right', href='dashboard?action=add_question_group' ).add_text('Add Question Group') ).append( safe_dom.Element( 'div', style='clear: both; padding-top: 2px;' ) ) output.append( safe_dom.Element('h3').add_text('Question Groups') ) # TODO(jorr): Hook this into the datastore all_question_groups = QuestionGroupDAO.get_all() if all_question_groups: ol = safe_dom.Element('ol') for question_group in all_question_groups: edit_url = 'dashboard?action=edit_question_group&key=%s' % ( question_group.id) li = safe_dom.Element('li') li.add_text( question_group.description ).add_child( safe_dom.Entity(' ') ).add_child( safe_dom.Element('a', href=edit_url).add_text('[Edit]')) ol.add_child(li) output.append(ol) else: output.append(safe_dom.Element('blockquote').add_text('< none >')) return output
def _render_edit_form_for( self, rest_handler_cls, title, annotations_dict=None, delete_xsrf_token="delete-unit", page_description=None ): """Renders an editor form for a given REST handler class.""" if not annotations_dict: annotations_dict = rest_handler_cls.SCHEMA_ANNOTATIONS_DICT key = self.request.get("key") extra_args = {} if self.request.get("is_newly_created"): extra_args["is_newly_created"] = 1 exit_url = self.canonicalize_url("/dashboard") rest_url = self.canonicalize_url(rest_handler_cls.URI) delete_url = "%s?%s" % ( self.canonicalize_url(rest_handler_cls.URI), urllib.urlencode({"key": key, "xsrf_token": cgi.escape(self.create_xsrf_token(delete_xsrf_token))}), ) form_html = oeditor.ObjectEditor.get_html_for( self, rest_handler_cls.SCHEMA_JSON, annotations_dict, key, rest_url, exit_url, extra_args=extra_args, delete_url=delete_url, delete_method="delete", read_only=not filer.is_editable_fs(self.app_context), required_modules=rest_handler_cls.REQUIRED_MODULES, ) template_values = {} template_values["page_title"] = self.format_title("Edit %s" % title) if page_description: template_values["page_description"] = page_description template_values["main_content"] = form_html self.render_page(template_values)
def list_questions(self): """Prepare a list of the question bank contents.""" if not filer.is_editable_fs(self.app_context): return safe_dom.NodeList() output = safe_dom.NodeList().append( safe_dom.Element( 'a', className='gcb-button gcb-pull-right', href='dashboard?action=add_mc_question' ).add_text('Add Multiple Choice') ).append( safe_dom.Element( 'a', className='gcb-button gcb-pull-right', href='dashboard?action=add_sa_question' ).add_text('Add Short Answer') ).append( safe_dom.Element('div', style='clear: both; padding-top: 2px;') ).append( safe_dom.Element('h3').add_text('Question Bank') ) all_questions = QuestionDAO.get_all() if all_questions: ol = safe_dom.Element('ol') for question in all_questions: edit_url = 'dashboard?action=edit_question&key=%s' % question.id li = safe_dom.Element('li') li.add_text( question.description ).add_child( safe_dom.Entity(' ') ).add_child( safe_dom.Element('a', href=edit_url).add_text('[Edit]')) ol.add_child(li) output.append(ol) else: output.append(safe_dom.Element('blockquote').add_text('< none >')) return output
def _render_edit_form_for( self, rest_handler_cls, title, annotations_dict=None, delete_xsrf_token='delete-unit', page_description=None): """Renders an editor form for a given REST handler class.""" if not annotations_dict: annotations_dict = rest_handler_cls.SCHEMA_ANNOTATIONS_DICT key = self.request.get('key') extra_args = {} if self.request.get('is_newly_created'): extra_args['is_newly_created'] = 1 exit_url = self.canonicalize_url('/dashboard') rest_url = self.canonicalize_url(rest_handler_cls.URI) delete_url = '%s?%s' % ( self.canonicalize_url(rest_handler_cls.URI), urllib.urlencode({ 'key': key, 'xsrf_token': cgi.escape( self.create_xsrf_token(delete_xsrf_token)) })) form_html = oeditor.ObjectEditor.get_html_for( self, rest_handler_cls.SCHEMA_JSON, annotations_dict, key, rest_url, exit_url, extra_args=extra_args, delete_url=delete_url, delete_method='delete', read_only=not filer.is_editable_fs(self.app_context), required_modules=rest_handler_cls.REQUIRED_MODULES) template_values = {} template_values['page_title'] = self.format_title('Edit %s' % title) if page_description: template_values['page_description'] = page_description template_values['main_content'] = form_html self.render_page(template_values)
def render_course_outline_to_html(self): """CGL-MOOC-Builder: The original function was modified to cooperate with Section -> Units -> Lessons course structure. Renders course outline to HTML.""" course = courses.Course(self) if not course.get_units(): return [] is_editable = filer.is_editable_fs(self.app_context) # CGL-MOOC-Builder: Sort and group all units by section_id unitObj = course.get_units() sortedUnits = sorted(unitObj, key = lambda x: int(x.section_id or 0)) groups = [] keys = [] for k, g in groupby(sortedUnits, key = lambda x: int(x.section_id or 0)): groups.append(list(g)) keys.append(k) # CGL-MOOC-Builder: Loop through Section, Units and Lessons outline = safe_dom.Element('ul', style='list-style: none;') for s in groups: lines = safe_dom.Element('ul', style='list-style: none;') for unit in s: if unit.type == verify.UNIT_TYPE_ASSESSMENT: li = safe_dom.Element('li').add_child( safe_dom.Element( 'a', href='assessment?name=%s' % unit.unit_id, className='strong' ).add_text(unit.title) ).add_child(self._get_availability(unit)) if is_editable: url = self.canonicalize_url( '/dashboard?%s') % urllib.urlencode({ 'action': 'edit_assessment', 'key': unit.unit_id}) li.add_child(self._get_edit_link(url)) lines.add_child(li) continue if unit.type == verify.UNIT_TYPE_LINK: li = safe_dom.Element('li').add_child( safe_dom.Element( 'a', href=unit.href, className='strong' ).add_text(unit.title) ).add_child(self._get_availability(unit)) if is_editable: url = self.canonicalize_url( '/dashboard?%s') % urllib.urlencode({ 'action': 'edit_link', 'key': unit.unit_id}) li.add_child(self._get_edit_link(url)) lines.add_child(li) continue if unit.type == verify.UNIT_TYPE_UNIT: li = safe_dom.Element('li').add_child( safe_dom.Element( 'a', href='unit?unit=%s' % unit.unit_id, className='strong').add_text( 'Unit %s - %s' % (unit.index, unit.title)) ).add_child(self._get_availability(unit)) if is_editable: url = self.canonicalize_url( '/dashboard?%s') % urllib.urlencode({ 'action': 'edit_unit', 'key': unit.unit_id}) li.add_child(self._get_edit_link(url)) ol = safe_dom.Element('ol') for lesson in course.get_lessons(unit.unit_id): li2 = safe_dom.Element('li').add_child( safe_dom.Element( 'a', href='unit?unit=%s&lesson=%s' % ( unit.unit_id, lesson.lesson_id), ).add_text(lesson.title) ).add_child(self._get_availability(lesson)) if is_editable: url = self.get_action_url( 'edit_lesson', key=lesson.lesson_id) li2.add_child(self._get_edit_link(url)) ol.add_child(li2) li.add_child(ol) lines.add_child(li) continue raise Exception('Unknown unit type: %s.' % unit.type) liSection = safe_dom.Element('li') liSection.add_child(safe_dom.Element( 'span')).add_text( 'Section %s - %s' % ( unit.section_id, unit.section_title)) # CGL-MOOC-Builder: adds a link for edit section content if is_editable: section_edit_url = self.canonicalize_url( '/dashboard?%s') % urllib.urlencode({ 'action': 'edit_section', 'key': unit.unit_id}) liSection.add_child(self._get_edit_link(section_edit_url)) liSection.add_child(lines) outline.add_child(liSection) return outline
def get_outline(self): """Renders course outline view.""" pages_info = [ safe_dom.Element( 'a', href=self.canonicalize_url('/announcements') ).add_text('Announcements'), safe_dom.Element( 'a', href=self.canonicalize_url('/course') ).add_text('Course')] outline_actions = [] if filer.is_editable_fs(self.app_context): outline_actions.append({ 'id': 'edit_unit_lesson', 'caption': 'Organize', 'href': self.get_action_url('edit_unit_lesson')}) all_units = courses.Course(self).get_units() if any([unit.type == verify.UNIT_TYPE_UNIT for unit in all_units]): outline_actions.append({ 'id': 'add_lesson', 'caption': 'Add Lesson', 'action': self.get_action_url('add_lesson'), 'xsrf_token': self.create_xsrf_token('add_lesson')}) outline_actions.append({ 'id': 'add_unit', 'caption': 'Add Unit', 'action': self.get_action_url('add_unit'), 'xsrf_token': self.create_xsrf_token('add_unit')}) outline_actions.append({ 'id': 'add_link', 'caption': 'Add Link', 'action': self.get_action_url('add_link'), 'xsrf_token': self.create_xsrf_token('add_link')}) outline_actions.append({ 'id': 'add_assessment', 'caption': 'Add Assessment', 'action': self.get_action_url('add_assessment'), 'xsrf_token': self.create_xsrf_token('add_assessment')}) if not courses.Course(self).get_units(): outline_actions.append({ 'id': 'import_course', 'caption': 'Import', 'href': self.get_action_url('import_course') }) data_info = self.list_files('/data/') sections = [ { 'title': 'Pages', 'description': messages.PAGES_DESCRIPTION, 'children': pages_info}, { 'title': 'Course Outline', 'description': messages.COURSE_OUTLINE_DESCRIPTION, 'actions': outline_actions, 'pre': self.render_course_outline_to_html()}, { 'title': 'Data Files', 'description': messages.DATA_FILES_DESCRIPTION, 'children': data_info}] template_values = {} template_values['page_title'] = self.format_title('Outline') template_values['alerts'] = self._get_alerts() template_values['sections'] = sections self.render_page(template_values)
def render_course_outline_to_html(self): """Renders course outline to HTML.""" course = courses.Course(self) if not course.get_units(): return [] is_editable = filer.is_editable_fs(self.app_context) lines = safe_dom.Element('ul', style='list-style: none;') for unit in course.get_units(): if unit.type == verify.UNIT_TYPE_ASSESSMENT: li = safe_dom.Element('li').add_child( safe_dom.Element( 'a', href='assessment?name=%s' % unit.unit_id, className='strong' ).add_text(unit.title) ).add_child(self._get_availability(unit)) if is_editable: url = self.canonicalize_url( '/dashboard?%s') % urllib.urlencode({ 'action': 'edit_assessment', 'key': unit.unit_id}) li.add_child(self._get_edit_link(url)) lines.add_child(li) continue if unit.type == verify.UNIT_TYPE_LINK: li = safe_dom.Element('li').add_child( safe_dom.Element( 'a', href=unit.href, className='strong' ).add_text(unit.title) ).add_child(self._get_availability(unit)) if is_editable: url = self.canonicalize_url( '/dashboard?%s') % urllib.urlencode({ 'action': 'edit_link', 'key': unit.unit_id}) li.add_child(self._get_edit_link(url)) lines.add_child(li) continue if unit.type == verify.UNIT_TYPE_UNIT: li = safe_dom.Element('li').add_child( safe_dom.Element( 'a', href='unit?unit=%s' % unit.unit_id, className='strong').add_text( 'Unit %s - %s' % (unit.index, unit.title)) ).add_child(self._get_availability(unit)) if is_editable: url = self.canonicalize_url( '/dashboard?%s') % urllib.urlencode({ 'action': 'edit_unit', 'key': unit.unit_id}) li.add_child(self._get_edit_link(url)) ol = safe_dom.Element('ol') for lesson in course.get_lessons(unit.unit_id): li2 = safe_dom.Element('li').add_child( safe_dom.Element( 'a', href='unit?unit=%s&lesson=%s' % ( unit.unit_id, lesson.lesson_id), ).add_text(lesson.title) ).add_child(self._get_availability(lesson)) if is_editable: url = self.get_action_url( 'edit_lesson', key=lesson.lesson_id) li2.add_child(self._get_edit_link(url)) ol.add_child(li2) li.add_child(ol) lines.add_child(li) continue raise Exception('Unknown unit type: %s.' % unit.type) return lines
def list_and_format_file_list( self, title, subfolder, links=False, upload=False, prefix=None, caption_if_empty='< none >', edit_url_template=None, merge_local_files=False, sub_title=None): """Walks files in folders and renders their names in a section.""" # keep a list of files without merging unmerged_files = {} if merge_local_files: unmerged_files = self.list_files(subfolder, merge_local_files=False) items = safe_dom.NodeList() count = 0 for filename in self.list_files( subfolder, merge_local_files=merge_local_files): if prefix and not filename.startswith(prefix): continue # show different captions depending if the override exists or not has_override = filename in unmerged_files link_caption = '[Override]' if has_override or not merge_local_files: link_caption = '[Edit]' # make a <li> item li = safe_dom.Element('li') if links: li.add_child(safe_dom.Element( 'a', href=urllib.quote(filename)).add_text(filename)) else: li.add_text(filename) # add actions if available if (edit_url_template and self.app_context.fs.impl.is_read_write()): edit_url = edit_url_template % urllib.quote(filename) li.add_child( safe_dom.Entity(' ') ).add_child( safe_dom.Element('a', href=edit_url).add_text(link_caption)) count += 1 items.append(li) output = safe_dom.NodeList() if filer.is_editable_fs(self.app_context) and upload: output.append( safe_dom.Element( 'a', className='gcb-button gcb-pull-right', href='dashboard?%s' % urllib.urlencode( {'action': 'add_asset', 'base': subfolder}) ).add_text( 'Upload to ' + filer.strip_leading_and_trailing_slashes(subfolder)) ).append( safe_dom.Element( 'div', style='clear: both; padding-top: 2px;' ) ) if title: h3 = safe_dom.Element('h3') if count: h3.add_text('%s (%s)' % (title, count)) else: h3.add_text(title) output.append(h3) if sub_title: output.append(safe_dom.Element('blockquote').add_text(sub_title)) if items: output.append(safe_dom.Element('ol').add_children(items)) else: if caption_if_empty: output.append( safe_dom.Element('blockquote').add_text(caption_if_empty)) return output
def get_outline(self): """Renders course outline view.""" pages_info = [ safe_dom.Element('a', href=self.canonicalize_url( '/announcements')).add_text('Announcements'), safe_dom.Element( 'a', href=self.canonicalize_url('/course')).add_text('Course') ] outline_actions = [] if filer.is_editable_fs(self.app_context): outline_actions.append({ 'id': 'edit_unit_lesson', 'caption': 'Organize', 'href': self.get_action_url('edit_unit_lesson') }) all_units = courses.Course(self).get_units() if any([unit.type == verify.UNIT_TYPE_UNIT for unit in all_units]): outline_actions.append({ 'id': 'add_lesson', 'caption': 'Add Lesson', 'action': self.get_action_url('add_lesson'), 'xsrf_token': self.create_xsrf_token('add_lesson') }) outline_actions.append({ 'id': 'add_unit', 'caption': 'Add Unit', 'action': self.get_action_url('add_unit'), 'xsrf_token': self.create_xsrf_token('add_unit') }) outline_actions.append({ 'id': 'add_link', 'caption': 'Add Link', 'action': self.get_action_url('add_link'), 'xsrf_token': self.create_xsrf_token('add_link') }) outline_actions.append({ 'id': 'add_assessment', 'caption': 'Add Assessment', 'action': self.get_action_url('add_assessment'), 'xsrf_token': self.create_xsrf_token('add_assessment') }) if not courses.Course(self).get_units(): outline_actions.append({ 'id': 'import_course', 'caption': 'Import', 'href': self.get_action_url('import_course') }) data_info = self.list_files('/data/') sections = [{ 'title': 'Pages', 'description': messages.PAGES_DESCRIPTION, 'children': pages_info }, { 'title': 'Course Outline', 'description': messages.COURSE_OUTLINE_DESCRIPTION, 'actions': outline_actions, 'pre': self.render_course_outline_to_html() }, { 'title': 'Data Files', 'description': messages.DATA_FILES_DESCRIPTION, 'children': data_info }] template_values = {} template_values['page_title'] = self.format_title('Outline') template_values['alerts'] = self._get_alerts() template_values['sections'] = sections self.render_page(template_values)
def render_course_outline_to_html(self): """Renders course outline to HTML.""" course = courses.Course(self) if not course.get_units(): return [] is_editable = filer.is_editable_fs(self.app_context) lines = safe_dom.Element('ul', style='list-style: none;') for unit in course.get_units(): if unit.type == verify.UNIT_TYPE_ASSESSMENT: li = safe_dom.Element('li').add_child( safe_dom.Element('a', href='assessment?name=%s' % unit.unit_id, className='strong').add_text( unit.title)).add_child( self._get_availability(unit)) if is_editable: url = self.canonicalize_url( '/dashboard?%s') % urllib.urlencode({ 'action': 'edit_assessment', 'key': unit.unit_id }) li.add_child(self._get_edit_link(url)) lines.add_child(li) continue if unit.type == verify.UNIT_TYPE_LINK: li = safe_dom.Element('li').add_child( safe_dom.Element('a', href=unit.href, className='strong').add_text( unit.title)).add_child( self._get_availability(unit)) if is_editable: url = self.canonicalize_url( '/dashboard?%s') % urllib.urlencode({ 'action': 'edit_link', 'key': unit.unit_id }) li.add_child(self._get_edit_link(url)) lines.add_child(li) continue if unit.type == verify.UNIT_TYPE_UNIT: li = safe_dom.Element('li').add_child( safe_dom.Element('a', href='unit?unit=%s' % unit.unit_id, className='strong').add_text( 'Unit %s - %s' % (unit.index, unit.title))).add_child( self._get_availability(unit)) if is_editable: url = self.canonicalize_url( '/dashboard?%s') % urllib.urlencode({ 'action': 'edit_unit', 'key': unit.unit_id }) li.add_child(self._get_edit_link(url)) ol = safe_dom.Element('ol') for lesson in course.get_lessons(unit.unit_id): li2 = safe_dom.Element('li').add_child( safe_dom.Element( 'a', href='unit?unit=%s&lesson=%s' % (unit.unit_id, lesson.lesson_id), ).add_text(lesson.title)).add_child( self._get_availability(lesson)) if is_editable: url = self.get_action_url('edit_lesson', key=lesson.lesson_id) li2.add_child(self._get_edit_link(url)) ol.add_child(li2) li.add_child(ol) lines.add_child(li) continue raise Exception('Unknown unit type: %s.' % unit.type) return lines
def render_course_outline_to_html(self): """Renders course outline to HTML.""" course = courses.Course(self) if not course.get_units(): return [] is_editable = filer.is_editable_fs(self.app_context) lines = [] lines.append('<ul style="list-style: none;">') for unit in course.get_units(): if unit.type == 'A': lines.append('<li>') lines.append( '<strong><a href="assessment?name=%s">%s</a></strong>' % ( unit.unit_id, cgi.escape(unit.title))) lines.append(self._get_availability(unit)) if is_editable: url = self.canonicalize_url( '/dashboard?%s') % urllib.urlencode({ 'action': 'edit_assessment', 'key': unit.unit_id}) lines.append(self._get_edit_link(url)) lines.append('</li>\n') continue if unit.type == 'O': lines.append('<li>') lines.append( '<strong><a href="%s">%s</a></strong>' % ( unit.href, cgi.escape(unit.title))) lines.append(self._get_availability(unit)) if is_editable: url = self.canonicalize_url( '/dashboard?%s') % urllib.urlencode({ 'action': 'edit_link', 'key': unit.unit_id}) lines.append(self._get_edit_link(url)) lines.append('</li>\n') continue if unit.type == 'U': lines.append('<li>') lines.append( ('<strong><a href="unit?unit=%s">Unit %s - %s</a>' '</strong>') % ( unit.unit_id, unit.index, cgi.escape(unit.title))) lines.append(self._get_availability(unit)) if is_editable: url = self.canonicalize_url( '/dashboard?%s') % urllib.urlencode({ 'action': 'edit_unit', 'key': unit.unit_id}) lines.append(self._get_edit_link(url)) lines.append('<ol>') for lesson in course.get_lessons(unit.unit_id): lines.append( '<li><a href="unit?unit=%s&lesson=%s">%s</a>\n' % ( unit.unit_id, lesson.lesson_id, cgi.escape(lesson.title))) lines.append(self._get_availability(lesson)) if is_editable: url = self.get_action_url( 'edit_lesson', key=lesson.lesson_id) lines.append(self._get_edit_link(url)) lines.append('</li>') lines.append('</ol>') lines.append('</li>\n') continue raise Exception('Unknown unit type: %s.' % unit.type) lines.append('</ul>') return ''.join(lines)
def render_course_outline_to_html(self): """Renders course outline to HTML.""" course = courses.Course(self) if not course.get_units(): return [] is_editable = filer.is_editable_fs(self.app_context) lines = [] lines.append('<ul style="list-style: none;">') for unit in course.get_units(): if unit.type == 'A': lines.append('<li>') lines.append( '<strong><a href="assessment?name=%s">%s</a></strong>' % (unit.unit_id, cgi.escape(unit.title))) lines.append(self._get_availability(unit)) if is_editable: url = self.canonicalize_url( '/dashboard?%s') % urllib.urlencode({ 'action': 'edit_assessment', 'key': unit.unit_id }) lines.append(self._get_edit_link(url)) lines.append('</li>\n') continue if unit.type == 'O': lines.append('<li>') lines.append('<strong><a href="%s">%s</a></strong>' % (unit.href, cgi.escape(unit.title))) lines.append(self._get_availability(unit)) if is_editable: url = self.canonicalize_url( '/dashboard?%s') % urllib.urlencode({ 'action': 'edit_link', 'key': unit.unit_id }) lines.append(self._get_edit_link(url)) lines.append('</li>\n') continue if unit.type == 'U': lines.append('<li>') lines.append( ('<strong><a href="unit?unit=%s">Unit %s - %s</a>' '</strong>') % (unit.unit_id, unit.index, cgi.escape(unit.title))) lines.append(self._get_availability(unit)) if is_editable: url = self.canonicalize_url( '/dashboard?%s') % urllib.urlencode({ 'action': 'edit_unit', 'key': unit.unit_id }) lines.append(self._get_edit_link(url)) lines.append('<ol>') for lesson in course.get_lessons(unit.unit_id): lines.append( '<li><a href="unit?unit=%s&lesson=%s">%s</a>\n' % (unit.unit_id, lesson.lesson_id, cgi.escape(lesson.title))) lines.append(self._get_availability(lesson)) if is_editable: url = self.get_action_url('edit_lesson', key=lesson.lesson_id) lines.append(self._get_edit_link(url)) lines.append('</li>') lines.append('</ol>') lines.append('</li>\n') continue raise Exception('Unknown unit type: %s.' % unit.type) lines.append('</ul>') return ''.join(lines)
def get_settings(self): """Renders course settings view.""" yaml_actions = [] basic_setting_actions = [] # Basic course info. course_info = [ 'Course Title: %s' % self.app_context.get_environ()['course'][ 'title'], 'Context Path: %s' % self.app_context.get_slug(), 'Datastore Namespace: %s' % self.app_context.get_namespace_name()] # Course file system. fs = self.app_context.fs.impl course_info.append(('File System: %s' % fs.__class__.__name__)) if fs.__class__ == vfs.LocalReadOnlyFileSystem: course_info.append(('Home Folder: %s' % sites.abspath( self.app_context.get_home_folder(), '/'))) # Enable editing if supported. if filer.is_editable_fs(self.app_context): yaml_actions.append({ 'id': 'edit_course_yaml', 'caption': 'Advanced Edit', 'action': self.get_action_url('create_or_edit_settings'), 'xsrf_token': self.create_xsrf_token( 'create_or_edit_settings')}) yaml_actions.append({ 'id': 'edit_basic_course_settings', 'caption': 'Edit', 'action': self.get_action_url('edit_basic_course_settings'), 'xsrf_token': self.create_xsrf_token( 'edit_basic_course_settings')}) # course.yaml file content. yaml_info = [] yaml_stream = self.app_context.fs.open( self.app_context.get_config_filename()) if yaml_stream: yaml_lines = yaml_stream.read().decode('utf-8') for line in yaml_lines.split('\n'): yaml_info.append(line) else: yaml_info.append('< empty file >') # course_template.yaml file contents course_template_info = [] course_template_stream = open(os.path.join(os.path.dirname( __file__), '../../course_template.yaml'), 'r') if course_template_stream: course_template_lines = course_template_stream.read().decode( 'utf-8') for line in course_template_lines.split('\n'): course_template_info.append(line) else: course_template_info.append('< empty file >') # Prepare template values. template_values = { 'page_title': self.format_title('Settings'), 'page_title_linked': self.format_title('Settings', as_link=True), 'page_description': messages.SETTINGS_DESCRIPTION, } template_values['sections'] = [ { 'title': 'About the Course', 'description': messages.ABOUT_THE_COURSE_DESCRIPTION, 'actions': basic_setting_actions, 'children': course_info}, { 'title': 'Contents of course.yaml file', 'description': messages.CONTENTS_OF_THE_COURSE_DESCRIPTION, 'actions': yaml_actions, 'children': yaml_info}, { 'title': 'Contents of course_template.yaml file', 'description': messages.COURSE_TEMPLATE_DESCRIPTION, 'children': course_template_info}] self.render_page(template_values)