diff --git a/.gitignore b/.gitignore index b823e313b4..246be0f34b 100644 --- a/.gitignore +++ b/.gitignore @@ -101,3 +101,4 @@ ENV/ .mypy_cache/ .vagrant +.vscode/settings.json diff --git a/.project b/.project new file mode 100644 index 0000000000..7f0df834a7 --- /dev/null +++ b/.project @@ -0,0 +1,17 @@ + + + decide + + + + + + org.python.pydev.PyDevBuilder + + + + + + org.python.pydev.pythonNature + + diff --git a/.pydevproject b/.pydevproject new file mode 100644 index 0000000000..2b045655f8 --- /dev/null +++ b/.pydevproject @@ -0,0 +1,5 @@ + + + Default + python interpreter + diff --git a/.travis.yml b/.travis.yml index b72f88a6e0..5d9a021afb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,21 +1,32 @@ dist: xenial - services: - - postgresql +- postgresql addons: - postgresql: "9.4" + postgresql: '9.4' before_script: - - psql -U postgres -c "create user decide password 'decide'" - - psql -U postgres -c "create database test_decide owner decide" - - psql -U postgres -c "ALTER USER decide CREATEDB" +- psql -U postgres -c "create user decide password 'decide'" +- psql -U postgres -c "create database decidedb owner decide" +- psql -U postgres -c "ALTER USER decide CREATEDB" language: python python: - - "3.6" +- '3.6' install: - - pip install -r requirements.txt - - pip install codacy-coverage +- pip install -r requirements.txt +- pip install codacy-coverage script: - - cd decide - - coverage run --branch --source=. ./manage.py test --keepdb --with-xunit - - coverage xml - - python-codacy-coverage -r coverage.xml +- wget https://github.com/mozilla/geckodriver/releases/download/v0.27.0/geckodriver-v0.27.0-linux64.tar.gz +- tar -xzf geckodriver-v0.27.0-linux64.tar.gz +- chmod +x geckodriver +- sudo cp geckodriver /usr/bin/ +- rm geckodriver-v0.27.0-linux64.tar.gz +- cd decide +- cp travis_local_settings.py local_settings.py +- coverage run --branch --source=. ./manage.py test authentication visualizer voting --keepdb +- coverage xml +- python-codacy-coverage -r coverage.xml +deploy: + provider: heroku + app: picaro-decide + strategy: git + api_key: + secure: SDt7FSvAfUp9J0aA0vhQGKN7ZUfHvbyX/GMr/gVQmlkobFNWu9Wk8f5O2jzxEcHJfP9DKRPwzK5CF2d422bd/toKXEJldIoZL57YQnomlKElqetaLBoETyydhn/oZkkF+aTv/zZF92m2dQGetTlG6Zp1sqFSW9BwXFKBrMIh9XjqFton6AFDZ5DPCy6Gn9303OAkxtWmqG4EGTEzJ2VV9ambCEMs30ZSeAGn4eVbWC92CvSaef32aOBvKcHKSKIrBkN5Y0olYGHRj00s+tr0iBlVfxKyVb1lI6vwuuh85+8w2UGVXp+NCAEy+Dm1RLz3lhDi3hpIyXK1V9JCqw6arbuNgvB0vHvRuldAj8cw3lmpD9kLlmDfstyw5MJd8UAf22rwsI1nUA6Ga/qycAD1kOIOgPwF6oWLW16M+MOGE/+loZIj4NmQTs3wiYAemqwVqEHc9enViEAaSD2M2zUWPI7L2m9gd2iOll6UleKosqz9f8hQFBLKcaTuaoH5qRHAIPeSVIAZA+GmJhbj9lM++yVhZW5aJ0SVzx+RhGAXcgweVNtUIH8F2DU1Es001zNML90k+G47MpnGqfIHuZcxSVtttLS6raoJIHEQSNUzfwXsy4mBjnUzZvy4YeOf/DId8kb/Wrk0+8P/MOoaDVUEePae7rz4jRcHfHj1UXMPpd0= diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000000..18c002a3ca --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "python.pythonPath": "C:\\Python3\\python.exe" +} \ No newline at end of file diff --git a/Procfile b/Procfile new file mode 100644 index 0000000000..818fef7fe3 --- /dev/null +++ b/Procfile @@ -0,0 +1,4 @@ +% prepara el repositorio para su despliegue. +release: sh -c 'cd decide && python manage.py migrate' +% especifica el comando para lanzar Decide +web: sh -c 'cd decide && gunicorn decide.wsgi --log-file -' diff --git a/README.md b/README.md index 83d0a57e27..65a98dd5e1 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,4 @@ [![Build Status](https://travis-ci.com/wadobo/decide.svg?branch=master)](https://travis-ci.com/wadobo/decide) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/94a85eaa0e974c71af6899ea3b0d27e0)](https://www.codacy.com/app/Wadobo/decide?utm_source=github.com&utm_medium=referral&utm_content=wadobo/decide&utm_campaign=Badge_Grade) [![Codacy Badge](https://api.codacy.com/project/badge/Coverage/94a85eaa0e974c71af6899ea3b0d27e0)](https://www.codacy.com/app/Wadobo/decide?utm_source=github.com&utm_medium=referral&utm_content=wadobo/decide&utm_campaign=Badge_Coverage) - Plataforma voto electrónico educativa ===================================== diff --git a/decide/base/templates/base.html b/decide/base/templates/base.html index fa9cf4aa8a..b2f91e8768 100644 --- a/decide/base/templates/base.html +++ b/decide/base/templates/base.html @@ -1,14 +1,87 @@ +{% load i18n static %} - {% block title %}Decide!{% endblock %} + Decide Pícaro{% block title %}{% endblock %} + + + {% block extrahead %}{% endblock %} {% block content %} {% endblock %} - + +
+ {% csrf_token %} + + +
{% block extrabody %}{% endblock %} diff --git a/decide/base/urls.py b/decide/base/urls.py index 637600f58a..918c70cf9f 100644 --- a/decide/base/urls.py +++ b/decide/base/urls.py @@ -1 +1,6 @@ -urlpatterns = [] +from django.conf.urls import url +from django.urls import include + +urlpatterns = [ + url('i18n/', include('django.conf.urls.i18n')), +] diff --git a/decide/booth/templates/booth/booth.html b/decide/booth/templates/booth/booth.html index 164f547a31..bc8e2449ca 100644 --- a/decide/booth/templates/booth/booth.html +++ b/decide/booth/templates/booth/booth.html @@ -16,7 +16,7 @@ Decide - {% trans "logout" %} + {% trans "Logout" %} diff --git a/decide/decide/settings.py b/decide/decide/settings.py index 1d22b67324..542c2ac60c 100644 --- a/decide/decide/settings.py +++ b/decide/decide/settings.py @@ -27,6 +27,7 @@ ALLOWED_HOSTS = [] +from django.utils.translation import ugettext_lazy as _ # Application definition @@ -70,11 +71,24 @@ 'voting', ] -BASEURL = 'http://localhost:8000' +BASEURL = 'https://picaro-decide.herokuapp.com' + +APIS = { + 'authentication': BASEURL , + 'base': BASEURL , + 'booth': BASEURL , + 'census': BASEURL , + 'mixnet': BASEURL , + 'postproc': BASEURL , + 'store': BASEURL , + 'visualizer': BASEURL , + 'voting': BASEURL , + } MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.locale.LocaleMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', @@ -140,7 +154,16 @@ # Internationalization # https://docs.djangoproject.com/en/2.0/topics/i18n/ -LANGUAGE_CODE = 'en-us' +#LANGUAGE_CODE = 'es' +LANGUAGE_CODE = 'en' +_ = lambda s: s + +LANGUAGES = [ + ('en', _('English')), + ('es', _('Spanish')), + ('fr', _('French')), + ('de', _('German')), +] TIME_ZONE = 'UTC' @@ -150,6 +173,10 @@ USE_TZ = True +LOCALE_PATHS = [ + os.path.join(BASE_DIR, 'locale') +] + TEST_RUNNER = 'django_nose.NoseTestSuiteRunner' @@ -157,6 +184,21 @@ # https://docs.djangoproject.com/en/2.0/howto/static-files/ STATIC_URL = '/static/' +STATIC_ROOT = '' +STATIC_TMP = os.path.join(BASE_DIR, 'static') + +os.makedirs(STATIC_TMP, exist_ok=True) + +STATICFILES_DIRS = ( + 'static', +) + +MEDIA_URL = '/media/' +MEDIA_ROOT = '' + +MEDIAFILES_DIRS = ( + 'media', +) # number of bits for the key, all auths should use the same number of bits KEYBITS = 256 @@ -180,3 +222,6 @@ INSTALLED_APPS = INSTALLED_APPS + MODULES + +import django_heroku +django_heroku.settings(locals()) diff --git a/decide/decide/urls.py b/decide/decide/urls.py index d73f3cdb5d..9b29ba5217 100644 --- a/decide/decide/urls.py +++ b/decide/decide/urls.py @@ -18,7 +18,6 @@ from django.urls import path, include from rest_framework_swagger.views import get_swagger_view - schema_view = get_swagger_view(title='Decide API') urlpatterns = [ diff --git a/decide/locale/de/LC_MESSAGES/django.mo b/decide/locale/de/LC_MESSAGES/django.mo new file mode 100644 index 0000000000..7fc45e65e9 Binary files /dev/null and b/decide/locale/de/LC_MESSAGES/django.mo differ diff --git a/decide/locale/de/LC_MESSAGES/django.po b/decide/locale/de/LC_MESSAGES/django.po new file mode 100644 index 0000000000..2951f73685 --- /dev/null +++ b/decide/locale/de/LC_MESSAGES/django.po @@ -0,0 +1,246 @@ +# 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 , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-16 12:57+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \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" + +#: booth/templates/booth/booth.html:19 +msgid "Logout" +msgstr "Ausloggen" + +#: booth/templates/booth/booth.html:33 +msgid "Username" +msgstr "Nutzername" + +#: booth/templates/booth/booth.html:41 +msgid "Password" +msgstr "Passwort" + +#: booth/templates/booth/booth.html:49 +msgid "Login" +msgstr "Anmeldung" + +#: booth/templates/booth/booth.html:64 +msgid "Vote" +msgstr "Abstimmung" + +#: booth/templates/booth/booth.html:160 booth/templates/booth/booth.html:170 +#: booth/templates/booth/booth.html:201 +msgid "Error: " +msgstr "Fehler: " + +#: booth/templates/booth/booth.html:198 +msgid "Conglatulations. Your vote has been sent" +msgstr "Herzliche Glückwünsche. Ihre Stimme wurde gesendet" + +#: decide/settings.py:162 +msgid "English" +msgstr "Englisch" + +#: decide/settings.py:163 +msgid "Spanish" +msgstr "Spanisch" + +#: decide/settings.py:164 +msgid "French" +msgstr "Französisch" + +#: decide/settings.py:165 +msgid "German" +msgstr "Deutsch" + +#: visualizer/templates/visualizer/aboutUs.html:16 +#: visualizer/templates/visualizer/contactUs.html:20 +#: visualizer/templates/visualizer/visualizer.html:38 +#: visualizer/templates/visualizer/visualizer_home.html:37 +msgid "Decide Visualization" +msgstr "Decide Visualisierung" + +#: visualizer/templates/visualizer/aboutUs.html:20 +#: visualizer/templates/visualizer/contactUs.html:24 +#: visualizer/templates/visualizer/visualizer.html:60 +#: visualizer/templates/visualizer/visualizer.html:93 +#: visualizer/templates/visualizer/visualizer.html:176 +msgid "Return" +msgstr "Rückkehr" + +#: visualizer/templates/visualizer/aboutUs.html:26 +msgid "Visualization Team" +msgstr "Anzeigegeräte" + +#: visualizer/templates/visualizer/aboutUs.html:35 +#: visualizer/templates/visualizer/aboutUs.html:43 +#: visualizer/templates/visualizer/aboutUs.html:51 +#: visualizer/templates/visualizer/aboutUs.html:59 +#: visualizer/templates/visualizer/aboutUs.html:67 +#: visualizer/templates/visualizer/aboutUs.html:75 +msgid "Computer Engineering student in Software Engineering" +msgstr "Student der Computertechnik in Software Engineering" + +#: visualizer/templates/visualizer/aboutUs.html:37 +#: visualizer/templates/visualizer/aboutUs.html:45 +#: visualizer/templates/visualizer/aboutUs.html:53 +#: visualizer/templates/visualizer/aboutUs.html:61 +#: visualizer/templates/visualizer/aboutUs.html:69 +#: visualizer/templates/visualizer/aboutUs.html:77 +msgid "GitHub Profile" +msgstr "GitHub-Profil" + +#: visualizer/templates/visualizer/aboutUs.html:86 +#: visualizer/templates/visualizer/contactUs.html:95 +#: visualizer/templates/visualizer/visualizer.html:181 +#: visualizer/templates/visualizer/visualizer_home.html:106 +msgid "Evolution and Configuration Management" +msgstr "Entwicklung und Konfiguration des Managements" + +#: visualizer/templates/visualizer/contactUs.html:33 +msgid "Contact Info" +msgstr "Kontaktinformation" + +#: visualizer/templates/visualizer/contactUs.html:37 +msgid "Higher Technical School of Computer Engineering," +msgstr "Höhere technische Fakultät für Computertechnik," + +#: visualizer/templates/visualizer/contactUs.html:38 +msgid "Sevilla University, 41012" +msgstr "Sevilla Universität, 41012" + +#: visualizer/templates/visualizer/contactUs.html:64 +msgid "Send a Message" +msgstr "Eine Nachricht schicken" + +#: visualizer/templates/visualizer/contactUs.html:69 +msgid "Full name" +msgstr "Vollständiger Name" + +#: visualizer/templates/visualizer/contactUs.html:73 +msgid "Subject" +msgstr "Gegenstand" + +#: visualizer/templates/visualizer/contactUs.html:77 +msgid "Email address" +msgstr "E-Mail-Addresse" + +#: visualizer/templates/visualizer/contactUs.html:81 +msgid "Write your message here" +msgstr "Schreibe deine Nachricht hier" + +#: visualizer/templates/visualizer/contactUs.html:84 +msgid "Send" +msgstr "Senden" + +#: visualizer/templates/visualizer/visualizer.html:44 +#: visualizer/templates/visualizer/visualizer_home.html:44 +msgid "Contact us" +msgstr "Kontaktiere uns" + +#: visualizer/templates/visualizer/visualizer.html:45 +#: visualizer/templates/visualizer/visualizer_home.html:45 +msgid "About us" +msgstr "Über uns" + +#: visualizer/templates/visualizer/visualizer.html:46 +#, fuzzy +#| msgid "Visualization Team" +msgid "Visualizer" +msgstr "Anzeigegeräte" + +#: visualizer/templates/visualizer/visualizer.html:51 +msgid "Light mode" +msgstr "Licht Modus" + +#: visualizer/templates/visualizer/visualizer.html:53 +msgid "Dark mode" +msgstr "Dunkler Modus" + +#: visualizer/templates/visualizer/visualizer.html:59 +msgid "Voting not started" +msgstr "Abstimmung nicht gestartet" + +#: visualizer/templates/visualizer/visualizer.html:64 +msgid "Voting in progress" +msgstr "Abstimmung läuft" + +#: visualizer/templates/visualizer/visualizer.html:78 +#: visualizer/templates/visualizer/visualizer.html:240 +#: visualizer/templates/visualizer/visualizer_home.html:224 +msgid "Number of votes" +msgstr "Anzahl der Stimmen" + +#: visualizer/templates/visualizer/visualizer.html:97 +msgid "Results" +msgstr "Ergebnisse" + +#: visualizer/templates/visualizer/visualizer.html:105 +msgid "2nd place" +msgstr "2. Platz" + +#: visualizer/templates/visualizer/visualizer.html:106 +msgid "WINNER" +msgstr "GEWINNER" + +#: visualizer/templates/visualizer/visualizer.html:107 +msgid "3rd place" +msgstr "3. Platz" + +#: visualizer/templates/visualizer/visualizer.html:126 +msgid "Option" +msgstr "Möglichkeit" + +#: visualizer/templates/visualizer/visualizer.html:127 +msgid "Punctuation" +msgstr "Interpunktion" + +#: visualizer/templates/visualizer/visualizer.html:128 +msgid "Votes" +msgstr "Stimmen" + +#: visualizer/templates/visualizer/visualizer.html:151 +msgid "Donut Chart" +msgstr "Kreisdiagramm" + +#: visualizer/templates/visualizer/visualizer.html:152 +#: visualizer/templates/visualizer/visualizer_home.html:86 +msgid "Bar Chart" +msgstr "Balkendiagramm" + +#: visualizer/templates/visualizer/visualizer.html:162 +#: visualizer/templates/visualizer/visualizer.html:164 +#: visualizer/templates/visualizer/visualizer_home.html:95 +msgid "Save as PNG" +msgstr "Als PNG speichern" + +#: visualizer/templates/visualizer/visualizer.html:168 +msgid "Save as PDF" +msgstr "Als PDF speichern" + +#: visualizer/templates/visualizer/visualizer.html:402 +#: visualizer/templates/visualizer/visualizer_home.html:181 +msgid "This visualization page is pretty cool. Do you want to continue?" +msgstr "Diese Visualisierungsseite ist ziemlich cool. Wollen Sie fortfahren?" + +#: visualizer/templates/visualizer/visualizer_home.html:63 +msgid "Votings" +msgstr "Abstimmungen" + +#: visualizer/templates/visualizer/visualizer_home.html:64 +msgid "Start date" +msgstr "Anfangsdatum" + +#: visualizer/templates/visualizer/visualizer_home.html:65 +msgid "End date" +msgstr "Enddatum" diff --git a/decide/locale/es/LC_MESSAGES/django.mo b/decide/locale/es/LC_MESSAGES/django.mo new file mode 100644 index 0000000000..25c7f26d71 Binary files /dev/null and b/decide/locale/es/LC_MESSAGES/django.mo differ diff --git a/decide/locale/es/LC_MESSAGES/django.po b/decide/locale/es/LC_MESSAGES/django.po new file mode 100644 index 0000000000..870cd7ba83 --- /dev/null +++ b/decide/locale/es/LC_MESSAGES/django.po @@ -0,0 +1,261 @@ +# 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 , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-16 12:57+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \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" + +#: booth/templates/booth/booth.html:19 +#, fuzzy +#| msgid "logout" +msgid "Logout" +msgstr "Cerrar sesión" + +#: booth/templates/booth/booth.html:33 +msgid "Username" +msgstr "Nombre de usuario" + +#: booth/templates/booth/booth.html:41 +msgid "Password" +msgstr "Contraseña" + +#: booth/templates/booth/booth.html:49 +msgid "Login" +msgstr "Iniciar sesión" + +#: booth/templates/booth/booth.html:64 +msgid "Vote" +msgstr "Voto" + +#: booth/templates/booth/booth.html:160 booth/templates/booth/booth.html:170 +#: booth/templates/booth/booth.html:201 +msgid "Error: " +msgstr "Error: " + +#: booth/templates/booth/booth.html:198 +msgid "Conglatulations. Your vote has been sent" +msgstr "Enhorabuena. Tu voto ha sido enviado" + +#: decide/settings.py:162 +msgid "English" +msgstr "Inglés" + +#: decide/settings.py:163 +msgid "Spanish" +msgstr "Español" + +#: decide/settings.py:164 +msgid "French" +msgstr "Français" + +#: decide/settings.py:165 +msgid "German" +msgstr "Alemán" + +#: visualizer/templates/visualizer/aboutUs.html:16 +#: visualizer/templates/visualizer/contactUs.html:20 +#: visualizer/templates/visualizer/visualizer.html:38 +#: visualizer/templates/visualizer/visualizer_home.html:37 +msgid "Decide Visualization" +msgstr "Decide Visualización" + +#: visualizer/templates/visualizer/aboutUs.html:20 +#: visualizer/templates/visualizer/contactUs.html:24 +#: visualizer/templates/visualizer/visualizer.html:60 +#: visualizer/templates/visualizer/visualizer.html:93 +#: visualizer/templates/visualizer/visualizer.html:176 +msgid "Return" +msgstr "Volver" + +#: visualizer/templates/visualizer/aboutUs.html:26 +msgid "Visualization Team" +msgstr "Equipo de Visualización" + +#: visualizer/templates/visualizer/aboutUs.html:35 +#: visualizer/templates/visualizer/aboutUs.html:43 +#: visualizer/templates/visualizer/aboutUs.html:51 +#: visualizer/templates/visualizer/aboutUs.html:59 +#: visualizer/templates/visualizer/aboutUs.html:67 +#: visualizer/templates/visualizer/aboutUs.html:75 +msgid "Computer Engineering student in Software Engineering" +msgstr "Estudiante de Ingeniería Informática en Ingeniería del Software" + +#: visualizer/templates/visualizer/aboutUs.html:37 +#: visualizer/templates/visualizer/aboutUs.html:45 +#: visualizer/templates/visualizer/aboutUs.html:53 +#: visualizer/templates/visualizer/aboutUs.html:61 +#: visualizer/templates/visualizer/aboutUs.html:69 +#: visualizer/templates/visualizer/aboutUs.html:77 +msgid "GitHub Profile" +msgstr "Perfil en GitHub" + +#: visualizer/templates/visualizer/aboutUs.html:86 +#: visualizer/templates/visualizer/contactUs.html:95 +#: visualizer/templates/visualizer/visualizer.html:181 +#: visualizer/templates/visualizer/visualizer_home.html:106 +msgid "Evolution and Configuration Management" +msgstr "Evolución y Gestión de la Configuración" + +#: visualizer/templates/visualizer/contactUs.html:33 +msgid "Contact Info" +msgstr "Contáctanos" + +#: visualizer/templates/visualizer/contactUs.html:37 +msgid "Higher Technical School of Computer Engineering," +msgstr "Escuela Técnica Superior de Ingeniería Informática," + +#: visualizer/templates/visualizer/contactUs.html:38 +msgid "Sevilla University, 41012" +msgstr "Universidad de Sevilla, 41012" + +#: visualizer/templates/visualizer/contactUs.html:64 +msgid "Send a Message" +msgstr "Enviar un mensaje" + +#: visualizer/templates/visualizer/contactUs.html:69 +msgid "Full name" +msgstr "Nombre y apellidos" + +#: visualizer/templates/visualizer/contactUs.html:73 +msgid "Subject" +msgstr "Asunto" + +#: visualizer/templates/visualizer/contactUs.html:77 +msgid "Email address" +msgstr "Dirección de correo" + +#: visualizer/templates/visualizer/contactUs.html:81 +msgid "Write your message here" +msgstr "Escriba aquí su mensaje" + +#: visualizer/templates/visualizer/contactUs.html:84 +msgid "Send" +msgstr "Enviar" + +#: visualizer/templates/visualizer/visualizer.html:44 +#: visualizer/templates/visualizer/visualizer_home.html:44 +msgid "Contact us" +msgstr "Contáctanos" + +#: visualizer/templates/visualizer/visualizer.html:45 +#: visualizer/templates/visualizer/visualizer_home.html:45 +msgid "About us" +msgstr "Sobre nosotros" + +#: visualizer/templates/visualizer/visualizer.html:46 +#, fuzzy +#| msgid "Visualization Team" +msgid "Visualizer" +msgstr "Equipo de Visualización" + +#: visualizer/templates/visualizer/visualizer.html:51 +msgid "Light mode" +msgstr "Modo claro" + +#: visualizer/templates/visualizer/visualizer.html:53 +msgid "Dark mode" +msgstr "Modo oscuro" + +#: visualizer/templates/visualizer/visualizer.html:59 +msgid "Voting not started" +msgstr "Votación no comenzada" + +#: visualizer/templates/visualizer/visualizer.html:64 +msgid "Voting in progress" +msgstr "Votación en curso" + +#: visualizer/templates/visualizer/visualizer.html:78 +#: visualizer/templates/visualizer/visualizer.html:240 +#: visualizer/templates/visualizer/visualizer_home.html:224 +msgid "Number of votes" +msgstr "Número de votos" + +#: visualizer/templates/visualizer/visualizer.html:97 +msgid "Results" +msgstr "Resultados" + +#: visualizer/templates/visualizer/visualizer.html:105 +msgid "2nd place" +msgstr "2º puesto" + +#: visualizer/templates/visualizer/visualizer.html:106 +msgid "WINNER" +msgstr "GANADOR" + +#: visualizer/templates/visualizer/visualizer.html:107 +msgid "3rd place" +msgstr "3º puesto" + +#: visualizer/templates/visualizer/visualizer.html:126 +msgid "Option" +msgstr "Opción" + +#: visualizer/templates/visualizer/visualizer.html:127 +msgid "Punctuation" +msgstr "Puntuación" + +#: visualizer/templates/visualizer/visualizer.html:128 +#, fuzzy +#| msgid "Vote" +msgid "Votes" +msgstr "Voto" + +#: visualizer/templates/visualizer/visualizer.html:151 +msgid "Donut Chart" +msgstr "Gráfico Circular" + +#: visualizer/templates/visualizer/visualizer.html:152 +#: visualizer/templates/visualizer/visualizer_home.html:86 +msgid "Bar Chart" +msgstr "Gráfico de Barras" + +#: visualizer/templates/visualizer/visualizer.html:162 +#: visualizer/templates/visualizer/visualizer.html:164 +#: visualizer/templates/visualizer/visualizer_home.html:95 +msgid "Save as PNG" +msgstr "Guardar como PNG" + +#: visualizer/templates/visualizer/visualizer.html:168 +msgid "Save as PDF" +msgstr "Guardar como PDF" + +#: visualizer/templates/visualizer/visualizer.html:402 +#: visualizer/templates/visualizer/visualizer_home.html:181 +msgid "This visualization page is pretty cool. Do you want to continue?" +msgstr "Esta página de visualización está muy chula. ¿Quieres continuar?" + +#: visualizer/templates/visualizer/visualizer_home.html:63 +msgid "Votings" +msgstr "Votaciones" + +#: visualizer/templates/visualizer/visualizer_home.html:64 +msgid "Start date" +msgstr "Fecha de inicio" + +#: visualizer/templates/visualizer/visualizer_home.html:65 +msgid "End date" +msgstr "Fecha de finalización" + +#, fuzzy +#~| msgid "Number of votes" +#~ msgid "Número de votos" +#~ msgstr "Número de votos" + +#~ msgid "Last name" +#~ msgstr "Apellidos" + +#~ msgid "Mobile number" +#~ msgstr "Número de teléfono" diff --git a/decide/locale/fr/LC_MESSAGES/django.mo b/decide/locale/fr/LC_MESSAGES/django.mo new file mode 100644 index 0000000000..4773416d2b Binary files /dev/null and b/decide/locale/fr/LC_MESSAGES/django.mo differ diff --git a/decide/locale/fr/LC_MESSAGES/django.po b/decide/locale/fr/LC_MESSAGES/django.po new file mode 100644 index 0000000000..70075f9d4c --- /dev/null +++ b/decide/locale/fr/LC_MESSAGES/django.po @@ -0,0 +1,250 @@ +# 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 , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-01-16 12:57+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \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" + +#: booth/templates/booth/booth.html:19 +#, fuzzy +#| msgid "logout" +msgid "Logout" +msgstr "Fermer session" + +#: booth/templates/booth/booth.html:33 +msgid "Username" +msgstr "Utilisateur" + +#: booth/templates/booth/booth.html:41 +msgid "Password" +msgstr "Mot de passe" + +#: booth/templates/booth/booth.html:49 +msgid "Login" +msgstr "S'identifier" + +#: booth/templates/booth/booth.html:64 +msgid "Vote" +msgstr "Voter" + +#: booth/templates/booth/booth.html:160 booth/templates/booth/booth.html:170 +#: booth/templates/booth/booth.html:201 +msgid "Error: " +msgstr "Erreur: " + +#: booth/templates/booth/booth.html:198 +msgid "Conglatulations. Your vote has been sent" +msgstr "Felicitations. Votre vote a été envoyé" + +#: decide/settings.py:162 +msgid "English" +msgstr "Anglais" + +#: decide/settings.py:163 +msgid "Spanish" +msgstr "Espagnol" + +#: decide/settings.py:164 +msgid "French" +msgstr "Français" + +#: decide/settings.py:165 +msgid "German" +msgstr "Deutsch" + +#: visualizer/templates/visualizer/aboutUs.html:16 +#: visualizer/templates/visualizer/contactUs.html:20 +#: visualizer/templates/visualizer/visualizer.html:38 +#: visualizer/templates/visualizer/visualizer_home.html:37 +msgid "Decide Visualization" +msgstr "Decide Visualization" + +#: visualizer/templates/visualizer/aboutUs.html:20 +#: visualizer/templates/visualizer/contactUs.html:24 +#: visualizer/templates/visualizer/visualizer.html:60 +#: visualizer/templates/visualizer/visualizer.html:93 +#: visualizer/templates/visualizer/visualizer.html:176 +msgid "Return" +msgstr "Retour" + +#: visualizer/templates/visualizer/aboutUs.html:26 +msgid "Visualization Team" +msgstr "Equipe de visualization" + +#: visualizer/templates/visualizer/aboutUs.html:35 +#: visualizer/templates/visualizer/aboutUs.html:43 +#: visualizer/templates/visualizer/aboutUs.html:51 +#: visualizer/templates/visualizer/aboutUs.html:59 +#: visualizer/templates/visualizer/aboutUs.html:67 +#: visualizer/templates/visualizer/aboutUs.html:75 +msgid "Computer Engineering student in Software Engineering" +msgstr "Etudiant en Ingénierie Informatique en Ingénerie de Software" + +#: visualizer/templates/visualizer/aboutUs.html:37 +#: visualizer/templates/visualizer/aboutUs.html:45 +#: visualizer/templates/visualizer/aboutUs.html:53 +#: visualizer/templates/visualizer/aboutUs.html:61 +#: visualizer/templates/visualizer/aboutUs.html:69 +#: visualizer/templates/visualizer/aboutUs.html:77 +msgid "GitHub Profile" +msgstr "Profile GitHub" + +#: visualizer/templates/visualizer/aboutUs.html:86 +#: visualizer/templates/visualizer/contactUs.html:95 +#: visualizer/templates/visualizer/visualizer.html:181 +#: visualizer/templates/visualizer/visualizer_home.html:106 +msgid "Evolution and Configuration Management" +msgstr "Evolution et Gestion de la Configuration" + +#: visualizer/templates/visualizer/contactUs.html:33 +msgid "Contact Info" +msgstr "Information de contact" + +#: visualizer/templates/visualizer/contactUs.html:37 +msgid "Higher Technical School of Computer Engineering," +msgstr "Ecole Technique Supérieur d'Ingénerie Informatique," + +#: visualizer/templates/visualizer/contactUs.html:38 +msgid "Sevilla University, 41012" +msgstr "Universiter de Seville, 41012" + +#: visualizer/templates/visualizer/contactUs.html:64 +msgid "Send a Message" +msgstr "Envoyer en méssage" + +#: visualizer/templates/visualizer/contactUs.html:69 +msgid "Full name" +msgstr "Nom et prénom" + +#: visualizer/templates/visualizer/contactUs.html:73 +msgid "Subject" +msgstr "Sujet" + +#: visualizer/templates/visualizer/contactUs.html:77 +msgid "Email address" +msgstr "Adresse email" + +#: visualizer/templates/visualizer/contactUs.html:81 +msgid "Write your message here" +msgstr "Ecrivez votre méssage ici" + +#: visualizer/templates/visualizer/contactUs.html:84 +msgid "Send" +msgstr "Evoyer" + +#: visualizer/templates/visualizer/visualizer.html:44 +#: visualizer/templates/visualizer/visualizer_home.html:44 +msgid "Contact us" +msgstr "Contacter nous" + +#: visualizer/templates/visualizer/visualizer.html:45 +#: visualizer/templates/visualizer/visualizer_home.html:45 +msgid "About us" +msgstr "A propos de nous" + +#: visualizer/templates/visualizer/visualizer.html:46 +#, fuzzy +#| msgid "Visualization Team" +msgid "Visualizer" +msgstr "Equipe de visualization" + +#: visualizer/templates/visualizer/visualizer.html:51 +msgid "Light mode" +msgstr "Mode clair" + +#: visualizer/templates/visualizer/visualizer.html:53 +msgid "Dark mode" +msgstr "Mode sombre" + +#: visualizer/templates/visualizer/visualizer.html:59 +msgid "Voting not started" +msgstr "Le vote n'a pas commencé" + +#: visualizer/templates/visualizer/visualizer.html:64 +msgid "Voting in progress" +msgstr "Vote en cours" + +#: visualizer/templates/visualizer/visualizer.html:78 +#: visualizer/templates/visualizer/visualizer.html:240 +#: visualizer/templates/visualizer/visualizer_home.html:224 +msgid "Number of votes" +msgstr "Nombre de votes" + +#: visualizer/templates/visualizer/visualizer.html:97 +msgid "Results" +msgstr "Résultats" + +#: visualizer/templates/visualizer/visualizer.html:105 +msgid "2nd place" +msgstr "2ème place" + +#: visualizer/templates/visualizer/visualizer.html:106 +msgid "WINNER" +msgstr "GAGNANT" + +#: visualizer/templates/visualizer/visualizer.html:107 +msgid "3rd place" +msgstr "3ème place" + +#: visualizer/templates/visualizer/visualizer.html:126 +msgid "Option" +msgstr "Option" + +#: visualizer/templates/visualizer/visualizer.html:127 +msgid "Punctuation" +msgstr "Score" + +#: visualizer/templates/visualizer/visualizer.html:128 +#, fuzzy +#| msgid "Vote" +msgid "Votes" +msgstr "Vote" + +#: visualizer/templates/visualizer/visualizer.html:151 +msgid "Donut Chart" +msgstr "Graphique en anneau" + +#: visualizer/templates/visualizer/visualizer.html:152 +#: visualizer/templates/visualizer/visualizer_home.html:86 +msgid "Bar Chart" +msgstr "Graphique à barres" + +#: visualizer/templates/visualizer/visualizer.html:162 +#: visualizer/templates/visualizer/visualizer.html:164 +#: visualizer/templates/visualizer/visualizer_home.html:95 +msgid "Save as PNG" +msgstr "Sauver comme PNG" + +#: visualizer/templates/visualizer/visualizer.html:168 +msgid "Save as PDF" +msgstr "Sauver comme PDF" + +#: visualizer/templates/visualizer/visualizer.html:402 +#: visualizer/templates/visualizer/visualizer_home.html:181 +msgid "This visualization page is pretty cool. Do you want to continue?" +msgstr "Cette page de visualisation est plutôt cool. Voulez-vous continuer?" + +#: visualizer/templates/visualizer/visualizer_home.html:63 +msgid "Votings" +msgstr "Votations" + +#: visualizer/templates/visualizer/visualizer_home.html:64 +msgid "Start date" +msgstr "Date de commencement" + +#: visualizer/templates/visualizer/visualizer_home.html:65 +msgid "End date" +msgstr "Date de finalization" diff --git a/decide/postproc/views.py b/decide/postproc/views.py index f4c5de1e5f..47871478a6 100644 --- a/decide/postproc/views.py +++ b/decide/postproc/views.py @@ -11,7 +11,7 @@ def identity(self, options): out.append({ **opt, 'postproc': opt['votes'], - }); + }) out.sort(key=lambda x: -x['postproc']) return Response(out) diff --git a/decide/booth/static/booth/style.css b/decide/static/booth/style.css similarity index 100% rename from decide/booth/static/booth/style.css rename to decide/static/booth/style.css diff --git a/decide/booth/static/crypto/bigint.js b/decide/static/crypto/bigint.js similarity index 100% rename from decide/booth/static/crypto/bigint.js rename to decide/static/crypto/bigint.js diff --git a/decide/booth/static/crypto/elgamal.js b/decide/static/crypto/elgamal.js similarity index 100% rename from decide/booth/static/crypto/elgamal.js rename to decide/static/crypto/elgamal.js diff --git a/decide/booth/static/crypto/jsbn.js b/decide/static/crypto/jsbn.js similarity index 100% rename from decide/booth/static/crypto/jsbn.js rename to decide/static/crypto/jsbn.js diff --git a/decide/booth/static/crypto/jsbn2.js b/decide/static/crypto/jsbn2.js similarity index 100% rename from decide/booth/static/crypto/jsbn2.js rename to decide/static/crypto/jsbn2.js diff --git a/decide/booth/static/crypto/sjcl.js b/decide/static/crypto/sjcl.js similarity index 100% rename from decide/booth/static/crypto/sjcl.js rename to decide/static/crypto/sjcl.js diff --git a/decide/static/css/aboutUs.css b/decide/static/css/aboutUs.css new file mode 100644 index 0000000000..7a11b1d530 --- /dev/null +++ b/decide/static/css/aboutUs.css @@ -0,0 +1,70 @@ +@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@200;300;400;500;600;700;800;900&display=swap'); + +* { + margin: 0; + padding: 0; + box-sizing: border-box; + font-family: 'Poppins' ,sans-serif; +} +.au { + margin-top: 20px; + margin-left: 40px; +} +section { + position: relative; + display: flex; + justify-content: center; + align-items: center; + min-height: 140vh; +} +section::before { + content: ''; + position: absolute; + top: 0; + left: 0; + width: 50%; + height: 100%; +} +section .containerr { + position: relative; + min-width: 1100px; + min-height: 1000px; + display: flex; + +} +section .containerr .personalInfo { + position: absolute; + padding: 70px 50px; + background: white; + margin-left: 0px; + padding-left: 50px; + border-radius: 30px; + width: 100%; + height: 100%; + box-shadow: 0 50px 50px rgba(0, 0, 0, 0.5); +} +section .containerr .personalInfo .columna { + width: 14rem; + margin-right: 75px; + display: inline-block; + border-radius: 20px; + border-color: #6c757d; + border-width: 2px; + box-shadow: 0 50px 50px rgba(0, 0, 0, 0.5); +} +section .containerr .personalInfo .columna img { + width: 180px; + height: 170px; + margin-top: 20px; + margin-bottom: 10px; + border-radius: 20px; +} +section .containerr .personalInfo .columna h5 { + margin-top: 5px; +} +section .containerr .personalInfo .columna a { + margin-bottom: 4px; +} +section .containerr .personalInfo .col { + margin-top: 50px; +} \ No newline at end of file diff --git a/decide/static/css/contactUs.css b/decide/static/css/contactUs.css new file mode 100644 index 0000000000..88b6130ca4 --- /dev/null +++ b/decide/static/css/contactUs.css @@ -0,0 +1,180 @@ +@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@200;300;400;500;600;700;800;900&display=swap'); + +* { + margin: 0; + padding: 0; + box-sizing: border-box; + font-family: 'Poppins' ,sans-serif; +} +section { + position: relative; + display: flex; + justify-content: center; + align-items: center; + min-height: 82.5vh; +} +section::before { + content: ''; + position: absolute; + top: 0; + left: 0; + width: 50%; + height: 100%; +} +section .containerr { + position: relative; + min-width: 1100px; + min-height: 550px; + display: flex; + z-index: 1000; +} +section .containerr .contactInfo { + position: absolute; + top: 40px; + width: 350px; + height: calc(100% - 80px); + background: #6c757d; + z-index: 1; + padding: 40px; + display: flex; + flex-direction: column; + justify-content: space-between; + box-shadow: 0 20px 20px rgba(0, 0, 0, 0.2); +} +section .containerr .contactInfo h2 { + color: white; + font-size: 24px; + font-weight: 500px; +} +section .containerr .contactInfo .info { + position: relative; + margin: 20px 0; +} +section .containerr .contactInfo .info li { + position: relative; + list-style: none; + display: flex; + margin: 20px 0; + cursor: pointer; + align-items: flex-start; +} +section .containerr .contactInfo .info li span:nth-child(1) { + width: 30px; + min-width: 30px; +} +section .containerr .contactInfo .info li span:nth-child(1) img { + max-width: 100%; + filter: invert(1); + opacity: 0.5; +} +section .containerr .contactInfo .info li span:nth-child(2) { + color: white; + margin-left: 10px; + font-weight: 300; + opacity: 0.5; +} + +section .containerr .contactInfo .info li:hover span:nth-child(1) img, +section .containerr .contactInfo .info li:hover span:nth-child(2) { + opacity: 1; +} + +section .containerr .contactInfo .sci { + position: relative; + display: flex; +} +section .containerr .contactInfo .sci li { + list-style: none; + margin-right: 15px; +} +section .containerr .contactInfo .sci li a { + text-decoration: none; +} +section .containerr .contactInfo .sci li a i { + filter: invert(1); + color: white; + font-size: 28px; + opacity: 0.5; +} +section .containerr .contactInfo .sci li:hover a i { + opacity: 1; +} +section .containerr .contactForm { + position: absolute; + padding: 70px 50px; + background: white; + margin-left: 150px; + padding-left: 250px; + width: calc(100% - 150px); + height: 100%; + box-shadow: 0 50px 50px rgba(0, 0, 0, 0.5); +} +section .containerr .contactForm h2 { + color: #6c757d; + font-size: 24px; + font-weight: 500; +} +section .containerr .contactForm .formBox { + position: relative; + display: flex; + justify-content: space-between; + flex-wrap: wrap; + padding-top: 30px; +} +section .containerr .contactForm .formBox .inputBox { + position: relative; + margin: 0 0 35px 0; +} +section .containerr .contactForm .formBox .inputBox.w50 { + width: 47%; +} +section .containerr .contactForm .formBox .inputBox.w100 { + width: 100%; +} +section .containerr .contactForm .formBox .inputBox input, +section .containerr .contactForm .formBox .inputBox textarea { + width: 100% !important; + padding: 5px 0; + resize: none; + font-size: 18px; + font-weight: 300; + color: #333; + border: none; + border-bottom: 1px solid #777; + outline: none; +} +section .containerr .contactForm .formBox .inputBox textarea { + min-height: 120px; +} +section .containerr .contactForm .formBox .inputBox span { + position: absolute; + left: 0; + padding: 5px 0; + font-size: 18px; + font-weight: 300; + color: #333; + transition: 0.5s; + pointer-events: none; +} +section .containerr .contactForm .formBox .inputBox input:focus ~ span, +section .containerr .contactForm .formBox .inputBox textarea:focus ~ span, +section .containerr .contactForm .formBox .inputBox input:valid ~ span, +section .containerr .contactForm .formBox .inputBox textarea:valid ~ span { + transform: translateY(-20px); + font-size: 12px; + font-weight: 400; + letter-spacing: 1px; + color: #112d42; +} +section .containerr .contactForm .formBox .inputBox input[type="submit"] { + position: relative; + cursor: pointer; + background: #6c757d; + color: white; + border: none; + max-width: 150px; + padding: 12px; +} +section .containerr .contactForm .formBox .inputBox input[type="submit"]:hover { + background: #112d42; +} \ No newline at end of file diff --git a/decide/static/css/mfb.css b/decide/static/css/mfb.css new file mode 100644 index 0000000000..13a965bee2 --- /dev/null +++ b/decide/static/css/mfb.css @@ -0,0 +1,671 @@ +/** + * CONTENTS + * + * #Introduction........Naming conventions used throughout the code. + * + * #SETTINGS + * Variables............Globally-available variables and config. + * + * #TOOLS + * Mixins...............Useful mixins. + * + * #GENERIC + * Demo styles..........Styles for demo only (consider removing these). + * + * #BASE + * Raw styles...........The very basic component wrapper. + * Modifiers............The basic styles dependant on component placement. + * Debuggers............The basic styles dependant on component placement. + * + * #BUTTONS + * Base..................Wrapping and constraining every button. + * Modifiers.............Styles that depends on state and settings. + * Animations............Main animations of the component. + * Debuggers.............Styles for development. + * + * #LABELS + * Base..................Wrapping and constraining every label. + * Modifiers.............Styles that depends on state and settings. + * Debuggers.............Styles for development. + * + * #DEVELOPMENT + * In development........These styles are in development and not yet finalised + * Debuggers.............Helper styles and flags for development. + */ +/*------------------------------------*\ + #Introduction +\*------------------------------------*/ +/** + * The code AND the comments use naming conventions to refer to each part of + * the UI put in place by this component. If you see that somewhere they are + * not followed please consider a Pull Request. The naming conventions are: + * + * "Component" : the widget itself as a whole. This is the last time it will be + * called anything different than "component". So, stay away from + * "widget", "button" or anything else when referring to the + * Component in general. + * + * "Main Button" : the button that is always in view. Hovering or clicking on it + * will reveal the child buttons. + * + * "Child buttons" : if you've read the previous point you know what they are. + * Did you read the previous point? :) + * + * "Label(s)" : the tooltip that fades in when hovering over a button. + +/*------------------------------------*\ + #SETTINGS | Variables +\*------------------------------------*/ +/** + * These variables are the default styles that serve as fallback and can be + * easily customised at compile time. + * Consider overriding them in your own style sheets rather than editing them + * here. Refer to the docs for more info. + */ +/* COLORS ----------------------------*/ +/* EFFECTS ---------------------------*/ +/* SPEEDS ----------------------------*/ +/* SIZES -----------------------------*/ +/* SPACING ---------------------------*/ +/* OTHER VARIABLES -------------------*/ +/*------------------------------------*\ + #BASE | Raw styles +\*------------------------------------*/ +/** + * The very core styling of the button. + * These styles are shared by every instance of the button. + * Styles placed here should NOT care about placement in the screen, + * options chosen by the user or state of the button. + */ +.mfb-component--tl, .mfb-component--tr, .mfb-component--bl, .mfb-component--br { + box-sizing: border-box; + margin: 25px; + position: fixed; + white-space: nowrap; + z-index: 30; + padding-left: 0; + list-style: none; } + .mfb-component--tl *, .mfb-component--tr *, .mfb-component--bl *, .mfb-component--br *, .mfb-component--tl *:before, .mfb-component--tr *:before, .mfb-component--bl *:before, .mfb-component--br *:before, .mfb-component--tl *:after, .mfb-component--tr *:after, .mfb-component--bl *:after, .mfb-component--br *:after { + box-sizing: inherit; } + +/*------------------------------------*\ + #BASE | Modifiers +\*------------------------------------*/ +/** + * These styles depends on the placement of the button. + * Styles can be: + * 1. Top-left: modified by the " --tl " suffix. + * 2. Top-right: modified by the " --tr " suffix. + * 3. Bottom-left: modified by the " --bl " suffix. + * 4. Bottom-right: modified by the " --br " suffix. + */ +.mfb-component--tl { + left: 0; + top: 0; } + +.mfb-component--tr { + right: 0; + top: 0; } + +.mfb-component--bl { + left: 0; + bottom: 0; } + +.mfb-component--br { + right: 0; + bottom: 0; } + +/*------------------------------------*\ + #BUTTONS | Base +\*------------------------------------*/ +.mfb-component__button--main, .mfb-component__button--child { + background-color: #E40A5D; + display: inline-block; + position: relative; + border: none; + border-radius: 50%; + box-shadow: 0 0 4px rgba(0, 0, 0, 0.14), 0 4px 8px rgba(0, 0, 0, 0.28); + cursor: pointer; + outline: none; + padding: 0; + position: relative; + -webkit-user-drag: none; + color: #f1f1f1; } + +/** + * This is the unordered list for the list items that contain + * the child buttons. + * + */ +.mfb-component__list { + list-style: none; + margin: 0; + padding: 0; } + .mfb-component__list > li { + display: block; + position: absolute; + top: 0; + right: 1px; + padding: 10px 0; + margin: -10px 0; } + +/** + * These are the basic styles for all the icons inside the main button + */ +.mfb-component__icon, .mfb-component__main-icon--active, +.mfb-component__main-icon--resting, .mfb-component__child-icon { + position: absolute; + font-size: 18px; + text-align: center; + line-height: 56px; + width: 100%; } + +.mfb-component__wrap { + padding: 5px; + margin: -25px; } + +[data-mfb-toggle="hover"]:hover .mfb-component__icon, [data-mfb-toggle="hover"]:hover .mfb-component__main-icon--active, +[data-mfb-toggle="hover"]:hover .mfb-component__main-icon--resting, [data-mfb-toggle="hover"]:hover .mfb-component__child-icon, +[data-mfb-state="open"] .mfb-component__icon, +[data-mfb-state="open"] .mfb-component__main-icon--active, +[data-mfb-state="open"] .mfb-component__main-icon--resting, +[data-mfb-state="open"] .mfb-component__child-icon { + -webkit-transform: scale(1) rotate(0deg); + transform: scale(1) rotate(0deg); } + +/*------------------------------------*\ + #BUTTONS | Modifiers +\*------------------------------------*/ +.mfb-component__button--main { + height: 56px; + width: 56px; + z-index: 20; } + +.mfb-component__button--child { + height: 56px; + width: 56px; } + +.mfb-component__main-icon--active, +.mfb-component__main-icon--resting { + -webkit-transform: scale(1) rotate(360deg); + transform: scale(1) rotate(360deg); + -webkit-transition: -webkit-transform 150ms cubic-bezier(0.4, 0, 1, 1); + transition: transform 150ms cubic-bezier(0.4, 0, 1, 1); } + +.mfb-component__child-icon, +.mfb-component__child-icon { + line-height: 56px; + font-size: 18px; } + +.mfb-component__main-icon--active { + opacity: 0; } + +[data-mfb-toggle="hover"]:hover .mfb-component__main-icon, +[data-mfb-state="open"] .mfb-component__main-icon { + -webkit-transform: scale(1) rotate(0deg); + transform: scale(1) rotate(0deg); } +[data-mfb-toggle="hover"]:hover .mfb-component__main-icon--resting, +[data-mfb-state="open"] .mfb-component__main-icon--resting { + opacity: 0; + position: absolute !important; } +[data-mfb-toggle="hover"]:hover .mfb-component__main-icon--active, +[data-mfb-state="open"] .mfb-component__main-icon--active { + opacity: 1; } + +/*------------------------------------*\ + #BUTTONS | Animations +\*------------------------------------*/ +/** + * SLIDE IN + FADE + * When hovering the main button, the child buttons slide out from beneath + * the main button while transitioning from transparent to opaque. + * + */ +.mfb-component--tl.mfb-slidein .mfb-component__list li, +.mfb-component--tr.mfb-slidein .mfb-component__list li { + opacity: 0; + transition: all 0.5s; } +.mfb-component--tl.mfb-slidein[data-mfb-toggle="hover"]:hover .mfb-component__list li, .mfb-component--tl.mfb-slidein[data-mfb-state="open"] .mfb-component__list li, +.mfb-component--tr.mfb-slidein[data-mfb-toggle="hover"]:hover .mfb-component__list li, +.mfb-component--tr.mfb-slidein[data-mfb-state="open"] .mfb-component__list li { + opacity: 1; } +.mfb-component--tl.mfb-slidein[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(1), .mfb-component--tl.mfb-slidein[data-mfb-state="open"] .mfb-component__list li:nth-child(1), +.mfb-component--tr.mfb-slidein[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(1), +.mfb-component--tr.mfb-slidein[data-mfb-state="open"] .mfb-component__list li:nth-child(1) { + -webkit-transform: translateY(70px); + transform: translateY(70px); } +.mfb-component--tl.mfb-slidein[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(2), .mfb-component--tl.mfb-slidein[data-mfb-state="open"] .mfb-component__list li:nth-child(2), +.mfb-component--tr.mfb-slidein[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(2), +.mfb-component--tr.mfb-slidein[data-mfb-state="open"] .mfb-component__list li:nth-child(2) { + -webkit-transform: translateY(140px); + transform: translateY(140px); } +.mfb-component--tl.mfb-slidein[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(3), .mfb-component--tl.mfb-slidein[data-mfb-state="open"] .mfb-component__list li:nth-child(3), +.mfb-component--tr.mfb-slidein[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(3), +.mfb-component--tr.mfb-slidein[data-mfb-state="open"] .mfb-component__list li:nth-child(3) { + -webkit-transform: translateY(210px); + transform: translateY(210px); } +.mfb-component--tl.mfb-slidein[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(4), .mfb-component--tl.mfb-slidein[data-mfb-state="open"] .mfb-component__list li:nth-child(4), +.mfb-component--tr.mfb-slidein[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(4), +.mfb-component--tr.mfb-slidein[data-mfb-state="open"] .mfb-component__list li:nth-child(4) { + -webkit-transform: translateY(280px); + transform: translateY(280px); } + +.mfb-component--bl.mfb-slidein .mfb-component__list li, +.mfb-component--br.mfb-slidein .mfb-component__list li { + opacity: 0; + transition: all 0.5s; } +.mfb-component--bl.mfb-slidein[data-mfb-toggle="hover"]:hover .mfb-component__list li, .mfb-component--bl.mfb-slidein[data-mfb-state="open"] .mfb-component__list li, +.mfb-component--br.mfb-slidein[data-mfb-toggle="hover"]:hover .mfb-component__list li, +.mfb-component--br.mfb-slidein[data-mfb-state="open"] .mfb-component__list li { + opacity: 1; } +.mfb-component--bl.mfb-slidein[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(1), .mfb-component--bl.mfb-slidein[data-mfb-state="open"] .mfb-component__list li:nth-child(1), +.mfb-component--br.mfb-slidein[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(1), +.mfb-component--br.mfb-slidein[data-mfb-state="open"] .mfb-component__list li:nth-child(1) { + -webkit-transform: translateY(-70px); + transform: translateY(-70px); } +.mfb-component--bl.mfb-slidein[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(2), .mfb-component--bl.mfb-slidein[data-mfb-state="open"] .mfb-component__list li:nth-child(2), +.mfb-component--br.mfb-slidein[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(2), +.mfb-component--br.mfb-slidein[data-mfb-state="open"] .mfb-component__list li:nth-child(2) { + -webkit-transform: translateY(-140px); + transform: translateY(-140px); } +.mfb-component--bl.mfb-slidein[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(3), .mfb-component--bl.mfb-slidein[data-mfb-state="open"] .mfb-component__list li:nth-child(3), +.mfb-component--br.mfb-slidein[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(3), +.mfb-component--br.mfb-slidein[data-mfb-state="open"] .mfb-component__list li:nth-child(3) { + -webkit-transform: translateY(-210px); + transform: translateY(-210px); } +.mfb-component--bl.mfb-slidein[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(4), .mfb-component--bl.mfb-slidein[data-mfb-state="open"] .mfb-component__list li:nth-child(4), +.mfb-component--br.mfb-slidein[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(4), +.mfb-component--br.mfb-slidein[data-mfb-state="open"] .mfb-component__list li:nth-child(4) { + -webkit-transform: translateY(-280px); + transform: translateY(-280px); } + +/** + * SLIDE IN SPRING + * Same as slide-in but with a springy animation. + * + */ +.mfb-component--tl.mfb-slidein-spring .mfb-component__list li, +.mfb-component--tr.mfb-slidein-spring .mfb-component__list li { + opacity: 0; + transition: all 0.5s; + transition-timing-function: cubic-bezier(0.68, -0.55, 0.265, 1.55); } +.mfb-component--tl.mfb-slidein-spring .mfb-component__list li:nth-child(1), +.mfb-component--tr.mfb-slidein-spring .mfb-component__list li:nth-child(1) { + transition-delay: 0.05s; } +.mfb-component--tl.mfb-slidein-spring .mfb-component__list li:nth-child(2), +.mfb-component--tr.mfb-slidein-spring .mfb-component__list li:nth-child(2) { + transition-delay: 0.1s; } +.mfb-component--tl.mfb-slidein-spring .mfb-component__list li:nth-child(3), +.mfb-component--tr.mfb-slidein-spring .mfb-component__list li:nth-child(3) { + transition-delay: 0.15s; } +.mfb-component--tl.mfb-slidein-spring .mfb-component__list li:nth-child(4), +.mfb-component--tr.mfb-slidein-spring .mfb-component__list li:nth-child(4) { + transition-delay: 0.2s; } +.mfb-component--tl.mfb-slidein-spring[data-mfb-toggle="hover"]:hover .mfb-component__list li, .mfb-component--tl.mfb-slidein-spring[data-mfb-state="open"] .mfb-component__list li, +.mfb-component--tr.mfb-slidein-spring[data-mfb-toggle="hover"]:hover .mfb-component__list li, +.mfb-component--tr.mfb-slidein-spring[data-mfb-state="open"] .mfb-component__list li { + opacity: 1; } +.mfb-component--tl.mfb-slidein-spring[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(1), .mfb-component--tl.mfb-slidein-spring[data-mfb-state="open"] .mfb-component__list li:nth-child(1), +.mfb-component--tr.mfb-slidein-spring[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(1), +.mfb-component--tr.mfb-slidein-spring[data-mfb-state="open"] .mfb-component__list li:nth-child(1) { + transition-delay: 0.05s; + -webkit-transform: translateY(70px); + transform: translateY(70px); } +.mfb-component--tl.mfb-slidein-spring[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(2), .mfb-component--tl.mfb-slidein-spring[data-mfb-state="open"] .mfb-component__list li:nth-child(2), +.mfb-component--tr.mfb-slidein-spring[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(2), +.mfb-component--tr.mfb-slidein-spring[data-mfb-state="open"] .mfb-component__list li:nth-child(2) { + transition-delay: 0.1s; + -webkit-transform: translateY(140px); + transform: translateY(140px); } +.mfb-component--tl.mfb-slidein-spring[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(3), .mfb-component--tl.mfb-slidein-spring[data-mfb-state="open"] .mfb-component__list li:nth-child(3), +.mfb-component--tr.mfb-slidein-spring[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(3), +.mfb-component--tr.mfb-slidein-spring[data-mfb-state="open"] .mfb-component__list li:nth-child(3) { + transition-delay: 0.15s; + -webkit-transform: translateY(210px); + transform: translateY(210px); } +.mfb-component--tl.mfb-slidein-spring[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(4), .mfb-component--tl.mfb-slidein-spring[data-mfb-state="open"] .mfb-component__list li:nth-child(4), +.mfb-component--tr.mfb-slidein-spring[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(4), +.mfb-component--tr.mfb-slidein-spring[data-mfb-state="open"] .mfb-component__list li:nth-child(4) { + transition-delay: 0.2s; + -webkit-transform: translateY(280px); + transform: translateY(280px); } + +.mfb-component--bl.mfb-slidein-spring .mfb-component__list li, +.mfb-component--br.mfb-slidein-spring .mfb-component__list li { + opacity: 0; + transition: all 0.5s; + transition-timing-function: cubic-bezier(0.68, -0.55, 0.265, 1.55); } +.mfb-component--bl.mfb-slidein-spring .mfb-component__list li:nth-child(1), +.mfb-component--br.mfb-slidein-spring .mfb-component__list li:nth-child(1) { + transition-delay: 0.05s; } +.mfb-component--bl.mfb-slidein-spring .mfb-component__list li:nth-child(2), +.mfb-component--br.mfb-slidein-spring .mfb-component__list li:nth-child(2) { + transition-delay: 0.1s; } +.mfb-component--bl.mfb-slidein-spring .mfb-component__list li:nth-child(3), +.mfb-component--br.mfb-slidein-spring .mfb-component__list li:nth-child(3) { + transition-delay: 0.15s; } +.mfb-component--bl.mfb-slidein-spring .mfb-component__list li:nth-child(4), +.mfb-component--br.mfb-slidein-spring .mfb-component__list li:nth-child(4) { + transition-delay: 0.2s; } +.mfb-component--bl.mfb-slidein-spring[data-mfb-toggle="hover"]:hover .mfb-component__list li, .mfb-component--bl.mfb-slidein-spring[data-mfb-state="open"] .mfb-component__list li, +.mfb-component--br.mfb-slidein-spring[data-mfb-toggle="hover"]:hover .mfb-component__list li, +.mfb-component--br.mfb-slidein-spring[data-mfb-state="open"] .mfb-component__list li { + opacity: 1; } +.mfb-component--bl.mfb-slidein-spring[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(1), .mfb-component--bl.mfb-slidein-spring[data-mfb-state="open"] .mfb-component__list li:nth-child(1), +.mfb-component--br.mfb-slidein-spring[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(1), +.mfb-component--br.mfb-slidein-spring[data-mfb-state="open"] .mfb-component__list li:nth-child(1) { + transition-delay: 0.05s; + -webkit-transform: translateY(-70px); + transform: translateY(-70px); } +.mfb-component--bl.mfb-slidein-spring[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(2), .mfb-component--bl.mfb-slidein-spring[data-mfb-state="open"] .mfb-component__list li:nth-child(2), +.mfb-component--br.mfb-slidein-spring[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(2), +.mfb-component--br.mfb-slidein-spring[data-mfb-state="open"] .mfb-component__list li:nth-child(2) { + transition-delay: 0.1s; + -webkit-transform: translateY(-140px); + transform: translateY(-140px); } +.mfb-component--bl.mfb-slidein-spring[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(3), .mfb-component--bl.mfb-slidein-spring[data-mfb-state="open"] .mfb-component__list li:nth-child(3), +.mfb-component--br.mfb-slidein-spring[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(3), +.mfb-component--br.mfb-slidein-spring[data-mfb-state="open"] .mfb-component__list li:nth-child(3) { + transition-delay: 0.15s; + -webkit-transform: translateY(-210px); + transform: translateY(-210px); } +.mfb-component--bl.mfb-slidein-spring[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(4), .mfb-component--bl.mfb-slidein-spring[data-mfb-state="open"] .mfb-component__list li:nth-child(4), +.mfb-component--br.mfb-slidein-spring[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(4), +.mfb-component--br.mfb-slidein-spring[data-mfb-state="open"] .mfb-component__list li:nth-child(4) { + transition-delay: 0.2s; + -webkit-transform: translateY(-280px); + transform: translateY(-280px); } + +/** + * ZOOM-IN + * When hovering the main button, the child buttons grow + * from zero to normal size. + * + */ +.mfb-component--tl.mfb-zoomin .mfb-component__list li, +.mfb-component--tr.mfb-zoomin .mfb-component__list li { + -webkit-transform: scale(0); + transform: scale(0); } +.mfb-component--tl.mfb-zoomin .mfb-component__list li:nth-child(1), +.mfb-component--tr.mfb-zoomin .mfb-component__list li:nth-child(1) { + -webkit-transform: translateY(70px) scale(0); + transform: translateY(70px) scale(0); + transition: all 0.5s; + transition-delay: 0.15s; } +.mfb-component--tl.mfb-zoomin .mfb-component__list li:nth-child(2), +.mfb-component--tr.mfb-zoomin .mfb-component__list li:nth-child(2) { + -webkit-transform: translateY(140px) scale(0); + transform: translateY(140px) scale(0); + transition: all 0.5s; + transition-delay: 0.1s; } +.mfb-component--tl.mfb-zoomin .mfb-component__list li:nth-child(3), +.mfb-component--tr.mfb-zoomin .mfb-component__list li:nth-child(3) { + -webkit-transform: translateY(210px) scale(0); + transform: translateY(210px) scale(0); + transition: all 0.5s; + transition-delay: 0.05s; } +.mfb-component--tl.mfb-zoomin .mfb-component__list li:nth-child(4), +.mfb-component--tr.mfb-zoomin .mfb-component__list li:nth-child(4) { + -webkit-transform: translateY(280px) scale(0); + transform: translateY(280px) scale(0); + transition: all 0.5s; + transition-delay: 0s; } +.mfb-component--tl.mfb-zoomin[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(1), .mfb-component--tl.mfb-zoomin[data-mfb-state="open"] .mfb-component__list li:nth-child(1), +.mfb-component--tr.mfb-zoomin[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(1), +.mfb-component--tr.mfb-zoomin[data-mfb-state="open"] .mfb-component__list li:nth-child(1) { + -webkit-transform: translateY(70px) scale(1); + transform: translateY(70px) scale(1); + transition-delay: 0.05s; } +.mfb-component--tl.mfb-zoomin[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(2), .mfb-component--tl.mfb-zoomin[data-mfb-state="open"] .mfb-component__list li:nth-child(2), +.mfb-component--tr.mfb-zoomin[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(2), +.mfb-component--tr.mfb-zoomin[data-mfb-state="open"] .mfb-component__list li:nth-child(2) { + -webkit-transform: translateY(140px) scale(1); + transform: translateY(140px) scale(1); + transition-delay: 0.1s; } +.mfb-component--tl.mfb-zoomin[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(3), .mfb-component--tl.mfb-zoomin[data-mfb-state="open"] .mfb-component__list li:nth-child(3), +.mfb-component--tr.mfb-zoomin[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(3), +.mfb-component--tr.mfb-zoomin[data-mfb-state="open"] .mfb-component__list li:nth-child(3) { + -webkit-transform: translateY(210px) scale(1); + transform: translateY(210px) scale(1); + transition-delay: 0.15s; } +.mfb-component--tl.mfb-zoomin[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(4), .mfb-component--tl.mfb-zoomin[data-mfb-state="open"] .mfb-component__list li:nth-child(4), +.mfb-component--tr.mfb-zoomin[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(4), +.mfb-component--tr.mfb-zoomin[data-mfb-state="open"] .mfb-component__list li:nth-child(4) { + -webkit-transform: translateY(280px) scale(1); + transform: translateY(280px) scale(1); + transition-delay: 0.2s; } + +.mfb-component--bl.mfb-zoomin .mfb-component__list li, +.mfb-component--br.mfb-zoomin .mfb-component__list li { + -webkit-transform: scale(0); + transform: scale(0); } +.mfb-component--bl.mfb-zoomin .mfb-component__list li:nth-child(1), +.mfb-component--br.mfb-zoomin .mfb-component__list li:nth-child(1) { + -webkit-transform: translateY(-70px) scale(0); + transform: translateY(-70px) scale(0); + transition: all 0.5s; + transition-delay: 0.15s; } +.mfb-component--bl.mfb-zoomin .mfb-component__list li:nth-child(2), +.mfb-component--br.mfb-zoomin .mfb-component__list li:nth-child(2) { + -webkit-transform: translateY(-140px) scale(0); + transform: translateY(-140px) scale(0); + transition: all 0.5s; + transition-delay: 0.1s; } +.mfb-component--bl.mfb-zoomin .mfb-component__list li:nth-child(3), +.mfb-component--br.mfb-zoomin .mfb-component__list li:nth-child(3) { + -webkit-transform: translateY(-210px) scale(0); + transform: translateY(-210px) scale(0); + transition: all 0.5s; + transition-delay: 0.05s; } +.mfb-component--bl.mfb-zoomin .mfb-component__list li:nth-child(4), +.mfb-component--br.mfb-zoomin .mfb-component__list li:nth-child(4) { + -webkit-transform: translateY(-280px) scale(0); + transform: translateY(-280px) scale(0); + transition: all 0.5s; + transition-delay: 0s; } +.mfb-component--bl.mfb-zoomin[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(1), .mfb-component--bl.mfb-zoomin[data-mfb-state="open"] .mfb-component__list li:nth-child(1), +.mfb-component--br.mfb-zoomin[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(1), +.mfb-component--br.mfb-zoomin[data-mfb-state="open"] .mfb-component__list li:nth-child(1) { + -webkit-transform: translateY(-70px) scale(1); + transform: translateY(-70px) scale(1); + transition-delay: 0.05s; } +.mfb-component--bl.mfb-zoomin[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(2), .mfb-component--bl.mfb-zoomin[data-mfb-state="open"] .mfb-component__list li:nth-child(2), +.mfb-component--br.mfb-zoomin[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(2), +.mfb-component--br.mfb-zoomin[data-mfb-state="open"] .mfb-component__list li:nth-child(2) { + -webkit-transform: translateY(-140px) scale(1); + transform: translateY(-140px) scale(1); + transition-delay: 0.1s; } +.mfb-component--bl.mfb-zoomin[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(3), .mfb-component--bl.mfb-zoomin[data-mfb-state="open"] .mfb-component__list li:nth-child(3), +.mfb-component--br.mfb-zoomin[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(3), +.mfb-component--br.mfb-zoomin[data-mfb-state="open"] .mfb-component__list li:nth-child(3) { + -webkit-transform: translateY(-210px) scale(1); + transform: translateY(-210px) scale(1); + transition-delay: 0.15s; } +.mfb-component--bl.mfb-zoomin[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(4), .mfb-component--bl.mfb-zoomin[data-mfb-state="open"] .mfb-component__list li:nth-child(4), +.mfb-component--br.mfb-zoomin[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(4), +.mfb-component--br.mfb-zoomin[data-mfb-state="open"] .mfb-component__list li:nth-child(4) { + -webkit-transform: translateY(-280px) scale(1); + transform: translateY(-280px) scale(1); + transition-delay: 0.2s; } + +/** + * FOUNTAIN + * When hovering the main button the child buttons + * jump into view from outside the viewport + */ +.mfb-component--tl.mfb-fountain .mfb-component__list li, +.mfb-component--tr.mfb-fountain .mfb-component__list li { + -webkit-transform: scale(0); + transform: scale(0); } +.mfb-component--tl.mfb-fountain .mfb-component__list li:nth-child(1), +.mfb-component--tr.mfb-fountain .mfb-component__list li:nth-child(1) { + -webkit-transform: translateY(-70px) scale(0); + transform: translateY(-70px) scale(0); + transition: all 0.5s; + transition-delay: 0.15s; } +.mfb-component--tl.mfb-fountain .mfb-component__list li:nth-child(2), +.mfb-component--tr.mfb-fountain .mfb-component__list li:nth-child(2) { + -webkit-transform: translateY(-140px) scale(0); + transform: translateY(-140px) scale(0); + transition: all 0.5s; + transition-delay: 0.1s; } +.mfb-component--tl.mfb-fountain .mfb-component__list li:nth-child(3), +.mfb-component--tr.mfb-fountain .mfb-component__list li:nth-child(3) { + -webkit-transform: translateY(-210px) scale(0); + transform: translateY(-210px) scale(0); + transition: all 0.5s; + transition-delay: 0.05s; } +.mfb-component--tl.mfb-fountain .mfb-component__list li:nth-child(4), +.mfb-component--tr.mfb-fountain .mfb-component__list li:nth-child(4) { + -webkit-transform: translateY(-280px) scale(0); + transform: translateY(-280px) scale(0); + transition: all 0.5s; + transition-delay: 0s; } +.mfb-component--tl.mfb-fountain[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(1), .mfb-component--tl.mfb-fountain[data-mfb-state="open"] .mfb-component__list li:nth-child(1), +.mfb-component--tr.mfb-fountain[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(1), +.mfb-component--tr.mfb-fountain[data-mfb-state="open"] .mfb-component__list li:nth-child(1) { + -webkit-transform: translateY(70px) scale(1); + transform: translateY(70px) scale(1); + transition-delay: 0.05s; } +.mfb-component--tl.mfb-fountain[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(2), .mfb-component--tl.mfb-fountain[data-mfb-state="open"] .mfb-component__list li:nth-child(2), +.mfb-component--tr.mfb-fountain[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(2), +.mfb-component--tr.mfb-fountain[data-mfb-state="open"] .mfb-component__list li:nth-child(2) { + -webkit-transform: translateY(140px) scale(1); + transform: translateY(140px) scale(1); + transition-delay: 0.1s; } +.mfb-component--tl.mfb-fountain[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(3), .mfb-component--tl.mfb-fountain[data-mfb-state="open"] .mfb-component__list li:nth-child(3), +.mfb-component--tr.mfb-fountain[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(3), +.mfb-component--tr.mfb-fountain[data-mfb-state="open"] .mfb-component__list li:nth-child(3) { + -webkit-transform: translateY(210px) scale(1); + transform: translateY(210px) scale(1); + transition-delay: 0.15s; } +.mfb-component--tl.mfb-fountain[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(4), .mfb-component--tl.mfb-fountain[data-mfb-state="open"] .mfb-component__list li:nth-child(4), +.mfb-component--tr.mfb-fountain[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(4), +.mfb-component--tr.mfb-fountain[data-mfb-state="open"] .mfb-component__list li:nth-child(4) { + -webkit-transform: translateY(280px) scale(1); + transform: translateY(280px) scale(1); + transition-delay: 0.2s; } + +.mfb-component--bl.mfb-fountain .mfb-component__list li, +.mfb-component--br.mfb-fountain .mfb-component__list li { + -webkit-transform: scale(0); + transform: scale(0); } +.mfb-component--bl.mfb-fountain .mfb-component__list li:nth-child(1), +.mfb-component--br.mfb-fountain .mfb-component__list li:nth-child(1) { + -webkit-transform: translateY(70px) scale(0); + transform: translateY(70px) scale(0); + transition: all 0.5s; + transition-delay: 0.15s; } +.mfb-component--bl.mfb-fountain .mfb-component__list li:nth-child(2), +.mfb-component--br.mfb-fountain .mfb-component__list li:nth-child(2) { + -webkit-transform: translateY(140px) scale(0); + transform: translateY(140px) scale(0); + transition: all 0.5s; + transition-delay: 0.1s; } +.mfb-component--bl.mfb-fountain .mfb-component__list li:nth-child(3), +.mfb-component--br.mfb-fountain .mfb-component__list li:nth-child(3) { + -webkit-transform: translateY(210px) scale(0); + transform: translateY(210px) scale(0); + transition: all 0.5s; + transition-delay: 0.05s; } +.mfb-component--bl.mfb-fountain .mfb-component__list li:nth-child(4), +.mfb-component--br.mfb-fountain .mfb-component__list li:nth-child(4) { + -webkit-transform: translateY(280px) scale(0); + transform: translateY(280px) scale(0); + transition: all 0.5s; + transition-delay: 0s; } +.mfb-component--bl.mfb-fountain[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(1), .mfb-component--bl.mfb-fountain[data-mfb-state="open"] .mfb-component__list li:nth-child(1), +.mfb-component--br.mfb-fountain[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(1), +.mfb-component--br.mfb-fountain[data-mfb-state="open"] .mfb-component__list li:nth-child(1) { + -webkit-transform: translateY(-70px) scale(1); + transform: translateY(-70px) scale(1); + transition-delay: 0.05s; } +.mfb-component--bl.mfb-fountain[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(2), .mfb-component--bl.mfb-fountain[data-mfb-state="open"] .mfb-component__list li:nth-child(2), +.mfb-component--br.mfb-fountain[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(2), +.mfb-component--br.mfb-fountain[data-mfb-state="open"] .mfb-component__list li:nth-child(2) { + -webkit-transform: translateY(-140px) scale(1); + transform: translateY(-140px) scale(1); + transition-delay: 0.1s; } +.mfb-component--bl.mfb-fountain[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(3), .mfb-component--bl.mfb-fountain[data-mfb-state="open"] .mfb-component__list li:nth-child(3), +.mfb-component--br.mfb-fountain[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(3), +.mfb-component--br.mfb-fountain[data-mfb-state="open"] .mfb-component__list li:nth-child(3) { + -webkit-transform: translateY(-210px) scale(1); + transform: translateY(-210px) scale(1); + transition-delay: 0.15s; } +.mfb-component--bl.mfb-fountain[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(4), .mfb-component--bl.mfb-fountain[data-mfb-state="open"] .mfb-component__list li:nth-child(4), +.mfb-component--br.mfb-fountain[data-mfb-toggle="hover"]:hover .mfb-component__list li:nth-child(4), +.mfb-component--br.mfb-fountain[data-mfb-state="open"] .mfb-component__list li:nth-child(4) { + -webkit-transform: translateY(-280px) scale(1); + transform: translateY(-280px) scale(1); + transition-delay: 0.2s; } + +/*------------------------------------*\ + #LABELS | base +\*------------------------------------*/ +/** + * These are the labels associated to each button, + * exposed only when hovering the related button. + * They are called labels but are in fact data-attributes of + * each button (an anchor tag). + */ +[data-mfb-label]:after { + content: attr(data-mfb-label); + opacity: 0; + transition: all 0.5s; + background: rgba(0, 0, 0, 0.4); + padding: 4px 10px; + border-radius: 3px; + color: rgba(255, 255, 255, 0.8); + font-size: 14px; + font-weight: normal; + pointer-events: none; + line-height: normal; + position: absolute; + top: 50%; + margin-top: -11px; + transition: all 0.5s; } + +[data-mfb-toggle="hover"] [data-mfb-label]:hover:after, +[data-mfb-state="open"] [data-mfb-label]:after { + content: attr(data-mfb-label); + opacity: 1; + transition: all 0.3s; } + +/*------------------------------------*\ + #LABELS | Modifiers +\*------------------------------------*/ +.mfb-component--br [data-mfb-label]:after, .mfb-component--tr [data-mfb-label]:after { + content: attr(data-mfb-label); + right: 70px; } + +.mfb-component--br .mfb-component__list [data-mfb-label]:after, .mfb-component--tr .mfb-component__list [data-mfb-label]:after { + content: attr(data-mfb-label); + right: 70px; } + +.mfb-component--tl [data-mfb-label]:after, .mfb-component--bl [data-mfb-label]:after { + content: attr(data-mfb-label); + left: 70px; } + +.mfb-component--tl .mfb-component__list [data-mfb-label]:after, .mfb-component--bl .mfb-component__list [data-mfb-label]:after { + content: attr(data-mfb-label); + left: 70px; } + +/*------------------------------------*\ + #DEVELOPMENT | In development +\*------------------------------------*/ +/** + * This part is where unfinished code should stay. + * When a feature is ready(sh) move these styles to their proper place. + */ +/*------------------------------------*\ + #DEVELOPMENT | Debuggers +\*------------------------------------*/ +/** + * These are mainly helpers for development. They do not have to end up + * in production but it's handy to keep them when developing. + */ +/** + * Apply this class to the html tag when developing the slide-in button + */ + +/*# sourceMappingURL=mfb.css.map */ diff --git a/decide/static/css/visualizer.css b/decide/static/css/visualizer.css new file mode 100644 index 0000000000..cd6aa464bd --- /dev/null +++ b/decide/static/css/visualizer.css @@ -0,0 +1,95 @@ +@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@200;300;400;500;600;700;800;900&display=swap'); + +* { + margin: 0; + padding: 0; + box-sizing: border-box; + font-family: 'Poppins' ,sans-serif; +} +.voting { + margin-top: 20px; + margin-left: 40px; +} +.voting h2 { + margin-bottom: 25px; +} +.voting .podium { + position: relative; + display: flex; + justify-content: center; + align-items: center; + width: 60%; + margin-top: 20px; + margin-bottom: 20px; + margin-left: 30%; + margin-right: 30%; + background: white; + border-radius: 20px; + box-shadow: 0 50px 50px rgba(0, 0, 0, 0.5); +} +.voting .theTable, .voting section { + position: relative; + display: flex; + justify-content: center; + align-items: center; + width: 90%; + margin-left: 15%; + margin-right: 15%; + background: white; + border-radius: 20px; + box-shadow: 0 50px 50px rgba(0, 0, 0, 0.5); +} +.voting .theTable .tb, .voting section .tb { + margin: 20px; +} +.voting .theTable .tb th, td { + border-bottom: 2px solid #ddd; +} +.voting section { + position: relative; + display: flex; + text-align: center; + justify-content: center; + align-items: center; + width: 100%; + margin-top: 20px; + margin-bottom: 100px; + margin-left: 11%; + margin-right: 7%; + background: white; + border-radius: 20px; + box-shadow: 0 50px 50px rgba(0, 0, 0, 0.5); +} +.podio{ + height: 300px; + vertical-align: bottom; + padding: 5px; + } + #response{ + font-family: courier-new, courier; + } + #podium0, #podium1, #podium2{ + width: 150px; + font-size: 5mm; + text-align: center; + font-weight: 700; + } + #winner{ + width: 150px; + font-size: 7mm; + text-align: center; + font-weight: 700; + } + + #podium0 { /* gold */ + height: 250px; + background: rgb(255, 215, 0); + } + #podium1 { /* silver */ + height: 200px; + background: rgb(192, 192, 192); + } + #podium2 { /* bronze */ + height: 150px; + background: rgb(205,127,50); + } \ No newline at end of file diff --git a/decide/static/favicon/picaro.png b/decide/static/favicon/picaro.png new file mode 100644 index 0000000000..19ac79cb3b Binary files /dev/null and b/decide/static/favicon/picaro.png differ diff --git a/decide/static/images/AbrahamG.jpg b/decide/static/images/AbrahamG.jpg new file mode 100644 index 0000000000..0c8ffcf172 Binary files /dev/null and b/decide/static/images/AbrahamG.jpg differ diff --git a/decide/static/images/DavidS.jpeg b/decide/static/images/DavidS.jpeg new file mode 100644 index 0000000000..7ee0b6d5f6 Binary files /dev/null and b/decide/static/images/DavidS.jpeg differ diff --git a/decide/static/images/GabrielG.jpg b/decide/static/images/GabrielG.jpg new file mode 100644 index 0000000000..84c2611d0e Binary files /dev/null and b/decide/static/images/GabrielG.jpg differ diff --git a/decide/static/images/MartinA.jpeg b/decide/static/images/MartinA.jpeg new file mode 100644 index 0000000000..7ef7ec34f9 Binary files /dev/null and b/decide/static/images/MartinA.jpeg differ diff --git a/decide/static/images/PabloF.jpeg b/decide/static/images/PabloF.jpeg new file mode 100644 index 0000000000..329e74c0f8 Binary files /dev/null and b/decide/static/images/PabloF.jpeg differ diff --git a/decide/static/images/ThibautL.jpeg b/decide/static/images/ThibautL.jpeg new file mode 100644 index 0000000000..1855a949d1 Binary files /dev/null and b/decide/static/images/ThibautL.jpeg differ diff --git a/decide/static/images/england.jpg b/decide/static/images/england.jpg new file mode 100644 index 0000000000..72ec86a356 Binary files /dev/null and b/decide/static/images/england.jpg differ diff --git a/decide/static/images/france.jpg b/decide/static/images/france.jpg new file mode 100644 index 0000000000..2306673a10 Binary files /dev/null and b/decide/static/images/france.jpg differ diff --git a/decide/static/images/german.jpg b/decide/static/images/german.jpg new file mode 100644 index 0000000000..bdcb0b2c27 Binary files /dev/null and b/decide/static/images/german.jpg differ diff --git a/decide/static/images/location.png b/decide/static/images/location.png new file mode 100644 index 0000000000..9547c12d96 Binary files /dev/null and b/decide/static/images/location.png differ diff --git a/decide/static/images/mail.png b/decide/static/images/mail.png new file mode 100644 index 0000000000..914f4f9301 Binary files /dev/null and b/decide/static/images/mail.png differ diff --git a/decide/static/images/phone.png b/decide/static/images/phone.png new file mode 100644 index 0000000000..c2ff36afc1 Binary files /dev/null and b/decide/static/images/phone.png differ diff --git a/decide/static/images/spain.jpg b/decide/static/images/spain.jpg new file mode 100644 index 0000000000..e1f46f2c93 Binary files /dev/null and b/decide/static/images/spain.jpg differ diff --git a/decide/static/js/mfb.js b/decide/static/js/mfb.js new file mode 100644 index 0000000000..ea6ce731fe --- /dev/null +++ b/decide/static/js/mfb.js @@ -0,0 +1,98 @@ +/** + * Material floating button + * By: Nobita + * Repo and docs: https://github.com/nobitagit/material-floating-button + * + * License: MIT + */ + + // build script hook - don't remove + ;(function ( window, document, undefined ) { + + + 'use strict'; + + /** + * Some defaults + */ + var clickOpt = 'click', + hoverOpt = 'hover', + toggleMethod = 'data-mfb-toggle', + menuState = 'data-mfb-state', + isOpen = 'open', + isClosed = 'closed', + mainButtonClass = 'mfb-component__button--main'; + + /** + * Internal references + */ + var elemsToClick, + elemsToHover, + mainButton, + target, + currentState; + + /** + * For every menu we need to get the main button and attach the appropriate evt. + */ + function attachEvt( elems, evt ){ + for( var i = 0, len = elems.length; i < len; i++ ){ + mainButton = elems[i].querySelector('.' + mainButtonClass); + mainButton.addEventListener( evt , toggleButton, false); + } + } + + /** + * Remove the hover option, set a click toggle and a default, + * initial state of 'closed' to menu that's been targeted. + */ + function replaceAttrs( elems ){ + for( var i = 0, len = elems.length; i < len; i++ ){ + elems[i].setAttribute( toggleMethod, clickOpt ); + elems[i].setAttribute( menuState, isClosed ); + } + } + + function getElemsByToggleMethod( selector ){ + return document.querySelectorAll('[' + toggleMethod + '="' + selector + '"]'); + } + + /** + * The open/close action is performed by toggling an attribute + * on the menu main element. + * + * First, check if the target is the menu itself. If it's a child + * keep walking up the tree until we found the main element + * where we can toggle the state. + */ + function toggleButton( evt ){ + + target = evt.target; + while ( target && !target.getAttribute( toggleMethod ) ){ + target = target.parentNode; + if(!target) { return; } + } + + currentState = target.getAttribute( menuState ) === isOpen ? isClosed : isOpen; + + target.setAttribute(menuState, currentState); + + } + + /** + * On touch enabled devices we assume that no hover state is possible. + * So, we get the menu with hover action configured and we set it up + * in order to make it usable with tap/click. + **/ + if ( window.Modernizr && Modernizr.touch ){ + elemsToHover = getElemsByToggleMethod( hoverOpt ); + replaceAttrs( elemsToHover ); + } + + elemsToClick = getElemsByToggleMethod( clickOpt ); + + attachEvt( elemsToClick, 'click' ); + +// build script hook - don't remove +})( window, document ); + diff --git a/decide/store/views.py b/decide/store/views.py index 543d009a14..a428c4ae6c 100644 --- a/decide/store/views.py +++ b/decide/store/views.py @@ -18,8 +18,9 @@ class StoreView(generics.ListAPIView): filter_fields = ('voting_id', 'voter_id') def get(self, request): - self.permission_classes = (UserIsStaff,) - self.check_permissions(request) + #self.permission_classes = (UserIsStaff,) + #self.check_permissions(request) + return super().get(request) def post(self, request): diff --git a/decide/travis_local_settings.py b/decide/travis_local_settings.py new file mode 100644 index 0000000000..d4162dae92 --- /dev/null +++ b/decide/travis_local_settings.py @@ -0,0 +1,41 @@ +ALLOWED_HOSTS = ["*"] + +# Modules in use, commented modules that you won't use +MODULES = [ + 'authentication', + 'base', + 'booth', + 'census', + 'mixnet', + 'postproc', + 'store', + 'visualizer', + 'voting', +] + +APIS = { + 'authentication': 'http://localhost:8000', + 'base': 'http://localhost:8000', + 'booth': 'http://localhost:8000', + 'census': 'http://localhost:8000', + 'mixnet': 'http://localhost:8000', + 'postproc': 'http://localhost:8000', + 'store': 'http://localhost:8000', + 'visualizer': 'http://localhost:8000', + 'voting': 'http://localhost:8000', +} + +BASEURL = 'http://localhost:8000' + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.postgresql', + 'NAME': 'postgres', + 'USER': 'postgres', + 'HOST': 'localhost', + 'PORT': '5432', + } +} + +# number of bits for the key, all auths should use the same number of bits +KEYBITS = 256 diff --git a/decide/visualizer/templates/visualizer/aboutUs.html b/decide/visualizer/templates/visualizer/aboutUs.html new file mode 100644 index 0000000000..18ec413787 --- /dev/null +++ b/decide/visualizer/templates/visualizer/aboutUs.html @@ -0,0 +1,150 @@ +{% extends "base.html" %} +{% load i18n static %} + +{% block title %} - Visualización{% endblock %} +{% block extrahead %} + + + + + +{% endblock %} + +{% block content %} + + + {% trans "Decide Visualization" %} + + + + + + + + +
+

