Commits

Edu  committed cde7215

Initial configuration and port

  • Participants

Comments (0)

Files changed (392)

File config/config.nginx

+server {                                                                                                                                                   
+    listen   80;
+    server_name yearcam.com;
+    # no security problem here, since / is alway passed to upstream
+    root /home/edu/temp/yearcam;
+    # serve directly - analogous for static/staticfiles
+    location /static/ {
+        # if asset versioning is used
+        if ($query_string) {
+            expires max;
+        }
+    }
+    location /admin/media/ {
+        # this changes depending on your python version
+        root /home/edu/temp/yearcam/staticadmin;
+    }
+#    location /static/ {
+#        # this changes depending on your python version
+#        root /home/edu/temp/yearcam/static;
+#    }
+
+    location / {
+        proxy_pass_header Server;
+        proxy_set_header Host $http_host;
+        proxy_redirect off;
+        proxy_set_header X-Real-IP $remote_addr;
+        proxy_set_header X-Scheme $scheme;
+        proxy_connect_timeout 10;
+        proxy_read_timeout 10;
+        proxy_pass http://localhost:8000/;
+    }
+    # what to serve if upstream is not available or crashes
+    error_page 500 502 503 504 /media/50x.html;
+}
+

File config/pasos_instalacion_desde_cero.txt

+-----------------------------------------------------
+Pasos instalación desde cero para template-django-app
+------------------------------------------------------
+
+## Crear entorno virtual
+mkvirtualenv entorno
+
+## Dependencias de sistema ##
+    apt-get install redis-server
+        La version 1.4 de debian stable no es suficiente
+
+## Clonar el repo con el template ##
+    git clone git@bitbucket.org:eduherraiz/yearcam.git
+
+## Configurar las propiedades del server
+    cp properties.py.template properties.py
+    vim properties.py
+        configurar las rutas
+
+## Instalar los requerimientos dede el archivo del repositorio
+    pip install -r requeriments.txt
+
+## Configurar el webserver (nginx!)
+    config/config.ngix
+        retocar las rutas
+        puerto por aplicación
+        solo para testing en local
+
+## Configurar el settings.py
+    keys de api de facebook
+    keys de api de twitter
+    idioma por defecto
+    alias de cache (uno por proyecto)
+    configuración de envío de correo
+
+## Sincronización de la base de datos
+    python manage.py syncdb
+    python manage.py migrate
+    
+## Google analytics
+    introducir el código en templates/base.html
+
+
+

File frontend/__init__.py

Empty file added.

File frontend/context_processors.py

+def debug_mode(request):
+    from django.conf import settings
+    return {'DEBUG': settings.DEBUG} 

File frontend/facebook.py

+from django.contrib.auth import BACKEND_SESSION_KEY
+from django.contrib.auth.models import AnonymousUser
+from django.http import HttpResponse
+from django.shortcuts import render_to_response
+from django.template.context import RequestContext
+
+from django.views.decorators.csrf import csrf_exempt
+from django.core.cache import cache
+
+from social_auth.models import UserSocialAuth
+from social_auth.views import complete as social_complete
+from social_auth.utils import setting
+from social_auth.backends.facebook import load_signed_request, FacebookBackend
+
+def is_complete_authentication(request):
+    return request.user.is_authenticated() and FacebookBackend.__name__ in request.session.get(BACKEND_SESSION_KEY, '')
+
+def get_access_token(user):
+    key = str(user.id)
+    access_token = cache.get(key)
+
+    # If cache is empty read the database
+    if access_token is None:
+        try:
+            social_user = user.social_user if hasattr(user, 'social_user') \
+                                           else UserSocialAuth.objects.get(user=user.id, provider=FacebookBackend.name)
+        except UserSocialAuth.DoesNotExist:
+            return None
+
+        if social_user.extra_data:
+            access_token = social_user.extra_data.get('access_token')
+            expires = social_user.extra_data.get('expires')
+
+            cache.set(key, access_token, int(expires) if expires is not None else 0)
+
+    return access_token
+
+# Facebook decorator to setup environment
+def facebook_decorator(func):
+    def wrapper(request, *args, **kwargs):
+        user = request.user
+
+        # User must me logged via FB backend in order to ensure we talk about the same person
+        if not is_complete_authentication(request):
+            try:
+                user = social_complete(request, FacebookBackend.name)
+            except ValueError:
+                pass # no matter if failed
+
+        # Not recommended way for FB, but still something we need to be aware of
+        if isinstance(user, HttpResponse):
+            kwargs.update({'auth_response': user})
+        # Need to re-check the completion
+        else:
+            if is_complete_authentication(request):
+                kwargs.update({'access_token': get_access_token(request.user)})
+            else:
+                request.user = AnonymousUser()
+
+        signed_request = load_signed_request(request.REQUEST.get('signed_request', ''))
+        if signed_request:
+            kwargs.update({'signed_request': signed_request})
+
+        return func(request, *args, **kwargs)
+
+    return wrapper
+
+
+@csrf_exempt
+@facebook_decorator
+def facebook_view(request, *args, **kwargs):
+    # If there is a ready response just return it. Not recommended though.
+    auth_response =  kwargs.get('auth_response')
+    if auth_response:
+        return auth_response
+
+    return render_to_response('facebook.html', {'fb_app_id':setting('FACEBOOK_APP_ID'),
+                                                'warning': request.method == 'GET'}, RequestContext(request)) 

