Skip to content

Commit

Permalink
Merged and deconflicted with gae-init-babel of 2013-12-15
Browse files Browse the repository at this point in the history
  • Loading branch information
mdxs committed Dec 16, 2013
2 parents f2f38d9 + 55fd078 commit 8fb65d3
Show file tree
Hide file tree
Showing 66 changed files with 804 additions and 526 deletions.
25 changes: 24 additions & 1 deletion CHANGESET.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,30 @@
Version 0.9.0 - 2013-10-20
Version 0.9.0 - tbd
--------------------------
- Updated Bootstrap to 3.0.3
- Updated Font Awesome to 4.0.3
- Updated Moment.js to 2.4.0
- Updated Flask Login to 0.2.7
- Introduced `auth_ids` in the `User` model instead of separete auth ids per provider
- To upgrade the existing user data deploy the `gae-init-migrate` to your GAE app and run the upgrade task
- Administrators can now delete users
- Administrators can now edit user profiles and change username
- Added function to check for uniqueness of a username
- Showing in the profile and user list the connected accounts
- Using protocol independent absolute paths
- Added support for the size (s) argument in the Gravatar API
- Removed GitHub oauth (it can be found in gae-init-auth)
- Updated sign-in buttons to the latest version
- Fixed avatar for HDPI screens in `user_list.html`
- Added filters for WTForms: `util.strip_filter` & `util.email_filter`
- Form macros are now accepting keyword arguments for stuff like `autofocus`, `placeholder`, etc
- Autofocus flag is now set to the first input in forms
- Added link to GAE instances in admin config
- Changed the soon to be depricated wtf.TextField for wtf.StringField
- Added `show_notifications()` and `clear_notifications()` as JS functions
- Using `flask.ext` notation when importing instead of `flaskext`
- Moved all the Flask extensions to root lib directory and removed the `lib/flaskext` directory completely
- Organized imports by standard, libs and local
- Bunch fixes and optimizations

Version 0.8.4 - 2013-10-19
--------------------------
Expand Down
12 changes: 8 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ To test it visit `http://localhost:8080/` in your browser.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

To watch for changes of your `*.less` & `*.coffee` files and compile them
automatically to `*.css` & `*.js` run in another bash:
automatically to `*.css` & `*.js` execute in another bash:

$ ./run.py -w

Expand All @@ -33,7 +33,12 @@ For a complete list of commands:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

[Grunt][] is used only for watching for changes and live reloading the page:
Grunt is used only for watching for changes and live reloading the page.
Install [grunt command line interface][grunt-cli] as a global package:

$ npm install -g grunt-cli

and then from the root execute with no arguments:

$ grunt

Expand Down Expand Up @@ -91,9 +96,8 @@ Author
[gae-init]: http://gae-init.appspot.com
[google app engine sdk for python]: https://developers.google.com/appengine/downloads
[google app engine]: https://developers.google.com/appengine/
[grunt]: http://gruntjs.com/
[grunt-cli]: https://github.com/gruntjs/grunt-cli
[jinja2]: http://jinja.pocoo.org/docs/
[joernhees]: https://github.com/joernhees
[jquery]: http://jquery.com/
[lesscss]: http://lesscss.org/
[lipis]: http://stackoverflow.com/users/8418/lipis
Expand Down
29 changes: 15 additions & 14 deletions main/admin.py
Original file line number Diff line number Diff line change
@@ -1,31 +1,32 @@
# -*- coding: utf-8 -*-

from google.appengine.api import app_identity
import flask
from flask.ext import wtf
from flask.ext.babel import lazy_gettext as _
from flask.ext.babel import gettext as __
from flask.ext.babel import lazy_gettext as _
from google.appengine.api import app_identity
import flask

import auth
import util
import model
import config
import i18n
import model
import util

from main import app


class ConfigUpdateForm(wtf.Form):
analytics_id = wtf.TextField('Analytics ID', filters=[util.strip_filter])
class ConfigUpdateForm(i18n.Form):
analytics_id = wtf.StringField('Analytics ID', filters=[util.strip_filter])
announcement_html = wtf.TextAreaField('Announcement HTML', filters=[util.strip_filter])
announcement_type = wtf.SelectField('Announcement Type', choices=[(t, t.title()) for t in model.Config.announcement_type._choices])
brand_name = wtf.TextField('Brand Name', [wtf.validators.required()], filters=[util.strip_filter])
facebook_app_id = wtf.TextField('Facebook App ID', filters=[util.strip_filter])
facebook_app_secret = wtf.TextField('Facebook App Secret', filters=[util.strip_filter])
feedback_email = wtf.TextField('Feedback Email', [wtf.validators.optional(), wtf.validators.email()], filters=[util.email_filter])
flask_secret_key = wtf.TextField('Flask Secret Key', [wtf.validators.required()], filters=[util.strip_filter])
brand_name = wtf.StringField('Brand Name', [wtf.validators.required()], filters=[util.strip_filter])
facebook_app_id = wtf.StringField('Facebook App ID', filters=[util.strip_filter])
facebook_app_secret = wtf.StringField('Facebook App Secret', filters=[util.strip_filter])
feedback_email = wtf.StringField('Feedback Email', [wtf.validators.optional(), wtf.validators.email()], filters=[util.email_filter])
flask_secret_key = wtf.StringField('Flask Secret Key', [wtf.validators.required()], filters=[util.strip_filter])
locale = wtf.SelectField('Default Locale', choices=config.LOCALE_SORTED)
twitter_consumer_key = wtf.TextField('Twitter Consumer Key', filters=[util.strip_filter])
twitter_consumer_secret = wtf.TextField('Twitter Consumer Secret', filters=[util.strip_filter])
twitter_consumer_key = wtf.StringField('Twitter Consumer Key', filters=[util.strip_filter])
twitter_consumer_secret = wtf.StringField('Twitter Consumer Secret', filters=[util.strip_filter])