{% trans "Visualization Team" %}

+
+
+
+
+
+ Pablo +
Pablo
+
Franco Sánchez
+

{% trans "Computer Engineering student in Software Engineering" %}

+ + {% trans "GitHub Profile" %} +
+
+ Abraham +
Abraham
+
García Villalobos
+

{% trans "Computer Engineering student in Software Engineering" %}

+ + {% trans "GitHub Profile" %} +
+
+ Martin +
Martín Arturo
+
Guerrero Romero
+

{% trans "Computer Engineering student in Software Engineering" %}

+ + {% trans "GitHub Profile" %} +
+
+ Gabriel +
Gabriel
+
Gutiérrez Prieto
+

{% trans "Computer Engineering student in Software Engineering" %}

+ + {% trans "GitHub Profile" %} +
+
+ Thibaut +
Thibaut
+
Lopez
+

{% trans "Computer Engineering student in Software Engineering" %}

+ + {% trans "GitHub Profile" %} +
+
+ David +
David
+
Soto Ponce
+

{% trans "Computer Engineering student in Software Engineering" %}

+ + {% trans "GitHub Profile" %} +
+
+
+
+ + + +
+ {% trans "Evolution and Configuration Management" %} · Decide + Decide Pícaro · Visualización © 2021 +
+
+ +{% endblock %} + +{% block extrabody %} + + + + + + + + + + + +{% endblock %} diff --git a/decide/visualizer/templates/visualizer/contactUs.html b/decide/visualizer/templates/visualizer/contactUs.html new file mode 100644 index 0000000000..a7fd7a9919 --- /dev/null +++ b/decide/visualizer/templates/visualizer/contactUs.html @@ -0,0 +1,153 @@ +{% extends "base.html" %} +{% load i18n static %} + +{% block title %} - Visualización{% endblock %} +{% block extrahead %} + + + + + + + +{% endblock %} + +{% block content %} +
+ + + + {% trans "Decide Visualization" %} + + + + + + + + +
+
+
+
+