File frontend/forms.py

+ #-*- coding: UTF-8 -*-
+from django.forms import ModelForm, Textarea, Form, CharField, EmailField
+from django.utils.translation import ugettext_lazy as _
+from frontend.models import CustomUser
+
+class ContactForm(Form):
+    subject = CharField(label=_("Message subject"),max_length=200,required=True)
+    message = CharField(label=_("Your message"),widget=Textarea(),required=True )
+    sender = EmailField(label=_("Email address"), required=True)
+    name = CharField(label=_("Your name or company"),max_length=200,required=True)
+    #cc_myself = forms.BooleanField(required=False) 
+
+class ConfigForm(ModelForm):
+    class Meta:
+        model = CustomUser
+        fields = ('email',)
+        #widgets = {
+            #'text': Textarea(attrs={'cols': 40, 'rows': 5}),
+        #}       
+ 

File frontend/locale/ca/LC_MESSAGES/django.mo

Binary file added.

File frontend/locale/ca/LC_MESSAGES/django.po

+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-10-20 01:40+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1)\n"
+
+#: frontend/forms.py:7
+msgid "Message subject"
+msgstr "Assumpte del missatge"
+
+#: frontend/forms.py:8
+msgid "Your message"
+msgstr "El teu missatge"
+
+#: frontend/forms.py:9
+msgid "Email address"
+msgstr "Direcció de correu electrónic"
+
+#: frontend/forms.py:10
+msgid "Your name or company"
+msgstr "El teu nom o de la teva empressa"
+
+#: frontend/templates/403.html:31
+msgid "Permision denied"
+msgstr "Sense permís"
+
+#: frontend/templates/403.html:32
+msgid "Sorry, you don't have permision to access this page."
+msgstr "No teniu permís per veure aquesta pàgina"
+
+#: frontend/templates/404.html:31
+msgid "Page not found"
+msgstr "La pàgina no existeix"
+
+#: frontend/templates/500.html:31
+msgid "Application error!"
+msgstr "Error a la aplicació"
+
+#: frontend/templates/500.html:32
+msgid ""
+"We have a problem in the application. Please, contact with info@foowill.com "
+"and try to help us writting whats happened. Thank you!"
+msgstr "Tenim problemes a la aplicació. Per favor, contacta amb email@email.es"
+" i prova d'ajudarnos escriguent damunt el que ha passat. Gràcies!"
+
+#: frontend/templates/base.html:9
+msgid "Description"
+msgstr "Descripció"
+
+#: frontend/templates/base.html:51
+msgid "Home"
+msgstr "Inici"
+
+#: frontend/templates/base.html:52
+msgid "Contact"
+msgstr "Contacte"
+
+#: frontend/templates/base.html:59
+msgid "Language"
+msgstr "Llengua"
+
+#: frontend/templates/base.html:83
+msgid "Logout"
+msgstr "Sortir"
+
+#: frontend/templates/base.html:90
+msgid "Login"
+msgstr "Conectar"
+
+#: frontend/templates/base.html:92
+msgid "Login with twitter"
+msgstr "Conectar amb twitter"
+
+#: frontend/templates/base.html:93
+msgid "Login with facebook"
+msgstr "Conectar amb facebook"
+
+#: frontend/templates/config.html:10
+msgid "Settings"
+msgstr "Configuració"
+
+#: frontend/templates/config.html:16
+msgid "Settings saved"
+msgstr "Configuració desada"
+
+#: frontend/templates/config.html:22
+msgid "You need to configure the application"
+msgstr "Necesites configurar la aplicació"
+
+#: frontend/templates/config.html:31
+msgid "Email"
+msgstr "Adreça de correu electrónic"
+
+#: frontend/templates/config.html:35
+msgid "We need your email."
+msgstr "Necesitam la teva adreça de correu electrónic"
+
+#: frontend/templates/config.html:42
+msgid "Save changes"
+msgstr "Desar els canvis"
+
+#: frontend/templates/contact.html:31
+msgid ""
+"Message sent, we'll try to reply as soon as possible to the your email "
+"address:"
+msgstr "Missatge enviat, mirarem de contestarli el mes aviat possible"
+" a la seva adreça: "
+
+#: frontend/templates/contact.html:37
+msgid "Message unsent. Form errors, correct the fields and try again."
+msgstr "Missatge NO enviat. El formulari te errors, per favor, torni a provar."
+
+#: frontend/templates/contact.html:101
+msgid "Send Message"
+msgstr "Enviar missatge"
+
+#: frontend/templates/footer.html:5
+msgid "About"
+msgstr "Referit"
+
+#: frontend/templates/home.html:35
+msgid "Text for share on twitter"
+msgstr "Texte per compartir a twitter"
+
+#: frontend/templates/home.html:41 frontend/templates/home.html.py:48
+#: frontend/templates/home.html:58
+msgid "Share on"
+msgstr "Comparteix"
+
+#: frontend/templatetags/extras.py:70
+#, python-format
+msgid "a year"
+msgid_plural "%(years)d years"
+msgstr[0] "un any"
+msgstr[1] "%(years)d anys"
+
+#: frontend/templatetags/extras.py:73
+#, python-format
+msgid "a month"
+msgid_plural "%(months)d months"
+msgstr[0] "un mes"
+msgstr[1] "%(months)d messos"
+
+#: frontend/templatetags/extras.py:76
+#, python-format
+msgid "a week"
+msgid_plural "%(weeks)d weeks"
+msgstr[0] "una setmana"
+msgstr[1] "%(weeks)d setmanes"
+
+#: frontend/templatetags/extras.py:79
+#, python-format
+msgid "a day"
+msgid_plural "%(days)d days"
+msgstr[0] "un dia"
+msgstr[1] "%(days)d dies"
+
+#: frontend/templatetags/extras.py:82
+#, python-format
+msgid "a hour"
+msgid_plural "%(hours)d hours"
+msgstr[0] "una hora"
+msgstr[1] "%(hours)d hores"
+
+#: frontend/templatetags/extras.py:85
+#, python-format
+msgid "a minute"
+msgid_plural "%(minutes)d minutes"
+msgstr[0] "un minut"
+msgstr[1] "%(minutes)d minuts"
+
+#: frontend/templatetags/extras.py:87
+msgid "moments"
+msgstr "fa un moment"

