def list_files(self, subfolder, merge_local_files=False): """Makes a list of files in a subfolder. Args: subfolder: string. Relative path of the subfolder to list. merge_local_files: boolean. If True, the returned list will contain files found on either the datastore filesystem or the read-only local filesystem. If a file is found on both, its datastore filesystem version will trump its local filesystem version. Returns: List of relative, normalized file path strings. """ home = sites.abspath(self.app_context.get_home_folder(), '/') all_paths = set( self.app_context.fs.list( sites.abspath(self.app_context.get_home_folder(), subfolder))) if merge_local_files: all_paths = all_paths.union( set([ os.path.join(appengine_config.BUNDLE_ROOT, path) for path in self.local_fs.list(subfolder[1:]) ])) result = [] for abs_filename in all_paths: filename = os.path.relpath(abs_filename, home) result.append(vfs.AbstractFileSystem.normpath(filename)) return sorted(result)
def list_files(self, subfolder, merge_local_files=False): """Makes a list of files in a subfolder. Args: subfolder: string. Relative path of the subfolder to list. merge_local_files: boolean. If True, the returned list will contain files found on either the datastore filesystem or the read-only local filesystem. If a file is found on both, its datastore filesystem version will trump its local filesystem version. Returns: List of relative, normalized file path strings. """ home = sites.abspath(self.app_context.get_home_folder(), '/') all_paths = set(self.app_context.fs.list( sites.abspath(self.app_context.get_home_folder(), subfolder))) if merge_local_files: all_paths = all_paths.union(set([ os.path.join(appengine_config.BUNDLE_ROOT, path) for path in self.local_fs.list(subfolder[1:])])) result = [] for abs_filename in all_paths: filename = os.path.relpath(abs_filename, home) result.append(vfs.AbstractFileSystem.normpath(filename)) return sorted(result)
def list_files(self, subfolder): """Makes a list of files in a subfolder.""" home = sites.abspath(self.app_context.get_home_folder(), '/') files = self.app_context.fs.list( sites.abspath(self.app_context.get_home_folder(), subfolder)) result = [] for abs_filename in sorted(files): filename = os.path.relpath(abs_filename, home) result.append(vfs.AbstractFileSystem.normpath(filename)) return result
def get_assets(self): """Renders course assets view.""" all_paths = self.app_context.fs.list( sites.abspath(self.app_context.get_home_folder(), '/')) def inherits_from(folder): return '< inherited from %s >' % folder text_asset_url_template = 'dashboard?action=manage_text_asset&uri=%s' items = safe_dom.NodeList() for asset_lister in self.contrib_asset_listers: items.append(asset_lister(self)) items.append( self.list_questions() ).append( self.list_question_groups() ).append( self.list_and_format_file_list( 'Assessments', '/assets/js/', links=True, prefix='assets/js/assessment-', all_paths=all_paths) ).append( self.list_and_format_file_list( 'Activities', '/assets/js/', links=True, prefix='assets/js/activity-', all_paths=all_paths) ).append( self.list_and_format_file_list( 'Images & Documents', '/assets/img/', links=True, upload=True, edit_url_template='dashboard?action=delete_asset&uri=%s', caption_if_empty=inherits_from('/assets/img/'), all_paths=all_paths) ).append( self.list_and_format_file_list( 'Cascading Style Sheets', '/assets/css/', links=True, upload=True, edit_url_template=text_asset_url_template, caption_if_empty=inherits_from('/assets/css/'), merge_local_files=True, all_paths=all_paths) ).append( self.list_and_format_file_list( 'JavaScript Libraries', '/assets/lib/', links=True, upload=True, edit_url_template=text_asset_url_template, caption_if_empty=inherits_from('/assets/lib/'), merge_local_files=True, all_paths=all_paths) ).append( self.list_and_format_file_list( 'View Templates', '/views/', upload=True, edit_url_template=text_asset_url_template, caption_if_empty=inherits_from('/views/'), merge_local_files=True, all_paths=all_paths) ) template_values = { 'page_title': self.format_title('Assets'), 'page_title_linked': self.format_title('Assets', as_link=True), 'page_description': messages.ASSETS_DESCRIPTION, 'main_content': items, } self.render_page(template_values)
def get_assets(self): """Renders course assets view.""" template_values = {} template_values['page_title'] = self.format_title('Assets') lines = [] lines.append('<h3>Content Location</h3>') lines.append('<blockquote>%s</blockquote>' % sites.abspath(self.app_context.get_home_folder(), '/')) lines.append('<h3>Course Data Files</h3>') lines.append('<ol>') lines += self.list_and_format_file_list('/data/') lines.append('</ol>') lines.append('<h3>Course Assets</h3>') lines.append('<ol>') lines += self.list_and_format_file_list('/assets/', True) lines.append('</ol>') lines = ''.join(lines) template_values['main_content'] = lines self.render_page(template_values)
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 get_environ2(): """Returns currently defined course settings as a dictionary.""" gDefier_yaml = None gDefier_yaml_dict = None ns = ApplicationContext.get_namespace_name_for_request() app_context = sites.get_app_context_for_namespace(ns) course_data_filename = sites.abspath(app_context.get_home_folder(), DFR_CONFIG_FILENAME) if app_context.fs.isfile(course_data_filename): gDefier_yaml = app_context.fs.open(course_data_filename) if not gDefier_yaml: return deep_dict_merge(gDefier_model.DEFAULT_COURSE_GDEFIER_DICT, []) try: gDefier_yaml_dict = yaml.safe_load( gDefier_yaml.read().decode('utf-8')) except Exception as e: # pylint: disable-msg=broad-except logging.info( 'Error: gDefier.yaml file at %s not accessible, ' 'loading defaults. %s', course_data_filename, e) if not gDefier_yaml_dict: return deep_dict_merge(gDefier_model.DEFAULT_COURSE_GDEFIER_DICT, []) return deep_dict_merge( gDefier_yaml_dict, gDefier_model.DEFAULT_COURSE_GDEFIER_DICT)
def get_assets(self): """Renders course assets view.""" template_values = {} template_values['page_title'] = self.format_title('Assets') lines = [] lines.append('<h3>Content Location</h3>') lines.append('<blockquote>%s</blockquote>' % sites.abspath( self.app_context.get_home_folder(), '/')) lines.append('<h3>Course Data Files</h3>') lines.append('<ol>') lines += self.list_and_format_file_list('/data/') lines.append('</ol>') lines.append('<h3>Course Assets</h3>') lines.append('<ol>') lines += self.list_and_format_file_list('/assets/', True) lines.append('</ol>') lines = ''.join(lines) template_values['main_content'] = lines self.render_page(template_values)
def list_files(app_context, subfolder, merge_local_files=False, all_paths=None): """Makes a list of files in a subfolder. Args: app_context: app_context. subfolder: string. Relative path of the subfolder to list. merge_local_files: boolean. If True, the returned list will contain files found on either the datastore filesystem or the read-only local filesystem. If a file is found on both, its datastore filesystem version will trump its local filesystem version. all_paths: list. A list of all file paths in the underlying file system. Returns: List of relative, normalized file path strings. """ home = sites.abspath(app_context.get_home_folder(), '/') _paths = None if all_paths is not None: _paths = [] for _path in all_paths: if _path.startswith( sites.abspath(app_context.get_home_folder(), subfolder)): _paths.append(_path) _paths = set(_paths) else: _paths = set( app_context.fs.list( sites.abspath(app_context.get_home_folder(), subfolder))) if merge_local_files: local_fs = vfs.LocalReadOnlyFileSystem(logical_home_folder='/') _paths = _paths.union( set([ os.path.join(appengine_config.BUNDLE_ROOT, path) for path in local_fs.list(subfolder[1:]) ])) result = [] for abs_filename in _paths: filename = os.path.relpath(abs_filename, home) result.append(vfs.AbstractFileSystem.normpath(filename)) return sorted(result)
def list_and_format_file_list(self, subfolder, links=False): """Walks files in folders and renders their names.""" home = sites.abspath(self.app_context.get_home_folder(), '/') files = self.app_context.fs.list( sites.abspath(self.app_context.get_home_folder(), subfolder)) lines = [] for abs_filename in sorted(files): filename = os.path.relpath(abs_filename, home) if links: lines.append( '<li><a href="%s">%s</a></li>\n' % (filename, filename)) else: lines.append('<li>%s</li>\n' % filename) return lines
def list_and_format_file_list(self, subfolder, links=False): """Walks files in folders and renders their names.""" home = sites.abspath(self.app_context.get_home_folder(), '/') files = self.app_context.fs.list( sites.abspath(self.app_context.get_home_folder(), subfolder)) lines = [] for abs_filename in sorted(files): filename = os.path.relpath(abs_filename, home) if links: lines.append('<li><a href="%s">%s</a></li>\n' % (filename, filename)) else: lines.append('<li>%s</li>\n' % filename) return lines
def get_courses(self): """Shows a list of all courses available on this site.""" template_values = {} template_values['page_title'] = self.format_title('Courses') content = [] content.append('<h3>All Courses</h3>') content.append('<table>') content.append(""" <tr> <th>Course Title</th> <th>Context Path</th> <th>Content Location</th> <th>Datastore Namespace</th> </tr> """) courses = sites.get_all_courses() count = 0 for course in courses: count += 1 error = '' slug = course.get_slug() location = sites.abspath(course.get_home_folder(), '/') try: name = cgi.escape(course.get_environ()['course']['title']) except Exception as e: # pylint: disable-msg=broad-except name = 'UNKNOWN COURSE' error = ( '<p>Error in <strong>course.yaml</strong> file:<br/>' '<pre>\n%s\n%s\n</pre></p>' % ( e.__class__.__name__, cgi.escape(str(e)))) if slug == '/': link = '/dashboard' else: link = '%s/dashboard' % slug link = '<a href="%s">%s</a>' % (link, name) content.append(""" <tr> <td>%s%s</td> <td>%s</td> <td>%s</td> <td>%s</td> </tr> """ % ( link, error, slug, location, course.get_namespace_name())) content.append(""" <tr><td colspan="4" align="right">Total: %s item(s)</td></tr> """ % count) content.append('</table>') template_values['main_content'] = ''.join(content) self.render_page(template_values)
def get(self): """Handles GET requests.""" if not self.personalize_page_and_get_enrolled(): return # Cathing Khan answer if self.request.get('khandata'): self.academy_answer(self.request.get('khandata')) return defy_key = self.request.get('defy') course_info = get_course_dict() # Cathing END exercise if self.request.get('end'): self.end_defy(defy_key, self.request.get('end'), course_info['module']['n_defies']) defy = gDefier_model.GDefierDefy.get(defy_key) path = sites.abspath(self.app_context.get_home_folder(), GCB_GDEFIER_FOLDER_NAME) page = 'templates/gDefier_arena.html' nick = self.get_user().nickname() if defy.rname == nick: side = 'right' elif defy.lname == nick: side = 'left' else: side = None # Defy from others users... page = 'error.html' """ Getting rounds per defy and possible questions of this bloc""" rounds = course_info['module']['defy']['n_round'] for b in course_info['module']['blocks']: if defy.block_board.blockID == b['block_title']: question = b['question_cast'] break question = re.findall('[^>]+>', question) questions = [i+j for i,j in zip(question[::2],question[1::2])] t_round = course_info['module']['defy']['round_time'] template = self.get_template(page, additional_dirs=[path]) self.template_value['navbar'] = {'gDefier': True} self.template_value['defy'] = defy self.template_value['questions'] = questions self.template_value['rounds'] = rounds self.template_value['t_round'] = t_round self.template_value['side'] = side self.template_value['self'] = self self.render(template)
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_files(handler, subfolder, merge_local_files=False, all_paths=None): """Makes a list of files in a subfolder. Args: handler: webapp request handler. subfolder: string. Relative path of the subfolder to list. merge_local_files: boolean. If True, the returned list will contain files found on either the datastore filesystem or the read-only local filesystem. If a file is found on both, its datastore filesystem version will trump its local filesystem version. all_paths: list. A list of all file paths in the underlying file system. Returns: List of relative, normalized file path strings. """ home = sites.abspath(handler.app_context.get_home_folder(), '/') _paths = None if all_paths is not None: _paths = [] for _path in all_paths: if _path.startswith(sites.abspath( handler.app_context.get_home_folder(), subfolder)): _paths.append(_path) _paths = set(_paths) else: _paths = set(handler.app_context.fs.list( sites.abspath(handler.app_context.get_home_folder(), subfolder))) if merge_local_files: local_fs = vfs.LocalReadOnlyFileSystem(logical_home_folder='/') _paths = _paths.union(set([ os.path.join(appengine_config.BUNDLE_ROOT, path) for path in local_fs.list(subfolder[1:])])) result = [] for abs_filename in _paths: filename = os.path.relpath(abs_filename, home) result.append(vfs.AbstractFileSystem.normpath(filename)) return sorted(result)
def get_courses(self): """Shows a list of all courses available on this site.""" if hasattr(self, 'app_context'): this_namespace = self.app_context.get_namespace_name() else: this_namespace = None # GlobalAdminHandler all_courses = [] for course in sorted(sites.get_all_courses(), key=lambda course: course.get_title().lower()): slug = course.get_slug() name = course.get_title() if course.fs.is_read_write(): location = 'namespace: %s' % course.get_namespace_name() else: location = 'disk: %s' % sites.abspath( course.get_home_folder(), '/') if slug == '/': link = '/dashboard' else: link = '%s/dashboard' % slug is_selected_course = (course.get_namespace_name() == this_namespace) all_courses.append({ 'link': link, 'name': name, 'slug': slug, 'is_selected_course': is_selected_course, 'now_available': course.now_available }) delete_course_xsrf_token = crypto.XsrfTokenManager.create_xsrf_token( CourseDeleteHandler.XSRF_ACTION) add_course_xsrf_token = crypto.XsrfTokenManager.create_xsrf_token( modules.admin.config.CoursesItemRESTHandler.XSRF_ACTION) template_values = { 'page_title': self.format_title('Courses'), 'main_content': self.render_template_to_html( { 'add_course_link': '%s?action=add_course' % self.LINK_URL, 'delete_course_link': CourseDeleteHandler.URI, 'delete_course_xsrf_token': delete_course_xsrf_token, 'add_course_xsrf_token':add_course_xsrf_token, 'courses': all_courses, 'email': users.get_current_user().email(), }, 'courses.html', [TEMPLATE_DIR] ) } self.render_page(template_values, in_action='courses')
def _get_tab_content(tab, handler, add_assets): """Renders course assets view.""" all_paths = handler.app_context.fs.list( sites.abspath(handler.app_context.get_home_folder(), '/')) items = safe_dom.NodeList() add_assets(handler, items, tab.name, all_paths) title_text = 'Assets > %s' % tab.title template_values = { 'page_title': handler.format_title(title_text), 'main_content': items, } return template_values
def list_and_format_file_list(self, subfolder, links=False): """Walks files in folders and renders their names.""" home = sites.abspath(self.app_context.get_home_folder(), '/') start = sites.abspath(self.app_context.get_home_folder(), subfolder) files = [] for dirname, unused_dirnames, filenames in os.walk(start): for filename in filenames: files.append( os.path.relpath(os.path.join(dirname, filename), home)) files = sorted(files) lines = [] for filename in files: if links: lines.append( '<li><a href="%s">%s</a></li>' % (filename, filename)) else: lines.append('<li>%s</li>' % filename) return lines
def get(self): """Handles GET requests.""" if not self.personalize_page_and_get_enrolled(): return path = sites.abspath(self.app_context.get_home_folder(), GCB_GDEFIER_FOLDER_NAME) course = sites.get_course_for_current_request() if not course.get_slug().split("_")[-1] == "DFR": page = 'templates/gDefier_error.html' self.template_value['error_code'] = 'disabled_gDefier_module' self.template_value['is_dashboard'] = False else: page = 'templates/gDefier.html' # Patch to double apparition of registration registration = None if gDefier_model.player_has_blocks(self): if self.request.get('registered')=='yes': registration = False else: registration = True else: registration = False entity = get_course_dict() player = gDefier_model.get_player(self) prctng = [] for b in player.blocks: n = int(b.wins*100/entity['module']['n_defies']) for i in range(entity['module']['blocks'].__len__()): if entity['module']['blocks'][i]["block_title"]==b.blockID: prctng.insert(i, "n"+str(n)) noprctng = prctng noprctng = map(lambda s: s.strip('n'), noprctng) print noprctng template = self.get_template(page, additional_dirs=[path]) self.template_value['gDefier_transient_student'] = registration self.template_value['navbar'] = {'gDefier': True} self.template_value['entity'] = entity self.template_value['player'] = player self.template_value['prctng'] = prctng self.template_value['noprctng'] = noprctng self.render(template)
def _get_assets(handler, add_assets): """Renders course assets view.""" all_paths = handler.app_context.fs.list( sites.abspath(handler.app_context.get_home_folder(), '/')) tab = tabs.Registry.get_tab( 'assets', handler.request.get('tab') or 'questions') items = safe_dom.NodeList() add_assets(handler, items, tab.name, all_paths) title_text = 'Assets > %s' % tab.title template_values = { 'page_title': handler.format_title(title_text), 'page_description': messages.ASSETS_DESCRIPTION, 'main_content': items, } return template_values
def _get_about_course(handler): # Basic course info. template_values = {} course_info = [] course_actions = [] app_context = handler.app_context if not app_context.is_editable_fs(): course_info.append('The course is read-only.') currentCourse = courses.Course(handler) course_info.append('Schema Version: %s' % currentCourse.version) course_info.append('Context Path: %s' % app_context.get_slug()) course_info.append('Datastore Namespace: %s' % app_context.get_namespace_name()) # Course file system. fs = 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(app_context.get_home_folder(), '/'))) data_info = dashboard_utils.list_files(handler, '/data/') sections = [ { 'description': messages.ABOUT_THE_COURSE_DESCRIPTION, 'actions': course_actions, 'children': course_info }, ] if currentCourse.version == courses.COURSE_MODEL_VERSION_1_2: sections.append({ 'title': 'Data Files', 'description': messages.DATA_FILES_DESCRIPTION, 'children': data_info }) template_values['alerts'] = handler.get_alerts() template_values['sections'] = sections return template_values
def _get_about_course(handler): # Basic course info. template_values = {} course_info = [] course_actions = [] app_context = handler.app_context if not app_context.is_editable_fs(): course_info.append('The course is read-only.') currentCourse = courses.Course(handler) course_info.append('Schema Version: %s' % currentCourse.version) course_info.append('Context Path: %s' % app_context.get_slug()) course_info.append('Datastore Namespace: %s' % app_context.get_namespace_name()) # Course file system. fs = 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( app_context.get_home_folder(), '/'))) data_info = dashboard_utils.list_files(handler, '/data/') sections = [ { 'description': messages.ABOUT_THE_COURSE_DESCRIPTION, 'actions': course_actions, 'children': course_info},] if currentCourse.version == courses.COURSE_MODEL_VERSION_1_2: sections.append({ 'title': 'Data Files', 'description': messages.DATA_FILES_DESCRIPTION, 'children': data_info}) template_values['alerts'] = handler.get_alerts() template_values['sections'] = sections return template_values
def get(self): user = self.personalize_page_and_get_user() if user is not None: student = models.Student.get_enrolled_student_by_user(user) if student is not None: events = CalendarService.get_events() path = sites.abspath(self.app_context.get_home_folder(), TEMPLATES_FOLDER) template = self.get_template('calendar_view.html', additional_dirs=[path]) self.response.out.write(template.render(self.template_value, events=events)) else: self.response.out.write("You are not registered") else: self.redirect('/')
def get_settings(self): """Renders course settings view.""" template_values = {} template_values['page_title'] = self.format_title('Settings') # Course identity. title = self.app_context.get_environ()['course']['title'] location = sites.abspath(self.app_context.get_home_folder(), '/') yaml = self.app_context.get_config_filename() slug = self.app_context.get_slug() namespace = self.app_context.get_namespace_name() course_info = [] course_info.append('<h3>About the Course</h3>') course_info.append(""" <ol> <li>Course Title: %s</li> <li>Content Location: %s</li> <li>config.yaml: %s</li> <li>Context Path: %s</li> <li>Datastore Namespace: %s</li> </ol> """ % (title, location, yaml, slug, namespace)) course_info = ''.join(course_info) # Yaml file content. yaml_content = [] yaml_content.append( '<h3>Contents of <code>course.yaml</code> file</h3>') yaml_content.append('<ol>') yaml_lines = self.app_context.fs.open( self.app_context.get_config_filename()).read().decode('utf-8') for line in yaml_lines.split('\n'): yaml_content.append('<li>%s</li>\n' % cgi.escape(line)) yaml_content.append('</ol>') yaml_content = ''.join(yaml_content) template_values['main_content'] = course_info + yaml_content self.render_page(template_values)
def get_settings(self): """Renders course settings view.""" template_values = {} template_values['page_title'] = self.format_title('Settings') # Course identity. title = self.app_context.get_environ()['course']['title'] location = sites.abspath(self.app_context.get_home_folder(), '/') yaml = self.app_context.get_config_filename() slug = self.app_context.get_slug() namespace = self.app_context.get_namespace_name() course_info = [] course_info.append('<h3>About the Course</h3>') course_info.append(""" <ol> <li>Course Title: %s</li> <li>Content Location: %s</li> <li>config.yaml: %s</li> <li>Context Path: %s</li> <li>Datastore Namespace: %s</li> </ol> """ % (title, location, yaml, slug, namespace)) course_info = ''.join(course_info) # Yaml file content. yaml_content = [] yaml_content.append( '<h3>Contents of <code>course.yaml</code> file</h3>') yaml_content.append('<ol>') yaml_lines = open( self.app_context.get_config_filename(), 'r').readlines() for line in yaml_lines: yaml_content.append('<li>%s</li>' % cgi.escape(line)) yaml_content.append('</ol>') yaml_content = ''.join(yaml_content) template_values['main_content'] = course_info + yaml_content self.render_page(template_values)
def get_gDefier_config_filename(self): """Returns absolute location of a course configuration file.""" filename = sites.abspath(self.app_context.get_home_folder(), DFR_CONFIG_FILENAME) return filename
def get(self): """Process GET request.""" # TODO(emichael): move timing to Javascript if not custom_module.enabled: self.error(404) return student = self.personalize_page_and_get_enrolled( supports_transient_student=True) if not student: return try: start = time.time() # TODO(emichael): Don't use get because it can't handle utf-8 query = self.request.get('query') offset = self.request.get('offset') self.template_value['navbar'] = {} if query: try: offset = int(offset) except (ValueError, TypeError): offset = 0 self.template_value['query'] = query SEARCH_QUERIES_MADE.inc() response = fetch(self.get_course(), query, offset=offset) response = self.filter(response, student) self.template_value['time'] = '%.2f' % (time.time() - start) self.template_value['search_results'] = response['results'] total_found = response['total_found'] if offset + RESULTS_LIMIT < total_found: self.template_value['next_link'] = ( 'search?query=%s&offset=%d' % (query, offset + RESULTS_LIMIT)) if offset - RESULTS_LIMIT >= 0: self.template_value['previous_link'] = ( 'search?query=%s&offset=%d' % (query, offset - RESULTS_LIMIT)) self.template_value['page_number'] = offset / RESULTS_LIMIT + 1 self.template_value['total_pages'] = int( math.ceil(float(total_found) / RESULTS_LIMIT)) if response['results']: SEARCH_RESULTS_RETURNED.inc(len(response['results'])) # TODO(emichael): Remove this check when the unicode issue is fixed in # dev_appserver. except UnicodeEncodeError as e: SEARCH_FAILURES.inc() if not appengine_config.PRODUCTION_MODE: # This message will only be displayed to the course author in # dev, so it does not need to be I18N'd self.template_value['search_error'] = ( 'There is a known issue in App Engine\'s SDK ' '(code.google.com/p/googleappengine/issues/detail?id=9335) ' 'which causes an error when generating search snippets ' 'which contain non-ASCII characters. This error does not ' 'occur in the production environment, so you can safely ' 'run your course with unicode characters on appspot.com.') logging.error( '[Unicode/Dev server issue] Error rendering the ' 'search page: %s.', e) else: self.template_value['search_error'] = SEARCH_ERROR_TEXT logging.error('Error rendering the search page: %s. %s', e, traceback.format_exc()) except Exception as e: # pylint: disable=broad-except SEARCH_FAILURES.inc() self.template_value['search_error'] = SEARCH_ERROR_TEXT logging.error('Error rendering the search page: %s. %s', e, traceback.format_exc()) finally: path = sites.abspath(self.app_context.get_home_folder(), GCB_SEARCH_FOLDER_NAME) template = self.get_template('search.html', additional_dirs=[path]) self.template_value['navbar'] = {} self.response.out.write(template.render(self.template_value))
def get_home_folder(app_context): return sites.abspath(app_context.get_home_folder(), '/')
def get_courses(self): """Shows a list of all courses available on this site.""" template_values = {} template_values['page_title'] = self.format_title('Courses') template_values['page_description'] = messages.COURSES_DESCRIPTION content = safe_dom.NodeList() content.append( safe_dom.Element( 'a', id='add_course', className='gcb-button gcb-pull-right', role='button', href='%s?action=add_course' % self.LINK_URL).add_text('Add Course')).append( safe_dom.Element( 'div', style='clear: both; padding-top: 2px;')).append( safe_dom.Element('h3').add_text('All Courses')) table = safe_dom.Element('table') content.append(table) table.add_child( safe_dom.Element('tr').add_child( safe_dom.Element('th').add_text('Course Title')).add_child( safe_dom.Element('th').add_text('Context Path')).add_child( safe_dom.Element('th').add_text('Content Location')). add_child( safe_dom.Element('th').add_text('Student Data Location'))) count = 0 for course in sorted(sites.get_all_courses(), key=lambda course: course.get_title().lower()): count += 1 error = safe_dom.Text('') slug = course.get_slug() name = course.get_title() if course.fs.is_read_write(): location = 'namespace: %s' % course.get_namespace_name() else: location = 'disk: %s' % sites.abspath(course.get_home_folder(), '/') if slug == '/': link = '/dashboard' else: link = '%s/dashboard' % slug link = safe_dom.Element('a', href=link).add_text(name) table.add_child( safe_dom.Element('tr').add_child( safe_dom.Element('td').add_child(link).add_child(error)). add_child(safe_dom.Element('td').add_text(slug)).add_child( safe_dom.Element('td').add_text(location)).add_child( safe_dom.Element('td').add_text( 'namespace: %s' % course.get_namespace_name()))) table.add_child( safe_dom.Element('tr').add_child( safe_dom.Element('td', colspan='4', align='right').add_text( 'Total: %s item(s)' % count))) template_values['main_content'] = content self.render_page(template_values)
def get(self): if not self.personalize_page_and_get_enrolled(): return block_title = self.request.get('title') course_info = get_course_dict() for b in course_info['module']['blocks']: if b['block_title'] == block_title: b_info = b # Sending, accepting or rejecting an invitation to create challenge if self.request.get('request'): self.send_request(self.request.get('request'), block_title) if self.request.get('accept'): self.accept_request(self.request.get('accept'), block_title) if self.request.get('reject'): self.reject_request(self.request.get('reject'), block_title) block = gDefier_model.add_block_to_player(self, block_title) invitations=[] if block.request: invitations = block.request b_stats = gDefier_model.to_dict(block) b_stats.pop('player') b_stats.pop('blockID') b_info.pop('question_cast') path = sites.abspath(self.app_context.get_home_folder(), GCB_GDEFIER_FOLDER_NAME) page = 'templates/gDefier_blocks.html' # Avoiding repeated opponents or defies players = gDefier_model.get_players(self) board_block = gDefier_model.GDefierBoardBlock.gql("WHERE blockID = '" + block_title + "'").get() opponents = [] s1 = "" s2 = "" me = self.get_user().nickname() for p in players: existing_defy = False if p.blocks.count() == 0: #User unregistered in G-Defier module yet continue for s1 in block.sends: if p.name == s1: break for s2 in block.request: if p.name == s2: break if p.name == s1 or p.name == s2 or p.name == me: continue for df in board_block.defies: if df.rname == p.name and df.lname == me: existing_defy = True break elif df.rname == me and df.lname == p.name: existing_defy = True break if existing_defy: continue opponents.append(p.name) my_defies = gDefier_model.player_defies(self, block_title) template = self.get_template(page, additional_dirs=[path]) self.template_value['navbar'] = {'gDefier': True} self.template_value['w_module'] = course_info['module']['w_module'] self.template_value['b_info'] = b_info self.template_value['b_stats'] = b_stats self.template_value['block'] = block self.template_value['players'] = opponents self.template_value['invitations'] = invitations self.template_value['user'] = self.get_user().nickname() self.template_value['my_defies'] = my_defies self.render(template)
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)
def get_courses(self): """Shows a list of all courses available on this site.""" template_values = {} template_values['page_title'] = self.format_title('Courses') template_values['page_description'] = messages.COURSES_DESCRIPTION content = safe_dom.NodeList() content.append( safe_dom.Element( 'a', id='add_course', className='gcb-button gcb-pull-right', role='button', href='%s?action=add_course' % self.LINK_URL ).add_text('Add Course') ).append( safe_dom.Element('div', style='clear: both; padding-top: 2px;') ).append( safe_dom.Element('h3').add_text('All Courses') ) table = safe_dom.Element('table') content.append(table) table.add_child( safe_dom.Element('tr').add_child( safe_dom.Element('th').add_text('Course Title') ).add_child( safe_dom.Element('th').add_text('Context Path') ).add_child( safe_dom.Element('th').add_text('Content Location') ).add_child( safe_dom.Element('th').add_text('Student Data Location') ) ) count = 0 for course in sorted( sites.get_all_courses(), key=lambda course: course.get_title().lower()): count += 1 error = safe_dom.Text('') slug = course.get_slug() name = course.get_title() if course.fs.is_read_write(): location = 'namespace: %s' % course.get_namespace_name() else: location = 'disk: %s' % sites.abspath( course.get_home_folder(), '/') if slug == '/': link = '/dashboard' else: link = '%s/dashboard' % slug link = safe_dom.Element('a', href=link).add_text(name) table.add_child( safe_dom.Element('tr').add_child( safe_dom.Element('td').add_child(link).add_child(error) ).add_child( safe_dom.Element('td').add_text(slug) ).add_child( safe_dom.Element('td').add_text(location) ).add_child( safe_dom.Element('td').add_text( 'namespace: %s' % course.get_namespace_name()) )) table.add_child( safe_dom.Element('tr').add_child( safe_dom.Element('td', colspan='4', align='right').add_text( 'Total: %s item(s)' % count))) template_values['main_content'] = content self.render_page(template_values)
def get_courses(self): """Shows a list of all courses available on this site.""" template_values = {} template_values['page_title'] = self.format_title('Courses') template_values['page_description'] = messages.COURSES_DESCRIPTION content = [] content.append( '<a id="add_course" class="gcb-button pull-right" ' 'role="button" href="admin?action=add_course">Add Course</a>' '<div style="clear: both; padding-top: 2px;" />') content.append('<h3>All Courses</h3>') content.append('<table>') content.append(""" <tr> <th>Course Title</th> <th>Context Path</th> <th>Content Location</th> <th>Student Data Location</th> </tr> """) courses = sites.get_all_courses() count = 0 for course in courses: count += 1 error = '' slug = course.get_slug() try: name = escape(course.get_title()) except Exception as e: # pylint: disable-msg=broad-except name = 'UNKNOWN COURSE' error = ( '<p>Error in <strong>course.yaml</strong> file:<br/>' '<pre>\n%s\n%s\n</pre></p>' % ( e.__class__.__name__, escape(str(e)))) if course.fs.is_read_write(): location = 'namespace: %s' % course.get_namespace_name() else: location = 'disk: %s' % sites.abspath( course.get_home_folder(), '/') if slug == '/': link = '/dashboard' else: link = '%s/dashboard' % slug link = '<a href="%s">%s</a>' % (link, name) content.append(""" <tr> <td>%s%s</td> <td>%s</td> <td>%s</td> <td>%s</td> </tr> """ % ( link, escape(error), escape(slug), escape(location), escape( 'namespace: %s' % course.get_namespace_name()))) content.append(""" <tr><td colspan="4" align="right">Total: %s item(s)</td></tr> """ % count) content.append('</table>') template_values['main_content'] = ''.join(content) self.render_page(template_values)
def get_courses(self): """Shows a list of all courses available on this site.""" template_values = {} template_values['page_title'] = self.format_title('Courses') template_values['page_description'] = messages.COURSES_DESCRIPTION content = safe_dom.NodeList() content.append( safe_dom.Element( 'a', id='add_course', className='gcb-button gcb-pull-right', role='button', href='admin?action=add_course').add_text('Add Course')).append( safe_dom.Element( 'div', style='clear: both; padding-top: 2px;')).append( safe_dom.Element('h3').add_text('All Courses')) table = safe_dom.Element('table') content.append(table) table.add_child( safe_dom.Element('tr').add_child( safe_dom.Element('th').add_text('Course Title')).add_child( safe_dom.Element('th').add_text('Context Path')).add_child( safe_dom.Element('th').add_text('Content Location')). add_child( safe_dom.Element('th').add_text('Student Data Location'))) courses = sites.get_all_courses() count = 0 for course in courses: count += 1 error = safe_dom.Text('') slug = course.get_slug() try: name = course.get_title() except Exception as e: # pylint: disable-msg=broad-except name = 'UNKNOWN COURSE' error = safe_dom.Element('p').add_text('Error in ').add_child( safe_dom.Element('strong').add_text( 'course.yaml')).add_text(' file. ').add_child( safe_dom.Element('br')).add_child( safe_dom.Element('pre').add_text( '\n%s\n%s\n' % (e.__class__.__name__, str(e)))) if course.fs.is_read_write(): location = 'namespace: %s' % course.get_namespace_name() else: location = 'disk: %s' % sites.abspath(course.get_home_folder(), '/') if slug == '/': link = '/dashboard' else: link = '%s/dashboard' % slug link = safe_dom.Element('a', href=link).add_text(name) table.add_child( safe_dom.Element('tr').add_child( safe_dom.Element('td').add_child(link).add_child(error)). add_child(safe_dom.Element('td').add_text(slug)).add_child( safe_dom.Element('td').add_text(location)).add_child( safe_dom.Element('td').add_text( 'namespace: %s' % course.get_namespace_name()))) table.add_child( safe_dom.Element('tr').add_child( safe_dom.Element('td', colspan='4', align='right').add_text( 'Total: %s item(s)' % count))) template_values['main_content'] = content self.render_page(template_values)
def get_courses(self): """Shows a list of all courses available on this site.""" template_values = {} template_values['page_title'] = self.format_title('Courses') template_values['page_description'] = messages.COURSES_DESCRIPTION content = safe_dom.NodeList() content.append( safe_dom.Element( 'a', id='add_course', className='gcb-button gcb-pull-right', role='button', href='admin?action=add_course' ).add_text('Add Course') ).append( safe_dom.Element('div', style='clear: both; padding-top: 2px;') ).append( safe_dom.Element('h3').add_text('All Courses') ) table = safe_dom.Element('table') content.append(table) table.add_child( safe_dom.Element('tr').add_child( safe_dom.Element('th').add_text('Course Title') ).add_child( safe_dom.Element('th').add_text('Context Path') ).add_child( safe_dom.Element('th').add_text('Content Location') ).add_child( safe_dom.Element('th').add_text('Student Data Location') ) ) courses = sites.get_all_courses() count = 0 for course in courses: count += 1 error = safe_dom.Text('') slug = course.get_slug() try: name = course.get_title() except Exception as e: # pylint: disable-msg=broad-except name = 'UNKNOWN COURSE' error = safe_dom.Element('p').add_text('Error in ').add_child( safe_dom.Element('strong').add_text('course.yaml') ).add_text(' file. ').add_child( safe_dom.Element('br') ).add_child( safe_dom.Element('pre').add_text('\n%s\n%s\n' % ( e.__class__.__name__, str(e))) ) if course.fs.is_read_write(): location = 'namespace: %s' % course.get_namespace_name() else: location = 'disk: %s' % sites.abspath( course.get_home_folder(), '/') if slug == '/': link = '/dashboard' else: link = '%s/dashboard' % slug link = safe_dom.Element('a', href=link).add_text(name) table.add_child( safe_dom.Element('tr').add_child( safe_dom.Element('td').add_child(link).add_child(error) ).add_child( safe_dom.Element('td').add_text(slug) ).add_child( safe_dom.Element('td').add_text(location) ).add_child( safe_dom.Element('td').add_text( 'namespace: %s' % course.get_namespace_name()) )) table.add_child( safe_dom.Element('tr').add_child( safe_dom.Element('td', colspan='4', align='right').add_text( 'Total: %s item(s)' % count))) template_values['main_content'] = content self.render_page(template_values)
def get_courses(self): """Shows a list of all courses available on this site.""" template_values = {} template_values["page_title"] = self.format_title("Courses") template_values["page_description"] = messages.COURSES_DESCRIPTION content = [] content.append( '<a id="add_course" class="gcb-button pull-right" ' 'role="button" href="admin?action=add_course">Add Course</a>' '<div style="clear: both; padding-top: 2px;" />' ) content.append("<h3>All Courses</h3>") content.append("<table>") content.append( """ <tr> <th>Course Title</th> <th>Context Path</th> <th>Content Location</th> <th>Student Data Location</th> </tr> """ ) courses = sites.get_all_courses() count = 0 for course in courses: count += 1 error = "" slug = course.get_slug() try: name = escape(course.get_title()) except Exception as e: # pylint: disable-msg=broad-except name = "UNKNOWN COURSE" error = "<p>Error in <strong>course.yaml</strong> file:<br/>" "<pre>\n%s\n%s\n</pre></p>" % ( e.__class__.__name__, escape(str(e)), ) if course.fs.is_read_write(): location = "namespace: %s" % course.get_namespace_name() else: location = "disk: %s" % sites.abspath(course.get_home_folder(), "/") if slug == "/": link = "/dashboard" else: link = "%s/dashboard" % slug link = '<a href="%s">%s</a>' % (link, name) content.append( """ <tr> <td>%s%s</td> <td>%s</td> <td>%s</td> <td>%s</td> </tr> """ % ( link, escape(error), escape(slug), escape(location), escape("namespace: %s" % course.get_namespace_name()), ) ) content.append( """ <tr><td colspan="4" align="right">Total: %s item(s)</td></tr> """ % count ) content.append("</table>") template_values["main_content"] = "".join(content) self.render_page(template_values)
def get(self): """Process GET request.""" # TODO(emichael): move timing to Javascript if not custom_module.enabled: self.error(404) return student = self.personalize_page_and_get_enrolled( supports_transient_student=True) if not student: return try: start = time.time() # TODO(emichael): Don't use get because it can't handle utf-8 query = self.request.get('query') offset = self.request.get('offset') self.template_value['navbar'] = {} if query: try: offset = int(offset) except (ValueError, TypeError): offset = 0 self.template_value['query'] = query SEARCH_QUERIES_MADE.inc() response = fetch(self.get_course(), query, offset=offset) response = self.filter(response, student) self.template_value['time'] = '%.2f' % (time.time() - start) self.template_value['search_results'] = response['results'] total_found = response['total_found'] if offset + RESULTS_LIMIT < total_found: self.template_value['next_link'] = ( 'search?query=%s&offset=%d' % (query, offset + RESULTS_LIMIT)) if offset - RESULTS_LIMIT >= 0: self.template_value['previous_link'] = ( 'search?query=%s&offset=%d' % (query, offset - RESULTS_LIMIT)) self.template_value['page_number'] = offset / RESULTS_LIMIT + 1 self.template_value['total_pages'] = int(math.ceil( float(total_found) / RESULTS_LIMIT)) if response['results']: SEARCH_RESULTS_RETURNED.inc(len(response['results'])) # TODO(emichael): Remove this check when the unicode issue is fixed in # dev_appserver. except UnicodeEncodeError as e: SEARCH_FAILURES.inc() if not appengine_config.PRODUCTION_MODE: # This message will only be displayed to the course author in # dev, so it does not need to be I18N'd self.template_value['search_error'] = ( 'There is a known issue in App Engine\'s SDK ' '(code.google.com/p/googleappengine/issues/detail?id=9335) ' 'which causes an error when generating search snippets ' 'which contain non-ASCII characters. This error does not ' 'occur in the production environment, so you can safely ' 'run your course with unicode characters on appspot.com.') logging.error('[Unicode/Dev server issue] Error rendering the ' 'search page: %s.', e) else: self.template_value['search_error'] = SEARCH_ERROR_TEXT logging.error('Error rendering the search page: %s. %s', e, traceback.format_exc()) except Exception as e: # pylint: disable=broad-except SEARCH_FAILURES.inc() self.template_value['search_error'] = SEARCH_ERROR_TEXT logging.error('Error rendering the search page: %s. %s', e, traceback.format_exc()) finally: path = sites.abspath(self.app_context.get_home_folder(), GCB_SEARCH_FOLDER_NAME) template = self.get_template('search.html', additional_dirs=[path]) self.template_value['navbar'] = {} self.response.out.write(template.render(self.template_value))
def _get_about_course(handler): # Basic course info. template_values = {} course_info = [] course_actions = [] app_context = handler.app_context if not app_context.is_editable_fs(): course_info.append('The course is read-only.') else: if app_context.now_available: if app_context.get_environ()['course']['browsable']: browsable = True course_browsability_caption = ( 'Hide Course From Unregistered Users') course_info.append('The course is is browsable by ' 'un-registered users') else: browsable = False course_browsability_caption = ( 'Allow Unregistered Users to Browse Course') course_info.append('The course is not visible to ' 'un-registered users.') course_actions.append({ 'id': 'course_browsability', 'caption': course_browsability_caption, 'action': handler.get_action_url('course_browsability'), 'xsrf_token': crypto.XsrfTokenManager.create_xsrf_token( 'course_browsability'), 'params': {'browsability': not browsable}, }) currentCourse = courses.Course(handler) course_info.append('Schema Version: %s' % currentCourse.version) course_info.append('Context Path: %s' % app_context.get_slug()) course_info.append('Datastore Namespace: %s' % app_context.get_namespace_name()) # Course file system. fs = 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( app_context.get_home_folder(), '/'))) data_info = dashboard_utils.list_files(handler, '/data/') sections = [ { 'title': 'About the Course', 'description': messages.ABOUT_THE_COURSE_DESCRIPTION, 'actions': course_actions, 'children': course_info},] if currentCourse.version == courses.COURSE_MODEL_VERSION_1_2: sections.append({ 'title': 'Data Files', 'description': messages.DATA_FILES_DESCRIPTION, 'children': data_info}) template_values['alerts'] = handler.get_alerts() template_values['sections'] = sections return template_values