{% trans "Contact Info" %}

+ +
+
    +
  • +
  • +
  • +
  • +
  • +
  • +
  • +
+
+
+

{% trans "Send a Message" %}

+
+
+
+ + {% trans "Full name" %} * +
+
+ + {% trans "Subject" %} * +
+
+ + {% trans "Email address" %} * +
+
+ + {% trans "Write your message here" %} * +
+
+ +
+
+
+
+
+
+ + + +
+ {% trans "Evolution and Configuration Management" %} · Decide + Decide Pícaro · Visualización © 2021 +
+
+
+{% endblock %} + +{% block extrabody %} + + + + + + + + + + + + +{% endblock %} diff --git a/decide/visualizer/templates/visualizer/visualizer.html b/decide/visualizer/templates/visualizer/visualizer.html index 0faed6bac3..079c647201 100644 --- a/decide/visualizer/templates/visualizer/visualizer.html +++ b/decide/visualizer/templates/visualizer/visualizer.html @@ -1,57 +1,191 @@ {% extends "base.html" %} {% load i18n static %} +{% block title %} - Visualización{% endblock %} {% block extrahead %} - - - + + + + + + + + + + + + + + + + + + + + + + + + + + {% endblock %} {% block content %}
- - - Decide + + + {% trans "Decide Visualization" %} + + + +
+ Telegram + + + {% trans "Visualizer" %} +
+ + + + +
-