File frontend/locale/es/LC_MESSAGES/django.mo

Binary file added.

File frontend/locale/es/LC_MESSAGES/django.po

+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2012-10-20 01:40+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1)\n"
+
+#: frontend/forms.py:7
+msgid "Message subject"
+msgstr "Asunto del mensaje"
+
+#: frontend/forms.py:8
+msgid "Your message"
+msgstr "Tu mensaje"
+
+#: frontend/forms.py:9
+msgid "Email address"
+msgstr "Dirección de correo electrónico"
+
+#: frontend/forms.py:10
+msgid "Your name or company"
+msgstr "Tu nombre o de tu empresa"
+
+#: frontend/templates/403.html:31
+msgid "Permision denied"
+msgstr "Permiso denegado"
+
+#: frontend/templates/403.html:32
+msgid "Sorry, you don't have permision to access this page."
+msgstr "Lo siento, pero no tienes permiso para ver esta página"
+
+#: frontend/templates/404.html:31
+msgid "Page not found"
+msgstr "La página no existe"
+
+#: frontend/templates/500.html:31
+msgid "Application error!"
+msgstr "Error en la aplicación"
+
+#: frontend/templates/500.html:32
+msgid ""
+"We have a problem in the application. Please, contact with info@foowill.com "
+"and try to help us writting whats happened. Thank you!"
+msgstr "Tenemos un problema en la aplicación. Por favor, contacta con email@email.es"
+" y trata de ayudarnos escribiendo que ha ocurrido. Gracias!"
+
+#: frontend/templates/base.html:9
+msgid "Description"
+msgstr "Descripción"
+
+#: frontend/templates/base.html:51
+msgid "Home"
+msgstr "Inicio"
+
+#: frontend/templates/base.html:52
+msgid "Contact"
+msgstr "Contacto"
+
+#: frontend/templates/base.html:59
+msgid "Language"
+msgstr "Idioma"
+
+#: frontend/templates/base.html:83
+msgid "Logout"
+msgstr "Salir"
+
+#: frontend/templates/base.html:90
+msgid "Login"
+msgstr "Conectar"
+
+#: frontend/templates/base.html:92
+msgid "Login with twitter"
+msgstr "Conectar mediante twitter"
+
+#: frontend/templates/base.html:93
+msgid "Login with facebook"
+msgstr "Conectar mediante facebook"
+
+#: frontend/templates/config.html:10
+msgid "Settings"
+msgstr "Configuración"
+
+#: frontend/templates/config.html:16
+msgid "Settings saved"
+msgstr "Configuración guardada"
+
+#: frontend/templates/config.html:22
+msgid "You need to configure the application"
+msgstr "Necesitas configurar la aplicación"
+
+#: frontend/templates/config.html:31
+msgid "Email"
+msgstr "Dirección de correo electrónico"
+
+#: frontend/templates/config.html:35
+msgid "We need your email."
+msgstr "Necesitamos tu dirección de correo electrónico"
+
+#: frontend/templates/config.html:42
+msgid "Save changes"
+msgstr "Guardar cambios"
+
+#: frontend/templates/contact.html:31
+msgid ""
+"Message sent, we'll try to reply as soon as possible to the your email "
+"address:"
+msgstr "Mensaje enviado, trataremos de contestarle tan pronto como nos"
+" sea posible a su dirección: "
+
+#: frontend/templates/contact.html:37
+msgid "Message unsent. Form errors, correct the fields and try again."
+msgstr "Mensaje NO enviado. Formulario con errores, por favor, corríjalos y pruebe otra vez"
+
+#: frontend/templates/contact.html:101
+msgid "Send Message"
+msgstr "Enviar mensaje"
+
+#: frontend/templates/footer.html:5
+msgid "About"
+msgstr "Sobre"
+
+#: frontend/templates/home.html:35
+msgid "Text for share on twitter"
+msgstr "Texto para compartir en twitter"
+
+#: frontend/templates/home.html:41 frontend/templates/home.html.py:48
+#: frontend/templates/home.html:58
+msgid "Share on"
+msgstr "Comparte"
+
+#: frontend/templatetags/extras.py:70
+#, python-format
+msgid "a year"
+msgid_plural "%(years)d years"
+msgstr[0] "un año"
+msgstr[1] "%(years)d años"
+
+#: frontend/templatetags/extras.py:73
+#, python-format
+msgid "a month"
+msgid_plural "%(months)d months"
+msgstr[0] "un mes"
+msgstr[1] "%(months)d meses"
+
+#: frontend/templatetags/extras.py:76
+#, python-format
+msgid "a week"
+msgid_plural "%(weeks)d weeks"
+msgstr[0] "una semana"
+msgstr[1] "%(weeks)d semanas"
+
+#: frontend/templatetags/extras.py:79
+#, python-format
+msgid "a day"
+msgid_plural "%(days)d days"
+msgstr[0] "un día"
+msgstr[1] "%(days)d días"
+
+#: frontend/templatetags/extras.py:82
+#, python-format
+msgid "a hour"
+msgid_plural "%(hours)d hours"
+msgstr[0] "una hora"
+msgstr[1] "%(hours)d horas"
+
+#: frontend/templatetags/extras.py:85
+#, python-format
+msgid "a minute"
+msgid_plural "%(minutes)d minutes"
+msgstr[0] "un minuto"
+msgstr[1] "%(minutes)d minutos"
+
+#: frontend/templatetags/extras.py:87
+msgid "moments"
+msgstr "hace un momento"

