def get(self, relpath): output = [] if relpath == "authors": profiles = {} for p in models.get_sorted_profiles(): # This query is memcached. profile_id = p["id"] profiles[profile_id] = p geo_location = profiles[profile_id]["geo_location"] profiles[profile_id]["geo_location"] = str(geo_location) output = profiles elif relpath == "tutorials": output = TagsHandler()._query_to_serializable_list(TagsHandler().get_as_db("type:tutorial")) elif relpath == "articles": output = TagsHandler()._query_to_serializable_list(TagsHandler().get_as_db("type:article")) elif relpath == "casestudies": output = TagsHandler()._query_to_serializable_list(TagsHandler().get_as_db("type:casestudy")) elif relpath == "demos": output = TagsHandler()._query_to_serializable_list(TagsHandler().get_as_db("type:demo")) elif relpath == "samples": output = TagsHandler()._query_to_serializable_list(TagsHandler().get_as_db("type:sample")) elif relpath == "presentations": output = TagsHandler()._query_to_serializable_list(TagsHandler().get_as_db("type:presentation")) elif relpath == "announcements": output = TagsHandler()._query_to_serializable_list(TagsHandler().get_as_db("type:announcement")) elif relpath == "videos": output = TagsHandler()._query_to_serializable_list(TagsHandler().get_as_db("type:video")) self.response.headers.add_header("Access-Control-Allow-Origin", "*") self.response.headers["Content-Type"] = "application/json" self.response.out.write(simplejson.dumps(output))
def post(self, relpath): if relpath == 'live': # Get first (and only) result. live_data = models.LiveData.all().get() if live_data is None: live_data = models.LiveData() live_data.gdl_page_url = self.request.get('gdl_page_url') or None #if live_data.gdl_page_url is not None: live_data.put() return self.redirect('/database/live') elif relpath == 'author': try: given_name = self.request.get('given_name') family_name = self.request.get('family_name') author = models.Author( key_name=''.join([given_name, family_name]).lower(), given_name=given_name, family_name=family_name, org=self.request.get('org'), unit=self.request.get('unit'), city=self.request.get('city'), state=self.request.get('state'), country=self.request.get('country'), homepage=self.request.get('homepage') or None, google_account=self.request.get('google_account') or None, twitter_account=self.request.get('twitter_account') or None, email=self.request.get('email') or None, lanyrd=self.request.get('lanyrd') == 'on') lat = self.request.get('lat') lon = self.request.get('lon') if lat and lon: author.geo_location = db.GeoPt(float(lat), float(lon)) author.put() except db.Error, e: # TODO: Doesn't repopulate lat/lng or return errors for it. form = models.AuthorForm(self.request.POST) if not form.is_valid(): sorted_profiles = models.get_sorted_profiles( update_cache=True) template_data = { 'sorted_profiles': sorted_profiles, 'profile_amount': len(sorted_profiles), 'author_form': form } return self.render( data=template_data, template_path='database/author_new.html', relpath=relpath) else: self.redirect('/database/author')
def post(self, relpath): if relpath == 'live': # Get first (and only) result. live_data = models.LiveData.all().get() if live_data is None: live_data = models.LiveData() live_data.gdl_page_url = self.request.get('gdl_page_url') or None #if live_data.gdl_page_url is not None: live_data.put() return self.redirect('/database/live') elif relpath == 'author': try: given_name = self.request.get('given_name') family_name = self.request.get('family_name') author = models.Author( key_name=''.join([given_name, family_name]).lower(), given_name=given_name, family_name=family_name, org=self.request.get('org'), unit=self.request.get('unit'), city=self.request.get('city'), state=self.request.get('state'), country=self.request.get('country'), homepage=self.request.get('homepage') or None, google_account=self.request.get('google_account') or None, twitter_account=self.request.get('twitter_account') or None, email=self.request.get('email') or None, lanyrd=self.request.get('lanyrd') == 'on') lat = self.request.get('lat') lon = self.request.get('lon') if lat and lon: author.geo_location = db.GeoPt(float(lat), float(lon)) author.put() except db.Error, e: # TODO: Doesn't repopulate lat/lng or return errors for it. form = models.AuthorForm(self.request.POST) if not form.is_valid(): sorted_profiles = models.get_sorted_profiles(update_cache=True) template_data = { 'sorted_profiles': sorted_profiles, 'profile_amount': len(sorted_profiles), 'author_form': form } return self.render(data=template_data, template_path='database/author_new.html', relpath=relpath) else: self.redirect('/database/author')
def post(self, relpath): if relpath == "live": # Get first (and only) result. live_data = models.LiveData.all().get() if live_data is None: live_data = models.LiveData() live_data.gdl_page_url = self.request.get("gdl_page_url") or None # if live_data.gdl_page_url is not None: live_data.put() return self.redirect("/database/live") elif relpath == "author": try: given_name = self.request.get("given_name") family_name = self.request.get("family_name") author = models.Author( key_name="".join([given_name, family_name]).lower(), given_name=given_name, family_name=family_name, org=self.request.get("org"), unit=self.request.get("unit"), city=self.request.get("city"), state=self.request.get("state"), country=self.request.get("country"), homepage=self.request.get("homepage") or None, google_account=self.request.get("google_account") or None, twitter_account=self.request.get("twitter_account") or None, email=self.request.get("email") or None, lanyrd=self.request.get("lanyrd") == "on", ) lat = self.request.get("lat") lon = self.request.get("lon") if lat and lon: author.geo_location = db.GeoPt(float(lat), float(lon)) author.put() except db.Error, e: # TODO: Doesn't repopulate lat/lng or return errors for it. form = models.AuthorForm(self.request.POST) if not form.is_valid(): sorted_profiles = models.get_sorted_profiles(update_cache=True) template_data = { "sorted_profiles": sorted_profiles, "profile_amount": len(sorted_profiles), "author_form": form, } return self.render(data=template_data, template_path="database/author_new.html", relpath=relpath) else: self.redirect("/database/author")
def get(self, relpath): output = [] if relpath == 'authors': profiles = {} for p in models.get_sorted_profiles(): # This query is memcached. profile_id = p['id'] profiles[profile_id] = p geo_location = profiles[profile_id]['geo_location'] profiles[profile_id]['geo_location'] = str(geo_location) output = profiles elif relpath == 'tutorials': output = TagsHandler()._query_to_serializable_list( TagsHandler().get_as_db('type:tutorial')) elif relpath == 'articles': output = TagsHandler()._query_to_serializable_list( TagsHandler().get_as_db('type:article')) elif relpath == 'casestudies': output = TagsHandler()._query_to_serializable_list( TagsHandler().get_as_db('type:casestudy')) elif relpath == 'demos': output = TagsHandler()._query_to_serializable_list( TagsHandler().get_as_db('type:demo')) elif relpath == 'samples': output = TagsHandler()._query_to_serializable_list( TagsHandler().get_as_db('type:sample')) elif relpath == 'presentations': output = TagsHandler()._query_to_serializable_list( TagsHandler().get_as_db('type:presentation')) elif relpath == 'announcements': output = TagsHandler()._query_to_serializable_list( TagsHandler().get_as_db('type:announcement')) elif relpath == 'videos': output = TagsHandler()._query_to_serializable_list( TagsHandler().get_as_db('type:video')) self.response.headers.add_header('Access-Control-Allow-Origin', '*') self.response.headers['Content-Type'] = 'application/json' self.response.out.write(simplejson.dumps(output))
def get(self, relpath, post_id=None): self._set_cache_param() if (relpath == 'live'): user = users.get_current_user() # Restrict access to this page to admins and whitelisted users. if (not users.is_current_user_admin() and user.email() not in settings.WHITELISTED_USERS): return self.redirect('/') entity = models.LiveData.all().get() if entity: live_form = models.LiveForm( entity.to_dict(), initial={'gdl_page_url': entity.gdl_page_url}) else: live_form = models.LiveForm() template_data = {'live_form': live_form} return self.render(data=template_data, template_path='database/live.html', relpath=relpath) elif (relpath == 'author'): # adds a new author information into DataStore. sorted_profiles = models.get_sorted_profiles(update_cache=True) template_data = { 'sorted_profiles': sorted_profiles, 'profile_amount': len(sorted_profiles), 'author_form': models.AuthorForm() } return self.render(data=template_data, template_path='database/author_new.html', relpath=relpath) elif (relpath == 'drop_all'): if settings.PROD: return self.response.out.write( 'Handler not allowed in production.') self._NukeDB() elif (relpath == 'load_tutorials'): if settings.PROD: return self.response.out.write( 'Handler not allowed in production.') self._AddTestResources() elif (relpath == 'load_authors'): if settings.PROD: return self.response.out.write( 'Handler not allowed in production.') self._AddTestAuthors() elif (relpath == 'load_playground_samples'): if settings.PROD: return self.response.out.write( 'Handler not allowed in production.') self._AddTestPlaygroundSamples() elif (relpath == 'load_studio_samples'): if settings.PROD: return self.response.out.write( 'Handler not allowed in production.') self._AddTestStudioSamples() elif (relpath == 'load_all'): if settings.PROD: return self.response.out.write( 'Handler not allowed in production.') # TODO(ericbidelman): Make this async. self._AddTestAuthors() self._AddTestResources() self._AddTestPlaygroundSamples() self._AddTestStudioSamples() elif relpath == 'resource': tutorial_form = models.TutorialForm() if post_id: # /database/resource/1234 post = models.Resource.get_by_id(int(post_id)) if post: author_id = post.author.key().name() second_author_id = (post.second_author and post.second_author.key().name()) # Adjust browser support so it renders to the checkboxes correctly. browser_support = [ b.capitalize() for b in post.browser_support ] for b in browser_support: if len(b) == 2: browser_support[browser_support.index( b)] = b.upper() form_data = post.to_dict() form_data['tags'] = ', '.join(post.tags) form_data['author'] = author_id form_data['second_author'] = second_author_id or author_id form_data['browser_support'] = browser_support tutorial_form = models.TutorialForm(form_data) template_data = { 'tutorial_form': tutorial_form, # get_all() not used b/c we don't care about caching on this page. 'resources': (models.Resource.all().order('-publication_date').fetch( limit=settings.MAX_FETCH_LIMIT)), 'post_id': post_id and int(post_id) or '' } return self.render(data=template_data, template_path='database/resource_new.html', relpath=relpath) # Catch all to redirect to proper page. return self.redirect('/database/resource')
def get(self, relpath): self._set_cache_param() # Handle bug redirects before anything else, as it's trivial. if relpath == 'new-bug': return self.redirect( 'https://github.com/html5rocks/www.html5rocks.com/issues/new') # Handle humans before locale, to prevent redirect to /en/ # (but still ensure it's dynamic, ie we can't just redirect to a static url) if relpath == 'humans.txt': self.response.headers['Content-Type'] = 'text/plain' sorted_profiles = models.get_sorted_profiles() return self.render(data={ 'sorted_profiles': sorted_profiles, 'profile_amount': len(sorted_profiles) }, template_path='content/humans.txt', relpath=relpath) # Get the locale: if it's "None", redirect to English locale = self.get_language() if not locale: return self.redirect("/en/%s" % relpath, permanent=True) # If there is a locale specified but it has no leading slash, redirect if not relpath.startswith("%s/" % locale): return self.redirect("/%s/" % locale, permanent=True) # If we get here, is because the language is specified correctly, # so let's activate it self.activate_language(locale) # Strip off leading `/[en|de|fr|...]/` relpath = re.sub('^/?\w{2,3}(?:/)?', '', relpath) # Are we looking for a feed? is_feed = self.request.path.endswith('.xml') # Which CSS should this use? (Will get overwritten.) css_file = 'base' page_class = None include_home_link = True # Setup handling of redirected article URLs: If a user tries to access an # article from a non-supported language, we'll redirect them to the # English version (assuming it exists), with a `redirect_from_locale` GET # param. redirect_from_locale = self.request.get('redirect_from_locale', '') if not re.match('[a-zA-Z]{2,3}$', redirect_from_locale): redirect_from_locale = False else: translation.activate(redirect_from_locale) redirect_from_locale = { 'lang': redirect_from_locale, 'msg': _('Sorry, this article isn\'t available in your native ' 'language; we\'ve redirected you to the English version.') } translation.activate(locale) # Landing page or /tutorials|features|mobile|gaming|business\/? if ((relpath == '' or relpath[-1] == '/') or # Landing page. (relpath[-1] != '/' and relpath in [ 'mobile', 'tutorials', 'features', 'gaming', 'business', 'updates' ])): # Check if path ends with a / and adds if necessary if (relpath != '' and relpath[-1] != '/' and self.request.query_string == ''): return self.redirect(relpath + '/', permanent=True) # Check if path ends with a / and adds along with the query string elif (relpath != '' and relpath[-1] != '/' and self.request.query_string != ''): return self.redirect(relpath + '/?' + self.request.query_string, permanent=True) if (relpath == ''): include_home_link = None css_file = 'v2-combined' if (relpath == 'tutorials/'): css_file = 'v2-combined' page_class = 'article tutorial listing' path = os.path.join('content', relpath, 'index.html') else: path = os.path.join('content', relpath) # Render the .html page if it exists. Otherwise, check that the Atom feed # the user is requesting has a corresponding .html page that exists. if (relpath == 'profiles' or relpath == 'profiles/'): profiles = models.get_sorted_profiles() for p in profiles: p['tuts_by_author'] = models.Resource.get_tutorials_by_author( p['id']) return self.render(data={ 'include_home_link': include_home_link, 'page_class': page_class, 'css_file': css_file, 'sorted_profiles': profiles }, template_path='content/profiles.html', relpath=relpath) elif ((re.search('tutorials/.+', relpath) or re.search( 'mobile/.+', relpath) or re.search('gaming/.+', relpath) or re.search('business/.+', relpath) or re.search('updates/.+', relpath) or re.search('tutorials/casestudies/.+', relpath)) and not is_feed): # If this is an old-style mobile article or case study, redirect to the # new style. match = re.search(('(?P<type>mobile|tutorials/casestudies)' '/(?P<slug>[a-z-_0-9]+).html$'), relpath) if match: return self.redirect( '/%s/%s/%s/' % (locale, match.group('type'), match.group('slug'))) # If no trailing / (e.g. /tutorials/blah), redirect to /tutorials/blah/. if (relpath[-1] != '/' and not relpath.endswith('.html')): return self.redirect(self.request.url + '/') # Tutorials look like this on the filesystem: # # .../tutorials + # | # +-- article-slug + # | | # | +-- en + # | | | # | | +-- index.html # ... # # So, to determine if an HTML page exists for the requested language # `split` the file's path, add in the locale, and check existence: (dir, filename) = os.path.split(path) if os.path.isfile(os.path.join(dir, locale, filename)): # Lookup tutorial by its url. Return the first one that matches. # get_all() not used because we don't care about caching on individual # tut page. tut = models.Resource.all().filter('url =', '/' + relpath).get() # Localize title and description. if tut: if tut.title: tut.title = _(tut.title) if hasattr(tut, 'subtitle') and tut.subtitle: tut.subtitle = _(tut.subtitle) if tut.description: tut.description = _(tut.description) css_file = 'v2-combined' page_class = 'article tutorial' # Gather list of localizations by globbing matching directories, then # stripping out the current locale and 'static'. Once we have a list, # convert it to a series of dictionaries containing the localization's # path and name: langs = { 'de': 'Deutsch', 'en': 'English', 'fr': 'Français', 'es': 'Español', 'it': 'Italiano', 'ja': '日本語', 'ko': '한국어', 'pt': 'Português (Brasil)', 'ru': 'Pусский', 'zh': '中文 (简体)' } loc_list = [] for d in glob.glob(os.path.join(dir, '*', 'index.html')): loc = os.path.basename(os.path.dirname(d)) if loc not in [locale, 'static']: loc_list.append({ 'path': '/%s/%s' % (loc, relpath), 'lang': langs[loc], 'loc': loc }) data = { 'include_home_link': include_home_link, 'page_class': page_class, 'css_file': css_file, 'tut': tut, 'localizations': loc_list, 'redirect_from_locale': redirect_from_locale } return self.render(template_path=os.path.join( dir, locale, filename), data=data, relpath=relpath) # If the localized file doesn't exist, and the locale isn't English, look # for an english version of the file, and redirect the user there if # it's found: elif os.path.isfile(os.path.join(dir, 'en', filename)): return self.redirect("/en/%s?redirect_from_locale=%s" % (relpath, locale)) elif os.path.isfile(path): #TODO(ericbidelman): Don't need these tutorial/update results for query. page_number = int(self.request.get('page', default_value=0)) or None template_args = dict() if page_number: template_args['previous_page'] = page_number - 1 template_args['next_page'] = page_number + 1 if relpath[:-1] in ['mobile', 'gaming', 'business']: results = TagsHandler().get_as_db( relpath[:-1], limit=self.FEATURE_PAGE_WHATS_NEW_LIMIT) elif relpath == 'updates': results = [] else: include_updates = None if relpath == '': resource_limit = 9 include_updates = True else: resource_limit = None if page_number is not None: results = models.Resource.get_all( order='-publication_date', page=page_number, include_updates=include_updates) else: results = models.Resource.get_all( order='-publication_date', limit=resource_limit, include_updates=include_updates) tutorials = [] # List of final result set. authors = [] # List of authors related to the result set. for r in results: resource_type = [x for x in r.tags if x.startswith('type:')] if len(resource_type): resource_type = resource_type[0].replace('type:', '') if r.url.startswith('/'): # Localize title and description if article is localized. filepath = os.path.join(self.BASEDIR, 'content', r.url[1:], self.locale, 'index.html') if os.path.isfile(filepath): if r.title: r.title = _(r.title) if hasattr(r, 'subtitle') and r.subtitle: r.subtitle = _(r.subtitle) if r.description: r.description = _(r.description) # Point the article to the localized version, regardless. r.url = "/%s%s" % (self.locale, r.url) tutorials.append(r) tutorials[-1].classes = [ x.replace('class:', '') for x in r.tags if x.startswith('class:') ] tutorials[-1].tags = [ x for x in r.tags if not (x.startswith('class:') or x.startswith('type:')) ] tutorials[-1].type = resource_type #TODO(ericbidelman): Probably don't need author for every result query. authors.append(r.author) # Remove duplicate authors from the list. author_dict = {} for a in authors: if a is not None: author_dict[a.key().name()] = a authors = author_dict.values() data = { 'include_home_link': include_home_link, 'page_class': page_class, 'css_file': css_file, 'tutorials': tutorials, 'authors': authors, 'args': template_args } return self.render(data, template_path=path, relpath=relpath) elif os.path.isfile(path[:path.rfind('.')] + '.html'): return self.render(data={'css_file': css_file}, template_path=path[:path.rfind('.')] + '.html', relpath=relpath) elif os.path.isfile(path + '.html'): page_title = None if path == 'content/style-guide': css_file = 'v2-combined' page_class = 'article' page_title = 'Style Guide' category = relpath.replace('features/', '') updates = TagsHandler().get_as_db( 'class:' + category, limit=self.FEATURE_PAGE_WHATS_NEW_LIMIT) for r in updates: if r.url.startswith('/'): # Localize title if article is localized. filepath = os.path.join(self.BASEDIR, 'content', r.url[1:], self.locale, 'index.html') if r.url.startswith('/') and os.path.isfile( filepath) and r.title: r.title = _(r.title) # Point the article to the localized version, regardless. r.url = "/%s%s" % (self.locale, r.url) data = { 'include_home_link': include_home_link, 'page_title': page_title, 'page_class': page_class, 'css_file': css_file, 'category': category, 'updates': updates } if relpath == 'why': if os.path.isfile(os.path.join(path, locale, 'index.html')): data['local_content_path'] = os.path.join( relpath, locale, 'index.html') else: data['local_content_path'] = os.path.join( relpath, 'en', 'index.html') return self.render(data=data, template_path=path + '.html', relpath=relpath) # If we've reached here, assume 404. return self.render(status=404, message='Page Not Found', template_path='404.html')
def get(self, relpath, post_id=None): self._set_cache_param() if (relpath == 'live'): user = users.get_current_user() # Restrict access to this page to admins and whitelisted users. if (not users.is_current_user_admin() and user.email() not in settings.WHITELISTED_USERS): return self.redirect('/') entity = models.LiveData.all().get() if entity: live_form = models.LiveForm(entity.to_dict(), initial={ 'gdl_page_url': entity.gdl_page_url }) else: live_form = models.LiveForm() template_data = { 'live_form': live_form } return self.render(data=template_data, template_path='database/live.html', relpath=relpath) elif (relpath == 'author'): # adds a new author information into DataStore. sorted_profiles = models.get_sorted_profiles(update_cache=True) template_data = { 'sorted_profiles': sorted_profiles, 'profile_amount': len(sorted_profiles), 'author_form': models.AuthorForm() } return self.render(data=template_data, template_path='database/author_new.html', relpath=relpath) elif (relpath == 'drop_all'): if settings.PROD: return self.response.out.write('Handler not allowed in production.') self._NukeDB() elif (relpath == 'load_tutorials'): if settings.PROD: return self.response.out.write('Handler not allowed in production.') self._AddTestResources() elif (relpath == 'load_authors'): if settings.PROD: return self.response.out.write('Handler not allowed in production.') self._AddTestAuthors() elif (relpath == 'load_playground_samples'): if settings.PROD: return self.response.out.write('Handler not allowed in production.') self._AddTestPlaygroundSamples() elif (relpath == 'load_studio_samples'): if settings.PROD: return self.response.out.write('Handler not allowed in production.') self._AddTestStudioSamples() elif (relpath == 'load_all'): if settings.PROD: return self.response.out.write('Handler not allowed in production.') # TODO(ericbidelman): Make this async. self._AddTestAuthors() self._AddTestResources() self._AddTestPlaygroundSamples() self._AddTestStudioSamples() elif relpath == 'resource': tutorial_form = models.TutorialForm() if post_id: # /database/resource/1234 post = models.Resource.get_by_id(int(post_id)) if post: author_id = post.author.key().name() second_author_id = (post.second_author and post.second_author.key().name()) # Adjust browser support so it renders to the checkboxes correctly. browser_support = [b.capitalize() for b in post.browser_support] for b in browser_support: if len(b) == 2: browser_support[browser_support.index(b)] = b.upper() form_data = post.to_dict() form_data['tags'] = ', '.join(post.tags) form_data['author'] = author_id form_data['second_author'] = second_author_id or author_id form_data['browser_support'] = browser_support tutorial_form = models.TutorialForm(form_data) template_data = { 'tutorial_form': tutorial_form, # get_all() not used b/c we don't care about caching on this page. 'resources': (models.Resource.all().order('-publication_date') .fetch(limit=settings.MAX_FETCH_LIMIT)), 'post_id': post_id and int(post_id) or '' } return self.render(data=template_data, template_path='database/resource_new.html', relpath=relpath) # Catch all to redirect to proper page. return self.redirect('/database/resource')
def get(self, relpath): self._set_cache_param() # Handle bug redirects before anything else, as it's trivial. if relpath == 'new-bug': return self.redirect('https://github.com/html5rocks/www.html5rocks.com/issues/new') # Handle humans before locale, to prevent redirect to /en/ # (but still ensure it's dynamic, ie we can't just redirect to a static url) if relpath == 'humans.txt': self.response.headers['Content-Type'] = 'text/plain' sorted_profiles = models.get_sorted_profiles() return self.render(data={'sorted_profiles': sorted_profiles, 'profile_amount': len(sorted_profiles)}, template_path='content/humans.txt', relpath=relpath) # Get the locale: if it's "None", redirect to English locale = self.get_language() if not locale: return self.redirect("/en/%s" % relpath, permanent=True) # If there is a locale specified but it has no leading slash, redirect if not relpath.startswith("%s/" % locale): return self.redirect("/%s/" % locale, permanent=True) # If we get here, is because the language is specified correctly, # so let's activate it self.activate_language(locale) # Strip off leading `/[en|de|fr|...]/` relpath = re.sub('^/?\w{2,3}(?:/)?', '', relpath) # Are we looking for a feed? is_feed = self.request.path.endswith('.xml') # Which CSS should this use? (Will get overwritten.) css_file = 'base' # Setup handling of redirected article URLs: If a user tries to access an # article from a non-supported language, we'll redirect them to the # English version (assuming it exists), with a `redirect_from_locale` GET # param. redirect_from_locale = self.request.get('redirect_from_locale', '') if not re.match('[a-zA-Z]{2,3}$', redirect_from_locale): redirect_from_locale = False else: translation.activate(redirect_from_locale) redirect_from_locale = { 'lang': redirect_from_locale, 'msg': _('Sorry, this article isn\'t available in your native ' 'language; we\'ve redirected you to the English version.') } translation.activate(locale) # Landing page or /tutorials|features|mobile|gaming|business\/? if ((relpath == '' or relpath[-1] == '/') or # Landing page. (relpath[-1] != '/' and relpath in ['mobile', 'tutorials', 'features', 'gaming', 'business', 'updates'])): # Check if path ends with a / and adds if necessary if (relpath != '' and relpath[-1] != '/' and self.request.query_string == ''): return self.redirect(relpath + '/', permanent=True) # Check if path ends with a / and adds along with the query string elif (relpath != '' and relpath[-1] != '/' and self.request.query_string != ''): return self.redirect(relpath + '/?' + self.request.query_string, permanent=True) if (relpath == ''): css_file = 'home' path = os.path.join('content', relpath, 'index.html') else: path = os.path.join('content', relpath) # Render the .html page if it exists. Otherwise, check that the Atom feed # the user is requesting has a corresponding .html page that exists. if (relpath == 'profiles' or relpath == 'profiles/'): profiles = models.get_sorted_profiles() for p in profiles: p['tuts_by_author'] = models.Resource.get_tutorials_by_author(p['id']) return self.render(data={ 'css_file':css_file, 'sorted_profiles': profiles }, template_path='content/profiles.html', relpath=relpath) elif ((re.search('tutorials/.+', relpath) or re.search('mobile/.+', relpath) or re.search('gaming/.+', relpath) or re.search('business/.+', relpath) or re.search('updates/.+', relpath) or re.search('tutorials/casestudies/.+', relpath)) and not is_feed): # If this is an old-style mobile article or case study, redirect to the # new style. match = re.search(('(?P<type>mobile|tutorials/casestudies)' '/(?P<slug>[a-z-_0-9]+).html$'), relpath) if match: return self.redirect('/%s/%s/%s/' % (locale, match.group('type'), match.group('slug'))) # If no trailing / (e.g. /tutorials/blah), redirect to /tutorials/blah/. if (relpath[-1] != '/' and not relpath.endswith('.html')): return self.redirect(self.request.url + '/') # Tutorials look like this on the filesystem: # # .../tutorials + # | # +-- article-slug + # | | # | +-- en + # | | | # | | +-- index.html # ... # # So, to determine if an HTML page exists for the requested language # `split` the file's path, add in the locale, and check existence: (dir, filename) = os.path.split(path) if os.path.isfile(os.path.join(dir, locale, filename)): # Lookup tutorial by its url. Return the first one that matches. # get_all() not used because we don't care about caching on individual # tut page. tut = models.Resource.all().filter('url =', '/' + relpath).get() # If tutorial is marked as draft, redirect and don't show it. if tut and tut.draft: return self.redirect('/tutorials') # Localize title and description. if tut: if tut.title: tut.title = _(tut.title) if hasattr(tut, 'subtitle') and tut.subtitle: tut.subtitle = _(tut.subtitle) if tut.description: tut.description = _(tut.description) # Gather list of localizations by globbing matching directories, then # stripping out the current locale and 'static'. Once we have a list, # convert it to a series of dictionaries containing the localization's # path and name: langs = { 'de': 'Deutsch', 'en': 'English', 'fr': 'Français', 'es': 'Español', 'it': 'Italiano', 'ja': '日本語', 'ko': '한국어', 'pt': 'Português (Brasil)', 'ru': 'Pусский', 'zh': '中文 (简体)' } loc_list = [] for d in glob.glob(os.path.join(dir, '*', 'index.html')): loc = os.path.basename(os.path.dirname(d)) if loc not in [locale, 'static']: loc_list.append({'path': '/%s/%s' % (loc, relpath), 'lang': langs[loc]}) data = { 'css_file': css_file, 'tut': tut, 'localizations': loc_list, 'redirect_from_locale': redirect_from_locale } return self.render(template_path=os.path.join(dir, locale, filename), data=data, relpath=relpath) # If the localized file doesn't exist, and the locale isn't English, look # for an english version of the file, and redirect the user there if # it's found: elif os.path.isfile( os.path.join(dir, 'en', filename)): return self.redirect("/en/%s?redirect_from_locale=%s" % (relpath, locale)) elif os.path.isfile(path): #TODO(ericbidelman): Don't need these tutorial/update results for query. page_number = int(self.request.get('page', default_value=0)) or None template_args = dict() if page_number: template_args['previous_page'] = page_number - 1 template_args['next_page'] = page_number + 1 if relpath[:-1] in ['mobile', 'gaming', 'business']: results = TagsHandler().get_as_db( relpath[:-1], limit=self.FEATURE_PAGE_WHATS_NEW_LIMIT) elif relpath == 'updates': results = [] else: include_updates = None if relpath == '': resource_limit = 9 include_updates = True else: resource_limit = None if page_number is not None: results = models.Resource.get_all(order='-publication_date', page=page_number, include_updates=include_updates) else: results = models.Resource.get_all(order='-publication_date', limit=resource_limit, include_updates=include_updates) tutorials = [] # List of final result set. authors = [] # List of authors related to the result set. for r in results: resource_type = [x for x in r.tags if x.startswith('type:')] if len(resource_type): resource_type = resource_type[0].replace('type:', '') if r.url.startswith('/'): # Localize title and description if article is localized. filepath = os.path.join(self.BASEDIR, 'content', r.url[1:], self.locale, 'index.html') if os.path.isfile(filepath): if r.title: r.title = _(r.title) if hasattr(r, 'subtitle') and r.subtitle: r.subtitle = _(r.subtitle) if r.description: r.description = _(r.description) # Point the article to the localized version, regardless. r.url = "/%s%s" % (self.locale, r.url) tutorials.append(r) tutorials[-1].classes = [x.replace('class:', '') for x in r.tags if x.startswith('class:')] tutorials[-1].tags = [x for x in r.tags if not (x.startswith('class:') or x.startswith('type:'))] tutorials[-1].type = resource_type #TODO(ericbidelman): Probably don't need author for every result query. authors.append(r.author) # Remove duplicate authors from the list. author_dict = {} for a in authors: author_dict[a.key().name()] = a authors = author_dict.values() data = { 'css_file': css_file, 'tutorials': tutorials, 'authors': authors, 'args': template_args } return self.render(data, template_path=path, relpath=relpath) elif os.path.isfile(path[:path.rfind('.')] + '.html'): return self.render(data={'css_file': css_file}, template_path=path[:path.rfind('.')] + '.html', relpath=relpath) elif os.path.isfile(path + '.html'): category = relpath.replace('features/', '') updates = TagsHandler().get_as_db( 'class:' + category, limit=self.FEATURE_PAGE_WHATS_NEW_LIMIT) for r in updates: if r.url.startswith('/'): # Localize title if article is localized. filepath = os.path.join(self.BASEDIR, 'content', r.url[1:], self.locale, 'index.html') if r.url.startswith('/') and os.path.isfile(filepath) and r.title: r.title = _(r.title) # Point the article to the localized version, regardless. r.url = "/%s%s" % (self.locale, r.url) data = { 'css_file': css_file, 'category': category, 'updates': updates } if relpath == 'why': if os.path.isfile(os.path.join(path, locale, 'index.html')): data['local_content_path'] = os.path.join(relpath, locale, 'index.html') else: data['local_content_path'] = os.path.join(relpath, 'en', 'index.html') return self.render(data=data, template_path=path + '.html', relpath=relpath) # If we've reached here, assume 404. return self.render(status=404, message='Page Not Found', template_path='404.html')
def get(self, relpath, post_id=None): self._set_cache_param() if relpath == "live": user = users.get_current_user() # Restrict access to this page to admins and whitelisted users. if not users.is_current_user_admin() and user.email() not in settings.WHITELISTED_USERS: return self.redirect("/") entity = models.LiveData.all().get() if entity: live_form = models.LiveForm(entity.to_dict(), initial={"gdl_page_url": entity.gdl_page_url}) else: live_form = models.LiveForm() template_data = {"live_form": live_form} return self.render(data=template_data, template_path="database/live.html", relpath=relpath) elif relpath == "author": # adds a new author information into DataStore. sorted_profiles = models.get_sorted_profiles(update_cache=True) template_data = { "sorted_profiles": sorted_profiles, "profile_amount": len(sorted_profiles), "author_form": models.AuthorForm(), } return self.render(data=template_data, template_path="database/author_new.html", relpath=relpath) elif relpath == "drop_all": if settings.PROD: return self.response.out.write("Handler not allowed in production.") self._NukeDB() elif relpath == "load_tutorials": if settings.PROD: return self.response.out.write("Handler not allowed in production.") self._AddTestResources() elif relpath == "load_authors": if settings.PROD: return self.response.out.write("Handler not allowed in production.") self._AddTestAuthors() elif relpath == "load_playground_samples": if settings.PROD: return self.response.out.write("Handler not allowed in production.") self._AddTestPlaygroundSamples() elif relpath == "load_studio_samples": if settings.PROD: return self.response.out.write("Handler not allowed in production.") self._AddTestStudioSamples() elif relpath == "load_all": if settings.PROD: return self.response.out.write("Handler not allowed in production.") # TODO(ericbidelman): Make this async. self._AddTestAuthors() self._AddTestResources() self._AddTestPlaygroundSamples() self._AddTestStudioSamples() elif relpath == "resource": tutorial_form = models.TutorialForm() if post_id: # /database/resource/1234 post = models.Resource.get_by_id(int(post_id)) if post: author_id = post.author.key().name() second_author_id = post.second_author and post.second_author.key().name() # Adjust browser support so it renders to the checkboxes correctly. browser_support = [b.capitalize() for b in post.browser_support] for b in browser_support: if len(b) == 2: browser_support[browser_support.index(b)] = b.upper() form_data = post.to_dict() form_data["tags"] = ", ".join(post.tags) form_data["author"] = author_id form_data["second_author"] = second_author_id or author_id form_data["browser_support"] = browser_support tutorial_form = models.TutorialForm(form_data) template_data = { "tutorial_form": tutorial_form, # get_all() not used b/c we don't care about caching on this page. "resources": (models.Resource.all().order("-publication_date").fetch(limit=settings.MAX_FETCH_LIMIT)), "post_id": post_id and int(post_id) or "", } return self.render(data=template_data, template_path="database/resource_new.html", relpath=relpath) # Catch all to redirect to proper page. return self.redirect("/database/resource")
def get(self, relpath): self._set_cache_param() # Handle bug redirects before anything else, as it's trivial. if relpath == "new-bug": return self.redirect("https://github.com/html5rocks/www.html5rocks.com/issues/new") # Handle humans before locale, to prevent redirect to /en/ # (but still ensure it's dynamic, ie we can't just redirect to a static url) if relpath == "humans.txt": self.response.headers["Content-Type"] = "text/plain" sorted_profiles = models.get_sorted_profiles() return self.render( data={"sorted_profiles": sorted_profiles, "profile_amount": len(sorted_profiles)}, template_path="content/humans.txt", relpath=relpath, ) # Get the locale: if it's "None", redirect to English locale = self.get_language() if not locale: return self.redirect("/en/%s" % relpath, permanent=True) # If there is a locale specified but it has no leading slash, redirect if not relpath.startswith("%s/" % locale): return self.redirect("/%s/" % locale, permanent=True) # If we get here, is because the language is specified correctly, # so let's activate it self.activate_language(locale) # Strip off leading `/[en|de|fr|...]/` relpath = re.sub("^/?\w{2,3}(?:/)?", "", relpath) # Are we looking for a feed? is_feed = self.request.path.endswith(".xml") logging.info("relpath: " + relpath) # Setup handling of redirected article URLs: If a user tries to access an # article from a non-supported language, we'll redirect them to the # English version (assuming it exists), with a `redirect_from_locale` GET # param. redirect_from_locale = self.request.get("redirect_from_locale", "") if not re.match("[a-zA-Z]{2,3}$", redirect_from_locale): redirect_from_locale = False else: translation.activate(redirect_from_locale) redirect_from_locale = { "lang": redirect_from_locale, "msg": _( "Sorry, this article isn't available in your native " "language; we've redirected you to the English version." ), } translation.activate(locale) # Landing page or /tutorials|features|mobile|gaming|business\/? if (relpath == "" or relpath[-1] == "/") or ( # Landing page. relpath[-1] != "/" and relpath in ["mobile", "tutorials", "features", "gaming", "business"] ): path = os.path.join("content", relpath, "index.html") else: path = os.path.join("content", relpath) # Render the .html page if it exists. Otherwise, check that the Atom feed # the user is requesting has a corresponding .html page that exists. if relpath == "profiles" or relpath == "profiles/": profiles = models.get_sorted_profiles() for p in profiles: p["tuts_by_author"] = models.Resource.get_tutorials_by_author(p["id"]) return self.render( data={"sorted_profiles": profiles}, template_path="content/profiles.html", relpath=relpath ) elif ( re.search("tutorials/.+", relpath) or re.search("mobile/.+", relpath) or re.search("gaming/.+", relpath) or re.search("business/.+", relpath) or re.search("tutorials/casestudies/.+", relpath) ) and not is_feed: # If this is an old-style mobile article or case study, redirect to the # new style. match = re.search(("(?P<type>mobile|tutorials/casestudies)" "/(?P<slug>[a-z-_0-9]+).html$"), relpath) if match: logging.info("Redirecting from old-style URL to the new hotness.") return self.redirect("/%s/%s/%s/" % (locale, match.group("type"), match.group("slug"))) # If no trailing / (e.g. /tutorials/blah), redirect to /tutorials/blah/. if relpath[-1] != "/" and not relpath.endswith(".html"): return self.redirect(self.request.url + "/") # Tutorials look like this on the filesystem: # # .../tutorials + # | # +-- article-slug + # | | # | +-- en + # | | | # | | +-- index.html # ... # # So, to determine if an HTML page exists for the requested language # `split` the file's path, add in the locale, and check existence: logging.info("Building request for `%s` in locale `%s`", path, locale) (dir, filename) = os.path.split(path) if os.path.isfile(os.path.join(dir, locale, filename)): # Lookup tutorial by its url. Return the first one that matches. # get_all() not used because we don't care about caching on individual # tut page. tut = models.Resource.all().filter("url =", "/" + relpath).get() # If tutorial is marked as draft, redirect and don't show it. if tut and tut.draft: return self.redirect("/tutorials") # Localize title and description. if tut: if tut.title: tut.title = _(tut.title) if hasattr(tut, "subtitle") and tut.subtitle: tut.subtitle = _(tut.subtitle) if tut.description: tut.description = _(tut.description) # Gather list of localizations by globbing matching directories, then # stripping out the current locale and 'static'. Once we have a list, # convert it to a series of dictionaries containing the localization's # path and name: langs = { "de": "Deutsch", "en": "English", "fr": "Français", "es": "Español", "it": "Italiano", "ja": "日本語", "ko": "한국의", "pt": "Português (Brasil)", "ru": "Pусский", "zh": "中文 (简体)", } loc_list = [] for d in glob.glob(os.path.join(dir, "*", "index.html")): loc = os.path.basename(os.path.dirname(d)) if loc not in [locale, "static"]: loc_list.append({"path": "/%s/%s" % (loc, relpath), "lang": langs[loc]}) data = {"tut": tut, "localizations": loc_list, "redirect_from_locale": redirect_from_locale} return self.render(template_path=os.path.join(dir, locale, filename), data=data, relpath=relpath) # If the localized file doesn't exist, and the locale isn't English, look # for an english version of the file, and redirect the user there if # it's found: elif os.path.isfile(os.path.join(dir, "en", filename)): return self.redirect("/en/%s?redirect_from_locale=%s" % (relpath, locale)) elif os.path.isfile(path): # TODO(ericbidelman): Don't need these tutorial/update results for query. if relpath in ["mobile", "gaming", "business"]: results = TagsHandler().get_as_db(relpath, limit=self.FEATURE_PAGE_WHATS_NEW_LIMIT) else: if relpath == "": resource_limit = 10 else: resource_limit = None results = models.Resource.get_all(order="-publication_date", limit=resource_limit) tutorials = [] # List of final result set. authors = [] # List of authors related to the result set. for r in results: resource_type = [x for x in r.tags if x.startswith("type:")] if len(resource_type): resource_type = resource_type[0].replace("type:", "") if r.url.startswith("/"): # Localize title and description if article is localized. filepath = os.path.join(self.BASEDIR, "content", r.url[1:], self.locale, "index.html") if os.path.isfile(filepath): if r.title: r.title = _(r.title) if hasattr(r, "subtitle") and r.subtitle: r.subtitle = _(r.subtitle) if r.description: r.description = _(r.description) # Point the article to the localized version, regardless. r.url = "/%s%s" % (self.locale, r.url) tutorials.append(r) tutorials[-1].classes = [x.replace("class:", "") for x in r.tags if x.startswith("class:")] tutorials[-1].tags = [x for x in r.tags if not (x.startswith("class:") or x.startswith("type:"))] tutorials[-1].type = resource_type # TODO(ericbidelman): Probably don't need author for every result query. authors.append(r.author) # Remove duplicate authors from the list. author_dict = {} for a in authors: author_dict[a.key().name()] = a authors = author_dict.values() return self.render(data={"tutorials": tutorials, "authors": authors}, template_path=path, relpath=relpath) elif os.path.isfile(path[: path.rfind(".")] + ".html"): return self.render(data={}, template_path=path[: path.rfind(".")] + ".html", relpath=relpath) elif os.path.isfile(path + ".html"): category = relpath.replace("features/", "") updates = TagsHandler().get_as_db("class:" + category, limit=self.FEATURE_PAGE_WHATS_NEW_LIMIT) for r in updates: if r.url.startswith("/"): # Localize title if article is localized. filepath = os.path.join(self.BASEDIR, "content", r.url[1:], self.locale, "index.html") if r.url.startswith("/") and os.path.isfile(filepath) and r.title: r.title = _(r.title) # Point the article to the localized version, regardless. r.url = "/%s%s" % (self.locale, r.url) data = {"category": category, "updates": updates} if relpath == "why": if os.path.isfile(os.path.join(path, locale, "index.html")): data["local_content_path"] = os.path.join(relpath, locale, "index.html") else: data["local_content_path"] = os.path.join(relpath, "en", "index.html") return self.render(data=data, template_path=path + ".html", relpath=relpath) # If we've reached here, assume 404. return self.render(status=404, message="Page Not Found", template_path="404.html")