[[ voting.id ]] - [[ voting.name ]]

+
+

{% trans "Voting not started" %}

+ +
+ +
+

{% trans "Voting in progress" %}

+
+ + + + + + + + + +
[[voting.question.desc]]
+
+ + + + + + + + + + + + +
{% trans "Number of votes" %}
{{numero_votos}}
+
+
+
+ +
-

Votación no comenzada

-

Votación en curso

-

Resultados:

+

{% trans "Results" %}

+ +
+

+                
+
+ + + + + + +
{% trans "2nd place"%}
{% trans "WINNER" %}
{% trans "3rd place" %}
+
+ + +
+ + + + + + + + + +
[[voting.question.desc]]
+
+ + + + + + + + + + + + + + + +
{% trans "Option" %} {% trans "Punctuation" %} {% trans "Votes" %}
[[opt.option]][[opt.postproc]][[opt.votes]]
+
+
+
+ - + +
+
- - - + + - - - - + + + + + + + + + + +
OpciónPuntuaciónVotos
{% trans "Donut Chart" %}
{% trans "Bar Chart" %}
[[opt.option]][[opt.postproc]][[opt.votes]]
+
-
+ + + + +
+ {% trans "Evolution and Configuration Management" %} · Decide + Decide Pícaro · Visualización © 2021 +
+
{% endblock %} {% block extrabody %} - - - - - - + + + + + + + + + + + + + + + + + + + + + + + {% endblock %} diff --git a/decide/visualizer/templates/visualizer/visualizer_home.html b/decide/visualizer/templates/visualizer/visualizer_home.html new file mode 100644 index 0000000000..85998759e0 --- /dev/null +++ b/decide/visualizer/templates/visualizer/visualizer_home.html @@ -0,0 +1,240 @@ +{% extends "base.html" %} +{% load i18n static %} + +{% block title %} - Visualización{% endblock %} +{% block extrahead %} + + + + + + + + + + + + + + + + + + + + + + + + +{% endblock %} + +{% block content %} +
+ + + + {% trans "Decide Visualization" %} + + + +
+ + Telegram + + +
+ +
+
+ +
+ +
+ + + + +
+ + + + + + + + + + + + + + + + {% endfor %} + + + +
{% trans "Votings" %}
{% trans "Start date" %}
{% trans "End date" %}
+ {% for voting in votings %} +
{{ voting.name }}{{ voting.start_date }}{{ voting.end_date }}
+
+
+ + + + + + + + + + + + + +
{% trans "Bar Chart" %}
+
+
+
+
+ + + +
+ {% trans "Evolution and Configuration Management" %} · Decide + Decide Pícaro · Visualización © 2021 +
+
+
+{% endblock %} + +{% block extrabody %} + + + + + + + + + + +{% endblock %} diff --git a/decide/visualizer/tests.py b/decide/visualizer/tests.py index 7ce503c2dd..c4be3cb62f 100644 --- a/decide/visualizer/tests.py +++ b/decide/visualizer/tests.py @@ -1,3 +1,791 @@ from django.test import TestCase -# Create your tests here. +import unittest, time, re +from selenium import webdriver +from selenium.webdriver.common.by import By +from selenium.webdriver.support.ui import Select +from selenium.webdriver.common.action_chains import ActionChains +from selenium.webdriver.support import expected_conditions +from selenium.webdriver.support.wait import WebDriverWait +from selenium.webdriver.common.keys import Keys +from selenium.webdriver.common.desired_capabilities import DesiredCapabilities +from selenium.common.exceptions import NoSuchElementException +from selenium.common.exceptions import NoAlertPresentException + + + +class TestEmail(): + def setup(self): + options = webdriver.ChromeOptions() + options.headless = True + options.add_argument("--no-sandbox") + self.driver = webdriver.Chrome(options=options) + + def teardown(self): + self.driver.quit() + + def test_email(self): + self.driver.get("https://picaro-decide.herokuapp.com/admin/login/?next=/admin/") + self.driver.find_element_by_id('id_username').send_keys("admin") + self.driver.find_element_by_id('id_password').send_keys("picarodecide") + self.driver.find_element_by_id('login-form').click() + self.driver.get("https://picaro-decide.herokuapp.com/visualizer/5/") + self.driver.set_window_size(1552, 840) + self.driver.find_element(By.CSS_SELECTOR, ".btn-secondary:nth-child(2)").click() + self.driver.find_element(By.NAME, "name").click() + self.driver.find_element(By.NAME, "name").send_keys("test test") + self.driver.find_element(By.NAME, "subject").click() + self.driver.find_element(By.NAME, "subject").send_keys("test") + self.driver.find_element(By.NAME, "mail").click() + self.driver.find_element(By.NAME, "mail").send_keys("test@gmail.com") + self.driver.find_element(By.NAME, "Comment").click() + self.driver.find_element(By.NAME, "Comment").send_keys("test") + self.driver.find_element(By.CSS_SELECTOR, ".inputBox:nth-child(5) > input").click() + +class TestTraduccionFrances(): + def setup(self): + options = webdriver.ChromeOptions() + options.headless = True + options.add_argument("--no-sandbox") + self.driver = webdriver.Chrome(options=options) + + def teardown(self): + self.driver.quit() + + def test_traduccionFrances(self): + self.driver.get("https://picaro-decide.herokuapp.com/admin/login/?next=/admin/") + self.driver.find_element_by_id('id_username').send_keys("admin") + self.driver.find_element_by_id('id_password').send_keys("picarodecide") + self.driver.find_element_by_id('login-form').click() + self.driver.get("https://picaro-decide.herokuapp.com/visualizer/5/") + self.driver.set_window_size(1552, 840) + element = self.driver.find_element(By.CSS_SELECTOR, ".fa-language") + actions = ActionChains(self.driver) + actions.move_to_element(element).perform() + self.driver.find_element(By.CSS_SELECTOR, "li:nth-child(3) img").click() + assert self.driver.find_element(By.ID, "text").text == "Résultats" + +class TestTraduccionContactUs(): + def setup(self): + options = webdriver.ChromeOptions() + options.headless = True + options.add_argument("--no-sandbox") + self.driver = webdriver.Chrome(options=options) + + def teardown(self): + self.driver.quit() + + def test_traduccionContactUs(self): + self.driver.get("https://picaro-decide.herokuapp.com/visualizer/5/") + self.driver.set_window_size(1552, 840) + element = self.driver.find_element(By.CSS_SELECTOR, ".fa-language") + actions = ActionChains(self.driver) + actions.move_to_element(element).perform() + self.driver.find_element(By.CSS_SELECTOR, "li:nth-child(3) img").click() + self.driver.find_element(By.CSS_SELECTOR, ".btn-secondary:nth-child(2)").click() + assert self.driver.find_element(By.CSS_SELECTOR, ".contactForm > h2").text == "Envoyer en méssage" + +class TestQuestion(): + def setup(self): + options = webdriver.ChromeOptions() + options.headless = True + options.add_argument("--no-sandbox") + self.driver = webdriver.Chrome(options=options) + + def teardown(self): + self.driver.quit() + + def test_question(self): + self.driver.get("https://picaro-decide.herokuapp.com/admin/login/?next=/admin/") + self.driver.find_element_by_id('id_username').send_keys("admin") + self.driver.find_element_by_id('id_password').send_keys("picarodecide") + self.driver.find_element_by_id('login-form').click() + self.driver.get("https://picaro-decide.herokuapp.com/visualizer/5/") + self.driver.set_window_size(1552, 840) + elements = self.driver.find_elements(By.ID, "question") + assert len(elements) > 0 + +class TestMaps(): + def setup(self): + options = webdriver.ChromeOptions() + options.headless = True + options.add_argument("--no-sandbox") + self.driver = webdriver.Chrome(options=options) + + def teardown(self): + self.driver.quit() + + def test_maps(self): + self.driver.get("https://picaro-decide.herokuapp.com/admin/login/?next=/admin/") + self.driver.find_element_by_id('id_username').send_keys("admin") + self.driver.find_element_by_id('id_password').send_keys("picarodecide") + self.driver.find_element_by_id('login-form').click() + self.driver.get("https://picaro-decide.herokuapp.com/visualizer/5/") + self.driver.set_window_size(1552, 840) + self.driver.find_element(By.CSS_SELECTOR, ".btn-secondary:nth-child(2)").click() + elements = self.driver.find_elements(By.CSS_SELECTOR, "a > img") + assert len(elements) > 0 + +class TestContactUs(): + def setUp(self): + options = webdriver.ChromeOptions() + options.headless = True + options.add_argument("--no-sandbox") + self.driver = webdriver.Chrome(options=options) + self.driver.fullscreen_window() + + def test_contactUs(self): + self.driver.get("https://picaro-decide.herokuapp.com/admin/login/?next=/admin/") + self.driver.find_element_by_id('id_username').send_keys("admin") + self.driver.find_element_by_id('id_password').send_keys("picarodecide") + self.driver.find_element_by_id('login-form').click() + self.driver.get("https://picaro-decide.herokuapp.com/visualizer/5/") + element = self.driver.find_element(By.CSS_SELECTOR, ".fa-language") + actions = ActionChains(self.driver) + actions.move_to_element(element).perform() + self.driver.find_element(By.CSS_SELECTOR, "li:nth-child(1) > .pmd-floating-action-btn > img").click() + self.driver.find_element(By.CSS_SELECTOR, ".btn-secondary:nth-child(2)").click() + assert self.driver.find_element(By.CSS_SELECTOR, "div:nth-child(1) > h2").text == "Contact Info" + + def tearDown(self): + self.driver.quit() + +class TestContactUsBack(): + def setUp(self): + options = webdriver.ChromeOptions() + options.headless = True + options.add_argument("--no-sandbox") + self.driver = webdriver.Chrome(options=options) + self.driver.fullscreen_window() + + def test_contactUsBack(self): + self.driver.get("https://picaro-decide.herokuapp.com/admin/login/?next=/admin/") + self.driver.find_element_by_id('id_username').send_keys("admin") + self.driver.find_element_by_id('id_password').send_keys("picarodecide") + self.driver.find_element_by_id('login-form').click() + self.driver.get("https://picaro-decide.herokuapp.com/visualizer/5/") + element = self.driver.find_element(By.CSS_SELECTOR, ".fa-language") + actions = ActionChains(self.driver) + actions.move_to_element(element).perform() + self.driver.find_element(By.CSS_SELECTOR, "li:nth-child(1) > .pmd-floating-action-btn > img").click() + self.driver.find_element(By.CSS_SELECTOR, ".btn-secondary:nth-child(2)").click() + assert self.driver.find_element(By.CSS_SELECTOR, "div:nth-child(1) > h2").text == "Contact Info" + self.driver.find_element(By.CSS_SELECTOR, ".btn-secondary").click() + assert self.driver.find_element(By.ID, "saveAsPNG1").text == "Save as PNG" + + def tearDown(self): + self.driver.quit() + +class TestDarkMode(): + def setUp(self): + options = webdriver.ChromeOptions() + options.headless = True + options.add_argument("--no-sandbox") + self.driver = webdriver.Chrome(options=options) + self.driver.fullscreen_window() + + def test_darkMode(self): + self.driver.get("https://picaro-decide.herokuapp.com/admin/login/?next=/admin/") + self.driver.find_element_by_id('id_username').send_keys("admin") + self.driver.find_element_by_id('id_password').send_keys("picarodecide") + self.driver.find_element_by_id('login-form').click() + self.driver.get("https://picaro-decide.herokuapp.com/visualizer/5/") + self.driver.find_element(By.ID, "darkButton").click() + assert self.driver.find_element_by_tag_name('body').get_attribute("class") == "bg-dark" + element = self.driver.find_element(By.CSS_SELECTOR, ".fa-language") + actions = ActionChains(self.driver) + actions.move_to_element(element).perform() + self.driver.find_element(By.CSS_SELECTOR, "li:nth-child(1) > .pmd-floating-action-btn > img").click() + assert self.driver.find_element(By.ID, "lightButton").text == "Light mode" + + def tearDown(self): + self.driver.quit() + +class TestLightMode(): + def setUp(self): + options = webdriver.ChromeOptions() + options.headless = True + options.add_argument("--no-sandbox") + self.driver = webdriver.Chrome(options=options) + self.driver.fullscreen_window() + + def test_lightMode(self): + self.driver.get("https://picaro-decide.herokuapp.com/admin/login/?next=/admin/") + self.driver.find_element_by_id('id_username').send_keys("admin") + self.driver.find_element_by_id('id_password').send_keys("picarodecide") + self.driver.find_element_by_id('login-form').click() + self.driver.get("https://picaro-decide.herokuapp.com/visualizer/5/") + self.driver.find_element(By.ID, "darkButton").click() + self.driver.find_element(By.ID, "lightButton").click() + assert self.driver.find_element_by_tag_name('body').get_attribute("class") == "bg-light" + element = self.driver.find_element(By.CSS_SELECTOR, ".fa-language") + actions = ActionChains(self.driver) + actions.move_to_element(element).perform() + self.driver.find_element(By.CSS_SELECTOR, "li:nth-child(1) > .pmd-floating-action-btn > img").click() + assert self.driver.find_element(By.ID, "darkButton").text == "Dark mode" + + def tearDown(self): + self.driver.quit() + +class TestTraduccionEspanyol(): + def setup(self): + options = webdriver.ChromeOptions() + options.headless = True + options.add_argument("--no-sandbox") + self.driver = webdriver.Chrome(options=options) + self.driver.fullscreen_window() + + def test_traduccionEspanyol(self): + self.driver.get("https://picaro-decide.herokuapp.com/admin/login/?next=/admin/") + self.driver.find_element_by_id('id_username').send_keys("admin") + self.driver.find_element_by_id('id_password').send_keys("picarodecide") + self.driver.find_element_by_id('login-form').click() + self.driver.get("https://picaro-decide.herokuapp.com/visualizer/5/") + element = self.driver.find_element(By.CSS_SELECTOR, ".fa-language") + actions = ActionChains(self.driver) + actions.move_to_element(element).perform() + self.driver.find_element(By.CSS_SELECTOR, "li:nth-child(2) img").click() + assert self.driver.find_element(By.ID, "text").text == "Resultados" + + def teardown(self): + self.driver.quit() + +class TestTraduccionIngles(): + def setup(self): + options = webdriver.ChromeOptions() + options.headless = True + options.add_argument("--no-sandbox") + self.driver = webdriver.Chrome(options=options) + self.driver.fullscreen_window() + + def test_traduccionIngles(self): + self.driver.get("https://picaro-decide.herokuapp.com/admin/login/?next=/admin/") + self.driver.find_element_by_id('id_username').send_keys("admin") + self.driver.find_element_by_id('id_password').send_keys("picarodecide") + self.driver.find_element_by_id('login-form').click() + self.driver.get("https://picaro-decide.herokuapp.com/visualizer/5/") + element = self.driver.find_element(By.CSS_SELECTOR, ".fa-language") + actions = ActionChains(self.driver) + actions.move_to_element(element).perform() + self.driver.find_element(By.CSS_SELECTOR, "li:nth-child(2) img").click() + assert self.driver.find_element(By.ID, "text").text == "Resultados" + element = self.driver.find_element(By.CSS_SELECTOR, ".fa-language") + actions = ActionChains(self.driver) + actions.move_to_element(element).perform() + self.driver.find_element(By.CSS_SELECTOR, "li:nth-child(1) > .pmd-floating-action-btn > img").click() + assert self.driver.find_element(By.ID, "text").text == "Results" + + def teardown(self): + self.driver.quit() + +class TestAboutUs(): + def setUp(self): + options = webdriver.ChromeOptions() + options.headless = True + options.add_argument("--no-sandbox") + self.driver = webdriver.Chrome(options=options) + self.driver.fullscreen_window() + + def test_aboutUs(self): + self.driver.get("https://picaro-decide.herokuapp.com/admin/login/?next=/admin/") + self.driver.find_element_by_id('id_username').send_keys("admin") + self.driver.find_element_by_id('id_password').send_keys("picarodecide") + self.driver.find_element_by_id('login-form').click() + self.driver.get("https://picaro-decide.herokuapp.com/visualizer/5/") + element = self.driver.find_element(By.CSS_SELECTOR, ".fa-language") + actions = ActionChains(self.driver) + actions.move_to_element(element).perform() + self.driver.find_element(By.CSS_SELECTOR, "li:nth-child(1) > .pmd-floating-action-btn > img").click() + self.driver.find_element(By.CSS_SELECTOR, ".btn-group > .btn:nth-child(3)").click() + assert self.driver.find_element(By.CSS_SELECTOR, ".columna:nth-child(2) > .card-title").text == "Abraham" + assert self.driver.find_element(By.CSS_SELECTOR, ".columna:nth-child(3) > .card-title").text == "Martín Arturo" + assert self.driver.find_element(By.CSS_SELECTOR, ".columna:nth-child(4) > .card-title").text == "Gabriel" + assert self.driver.find_element(By.CSS_SELECTOR, ".columna:nth-child(5) > .card-title").text == "Thibaut" + assert self.driver.find_element(By.CSS_SELECTOR, ".columna:nth-child(6) > .card-title").text == "David" + assert self.driver.find_element(By.CSS_SELECTOR, ".columna:nth-child(1) > .card-title").text == "Pablo" + + def tearDown(self): + self.driver.quit() + +class TestAboutUsBack(): + def setUp(self): + options = webdriver.ChromeOptions() + options.headless = True + options.add_argument("--no-sandbox") + self.driver = webdriver.Chrome(options=options) + self.driver.fullscreen_window() + + def test_aboutUsBack(self): + self.driver.get("https://picaro-decide.herokuapp.com/admin/login/?next=/admin/") + self.driver.find_element_by_id('id_username').send_keys("admin") + self.driver.find_element_by_id('id_password').send_keys("picarodecide") + self.driver.find_element_by_id('login-form').click() + self.driver.get("https://picaro-decide.herokuapp.com/visualizer/5/") + element = self.driver.find_element(By.CSS_SELECTOR, ".fa-language") + actions = ActionChains(self.driver) + actions.move_to_element(element).perform() + self.driver.find_element(By.CSS_SELECTOR, "li:nth-child(1) > .pmd-floating-action-btn > img").click() + self.driver.find_element(By.CSS_SELECTOR, ".btn-group > .btn:nth-child(3)").click() + assert self.driver.find_element(By.CSS_SELECTOR, ".columna:nth-child(2) > .card-title").text == "Abraham" + assert self.driver.find_element(By.CSS_SELECTOR, ".columna:nth-child(3) > .card-title").text == "Martín Arturo" + assert self.driver.find_element(By.CSS_SELECTOR, ".columna:nth-child(4) > .card-title").text == "Gabriel" + assert self.driver.find_element(By.CSS_SELECTOR, ".columna:nth-child(5) > .card-title").text == "Thibaut" + assert self.driver.find_element(By.CSS_SELECTOR, ".columna:nth-child(6) > .card-title").text == "David" + assert self.driver.find_element(By.CSS_SELECTOR, ".columna:nth-child(1) > .card-title").text == "Pablo" + self.driver.find_element(By.CSS_SELECTOR, ".btn-secondary").click() + assert self.driver.find_element(By.ID, "saveAsPNG1").text == "Save as PNG" + + def tearDown(self): + self.driver.quit() + +class TestPNG1PNG2PDF(): + def setUp(self): + options = webdriver.ChromeOptions() + options.headless = True + options.add_argument("--no-sandbox") + self.driver = webdriver.Chrome(options=options) + self.driver.fullscreen_window() + + def testPNG1PNG2PDF(self): + self.driver.get("https://picaro-decide.herokuapp.com/admin/login/?next=/admin/") + self.driver.find_element_by_id('id_username').send_keys("admin") + self.driver.find_element_by_id('id_password').send_keys("picarodecide") + self.driver.find_element_by_id('login-form').click() + self.driver.get("https://picaro-decide.herokuapp.com/visualizer/5/") + element = self.driver.find_element(By.CSS_SELECTOR, ".fa-language") + actions = ActionChains(self.driver) + actions.move_to_element(element).perform() + self.driver.find_element(By.CSS_SELECTOR, "li:nth-child(1) > .pmd-floating-action-btn > img").click() + #self.driver.find_element(By.CSS_SELECTOR, "#saveAsPDF").click() + assert self.driver.find_element(By.ID, "saveAsPNG1").text == "Save as PNG" + assert self.driver.find_element(By.ID, "saveAsPNG2").text == "Save as PNG" + assert self.driver.find_element(By.ID, "saveAsPDF").text == "Save as PDF" + def tearDown(self): + self.driver.quit() + +class TestDarkModeCookies(): + def setUp(self): + options = webdriver.ChromeOptions() + options.headless = True + options.add_argument("--no-sandbox") + self.driver = webdriver.Chrome(options=options) + self.driver.fullscreen_window() + + def test_darkModeCookies(self): + self.driver.get("https://picaro-decide.herokuapp.com/admin/login/?next=/admin/") + self.driver.find_element_by_id('id_username').send_keys("admin") + self.driver.find_element_by_id('id_password').send_keys("picarodecide") + self.driver.find_element_by_id('login-form').click() + self.driver.get("https://picaro-decide.herokuapp.com/visualizer/5/") + element = self.driver.find_element(By.CSS_SELECTOR, ".fa-language") + actions = ActionChains(self.driver) + actions.move_to_element(element).perform() + self.driver.find_element(By.CSS_SELECTOR, "li:nth-child(1) > .pmd-floating-action-btn > img").click() + self.driver.find_element(By.ID, "darkButton").click() + assert self.driver.find_element_by_tag_name('body').get_attribute("class") == "bg-dark" + assert self.driver.find_element(By.ID, "lightButton").text == "Light mode" + self.driver.find_element(By.CSS_SELECTOR, ".btn-group > .btn:nth-child(3)").click() + assert self.driver.find_element_by_tag_name('body').get_attribute("class") == "bg-dark" + + def tearDown(self): + self.driver.quit() + +class TestLightModeCookies(): + def setUp(self): + options = webdriver.ChromeOptions() + options.headless = True + options.add_argument("--no-sandbox") + self.driver = webdriver.Chrome(options=options) + self.driver.fullscreen_window() + + def test_lightModeCookies(self): + self.driver.get("https://picaro-decide.herokuapp.com/admin/login/?next=/admin/") + self.driver.find_element_by_id('id_username').send_keys("admin") + self.driver.find_element_by_id('id_password').send_keys("picarodecide") + self.driver.find_element_by_id('login-form').click() + self.driver.get("https://picaro-decide.herokuapp.com/visualizer/5/") + element = self.driver.find_element(By.CSS_SELECTOR, ".fa-language") + actions = ActionChains(self.driver) + actions.move_to_element(element).perform() + self.driver.find_element(By.CSS_SELECTOR, "li:nth-child(1) > .pmd-floating-action-btn > img").click() + self.driver.find_element(By.ID, "darkButton").click() + assert self.driver.find_element_by_tag_name('body').get_attribute("class") == "bg-dark" + assert self.driver.find_element(By.ID, "lightButton").text == "Light mode" + self.driver.find_element(By.ID, "lightButton").click() + assert self.driver.find_element_by_tag_name('body').get_attribute("class") == "bg-light" + assert self.driver.find_element(By.ID, "darkButton").text == "Dark mode" + self.driver.find_element(By.CSS_SELECTOR, ".btn-group > .btn:nth-child(3)").click() + #Si esta en modo claro, al ser el modo por defecto, el backgraund es blanco, sin la necesidad de aplicar ningún cambio de CSS. + assert self.driver.find_element_by_tag_name('body').get_attribute("class") == "" + + def tearDown(self): + self.driver.quit() + +class TestGraficaBarras(): + def setUp(self): + options = webdriver.ChromeOptions() + options.headless = True + options.add_argument("--no-sandbox") + self.driver = webdriver.Chrome(options=options) + self.driver.fullscreen_window() + + def test_graficaBarras(self): + self.driver.get("https://picaro-decide.herokuapp.com/admin/login/?next=/admin/") + self.driver.find_element_by_id('id_username').send_keys("admin") + self.driver.find_element_by_id('id_password').send_keys("picarodecide") + self.driver.find_element_by_id('login-form').click() + self.driver.get("https://picaro-decide.herokuapp.com/visualizer/5/") + element = self.driver.find_element(By.CSS_SELECTOR, ".fa-language") + actions = ActionChains(self.driver) + actions.move_to_element(element).perform() + self.driver.find_element(By.CSS_SELECTOR, "li:nth-child(1) > .pmd-floating-action-btn > img").click() + assert self.driver.find_element(By.CSS_SELECTOR, "th:nth-child(2) > .heading").text == "Bar Chart" + #Sacamos una captura de pantalla de la gráfica de barras para comprobar que esta existe, dentro de la imagen screenshotgraficabarras.png aparece esta gráfica, solo que aparece algo distosionada + #las barras miden 1/5 menos de lo que miden en realidad, pero podemos comprobar que existe la gráfica y que tiene el número correcto de opciones. + self.driver.find_element_by_id('myChart2').screenshot('screenshotgraficabarras.png') + + def tearDown(self): + self.driver.quit() + +class TestPodium(): + def setUp(self): + options = webdriver.ChromeOptions() + options.headless = True + options.add_argument("--no-sandbox") + self.driver = webdriver.Chrome(options=options) + self.driver.fullscreen_window() + + def test_podium(self): + self.driver.get("https://picaro-decide.herokuapp.com/admin/login/?next=/admin/") + self.driver.find_element_by_id('id_username').send_keys("admin") + self.driver.find_element_by_id('id_password').send_keys("picarodecide") + self.driver.find_element_by_id('login-form').click() + self.driver.get("https://picaro-decide.herokuapp.com/visualizer/5/") + element = self.driver.find_element(By.CSS_SELECTOR, ".fa-language") + actions = ActionChains(self.driver) + actions.move_to_element(element).perform() + self.driver.find_element(By.CSS_SELECTOR, "li:nth-child(1) > .pmd-floating-action-btn > img").click() + assert self.driver.find_element(By.CSS_SELECTOR, ".podio:nth-child(2) > #winner").text == "WINNER" + assert self.driver.find_element(By.ID, "winner").text == "2nd place" + assert self.driver.find_element(By.CSS_SELECTOR, ".podio:nth-child(3) > #winner").text == "3rd place" + + def is_element_present(self, how, what): + try: self.driver.find_element(by=how, value=what) + except NoSuchElementException as e: return False + return True + + def is_alert_present(self): + try: self.driver.switch_to_alert() + except NoAlertPresentException as e: return False + return True + + def close_alert_and_get_its_text(self): + try: + alert = self.driver.switch_to_alert() + alert_text = alert.text + if self.accept_next_alert: + alert.accept() + else: + alert.dismiss() + return alert_text + finally: self.accept_next_alert = True + + def tearDown(self): + # To know more about the difference between verify and assert, + # visit https://www.seleniumhq.org/docs/06_test_design_considerations.jsp#validating-results + self.driver.quit() + +class TestTraduccionAleman(): + def setup(self): + options = webdriver.ChromeOptions() + options.headless = True + options.add_argument("--no-sandbox") + self.driver = webdriver.Chrome(options=options) + + def teardown(self): + self.driver.quit() + + def test_traduccionAleman(self): + self.driver.get("https://picaro-decide.herokuapp.com/admin/login/?next=/admin/") + self.driver.find_element_by_id('id_username').send_keys("admin") + self.driver.find_element_by_id('id_password').send_keys("picarodecide") + self.driver.find_element_by_id('login-form').click() + self.driver.get("https://picaro-decide.herokuapp.com/visualizer/5/") + self.driver.set_window_size(1552, 840) + element = self.driver.find_element(By.CSS_SELECTOR, ".fa-language") + actions = ActionChains(self.driver) + actions.move_to_element(element).perform() + self.driver.find_element(By.CSS_SELECTOR, "li:nth-child(4) img").click() + assert self.driver.find_element(By.ID, "text").text == "Ergebnisse" + +class TestPodiumTraduccionEspanol(): + def setup(self): + options = webdriver.ChromeOptions() + options.headless = True + options.add_argument("--no-sandbox") + self.driver = webdriver.Chrome(options=options) + + def teardown(self): + self.driver.quit() + + def test_podiumTraduccionEspañol(self): + self.driver.get("https://picaro-decide.herokuapp.com/admin/login/?next=/admin/") + self.driver.find_element_by_id('id_username').send_keys("admin") + self.driver.find_element_by_id('id_password').send_keys("picarodecide") + self.driver.find_element_by_id('login-form').click() + self.driver.get("https://picaro-decide.herokuapp.com/visualizer/5/") + self.driver.set_window_size(1552, 840) + element = self.driver.find_element(By.CSS_SELECTOR, ".fa-language") + actions = ActionChains(self.driver) + actions.move_to_element(element).perform() + self.driver.find_element(By.CSS_SELECTOR, "li:nth-child(2) img").click() + assert self.driver.find_element(By.CSS_SELECTOR, ".podio:nth-child(2) > #winner").text == "GANADOR" + assert self.driver.find_element(By.ID, "winner").text == "2º puesto" + assert self.driver.find_element(By.CSS_SELECTOR, ".podio:nth-child(3) > #winner").text == "3º puesto" + + +class TestGraficaDonut(): + def setUp(self): + options = webdriver.ChromeOptions() + options.headless = True + options.add_argument("--no-sandbox") + self.driver = webdriver.Chrome(options=options) + self.driver.fullscreen_window() + + def test_graficaDonut(self): + self.driver.get("https://picaro-decide.herokuapp.com/admin/login/?next=/admin/") + self.driver.find_element_by_id('id_username').send_keys("admin") + self.driver.find_element_by_id('id_password').send_keys("picarodecide") + self.driver.find_element_by_id('login-form').click() + self.driver.get("https://picaro-decide.herokuapp.com/visualizer/5/") + element = self.driver.find_element(By.CSS_SELECTOR, ".fa-language") + actions = ActionChains(self.driver) + actions.move_to_element(element).perform() + self.driver.find_element(By.CSS_SELECTOR, "li:nth-child(2) img").click() + #Aquí se comprueba que se encuentra la gráfica circular + assert self.driver.find_element(By.CSS_SELECTOR, "section > #table th:nth-child(1) > .heading").text == "Gráfico Circular" + elements = self.driver.find_elements(By.ID, "myChart") + assert len(elements) > 0 + + def tearDown(self): + self.driver.quit() + + +class TestTablaResultados(): + def setUp(self): + options = webdriver.ChromeOptions() + options.headless = True + options.add_argument("--no-sandbox") + self.driver = webdriver.Chrome(options=options) + self.driver.fullscreen_window() + + def test_graficaDonut(self): + self.driver.get("https://picaro-decide.herokuapp.com/admin/login/?next=/admin/") + self.driver.find_element_by_id('id_username').send_keys("admin") + self.driver.find_element_by_id('id_password').send_keys("picarodecide") + self.driver.find_element_by_id('login-form').click() + self.driver.get("https://picaro-decide.herokuapp.com/visualizer/5/") + element = self.driver.find_element(By.CSS_SELECTOR, ".fa-language") + actions = ActionChains(self.driver) + actions.move_to_element(element).perform() + self.driver.find_element(By.CSS_SELECTOR, "li:nth-child(1) img").click() + assert self.driver.find_element(By.CLASS_NAME, "theTable") + assert self.driver.find_element(By.ID, "exportarTab") + #Aquí se comprueba que aparecen los resultados de la votación (se comprueba que aparecen 2 opciones de la votación + #se supone que una votación tiene al menos 2 opciones) + opcion1 = self.driver.find_elements(By.CSS_SELECTOR, "tbody > tr:nth-child(1) > th") + assert len(opcion1) > 0 + opcion2 = self.driver.find_elements(By.CSS_SELECTOR, "tbody > tr:nth-child(1) > th") + assert len(opcion2) > 0 + + + def tearDown(self): + self.driver.quit() + + +class TestBotonReturn(): + def setUp(self): + options = webdriver.ChromeOptions() + options.headless = True + options.add_argument("--no-sandbox") + self.driver = webdriver.Chrome(options=options) + self.driver.fullscreen_window() + + def test_graficaDonut(self): + #Aqui se comprueba que si le das al botón return vuelve a la página anterior + self.driver.get("https://picaro-decide.herokuapp.com/admin/login/?next=/admin/") + self.driver.find_element_by_id('id_username').send_keys("admin") + self.driver.find_element_by_id('id_password').send_keys("picarodecide") + self.driver.find_element_by_id('login-form').click() + self.driver.get("https://picaro-decide.herokuapp.com/visualizer/contactUs") + assert self.driver.current_url == "https://picaro-decide.herokuapp.com/visualizer/contactUs/" + self.driver.get("https://picaro-decide.herokuapp.com/visualizer/5/") + assert self.driver.current_url == "https://picaro-decide.herokuapp.com/visualizer/5/" + self.driver.find_element(By.CSS_SELECTOR, "#app-visualizer > .btn").click() + assert self.driver.current_url == "https://picaro-decide.herokuapp.com/visualizer/contactUs/" + + + def tearDown(self): + self.driver.quit() + + +class TestVotacionNoEmpezada(): + def setUp(self): + options = webdriver.ChromeOptions() + options.headless = True + options.add_argument("--no-sandbox") + self.driver = webdriver.Chrome(options=options) + self.driver.fullscreen_window() + + def test_graficaDonut(self): + + self.driver.get("https://picaro-decide.herokuapp.com/admin/login/?next=/admin/") + self.driver.find_element_by_id('id_username').send_keys("admin") + self.driver.find_element_by_id('id_password').send_keys("picarodecide") + self.driver.find_element_by_id('login-form').click() + self.driver.get("https://picaro-decide.herokuapp.com/visualizer/6/") + element = self.driver.find_element(By.CSS_SELECTOR, ".fa-language") + actions = ActionChains(self.driver) + actions.move_to_element(element).perform() + self.driver.find_element(By.CSS_SELECTOR, "li:nth-child(2) img").click() + #Comprueba que efectivamente es una votación que no ha empezado, ya que la página de visualización de una votación no empezada, solo contiene ese texto + assert self.driver.find_element(By.ID, "text").text == "Votación no comenzada" + + + def tearDown(self): + self.driver.quit() + + +class TestVotacionNoFinalizada(): + def setUp(self): + options = webdriver.ChromeOptions() + options.headless = True + options.add_argument("--no-sandbox") + self.driver = webdriver.Chrome(options=options) + self.driver.fullscreen_window() + + def test_votacionEnCurso(self): + self.driver.get("https://picaro-decide.herokuapp.com/admin/login/?next=/admin/") + self.driver.find_element_by_id('id_username').send_keys("admin") + self.driver.find_element_by_id('id_password').send_keys("picarodecide") + self.driver.find_element_by_id('login-form').click() + self.driver.get("https://picaro-decide.herokuapp.com/visualizer/7/") + element = self.driver.find_element(By.CSS_SELECTOR, ".fa-language") + actions = ActionChains(self.driver) + actions.move_to_element(element).perform() + self.driver.find_element(By.CSS_SELECTOR, "li:nth-child(2) img").click() + #Comprueba que efectivamente es una votación que no ha empezado, ya que la página de visualización de una votación no empezada, solo contiene ese texto + assert self.driver.find_element(By.ID, "text").text == "Votación en curso" + + def test_tabla(self): + + self.driver.get("https://picaro-decide.herokuapp.com/admin/login/?next=/admin/") + self.driver.find_element_by_id('id_username').send_keys("admin") + self.driver.find_element_by_id('id_password').send_keys("picarodecide") + self.driver.find_element_by_id('login-form').click() + self.driver.get("https://picaro-decide.herokuapp.com/visualizer/7/") + element = self.driver.find_element(By.CSS_SELECTOR, ".fa-language") + actions = ActionChains(self.driver) + actions.move_to_element(element).perform() + self.driver.find_element(By.CSS_SELECTOR, "li:nth-child(1) img").click() + #Aquí se comprueba que la tabla con el número de votos existe y tiene la fila con el número de votos que hay + elements = self.driver.find_elements(By.CSS_SELECTOR, "tbody > tr > th") + assert len(elements) > 0 + + def tearDown(self): + self.driver.quit() + + +#class TestNumeroVotos(): +# def setUp(self): +# self.driver = webdriver.Chrome() +# +# def test_aumentaNumeroVotos(self): +# self.driver.get("https://picaro-decide.herokuapp.com/admin/login/?next=/admin/") +# self.driver.find_element_by_id('id_username').send_keys("admin") +# self.driver.find_element_by_id('id_password').send_keys("picarodecide") +# self.driver.find_element_by_id('login-form').click() +# self.driver.get("https://picaro-decide.herokuapp.com/admin") +# +# time.sleep(5) +# +# +# self.driver.find_element(By.ID, "id_voting_id").send_keys("7") +# self.driver.find_element(By.ID, "id_voter_id").send_keys("1") +# self.driver.find_element(By.ID, "id_a").send_keys("1") +# self.driver.find_element(By.ID, "id_b").send_keys("1") +# self.driver.find_element(By.NAME, "_addanother").click() +# self.driver.find_element(By.ID, "id_voting_id").send_keys("7") +# self.driver.find_element(By.ID, "id_voter_id").send_keys("2") +# self.driver.find_element(By.ID, "id_a").send_keys("1") +# self.driver.find_element(By.ID, "id_b").send_keys("3") +# self.driver.find_element(By.NAME, "_save").click() +# self.driver.get("https://picaro-decide.herokuapp.com/visualizer/7/") +# assert self.driver.find_element(By.CSS_SELECTOR, "tbody > tr > th").text =="4" + +# def tearDown(self): +# self.driver.quit() + + +# if __name__ == '__main__': +# unittest.main() + +class TestTestBotonTelegram(): + def setup(self): + options = webdriver.ChromeOptions() + options.headless = True + options.add_argument("--no-sandbox") + self.driver = webdriver.Chrome(options=options) + + def teardown(self): + self.driver.quit() + + def testBotonTelegram(self): + self.driver.get("https://picaro-decide.herokuapp.com/visualizer/5/") + self.driver.set_window_size(1295, 726) + self.driver.find_element(By.LINK_TEXT, "Telegram").click() + assert self.driver.find_element(By.CSS_SELECTOR, "span").text == "decide" +""" Comentado porque estos cambios no estan todavia en heroku +class TestHomeVisualizer(): + def setUp(self): + options = webdriver.ChromeOptions() + options.headless = True + self.driver = webdriver.Chrome(options=options) + self.driver.fullscreen_window() + + def test_home_visualizer(self): + self.driver.get("https://picaro-decide.herokuapp.com/admin/login/?next=/admin/") + self.driver.find_element_by_id('id_username').send_keys("admin") + self.driver.find_element_by_id('id_password').send_keys("picarodecide") + self.driver.find_element_by_id('login-form').click() + self.driver.get("https://picaro-decide.herokuapp.com/visualizer") + try: self.assertEqual("Votings", self.driver.find_element_by_id("question").text) + except AssertionError as e: self.verificationErrors.append(str(e)) + + def is_element_present(self, how, what): + try: self.driver.find_element(by=how, value=what) + except NoSuchElementException as e: return False + return True + + def is_alert_present(self): + try: self.driver.switch_to_alert() + except NoAlertPresentException as e: return False + return True + + def close_alert_and_get_its_text(self): + try: + alert = self.driver.switch_to_alert() + alert_text = alert.text + if self.accept_next_alert: + alert.accept() + else: + alert.dismiss() + return alert_text + finally: self.accept_next_alert = True + + def tearDown(self): + self.driver.quit() +""" + +# if __name__ == '__main__': +# unittest.main() diff --git a/decide/visualizer/urls.py b/decide/visualizer/urls.py index 4baef5f2b9..75676801cf 100644 --- a/decide/visualizer/urls.py +++ b/decide/visualizer/urls.py @@ -1,7 +1,12 @@ -from django.urls import path -from .views import VisualizerView - +from django.urls import path, include +from .views import VisualizerView, AboutUs, ContactUs, VisualizerHome +from django.conf.urls import url urlpatterns = [ path('/', VisualizerView.as_view()), + path('contactUs/', ContactUs.as_view()), + path('aboutUs/', AboutUs.as_view()), + path('', VisualizerHome.as_view()), + url('i18n/', include('django.conf.urls.i18n')), ] + diff --git a/decide/visualizer/views.py b/decide/visualizer/views.py index 8fea64ecb2..24f242e565 100644 --- a/decide/visualizer/views.py +++ b/decide/visualizer/views.py @@ -2,6 +2,8 @@ from django.views.generic import TemplateView from django.conf import settings from django.http import Http404 +from voting.models import Voting + from base import mods @@ -16,7 +18,72 @@ def get_context_data(self, **kwargs): try: r = mods.get('voting', params={'id': vid}) context['voting'] = json.dumps(r[0]) + if r[0]['start_date'] is None: + print('asd') + elif r[0]['end_date'] is None: + #print('asd') + numero_votos = get_numero_votos(vid) + + + context['numero_votos'] = numero_votos + print(context) + + except: raise Http404 return context + + + +def get_numero_votos (vid): + + + #census = mods.get('admin', entry_point= '/census/census', params={'voting_id': vid}) + #print('asd') + numero_votos=0 + voters = mods.get('store',params={'voting_id':vid}) + voters_id = [v['voting_id'] for v in voters] + numero_votos= len(voters_id) + + return numero_votos + +# Método para obtener los votos de todas las votaciones (gabgutpri, visualización) +def get_todos_votos(votings): + listaVotos = [] + for voting in votings: + votos = mods.get('store',params={'voting_id':voting.id}) + cuenta = [v['voting_id'] for v in votos] + listaVotos.append(len(cuenta)) + return listaVotos + +class ContactUs(TemplateView): + try: + template_name = 'visualizer/contactUs.html' + except: + raise Http404 + +class AboutUs(TemplateView): + try: + template_name = 'visualizer/aboutUs.html' + except: + raise Http404 + +class VisualizerHome(TemplateView): + template_name = 'visualizer/visualizer_home.html' + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + queryset = Voting.objects.all() + + # Parte de la gráfica --- gabgutpri (visualizacion) + votaciones = mods.get('voting', params={}) # Todas las votaciones + context['votaciones']= json.dumps(votaciones) # Transformación para que no de problemas en el script JS + votos = get_todos_votos(queryset) # Traer todos los votos de cada votación + context['votos'] = votos + # ------------ + + context.update({'votings': queryset}) + return context + + + \ No newline at end of file diff --git a/decide/voting/admin.py b/decide/voting/admin.py index dff206a94f..7dc1ac7ef1 100644 --- a/decide/voting/admin.py +++ b/decide/voting/admin.py @@ -12,12 +12,14 @@ def start(modeladmin, request, queryset): for v in queryset.all(): v.create_pubkey() v.start_date = timezone.now() + v.enviarTelegram("La votación "+str(v.name)+" ha comenzado") v.save() def stop(ModelAdmin, request, queryset): for v in queryset.all(): v.end_date = timezone.now() + v.enviarTelegram("La votación "+str(v.name)+" ha terminado") v.save() diff --git a/decide/voting/models.py b/decide/voting/models.py index a10ab2bcb6..08784ad368 100644 --- a/decide/voting/models.py +++ b/decide/voting/models.py @@ -2,6 +2,7 @@ from django.contrib.postgres.fields import JSONField from django.db.models.signals import post_save from django.dispatch import receiver +import requests from base import mods from base.models import Auth, Key @@ -96,6 +97,7 @@ def tally_votes(self, token=''): self.save() self.do_postproc() + def do_postproc(self): tally = self.tally @@ -112,12 +114,31 @@ def do_postproc(self): 'number': opt.number, 'votes': votes }) - + msn ="Votación: "+self.name+"\n\n" + for opt in opts: + msn = str(msn)+str(opt.get('option'))+": "+(str(opt.get('votes')))+" votos.\n" data = { 'type': 'IDENTITY', 'options': opts } postp = mods.post('postproc', json=data) + self.postproc = postp self.save() + self.enviarTelegram(msn) def __str__(self): return self.name + + #Método para enviar datos de los resultados por telegram (Pablo Franco Sánchez, visualización) + def enviarTelegram(self,msn): + id = "-1001460398324" + token = "1426657690:AAEmrAP5v4KFQvmzv5AyGdGvWwrbJbZup3M" + url = "https://api.telegram.org/bot" + token + "/sendMessage" + + params = { + 'chat_id': id, + 'text' : str(msn) + } + try: + requests.post(url, params=params) + except: + pass diff --git a/docker/Dockerfile b/docker/Dockerfile index 032eed28e2..3bb98458b2 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,4 +1,4 @@ -from python:alpine +from python:3.7-alpine RUN apk add --no-cache git postgresql-dev gcc libc-dev RUN apk add --no-cache gcc g++ make libffi-dev python3-dev build-base @@ -10,7 +10,7 @@ RUN pip install ipython WORKDIR /app -RUN git clone https://github.com/wadobo/decide.git . +RUN git clone https://github.com/pabfrasan/decide . RUN pip install -r requirements.txt WORKDIR /app/decide diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 095583eb02..4689c5ff98 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -4,11 +4,13 @@ services: db: restart: always container_name: decide_db - image: postgres:alpine + image: postgres:10.15-alpine volumes: - db:/var/lib/postgresql/data networks: - decide + environment: + - POSTGRES_PASSWORD=postgres web: restart: always container_name: decide_web diff --git a/docker/docker-settings.py b/docker/docker-settings.py index 01e643d936..49efb3d78f 100644 --- a/docker/docker-settings.py +++ b/docker/docker-settings.py @@ -5,6 +5,7 @@ 'ENGINE': 'django.db.backends.postgresql', 'NAME': 'postgres', 'USER': 'postgres', + 'PASSWORD' : 'postgres', 'HOST': 'db', 'PORT': 5432, } diff --git a/requirements.txt b/requirements.txt index d5860a1eb4..522ed458b8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,8 +4,13 @@ djangorestframework==3.7.7 django-cors-headers==2.1.0 requests==2.18.4 django-filter==1.1.0 -psycopg2==2.7.4 +psycopg2-binary==2.8.4 django-rest-swagger==2.2.0 coverage==4.5.2 django-nose==1.4.6 jsonnet==0.12.1 +django-heroku +gunicorn +selenium +pillow + diff --git a/vagrant/.python.yml.swp b/vagrant/.python.yml.swp new file mode 100644 index 0000000000..9b9c508ee8 Binary files /dev/null and b/vagrant/.python.yml.swp differ diff --git a/vagrant/Vagrantfile b/vagrant/Vagrantfile index 87c50e7375..54ed0beb3a 100644 --- a/vagrant/Vagrantfile +++ b/vagrant/Vagrantfile @@ -58,8 +58,8 @@ Vagrant.configure("2") do |config| # end config.vm.provider "virtualbox" do |v| - v.memory = 512 - v.cpus = 1 + v.memory = 1024 + v.cpus = 2 end # View the documentation for the provider you are using for more