File frontend/models.py

+# -*- coding: utf-8 -*-
+from django.db import models
+from django.conf import settings
+from social_auth.models import UserSocialAuth
+from datetime import datetime,timedelta
+from django_fields.tests import EncryptedCharField
+from django.core.mail import EmailMultiAlternatives
+from django.utils.translation import ugettext as _
+from django.shortcuts import render
+from frontend.utils import send_email_mandrill, connect_tweepy
+from django.template.loader import render_to_string
+import twitter
+import tweepy
+
+#from django.db.models.signals import post_save
+#from django.dispatch import receiver
+
+# Define a custom User class to work with django-social-auth
+class CustomUserManager(models.Manager):
+    def create_user(self, username, email):
+        return self.model._default_manager.create(username=username)
+
+
+class CustomUser(models.Model):
+    user = models.OneToOneField(UserSocialAuth)
+    configured = models.BooleanField(default=False)
+    username = models.CharField(max_length=128)
+    photo = models.URLField(blank=True, null=True)
+    language = models.CharField(max_length=128, default='en', blank=True)
+    #timezone = models.CharField(max_length=128, default='Europe/Madrid', blank=True)
+    #countrycode = models.CharField(max_length=4, default='ES', blank=True)
+
+    last_login = models.DateTimeField(blank=True, null=True)
+    
+    email = models.EmailField(blank=True)
+     
+    objects = CustomUserManager()  
+        
+    def update_login_date(self):
+        ##Checkin login in last day to update last_login, used in tasks
+        if not self.last_login:
+            self.last_login = datetime.utcnow()
+            self.save()
+        #elif self.last_login < (datetime.utcnow() - timedelta(seconds=settings.TIME_LOGIN)):
+            #self.last_login = datetime.utcnow()
+            #self.save()
+            
+    def update_twitter_status(self, text):
+        if text:
+            api = connect_tweepy(self.user)
+            api.update_status(text)
+
+    #def update_twitter_photo(self):
+        #api = connect_tweepy(self.user)
+        #user = api.get_user(self.username)
+        #self.photo = user.profile_image_url
+        #self.save()
+            
+       
+    def send_email(self, subject,  html_content):
+        send_email_mandrill(subject, html_content,settings.EMAIL_PROJECT ,settings.NAME_PROJECT,self.email, self.username)
+           
+    def admin_thumbnail(self):
+        return u'<img src="%s" />' % (self.photo)
+
+    admin_thumbnail.short_description = 'Thumbnail'
+    admin_thumbnail.allow_tags = True
+       
+    def is_authenticated(self):
+        return True
+    
+    def __unicode__(self):
+        return self.username
+
+#from social_auth.signals import pre_update
+#from social_auth.backends.facebook import FacebookBackend
+#from social_auth.backends import google
+#from social_auth.backends.twitter import TwitterBackend
+
+#def social_extra_values(sender, user, response, details, **kwargs):
+    #result = False
+    
+    #if "id" in response:
+        ##from apps.photo.models import Photo
+        #from urllib2 import urlopen, HTTPError
+        #from django.template.defaultfilters import slugify
+        ##from apps.account.utils import user_display
+        #from django.core.files.base import ContentFile
+
+        #try:
+            #url = None
+            #if sender == FacebookBackend:
+                #url = "http://graph.facebook.com/%s/picture?type=large" % response["id"]
+                #provider = "facebook"
+            #elif sender == TwitterBackend:
+                #url = response["profile_image_url"]
+                #provider = "twitter"
+            ##if url:
+                ##avatar = urlopen(url)
+                
+            #instance = UserSocialAuth.objects.filter(provider=provider,user=user).get()
+            #user = CustomUser.objects.filter(user=instance).get()
+
+            #user.photo = url
+            #user.save()
+            ##photo = Photo(author = user, is_avatar = True)
+            ##photo.picture.save(slugify(user.username + " social") + '.jpg', 
+            ##ContentFile(avatar.read()))
+
+            ##photo.save()
+
+        #except HTTPError:
+            #pass
+
+        #result = True
+    #return result
+
+#pre_update.connect(social_extra_values, sender=None)