@app.route('/_s/admin/config/', endpoint='admin_config_update_service')
Expand Down
1 change: 1 addition & 0 deletions main/appengine_config.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import sys

sys.path.insert(0, 'lib.zip')
sys.path.insert(0, 'libx')
47 changes: 23 additions & 24 deletions main/auth.py
Original file line number Diff line number Diff line change
@@ -1,29 +1,28 @@
# -*- coding: utf-8 -*-

from google.appengine.ext import ndb
from google.appengine.api import users

import functools
import re

import flask
from babel import localedata
from flask.ext import login
from flask.ext import oauth
from flask.ext.babel import lazy_gettext as _
from flask.ext.babel import gettext as __
from babel import localedata
from flask.ext.babel import lazy_gettext as _
from google.appengine.api import users
from google.appengine.ext import ndb
import flask

import util
import model
import config
import model
import util

from main import app
from main import babel


################################################################################
###############################################################################
# Babel stuff - i18n
################################################################################
###############################################################################
@babel.localeselector
def get_locale():
locale = flask.request.cookies.get('locale', config.LOCALE_DEFAULT)
Expand All @@ -47,9 +46,9 @@ def set_locale(locale):
return response


################################################################################
###############################################################################
# Flaskext Login
################################################################################
###############################################################################
login_manager = login.LoginManager()


Expand Down Expand Up @@ -115,9 +114,9 @@ def is_logged_in():
return login.current_user.id != 0


################################################################################
###############################################################################
# Decorators
################################################################################
###############################################################################
def login_required(f):
@functools.wraps(f)
def decorated_function(*args, **kws):
Expand All @@ -142,9 +141,9 @@ def decorated_function(*args, **kws):
return decorated_function


################################################################################
###############################################################################
# Sign in stuff
################################################################################
###############################################################################
@app.route('/login/')
@app.route('/signin/')
def signin():
Expand Down Expand Up @@ -174,9 +173,9 @@ def signout():
return flask.redirect(flask.url_for('welcome'))


################################################################################
###############################################################################
# Google
################################################################################
###############################################################################
@app.route('/signin/google/')
def signin_google():
google_url = users.create_login_url(
Expand Down Expand Up @@ -214,9 +213,9 @@ def retrieve_user_from_google(google_user):
)


################################################################################
###############################################################################
# Twitter
################################################################################
###############################################################################
twitter_oauth = oauth.OAuth()


Expand Down Expand Up @@ -280,9 +279,9 @@ def retrieve_user_from_twitter(response):
)


################################################################################
###############################################################################
# Facebook
################################################################################
###############################################################################
facebook_oauth = oauth.OAuth()

facebook = facebook_oauth.remote_app(
Expand Down Expand Up @@ -337,9 +336,9 @@ def retrieve_user_from_facebook(response):
)


################################################################################
###############################################################################
# Helpers
################################################################################
###############################################################################
def create_user_db(auth_id, name, username, email='', **params):
username = re.sub(r'_+|-+|\s+', '.', username.split('@')[0].lower().strip())
new_username = username
Expand Down
16 changes: 9 additions & 7 deletions main/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@

import os
import operator

try:
# This part is surrounded in try/except because the this config.py file is
# This part is surrounded in try/except because the config.py file is
# also used in the run.py script which is used to compile/minify the client
# side files (*.less, *.coffee, *.js) and is not aware of the GAE
import model
from datetime import datetime
import model
CONFIG_DB = model.Config.get_master_db()
SECRET_KEY = CONFIG_DB.flask_secret_key.encode('ascii')
LOCALE_DEFAULT = CONFIG_DB.locale
Expand All @@ -18,15 +19,15 @@
except:
pass

PRODUCTION = os.environ.get('SERVER_SOFTWARE', '').startswith('Google App Engine')
PRODUCTION = os.environ.get('SERVER_SOFTWARE', '').startswith('Google App Eng')
DEVELOPMENT = not PRODUCTION
DEBUG = DEVELOPMENT

DEFAULT_DB_LIMIT = 64

################################################################################
###############################################################################
# i18n Stuff
################################################################################
###############################################################################

# Languages: http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes
# Countries: http://en.wikipedia.org/wiki/ISO_3166-1
Expand All @@ -41,9 +42,9 @@

LOCALE_SORTED = sorted(LOCALE.iteritems(), key=operator.itemgetter(1))

################################################################################
###############################################################################
# Client modules, also used by the run.py script.
################################################################################
###############################################################################
STYLES = [
'src/style/style.less',
]
Expand All @@ -69,6 +70,7 @@
'src/script/common/service.coffee',
'src/script/site/app.coffee',
'src/script/site/profile.coffee',
'src/script/site/user.coffee',
'src/script/site/admin.coffee',
],
}
37 changes: 37 additions & 0 deletions main/i18n.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import os

from babel import support
from flask import _request_ctx_stack
from flask.ext import babel
from flask.ext import wtf


def _get_translations():
ctx = _request_ctx_stack.top
root = os.path.dirname(os.path.abspath(__file__))
translations_path = os.path.join(root, 'translations')
translations = support.Translations.load(
translations_path, [babel.get_locale()], domain='messages'
)
ctx.wtforms_translations = translations
return translations


class Translations(object):
def gettext(self, string):
t = _get_translations()
return string if t is None else t.ugettext(string)

def ngettext(self, singular, plural, n):
t = _get_translations()
if t is None:
return singular if n == 1 else plural
return t.ungettext(singular, plural, n)


translations = Translations()


class Form(wtf.Form):
def _get_translations(self):
return translations
Loading

0 comments on commit 8fb65d3

Please sign in to comment.