File frontend/pipeline.py

+from django.http import HttpResponseRedirect
+from social_auth.models import UserSocialAuth
+from frontend.models import CustomUser
+from social_auth.backends.facebook import FacebookBackend
+from social_auth.backends.twitter import TwitterBackend
+
+def create_profile(backend, request, user, response, details, is_new=False, *args, **kwargs): 
+
+    #backend = request.session.get('social_auth_last_login_backend')
+    
+    instance = UserSocialAuth.objects.filter(user=user.id).get()
+    
+    if is_new: 
+        profile = CustomUser.objects.create(user=instance, username=user.username)
+    else:
+        profile = CustomUser.objects.filter(user=instance).get()
+         
+    if backend.__class__ == FacebookBackend:
+        profile.photo = "http://graph.facebook.com/%s/picture?type=large" % response['id']
+    elif backend.__class__ == TwitterBackend:
+        profile.photo = response.get('profile_image_url', '').replace('_normal', '')
+        
+    profile.save()
+
+        
+
+#def get_user_avatar(backend, details, response, social_user, uid, user, *args, **kwargs):
+    
+    #instance = UserSocialAuth.objects.filter(provider=request.session.get('social_auth_last_login_backend'),user=request.user).get()
+    #user = CustomUser.objects.filter(user=instance).get()
+    
+    #url = None
+
+        #url = "http://graph.facebook.com/%s/picture?type=large" % response['id']
+ 
+    #elif backend.__class__ == TwitterBackend:
+        #url = response.get('profile_image_url', '').replace('_normal', '')
+ 
+    #if url:
+        #user.photo = url
+        #user.save()
+        #profile = user.get_profile()
+        #avatar = urlopen(url).read()
+        #fout = open(filepath, "wb") #filepath is where to save the image
+        #fout.write(avatar)
+        #fout.close()
+        #profile.photo = url_to_image # depends on where you saved it
+        #profile.save()

File frontend/static/GeoIP.dat

Binary file added.

File frontend/static/css/base.css

+#id_text{
+    width: 300px; 
+    overflow-x: hidden; 
+    overflow-y: hidden; 
+    height: 56px; 
+    padding-bottom: 5px;
+}
+
+.form-lang{
+    margin:0;
+}
+
+
+#slider_ai .ui-slider-handle, #slider_mi .ui-slider-handle, #slider_pi .ui-slider-handle { border-color: #081A33; background: #2885FF; }
+#slider_ai, #slider_mi, #slider_pi { background: #FFF1E2; }
+
+.control-label{ font-weight:bold;}
+
+.slider{
+    width:400px; 
+    margin-top:10px; 
+    margin-bottom:10px; 
+    margin-right:20px; 
+    float:left;
+}
+
+/*! TwitterFrieds v0.1 | Autor: Jhean Ceballos: @shogoki_vnz 
+is released under the MIT License <http://www.opensource.org/licenses/mit-license.php*/
+#twitterUsers{
+        position: absolute;
+        overflow: hidden;
+        display: none;
+        border: solid 2px #FFE8E9;
+        background-color: white;
+        color: #004363;
+        height:400px;
+        margin-top:400px;
+}
+
+.info{
+        height: 24px;
+        margin: 0 0 5px 0;
+        cursor: pointer;
+}
+
+.selected{
+        color: black;
+        background-color: #FFE8E9;
+}
+
+.info:hover{
+        color: black;
+        background-color: #F3EEFF;
+}
+
+.info img{
+        float: left;
+        margin: 0px 3px 0 0 !important;
+}
+
+.info p{
+        margin: 0;
+        padding-top: 5px;
+        text-align: left;
+}

File frontend/static/css/bootstrap-responsive.css

+/*!
+ * Bootstrap Responsive v2.0.4
+ *
+ * Copyright 2012 Twitter, Inc
+ * Licensed under the Apache License v2.0
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Designed and built with all the love in the world @twitter by @mdo and @fat.
+ */
+.clearfix {
+  *zoom: 1;
+}
+.clearfix:before,
+.clearfix:after {
+  display: table;
+  content: "";
+}
+.clearfix:after {
+  clear: both;
+}
+.hide-text {
+  font: 0/0 a;
+  color: transparent;
+  text-shadow: none;
+  background-color: transparent;
+  border: 0;
+}
+.input-block-level {
+  display: block;
+  width: 100%;
+  min-height: 28px;
+  -webkit-box-sizing: border-box;
+  -moz-box-sizing: border-box;
+  -ms-box-sizing: border-box;
+  box-sizing: border-box;
+}
+.hidden {
+  display: none;
+  visibility: hidden;
+}
+.visible-phone {
+  display: none !important;
+}
+.visible-tablet {
+  display: none !important;
+}
+.hidden-desktop {
+  display: none !important;
+}
+@media (max-width: 767px) {
+  .visible-phone {
+    display: inherit !important;
+  }
+  .hidden-phone {
+    display: none !important;
+  }
+  .hidden-desktop {
+    display: inherit !important;
+  }
+  .visible-desktop {
+    display: none !important;
+  }
+}
+@media (min-width: 768px) and (max-width: 979px) {
+  .visible-tablet {
+    display: inherit !important;
+  }
+  .hidden-tablet {
+    display: none !important;
+  }
+  .hidden-desktop {
+    display: inherit !important;
+  }
+  .visible-desktop {
+    display: none !important ;
+  }
+}
+@media (max-width: 480px) {
+  .nav-collapse {
+    -webkit-transform: translate3d(0, 0, 0);
+  }
+  .page-header h1 small {
+    display: block;
+    line-height: 18px;
+  }
+  input[type="checkbox"],
+  input[type="radio"] {
+    border: 1px solid #ccc;
+  }
+  .form-horizontal .control-group > label {
+    float: none;
+    width: auto;
+    padding-top: 0;
+    text-align: left;
+  }
+  .form-horizontal .controls {
+    margin-left: 0;
+  }
+  .form-horizontal .control-list {
+    padding-top: 0;
+  }
+  .form-horizontal .form-actions {
+    padding-left: 10px;
+    padding-right: 10px;
+  }
+  .modal {
+    position: absolute;
+    top: 10px;
+    left: 10px;
+    right: 10px;
+    width: auto;
+    margin: 0;
+  }
+  .modal.fade.in {
+    top: auto;
+  }
+  .modal-header .close {
+    padding: 10px;
+    margin: -10px;
+  }
+  .carousel-caption {
+    position: static;
+  }
+}
+@media (max-width: 767px) {
+  body {
+    padding-left: 20px;
+    padding-right: 20px;
+  }
+  .navbar-fixed-top,
+  .navbar-fixed-bottom {
+    margin-left: -20px;
+    margin-right: -20px;
+  }
+  .container-fluid {
+    padding: 0;
+  }
+  .dl-horizontal dt {
+    float: none;
+    clear: none;
+    width: auto;
+    text-align: left;
+  }
+  .dl-horizontal dd {
+    margin-left: 0;
+  }
+  .container {
+    width: auto;
+  }
+  .row-fluid {
+    width: 100%;
+  }
+  .row,
+  .thumbnails {
+    margin-left: 0;
+  }
+  [class*="span"],
+  .row-fluid [class*="span"] {
+    float: none;
+    display: block;
+    width: auto;
+    margin-left: 0;
+  }
+  .input-large,
+  .input-xlarge,
+  .input-xxlarge,
+  input[class*="span"],
+  select[class*="span"],
+  textarea[class*="span"],
+  .uneditable-input {
+    display: block;
+    width: 100%;
+    min-height: 28px;
+    -webkit-box-sizing: border-box;
+    -moz-box-sizing: border-box;
+    -ms-box-sizing: border-box;
+    box-sizing: border-box;
+  }
+  .input-prepend input,
+  .input-append input,
+  .input-prepend input[class*="span"],
+  .input-append input[class*="span"] {
+    display: inline-block;
+    width: auto;
+  }
+}
+@media (min-width: 768px) and (max-width: 979px) {
+  .row {
+    margin-left: -20px;
+    *zoom: 1;
+  }
+  .row:before,
+  .row:after {
+    display: table;
+    content: "";
+  }
+  .row:after {
+    clear: both;
+  }
+  [class*="span"] {
+    float: left;
+    margin-left: 20px;
+  }
+  .container,
+  .navbar-fixed-top .container,
+  .navbar-fixed-bottom .container {
+    width: 724px;
+  }
+  .span12 {
+    width: 724px;
+  }
+  .span11 {
+    width: 662px;
+  }
+  .span10 {
+    width: 600px;
+  }
+  .span9 {
+    width: 538px;
+  }
+  .span8 {
+    width: 476px;
+  }
+  .span7 {
+    width: 414px;
+  }
+  .span6 {
+    width: 352px;
+  }
+  .span5 {
+    width: 290px;
+  }
+  .span4 {
+    width: 228px;
+  }
+  .span3 {
+    width: 166px;
+  }
+  .span2 {
+    width: 104px;
+  }
+  .span1 {
+    width: 42px;
+  }
+  .offset12 {
+    margin-left: 764px;
+  }
+  .offset11 {
+    margin-left: 702px;
+  }
+  .offset10 {
+    margin-left: 640px;
+  }
+  .offset9 {
+    margin-left: 578px;
+  }
+  .offset8 {
+    margin-left: 516px;
+  }
+  .offset7 {
+    margin-left: 454px;
+  }
+  .offset6 {
+    margin-left: 392px;
+  }
+  .offset5 {
+    margin-left: 330px;
+  }
+  .offset4 {
+    margin-left: 268px;
+  }
+  .offset3 {
+    margin-left: 206px;
+  }
+  .offset2 {
+    margin-left: 144px;
+  }
+  .offset1 {
+    margin-left: 82px;
+  }
+  .row-fluid {
+    width: 100%;
+    *zoom: 1;
+  }
+  .row-fluid:before,
+  .row-fluid:after {
+    display: table;
+    content: "";
+  }
+  .row-fluid:after {
+    clear: both;
+  }
+  .row-fluid [class*="span"] {
+    display: block;
+    width: 100%;
+    min-height: 28px;
+    -webkit-box-sizing: border-box;
+    -moz-box-sizing: border-box;
+    -ms-box-sizing: border-box;
+    box-sizing: border-box;
+    float: left;
+    margin-left: 2.762430939%;
+    *margin-left: 2.709239449638298%;
+  }
+  .row-fluid [class*="span"]:first-child {
+    margin-left: 0;
+  }
+  .row-fluid .span12 {
+    width: 99.999999993%;
+    *width: 99.9468085036383%;
+  }
+  .row-fluid .span11 {
+    width: 91.436464082%;
+    *width: 91.38327259263829%;
+  }
+  .row-fluid .span10 {
+    width: 82.87292817100001%;
+    *width: 82.8197366816383%;
+  }
+  .row-fluid .span9 {
+    width: 74.30939226%;
+    *width: 74.25620077063829%;
+  }
+  .row-fluid .span8 {
+    width: 65.74585634900001%;
+    *width: 65.6926648596383%;
+  }
+  .row-fluid .span7 {
+    width: 57.182320438000005%;
+    *width: 57.129128948638304%;
+  }
+  .row-fluid .span6 {
+    width: 48.618784527%;
+    *width: 48.5655930376383%;
+  }
+  .row-fluid .span5 {
+    width: 40.055248616%;
+    *width: 40.0020571266383%;
+  }
+  .row-fluid .span4 {
+    width: 31.491712705%;
+    *width: 31.4385212156383%;
+  }
+  .row-fluid .span3 {
+    width: 22.928176794%;
+    *width: 22.874985304638297%;
+  }
+  .row-fluid .span2 {
+    width: 14.364640883%;
+    *width: 14.311449393638298%;
+  }
+  .row-fluid .span1 {
+    width: 5.801104972%;
+    *width: 5.747913482638298%;
+  }
+  input,
+  textarea,
+  .uneditable-input {
+    margin-left: 0;
+  }
+  input.span12, textarea.span12, .uneditable-input.span12 {
+    width: 714px;
+  }
+  input.span11, textarea.span11, .uneditable-input.span11 {
+    width: 652px;
+  }
+  input.span10, textarea.span10, .uneditable-input.span10 {
+    width: 590px;
+  }
+  input.span9, textarea.span9, .uneditable-input.span9 {
+    width: 528px;
+  }
+  input.span8, textarea.span8, .uneditable-input.span8 {
+    width: 466px;
+  }
+  input.span7, textarea.span7, .uneditable-input.span7 {
+    width: 404px;
+  }
+  input.span6, textarea.span6, .uneditable-input.span6 {
+    width: 342px;
+  }
+  input.span5, textarea.span5, .uneditable-input.span5 {
+    width: 280px;
+  }
+  input.span4, textarea.span4, .uneditable-input.span4 {
+    width: 218px;
+  }
+  input.span3, textarea.span3, .uneditable-input.span3 {
+    width: 156px;
+  }
+  input.span2, textarea.span2, .uneditable-input.span2 {
+    width: 94px;
+  }
+  input.span1, textarea.span1, .uneditable-input.span1 {
+    width: 32px;
+  }
+}
+@media (min-width: 1200px) {
+  .row {
+    margin-left: -30px;
+    *zoom: 1;
+  }
+  .row:before,
+  .row:after {
+    display: table;
+    content: "";
+  }
+  .row:after {
+    clear: both;
+  }
+  [class*="span"] {
+    float: left;
+    margin-left: 30px;
+  }
+  .container,
+  .navbar-fixed-top .container,
+  .navbar-fixed-bottom .container {
+    width: 1170px;
+  }
+  .span12 {
+    width: 1170px;
+  }
+  .span11 {
+    width: 1070px;
+  }
+  .span10 {
+    width: 970px;
+  }
+  .span9 {
+    width: 870px;
+  }
+  .span8 {
+    width: 770px;
+  }
+  .span7 {
+    width: 670px;
+  }
+  .span6 {
+    width: 570px;
+  }
+  .span5 {
+    width: 470px;
+  }
+  .span4 {
+    width: 370px;
+  }
+  .span3 {
+    width: 270px;
+  }
+  .span2 {
+    width: 170px;
+  }
+  .span1 {
+    width: 70px;
+  }
+  .offset12 {
+    margin-left: 1230px;
+  }
+  .offset11 {
+    margin-left: 1130px;
+  }
+  .offset10 {
+    margin-left: 1030px;
+  }
+  .offset9 {
+    margin-left: 930px;
+  }
+  .offset8 {
+    margin-left: 830px;
+  }
+  .offset7 {
+    margin-left: 730px;
+  }
+  .offset6 {
+    margin-left: 630px;
+  }
+  .offset5 {
+    margin-left: 530px;
+  }
+  .offset4 {
+    margin-left: 430px;
+  }
+  .offset3 {
+    margin-left: 330px;
+  }
+  .offset2 {
+    margin-left: 230px;
+  }
+  .offset1 {
+    margin-left: 130px;
+  }
+  .row-fluid {
+    width: 100%;
+    *zoom: 1;
+  }
+  .row-fluid:before,
+  .row-fluid:after {
+    display: table;
+    content: "";
+  }
+  .row-fluid:after {
+    clear: both;
+  }
+  .row-fluid [class*="span"] {
+    display: block;
+    width: 100%;
+    min-height: 28px;
+    -webkit-box-sizing: border-box;
+    -moz-box-sizing: border-box;
+    -ms-box-sizing: border-box;
+    box-sizing: border-box;
+    float: left;
+    margin-left: 2.564102564%;
+    *margin-left: 2.510911074638298%;
+  }
+  .row-fluid [class*="span"]:first-child {
+    margin-left: 0;
+  }
+  .row-fluid .span12 {
+    width: 100%;
+    *width: 99.94680851063829%;
+  }
+  .row-fluid .span11 {
+    width: 91.45299145300001%;
+    *width: 91.3997999636383%;
+  }
+  .row-fluid .span10 {
+    width: 82.905982906%;
+    *width: 82.8527914166383%;
+  }
+  .row-fluid .span9 {
+    width: 74.358974359%;
+    *width: 74.30578286963829%;
+  }
+  .row-fluid .span8 {
+    width: 65.81196581200001%;
+    *width: 65.7587743226383%;
+  }
+  .row-fluid .span7 {
+    width: 57.264957265%;
+    *width: 57.2117657756383%;
+  }
+  .row-fluid .span6 {
+    width: 48.717948718%;
+    *width: 48.6647572286383%;
+  }
+  .row-fluid .span5 {
+    width: 40.170940171000005%;
+    *width: 40.117748681638304%;
+  }
+  .row-fluid .span4 {
+    width: 31.623931624%;
+    *width: 31.5707401346383%;
+  }
+  .row-fluid .span3 {
+    width: 23.076923077%;
+    *width: 23.0237315876383%;
+  }
+  .row-fluid .span2 {
+    width: 14.529914530000001%;
+    *width: 14.4767230406383%;
+  }
+  .row-fluid .span1 {
+    width: 5.982905983%;
+    *width: 5.929714493638298%;
+  }
+  input,
+  textarea,
+  .uneditable-input {
+    margin-left: 0;
+  }
+  input.span12, textarea.span12, .uneditable-input.span12 {
+    width: 1160px;
+  }
+  input.span11, textarea.span11, .uneditable-input.span11 {
+    width: 1060px;
+  }
+  input.span10, textarea.span10, .uneditable-input.span10 {
+    width: 960px;
+  }
+  input.span9, textarea.span9, .uneditable-input.span9 {
+    width: 860px;
+  }
+  input.span8, textarea.span8, .uneditable-input.span8 {
+    width: 760px;
+  }
+  input.span7, textarea.span7, .uneditable-input.span7 {
+    width: 660px;
+  }
+  input.span6, textarea.span6, .uneditable-input.span6 {
+    width: 560px;
+  }
+  input.span5, textarea.span5, .uneditable-input.span5 {
+    width: 460px;
+  }
+  input.span4, textarea.span4, .uneditable-input.span4 {
+    width: 360px;
+  }
+  input.span3, textarea.span3, .uneditable-input.span3 {
+    width: 260px;
+  }
+  input.span2, textarea.span2, .uneditable-input.span2 {
+    width: 160px;
+  }
+  input.span1, textarea.span1, .uneditable-input.span1 {
+    width: 60px;
+  }
+  .thumbnails {
+    margin-left: -30px;
+  }
+  .thumbnails > li {
+    margin-left: 30px;
+  }
+  .row-fluid .thumbnails {
+    margin-left: 0;
+  }
+}
+@media (max-width: 979px) {
+  body {
+    padding-top: 0;
+  }
+  .navbar-fixed-top,
+  .navbar-fixed-bottom {
+    position: static;
+  }
+  .navbar-fixed-bottom {
+    margin-top: 18px;
+  }
+  .navbar-fixed-top .navbar-inner,
+  .navbar-fixed-bottom .navbar-inner {
+    padding: 5px;
+  }
+  .navbar .container {
+    width: auto;
+    padding: 0;
+  }
+  .navbar .brand {
+    padding-left: 10px;
+    padding-right: 10px;
+    margin: 0 0 0 -5px;
+  }
+  .nav-collapse {
+    clear: both;
+  }
+  .nav-collapse .nav {
+    float: none;
+    margin: 0 0 9px;
+  }
+  .nav-collapse .nav > li {
+    float: none;
+  }
+  .nav-collapse .nav > li > a {
+    margin-bottom: 2px;
+  }
+  .nav-collapse .nav > .divider-vertical {
+    display: none;
+  }
+  .nav-collapse .nav .nav-header {
+    color: #999999;
+    text-shadow: none;