[chronojump-server] MAJOR COMMIT - Chronojump Networks now runs under Django 1.11.1



commit edea1ea23fd3eb0baff84c77679404457fff5d0b
Author: Marcos Venteo <mventeo gmail com>
Date:   Mon Apr 2 22:04:18 2018 +0200

    MAJOR COMMIT - Chronojump Networks now runs under Django 1.11.1
    
    - Adding Docker support

 .gitignore                                         |    1 -
 chronojumpserver-django/babel.cfg                  |    3 +
 .../chronojump_networks/core/models.py             |   42 ++
 .../chronojump_networks/organizations/admin.py     |  108 ++++
 .../organizations/api/__init__.py                  |    1 +
 .../organizations/api/permissions.py               |    9 +
 .../organizations/api/serializers.py               |   35 ++
 .../chronojump_networks/organizations/api/urls.py  |   45 ++
 .../chronojump_networks/organizations/api/views.py |  112 ++++
 .../chronojump_networks/organizations/apps.py      |    9 +
 .../organizations/decorators.py                    |   21 +
 .../chronojump_networks/organizations/forms.py     |   29 +
 .../organizations/migrations/0001_initial.py       |  191 ++++++
 .../migrations/0002_auto_20180331_1224.py          |   25 +
 .../migrations/0003_auto_20180331_1259.py          |   22 +
 .../organizations/migrations/0004_group_gym.py     |   21 +
 .../migrations/0005_auto_20180401_2146.py          |   21 +
 .../migrations/0006_auto_20180402_1751.py          |   27 +
 .../chronojump_networks/organizations/models.py    |  242 ++++++++
 .../chronojump_networks/organizations/tests.py     |    6 +
 .../chronojump_networks/organizations/urls.py      |   51 ++
 .../chronojump_networks/organizations/views.py     |   93 +++
 .../chronojump_networks/results/admin.py           |    6 +
 .../chronojump_networks/results/apps.py            |    8 +
 .../chronojump_networks/results/models.py          |    6 +
 .../chronojump_networks/results/tests.py           |    6 +
 .../chronojump_networks/results/views.py           |    6 +
 .../static/css/styles-airport.css                  |   82 +++
 .../chronojump_networks/static/css/styles.css      |  132 +++++
 .../static/images/chronojump-logo.png              |  Bin 0 -> 18840 bytes
 .../static/images/details_close.png                |  Bin 0 -> 686 bytes
 .../static/images/details_open.png                 |  Bin 0 -> 709 bytes
 .../chronojump_networks/static/js/chronojump.js    |   40 ++
 .../chronojump_networks/static/js/tasks.js         |    1 +
 .../chronojump_networks/tasks/admin.py             |   11 +
 .../chronojump_networks/tasks/api/serializers.py   |   23 +
 .../chronojump_networks/tasks/api/urls.py          |   19 +
 .../chronojump_networks/tasks/api/views.py         |   52 ++
 .../chronojump_networks/tasks/apps.py              |    8 +
 .../tasks/migrations/0001_initial.py               |   30 +
 .../tasks/migrations/0002_auto_20180401_2209.py    |   89 +++
 .../tasks/migrations/0003_task_load.py             |   20 +
 .../chronojump_networks/tasks/models.py            |   67 +++
 .../chronojump_networks/tasks/tests.py             |    6 +
 .../chronojump_networks/tasks/views.py             |    6 +
 .../templates/admin/base_site.html                 |    9 +
 .../chronojump_networks/templates/base.html        |   39 ++
 .../chronojump_networks/templates/layout.html      |   62 ++
 .../organizations/groups/group_players_list.html   |  603 ++++++++++++++++++++
 .../organizations/groups/task_modal_form.html      |  254 ++++++++
 .../templates/organizations/gyms/gym_detail.html   |  193 +++++++
 .../organizations/organization_detail.html         |   25 +
 .../templates/organizations/organization_list.html |   17 +
 .../templates/pages/403_csrf.html                  |    9 +
 .../chronojump_networks/templates/pages/404.html   |    9 +
 .../chronojump_networks/templates/pages/500.html   |   13 +
 .../chronojump_networks/templates/pages/index.html |  121 ++++
 .../chronojump_networks/templates/users/login.html |   31 +
 chronojumpserver-django/config/settings/base.py    |  239 ++++++++
 chronojumpserver-django/config/settings/local.py   |   57 ++
 chronojumpserver-django/config/urls.py             |   38 ++
 chronojumpserver-django/config/wsgi.py             |   16 +
 .../locale/es/LC_MESSAGES/django.po                |  335 +++++++++++
 chronojumpserver-django/manage.py                  |   22 +
 chronojumpserver/__init__.py                       |   12 +-
 chronojumpserver/models.py                         |    2 +-
 chronojumpserver/templates/groups_and_players.html |   19 +
 chronojumpserver/views.py                          |    7 +
 compose/local/django/start.sh                      |    5 +
 compose/local/flask/chronojump.conf.template       |   20 +
 compose/local/flask/start.sh                       |    2 +
 compose/production/django/entrypoint.sh            |    8 +
 local.yml                                          |   50 ++
 requirements/base.txt                              |   26 +
 requirements/django/base.txt                       |   18 +
 requirements/django/local.txt                      |   25 +
 requirements/local.txt                             |    5 +
 requirements/production.txt                        |    4 +
 78 files changed, 4023 insertions(+), 4 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index 265c921..fdffc43 100644
--- a/.gitignore
+++ b/.gitignore
@@ -52,7 +52,6 @@ docs/_build/
 
 # PyBuilder
 target/
-
 Dockerfile
 chronojump.conf.example
 chronojumpserver/static/images/photos/
diff --git a/chronojumpserver-django/babel.cfg b/chronojumpserver-django/babel.cfg
new file mode 100644
index 0000000..f0234b3
--- /dev/null
+++ b/chronojumpserver-django/babel.cfg
@@ -0,0 +1,3 @@
+[python: **.py]
+[jinja2: **/templates/**.html]
+extensions=jinja2.ext.autoescape,jinja2.ext.with_
diff --git a/chronojumpserver-django/chronojump_networks/__init__.py 
b/chronojumpserver-django/chronojump_networks/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/chronojumpserver-django/chronojump_networks/core/__init__.py 
b/chronojumpserver-django/chronojump_networks/core/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/chronojumpserver-django/chronojump_networks/core/models.py 
b/chronojumpserver-django/chronojump_networks/core/models.py
new file mode 100644
index 0000000..dfa6ca8
--- /dev/null
+++ b/chronojumpserver-django/chronojump_networks/core/models.py
@@ -0,0 +1,42 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import models
+from django.utils.encoding import python_2_unicode_compatible
+
+import uuid as uuid_lib
+
+class TimeStampedModel(models.Model):
+    """
+    An abstract base class model that provides self-
+    updating ``created`` and ``modified`` fields.
+    """
+    created = models.DateTimeField(auto_now_add=True)
+    modified = models.DateTimeField(auto_now=True)
+
+    class Meta:
+        abstract = True
+
+@python_2_unicode_compatible # For Python 3.5+ and 2.7
+class ChronojumpBaseModel(models.Model):
+    """
+    An abstract base class model that provides self-
+    updating ``created`` and ``modified`` fields.
+    """
+    name = models.CharField(max_length=50)
+
+    class Meta:
+        abstract = True
+
+    def __str__(self):
+        return self.name
+
+class ChronojumpBaseModelWithUUID(ChronojumpBaseModel):
+    class Meta:
+        abstract = True
+
+    slug = models.SlugField(unique=True) # Used to find the web URL
+    uuid = models.UUIDField( # Used by the API to look up the record
+           db_index=True,
+           default=uuid_lib.uuid4,
+           editable=False)
diff --git a/chronojumpserver-django/chronojump_networks/organizations/__init__.py 
b/chronojumpserver-django/chronojump_networks/organizations/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/chronojumpserver-django/chronojump_networks/organizations/admin.py 
b/chronojumpserver-django/chronojump_networks/organizations/admin.py
new file mode 100644
index 0000000..4a25270
--- /dev/null
+++ b/chronojumpserver-django/chronojump_networks/organizations/admin.py
@@ -0,0 +1,108 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.contrib import admin
+from django.contrib.auth.admin import UserAdmin as AuthUserAdmin
+from django.contrib.auth.forms import UserChangeForm, UserCreationForm
+
+# Register your models here.
+from .models import Organization, OrganizationStaff, Group, GroupCoach
+from .models import Gym, Station, Exercise
+from .models import User
+from .models import Player, GroupPlayer
+
+
+class MyUserChangeForm(UserChangeForm):
+    class Meta(UserChangeForm.Meta):
+        model = User
+
+
+class MyUserCreationForm(UserCreationForm):
+
+    error_message = UserCreationForm.error_messages.update({
+        'duplicate_username': 'This username has already been taken.'
+    })
+
+    class Meta(UserCreationForm.Meta):
+        model = User
+
+    def clean_username(self):
+        username = self.cleaned_data["username"]
+        try:
+            User.objects.get(username=username)
+        except User.DoesNotExist:
+            return username
+        raise forms.ValidationError(self.error_messages['duplicate_username'])
+
+
+@admin.register(User)
+class MyUserAdmin(AuthUserAdmin):
+    form = MyUserChangeForm
+    add_form = MyUserCreationForm
+    fieldsets = (
+            ('User Profile', {'fields': ('name','language')}),
+    ) + AuthUserAdmin.fieldsets
+    list_display = ('username', 'name', 'organization_name', 'is_superuser')
+    search_fields = ['name']
+
+
+class OrganizationStaffInline(admin.TabularInline):
+    model = OrganizationStaff
+    extra = 1
+
+
+class OrganizationGroups(admin.TabularInline):
+    model = Group
+    extra = 1
+
+@admin.register(Organization)
+class OrganizationModelAdmin(admin.ModelAdmin):
+
+    list_display = ( 'name', 'country')
+    inlines = (OrganizationStaffInline, OrganizationGroups)
+
+class GroupCoachInline(admin.TabularInline):
+    model = GroupCoach
+    extra = 1
+
+class GroupPlayerInline(admin.TabularInline):
+    model = GroupPlayer
+    extra = 1
+
+
+@admin.register(Group)
+class GroupModelAdmin(admin.ModelAdmin):
+    list_display = ( 'name', 'organization', 'responsible', 'gym')
+    list_filter = ('organization', 'gym')
+
+    inlines = (GroupCoachInline, GroupPlayerInline,)
+
+
+@admin.register(Gym)
+class GymModelAdmin(admin.ModelAdmin):
+
+    list_display = ( 'name',  'organization', 'responsible')
+    list_filter = ('organization',)
+
+@admin.register(Player)
+class PlayerModelAdmin(admin.ModelAdmin):
+    list_display = ('number', 'name', 'organization')
+    list_filter = ('organization',)
+
+
+class ExerciseInlineAdmin(admin.TabularInline):
+    model = Exercise
+    extra = 1
+
+@admin.register(Station)
+class StationModelAdmin(admin.ModelAdmin):
+    list_display = ( 'name',  'organization', 'gym', 'type')
+    list_filter = ('gym', 'type')
+    inlines = [
+        ExerciseInlineAdmin
+    ]
+
+
+@admin.register(Exercise)
+class ExerciseModelAdmin(admin.ModelAdmin):
+    list_display = ( 'name', 'station', 'percentBodyMassDisplaced')
diff --git a/chronojumpserver-django/chronojump_networks/organizations/api/__init__.py 
b/chronojumpserver-django/chronojump_networks/organizations/api/__init__.py
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/chronojumpserver-django/chronojump_networks/organizations/api/__init__.py
@@ -0,0 +1 @@
+
diff --git a/chronojumpserver-django/chronojump_networks/organizations/api/permissions.py 
b/chronojumpserver-django/chronojump_networks/organizations/api/permissions.py
new file mode 100644
index 0000000..b638092
--- /dev/null
+++ b/chronojumpserver-django/chronojump_networks/organizations/api/permissions.py
@@ -0,0 +1,9 @@
+from rest_framework import permissions
+from django.utils.translation import ugettext_lazy as _
+
+class IsCoachOfTheGroup(permissions.BasePermission):
+    message = _('You are not a valid coach for this group. This will be notify')
+
+    def has_permission(self, request, view):
+        # TODO: Check that user is a coach and can see the group
+        return True
diff --git a/chronojumpserver-django/chronojump_networks/organizations/api/serializers.py 
b/chronojumpserver-django/chronojump_networks/organizations/api/serializers.py
new file mode 100644
index 0000000..d11ce78
--- /dev/null
+++ b/chronojumpserver-django/chronojump_networks/organizations/api/serializers.py
@@ -0,0 +1,35 @@
+from rest_framework import serializers
+
+from ..models import Player, Station, Exercise, Gym
+
+from chronojump_networks.tasks.api.serializers import PlayerTaskSerializer
+
+class PlayerSerializer(serializers.ModelSerializer):
+    player_tasks = PlayerTaskSerializer(many=True)
+    class Meta:
+        model = Player
+        fields = [ 'id', 'name', 'number', 'height', 'weight', 'image', 'player_tasks']
+
+
+class GymSerializer(serializers.ModelSerializer):
+    class Meta:
+        model = Gym
+        field = [ 'id', 'name', 'responsible']
+
+
+class StationSerializer(serializers.ModelSerializer):
+    class Meta:
+        model = Station
+        fields = [ 'id', 'name', 'type' ]
+
+class ExerciseSerializer(serializers.ModelSerializer):
+    class Meta:
+        model = Exercise
+        fields = [ 'id', 'name', 'percentBodyMassDisplaced' ]
+
+
+class GymStationsSerializer(serializers.ModelSerializer):
+    exercises = ExerciseSerializer(many=True)
+    class Meta:
+        model = Station
+        fields = [ 'id', 'name', 'type', 'exercises']
diff --git a/chronojumpserver-django/chronojump_networks/organizations/api/urls.py 
b/chronojumpserver-django/chronojump_networks/organizations/api/urls.py
new file mode 100644
index 0000000..e9c4342
--- /dev/null
+++ b/chronojumpserver-django/chronojump_networks/organizations/api/urls.py
@@ -0,0 +1,45 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.conf.urls import url
+
+from . import views
+
+urlpatterns = [
+    url(
+        regex=r'^(?P<organization_id>\d+)/(?P<group_id>\d+)/players$',
+        view=views.GroupPlayerListGenericAPIView.as_view(),
+        name='group_players_list'
+    ),
+    url(
+        regex=r'^(?P<organization_id>\d+)/(?P<group_id>\d+)/add_players$',
+        view=views.GroupAddPlayerListView.as_view(),
+        name='group_add_players_list'
+    ),
+    url(
+        regex=r'^(?P<organization_id>\d+)/(?P<group_id>\d+)/remove_players$',
+        view=views.RemovePlayerFromGroupDestroyView.as_view(),
+        name='remove_players_from_group'
+    ),
+    url(
+        regex=r'^(?P<organization_id>\d+)/players/$',
+        view=views.PlayerListView.as_view(),
+        name='players_list'
+    ),
+    # Get Stations from Gym
+    url(
+        regex=r'^(?P<organization_id>\d+)/gym_stations/$',
+        view=views.GymStationsListView.as_view(),
+        name='gym_stations'
+    ),
+    url(
+        regex=r'^(?P<organization_id>\d+)/station_exercises/$',
+        view=views.StationExercisesListView.as_view(),
+        name='station_exercises'
+    ),
+    url(
+        regex=r'^(?P<organization_id>\d+)/gym_stations/(?P<gym_id>\d+)$',
+        view=views.GymStationsListView.as_view(),
+        name='gym_stations'
+    ),
+]
diff --git a/chronojumpserver-django/chronojump_networks/organizations/api/views.py 
b/chronojumpserver-django/chronojump_networks/organizations/api/views.py
new file mode 100644
index 0000000..2f70b8b
--- /dev/null
+++ b/chronojumpserver-django/chronojump_networks/organizations/api/views.py
@@ -0,0 +1,112 @@
+from ..models import Player, GroupPlayer, Group, Station, Gym, Exercise
+from ..decorators import check_user_organization
+from .serializers import PlayerSerializer, StationSerializer, ExerciseSerializer, GymStationsSerializer
+
+from django.http import HttpResponse, JsonResponse
+from django.shortcuts import get_object_or_404
+from rest_framework.response import Response
+from rest_framework.generics import GenericAPIView, ListAPIView, ListCreateAPIView, DestroyAPIView, 
RetrieveUpdateDestroyAPIView
+from rest_framework.mixins import ListModelMixin, CreateModelMixin, DestroyModelMixin
+from rest_framework.permissions import IsAuthenticated
+
+from .permissions import IsCoachOfTheGroup
+
+
+class GroupPlayerListGenericAPIView(ListAPIView):
+    permission_classes = (IsAuthenticated, IsCoachOfTheGroup)
+    serializer_class = PlayerSerializer
+
+    def get_queryset(self):
+        group_id = int(self.kwargs['group_id'])
+        group = Group.objects.get(id=group_id)
+        return [p.player for p in group.players.all()]
+
+class GroupAddPlayerListView(ListCreateAPIView):
+    """ Class to get the available players that can be added to the
+        group """
+    permission_classes = (IsAuthenticated, IsCoachOfTheGroup)
+    serializer_class = PlayerSerializer
+
+    def get_queryset(self):
+        group_id = int(self.kwargs['group_id'])
+        organization_id = int(self.kwargs['organization_id'])
+        group = Group.objects.get(id=group_id)
+        players_ids = [p.player.id for p in group.players.all()]
+        return Player.objects.filter(organization_id=organization_id).exclude(id__in=players_ids)
+
+    def create(self, request, *args, **kwargs):
+        group_id = int(self.kwargs['group_id'])
+        organization_id = int(self.kwargs['organization_id'])
+        # Get the player_ids passed
+        data = dict(request.data)
+        player_ids = data['player_ids[]']
+        for player_id in player_ids:
+            GroupPlayer.objects.create(group_id=group_id, player_id=int(player_id))
+            print("Add player %d to group %d" % (int(player_id), group_id))
+
+        return JsonResponse({}, status=201, safe=False)
+
+class RemovePlayerFromGroupDestroyView(DestroyAPIView):
+    """Remove players from group"""
+    permission_classes = (IsAuthenticated, IsCoachOfTheGroup)
+    serializer_class = PlayerSerializer
+
+    def destroy(self, request, *args, **kwargs):
+        group_id = int(self.kwargs['group_id'])
+        data = dict(request.data)
+        player_ids = data['player_ids[]']
+        for player_id in player_ids:
+            o = GroupPlayer.objects.get(group_id=group_id, player_id=int(player_id))
+            o.delete()
+            print("Remove player %d from group %d" % (int(player_id), group_id))
+        return JsonResponse({}, status=204, safe=False)
+
+
+class GymStationsListView(ListAPIView):
+    """List stations of a gym """
+    permission_classes = (IsAuthenticated, )
+    serializer_class = StationSerializer
+
+    def list(self, request, *args, **kwargs):
+        # Get as dictionary the data given from ajax
+        data = dict(request.GET)
+        gym_id = int(data['gym_id'][0])
+        queryset = Station.objects.filter(gym_id=gym_id)
+        serializer = StationSerializer(queryset, many=True)
+        print(serializer.data)
+        return Response(serializer.data)
+
+class StationExercisesListView(ListAPIView):
+    """List exercises from station """
+    permission_classes = (IsAuthenticated, )
+    serializer_class = ExerciseSerializer
+
+    def list(self, request, *args, **kwargs):
+        # Get as dictionary the data given from ajax
+        data = dict(request.GET)
+        station_id = int(data['station_id'][0])
+        station = get_object_or_404(Station, pk=station_id)
+        queryset = station.exercises.all()
+        serializer = ExerciseSerializer(queryset, many=True)
+        return Response(serializer.data)
+
+
+class GymStationsListView(ListAPIView):
+    """List exercises from station """
+    permission_classes = (IsAuthenticated, )
+    serializer_class = GymStationsSerializer
+
+    def get_queryset(self):
+        # Get as dictionary the data given from ajax
+        gym_id = int(self.kwargs['gym_id'])
+        gym = get_object_or_404(Gym, pk=gym_id)
+        return gym.stations.all()
+
+class PlayerListView(ListCreateAPIView):
+    """Players of the organization"""
+    permission_classes = (IsAuthenticated, )
+    serializer_class = PlayerSerializer
+
+    def get_queryset(self):
+        organization_id = int(self.kwargs['organization_id'])
+        return Player.objects.filter(organization_id=organization_id)
diff --git a/chronojumpserver-django/chronojump_networks/organizations/apps.py 
b/chronojumpserver-django/chronojump_networks/organizations/apps.py
new file mode 100644
index 0000000..4406d32
--- /dev/null
+++ b/chronojumpserver-django/chronojump_networks/organizations/apps.py
@@ -0,0 +1,9 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.apps import AppConfig
+
+
+class OrganizationsConfig(AppConfig):
+    name = 'chronojump_networks.organizations'
+    verbose_name = "Organizations"
diff --git a/chronojumpserver-django/chronojump_networks/organizations/decorators.py 
b/chronojumpserver-django/chronojump_networks/organizations/decorators.py
new file mode 100644
index 0000000..dd59f89
--- /dev/null
+++ b/chronojumpserver-django/chronojump_networks/organizations/decorators.py
@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+from functools import wraps
+
+
+from django.http import HttpResponseForbidden
+from django.utils.translation import ugettext_lazy as _
+
+def check_user_organization(view_func):
+    """Check that user belongs to the same organization."""
+
+    @wraps(view_func)
+    def new_view_func(request, *args, **kwargs):
+        if request.user.organization().id == int(kwargs['organization_id']):
+            response = view_func(request, *args, **kwargs)
+
+            return response
+        else:
+            return HttpResponseForbidden(_("The user does not belongs to this organization."))
+
+    return new_view_func
diff --git a/chronojumpserver-django/chronojump_networks/organizations/forms.py 
b/chronojumpserver-django/chronojump_networks/organizations/forms.py
new file mode 100644
index 0000000..2bcb4e9
--- /dev/null
+++ b/chronojumpserver-django/chronojump_networks/organizations/forms.py
@@ -0,0 +1,29 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django import forms
+from django.utils.translation import ugettext_lazy as _
+from crispy_forms.helper import FormHelper
+
+from .models import User
+
+class UserLoginForm(forms.Form):
+
+    username = forms.CharField(
+        # Translators: Username for login form
+        label = _("Username"),
+        max_length = 25,
+        required = True
+    )
+
+    password = forms.CharField(
+        # Translators: Password for login form
+        label = _("Password"),
+        max_length=25,
+        required = True,
+        widget=forms.PasswordInput
+    )
+
+    def __init__(self, *args, **kwargs):
+        super(UserLoginForm, self).__init__(*args, **kwargs)
+        self.helper = FormHelper()
diff --git a/chronojumpserver-django/chronojump_networks/organizations/migrations/0001_initial.py 
b/chronojumpserver-django/chronojump_networks/organizations/migrations/0001_initial.py
new file mode 100644
index 0000000..0d7a2b9
--- /dev/null
+++ b/chronojumpserver-django/chronojump_networks/organizations/migrations/0001_initial.py
@@ -0,0 +1,191 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.1 on 2018-03-31 10:07
+from __future__ import unicode_literals
+
+from django.conf import settings
+import django.contrib.auth.models
+import django.contrib.auth.validators
+from django.db import migrations, models
+import django.db.models.deletion
+import django.utils.timezone
+
+
+class Migration(migrations.Migration):
+
+    initial = True
+
+    dependencies = [
+        ('auth', '0008_alter_user_username_max_length'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='User',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, 
verbose_name='ID')),
+                ('password', models.CharField(max_length=128, verbose_name='password')),
+                ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
+                ('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has 
all permissions without explicitly assigning them.', verbose_name='superuser status')),
+                ('username', models.CharField(error_messages={'unique': 'A user with that username already 
exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', 
max_length=150, unique=True, validators=[django.contrib.auth.validators.ASCIIUsernameValidator()], 
verbose_name='username')),
+                ('first_name', models.CharField(blank=True, max_length=30, verbose_name='first name')),
+                ('last_name', models.CharField(blank=True, max_length=30, verbose_name='last name')),
+                ('email', models.EmailField(blank=True, max_length=254, verbose_name='email address')),
+                ('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can 
log into this admin site.', verbose_name='staff status')),
+                ('is_active', models.BooleanField(default=True, help_text='Designates whether this user 
should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')),
+                ('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date 
joined')),
+                ('name', models.CharField(blank=True, max_length=100, verbose_name='Name of User')),
+                ('language', models.CharField(choices=[('es', 'Spanish'), ('ca', 'Catalan'), ('fr', 
'French'), ('en', 'English')], default='en', max_length=2)),
+            ],
+            options={
+                'db_table': 'user',
+            },
+            managers=[
+                ('objects', django.contrib.auth.models.UserManager()),
+            ],
+        ),
+        migrations.CreateModel(
+            name='Exercise',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, 
verbose_name='ID')),
+                ('name', models.CharField(max_length=50)),
+                ('percentBodyMassDisplaced', models.FloatField(default=0, null=True)),
+            ],
+            options={
+                'db_table': 'exercise',
+            },
+        ),
+        migrations.CreateModel(
+            name='Group',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, 
verbose_name='ID')),
+                ('name', models.CharField(max_length=50)),
+            ],
+            options={
+                'db_table': 'group_',
+            },
+        ),
+        migrations.CreateModel(
+            name='GroupCoach',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, 
verbose_name='ID')),
+                ('coach', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, 
related_name='groups_by_coach', to=settings.AUTH_USER_MODEL)),
+                ('group', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, 
related_name='coaches', to='organizations.Group')),
+            ],
+            options={
+                'db_table': 'groupCoach',
+            },
+        ),
+        migrations.CreateModel(
+            name='GroupPlayer',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, 
verbose_name='ID')),
+                ('group', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, 
related_name='players', to='organizations.Group')),
+            ],
+            options={
+                'db_table': 'groupPerson',
+            },
+        ),
+        migrations.CreateModel(
+            name='Gym',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, 
verbose_name='ID')),
+                ('name', models.CharField(max_length=50)),
+            ],
+            options={
+                'db_table': 'gym',
+            },
+        ),
+        migrations.CreateModel(
+            name='Organization',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, 
verbose_name='ID')),
+                ('name', models.CharField(max_length=50)),
+                ('country', models.CharField(blank=True, max_length=20, null=True)),
+                ('image', models.FileField(blank=True, upload_to='organizations')),
+                ('responsible', models.OneToOneField(blank=True, null=True, 
on_delete=django.db.models.deletion.SET_NULL, related_name='responsible_of', to=settings.AUTH_USER_MODEL)),
+            ],
+            options={
+                'db_table': 'organization',
+            },
+        ),
+        migrations.CreateModel(
+            name='OrganizationStaff',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, 
verbose_name='ID')),
+                ('role', models.IntegerField(choices=[(1, 'Coach'), (2, 'Coach Leader')])),
+                ('organization', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, 
related_name='users', to='organizations.Organization')),
+                ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, 
related_name='member_of', to=settings.AUTH_USER_MODEL)),
+            ],
+            options={
+                'db_table': 'organizationStaff',
+            },
+        ),
+        migrations.CreateModel(
+            name='Player',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, 
verbose_name='ID')),
+                ('name', models.CharField(max_length=50)),
+                ('height', models.FloatField(default=0)),
+                ('weight', models.FloatField(default=0)),
+                ('rfid', models.CharField(max_length=23, unique=True)),
+                ('image', models.FileField(blank=True, null=True, upload_to='players')),
+                ('is_available', models.BooleanField(default=True)),
+                ('organization', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, 
related_name='players', to='organizations.Organization')),
+            ],
+            options={
+                'db_table': 'person',
+            },
+        ),
+        migrations.CreateModel(
+            name='Station',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, 
verbose_name='ID')),
+                ('name', models.CharField(max_length=50)),
+                ('type', models.CharField(choices=[('S', 'Sprint'), ('I', 'Inertial'), ('G', 
'Gravitatory')], max_length=1)),
+                ('gym', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, 
related_name='stations', to='organizations.Gym')),
+            ],
+            options={
+                'db_table': 'station',
+            },
+        ),
+        migrations.AddField(
+            model_name='gym',
+            name='organization',
+            field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='gyms', 
to='organizations.Organization'),
+        ),
+        migrations.AddField(
+            model_name='gym',
+            name='responsible',
+            field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, 
related_name='responsible_of_gym', to=settings.AUTH_USER_MODEL),
+        ),
+        migrations.AddField(
+            model_name='groupplayer',
+            name='player',
+            field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='groups', 
to='organizations.Player'),
+        ),
+        migrations.AddField(
+            model_name='group',
+            name='organization',
+            field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='groups', 
to='organizations.Organization'),
+        ),
+        migrations.AddField(
+            model_name='group',
+            name='responsible',
+            field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, 
related_name='responsible_of_group', to='organizations.OrganizationStaff'),
+        ),
+        migrations.AddField(
+            model_name='exercise',
+            name='station',
+            field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='exercises', 
to='organizations.Station'),
+        ),
+        migrations.AddField(
+            model_name='user',
+            name='groups',
+            field=models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will 
get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', 
to='auth.Group', verbose_name='groups'),
+        ),
+        migrations.AddField(
+            model_name='user',
+            name='user_permissions',
+            field=models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', 
related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions'),
+        ),
+    ]
diff --git a/chronojumpserver-django/chronojump_networks/organizations/migrations/0002_auto_20180331_1224.py 
b/chronojumpserver-django/chronojump_networks/organizations/migrations/0002_auto_20180331_1224.py
new file mode 100644
index 0000000..6debeb7
--- /dev/null
+++ b/chronojumpserver-django/chronojump_networks/organizations/migrations/0002_auto_20180331_1224.py
@@ -0,0 +1,25 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.1 on 2018-03-31 12:24
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('organizations', '0001_initial'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='player',
+            name='number',
+            field=models.IntegerField(blank=True, null=True),
+        ),
+        migrations.AlterField(
+            model_name='organizationstaff',
+            name='role',
+            field=models.IntegerField(choices=[(1, 'Coach'), (2, 'Coach Lead')]),
+        ),
+    ]
diff --git a/chronojumpserver-django/chronojump_networks/organizations/migrations/0003_auto_20180331_1259.py 
b/chronojumpserver-django/chronojump_networks/organizations/migrations/0003_auto_20180331_1259.py
new file mode 100644
index 0000000..6c1758e
--- /dev/null
+++ b/chronojumpserver-django/chronojump_networks/organizations/migrations/0003_auto_20180331_1259.py
@@ -0,0 +1,22 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.1 on 2018-03-31 12:59
+from __future__ import unicode_literals
+
+from django.conf import settings
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('organizations', '0002_auto_20180331_1224'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='gym',
+            name='responsible',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, 
related_name='responsible_of_gym', to=settings.AUTH_USER_MODEL),
+        ),
+    ]
diff --git a/chronojumpserver-django/chronojump_networks/organizations/migrations/0004_group_gym.py 
b/chronojumpserver-django/chronojump_networks/organizations/migrations/0004_group_gym.py
new file mode 100644
index 0000000..25f354f
--- /dev/null
+++ b/chronojumpserver-django/chronojump_networks/organizations/migrations/0004_group_gym.py
@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.1 on 2018-04-01 18:18
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('organizations', '0003_auto_20180331_1259'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='group',
+            name='gym',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, 
related_name='gym_groups', to='organizations.Gym'),
+        ),
+    ]
diff --git a/chronojumpserver-django/chronojump_networks/organizations/migrations/0005_auto_20180401_2146.py 
b/chronojumpserver-django/chronojump_networks/organizations/migrations/0005_auto_20180401_2146.py
new file mode 100644
index 0000000..030621a
--- /dev/null
+++ b/chronojumpserver-django/chronojump_networks/organizations/migrations/0005_auto_20180401_2146.py
@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.1 on 2018-04-01 21:46
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('organizations', '0004_group_gym'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='group',
+            name='responsible',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, 
related_name='groups_responsible', to='organizations.OrganizationStaff'),
+        ),
+    ]
diff --git a/chronojumpserver-django/chronojump_networks/organizations/migrations/0006_auto_20180402_1751.py 
b/chronojumpserver-django/chronojump_networks/organizations/migrations/0006_auto_20180402_1751.py
new file mode 100644
index 0000000..d95b530
--- /dev/null
+++ b/chronojumpserver-django/chronojump_networks/organizations/migrations/0006_auto_20180402_1751.py
@@ -0,0 +1,27 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.1 on 2018-04-02 17:51
+from __future__ import unicode_literals
+
+from django.conf import settings
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('organizations', '0005_auto_20180401_2146'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='group',
+            name='responsible',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, 
related_name='groups_responsible', to=settings.AUTH_USER_MODEL),
+        ),
+        migrations.AlterField(
+            model_name='organizationstaff',
+            name='organization',
+            field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='staff', 
to='organizations.Organization'),
+        ),
+    ]
diff --git a/chronojumpserver-django/chronojump_networks/organizations/migrations/__init__.py 
b/chronojumpserver-django/chronojump_networks/organizations/migrations/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/chronojumpserver-django/chronojump_networks/organizations/models.py 
b/chronojumpserver-django/chronojump_networks/organizations/models.py
new file mode 100644
index 0000000..688b119
--- /dev/null
+++ b/chronojumpserver-django/chronojump_networks/organizations/models.py
@@ -0,0 +1,242 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.core.exceptions import ObjectDoesNotExist
+from django.contrib.auth.models import AbstractUser
+from django.db import models
+from django.urls import reverse
+from django.utils.translation import ugettext_lazy as _
+
+
+
+# Create your models here.
+from chronojump_networks.core.models import ChronojumpBaseModel, ChronojumpBaseModelWithUUID
+
+
+
+class User(AbstractUser):
+    # Language Code
+    LANGUAGE_SPANISH = 'es'
+    LANGUAGE_CATALAN = 'ca'
+    LANGUAGE_FRENCH = 'fr'
+    LANGUAGE_ENGLISH = 'en'
+
+    LANGUAGE_CHOICES = (
+        (LANGUAGE_SPANISH, _('Spanish')),
+        (LANGUAGE_CATALAN, _('Catalan')),
+        (LANGUAGE_FRENCH, _('French')),
+        (LANGUAGE_ENGLISH, _('English'))
+    )
+
+    class Meta:
+        db_table = "user"
+
+    # First Name and Last Name do not cover name patterns
+    # around the globe.
+    name = models.CharField(_('Name of User'), blank=True, max_length=100)
+    # Languages
+    language = models.CharField(
+           max_length=2,
+           choices=LANGUAGE_CHOICES,
+           default=LANGUAGE_ENGLISH
+       )
+    #
+
+
+    def __str__(self):
+        return ""
+
+    def __unicode__(self):
+        return u'%s' % self.name
+
+    def get_absolute_url(self):
+        return reverse('users:detail', kwargs={'username': self.username})
+
+
+    def organization(self):
+        """ Check if user is a member of an organization """
+        try:
+            org_staff = OrganizationStaff.objects.get(user=self.id)
+            return org_staff.organization
+        except ObjectDoesNotExist:
+            return None
+
+    def is_organization_member(self):
+        """ Check if user is a member of an organization """
+        if self.organization():
+            return True
+        else:
+            return False
+
+    def organization_name(self):
+        """ Check if user is a member of an organization """
+        organization = self.organization()
+        if organization:
+            return organization.name
+        else:
+            return ""
+
+
+class Organization(ChronojumpBaseModel):
+    class Meta:
+        db_table = 'organization'
+
+    name = models.CharField(max_length=50)
+    country = models.CharField(max_length=20, null=True, blank=True)
+    image = models.FileField(upload_to='organizations', blank=True)
+    responsible = models.OneToOneField(User,
+                                    on_delete=models.SET_NULL,
+                                    blank=True,
+                                    null=True,
+                                    related_name='responsible_of')
+
+
+class OrganizationStaff(models.Model):
+    ROLE_COACH_LEADER = 2
+    ROLE_COACH = 1
+
+    ROLE_CHOICES = (
+        (ROLE_COACH, _('Coach')),
+        (ROLE_COACH_LEADER, _('Coach Lead'))
+    )
+
+    role = models.IntegerField(
+        choices=ROLE_CHOICES
+    )
+
+    class Meta:
+        db_table = 'organizationStaff'
+
+    user = models.OneToOneField(User,
+                                on_delete=models.CASCADE,
+                                related_name='member_of')
+    organization = models.ForeignKey(Organization,
+                                on_delete=models.CASCADE,
+                                related_name='staff')
+
+    role = models.IntegerField(choices=ROLE_CHOICES)
+
+    def __str__(self):
+        return self.user.name
+
+
+
+class Gym(ChronojumpBaseModel):
+    """Gym Model"""
+
+    class Meta:
+        db_table = "gym"
+
+    organization = models.ForeignKey(Organization,
+                                     on_delete=models.CASCADE,
+                                     related_name='gyms')
+
+    responsible = models.ForeignKey(User,
+                                    on_delete=models.SET_NULL,
+                                    blank=True,
+                                    null=True,
+                                    related_name='responsible_of_gym')
+
+
+
+
+
+class Station(ChronojumpBaseModel):
+    """Station Model"""
+
+    STATION_INERTIAL = 'I'
+    STATION_GRAVITATORY = 'G'
+    STATION_SPRINT = 'S'
+
+    STATION_CHOICES = (
+        (STATION_SPRINT, _('Sprint')),
+        (STATION_INERTIAL, _('Inertial')),
+        (STATION_GRAVITATORY, _('Gravitatory'))
+    )
+
+    class Meta:
+        db_table = 'station'
+
+    gym = models.ForeignKey(Gym,
+                            on_delete=models.CASCADE,
+                            related_name='stations')
+    type = models.CharField(max_length=1, choices = STATION_CHOICES)
+
+    def organization(self):
+        return self.gym.organization
+
+class Exercise(ChronojumpBaseModel):
+    """Exercise Model"""
+
+    class Meta:
+        db_table = 'exercise'
+
+    station = models.ForeignKey(Station,
+                                on_delete=models.CASCADE,
+                                related_name='exercises')
+
+    percentBodyMassDisplaced = models.FloatField(null=True, default=0)
+
+
+class Player(ChronojumpBaseModel):
+
+    class Meta:
+        db_table = 'person'
+
+    organization = models.ForeignKey(Organization,
+                                     on_delete=models.CASCADE,
+                                     related_name='players')
+
+    height = models.FloatField(default=0)
+    weight = models.FloatField(default=0)
+    rfid = models.CharField(max_length=23, unique=True)
+    image = models.FileField(upload_to='players', null=True, blank=True)
+    is_available = models.BooleanField(default=True)
+    number = models.IntegerField(null=True,blank=True)
+
+
+class Group(ChronojumpBaseModel):
+
+    class Meta:
+        db_table = 'group_'
+
+    organization = models.ForeignKey(Organization,
+                                     on_delete = models.CASCADE,
+                                     related_name="groups")
+    responsible = models.ForeignKey(User,
+                                    on_delete=models.SET_NULL,
+                                    blank=True,
+                                    null=True,
+                                    related_name='groups_responsible')
+
+    gym = models.ForeignKey(Gym,
+                            on_delete=models.SET_NULL,
+                            related_name="gym_groups",
+                            blank=True,
+                            null=True)
+
+
+class GroupCoach(models.Model):
+
+    class Meta:
+        db_table = 'groupCoach'
+
+    coach = models.ForeignKey(User,
+                              on_delete=models.CASCADE,
+                              related_name="groups_by_coach")
+    group = models.ForeignKey(Group,
+                              on_delete=models.CASCADE,
+                              related_name="coaches")
+
+
+class GroupPlayer(models.Model):
+    class Meta:
+        db_table = 'groupPerson'
+
+    player = models.ForeignKey(Player,
+                               on_delete=models.CASCADE,
+                               related_name="groups")
+
+    group = models.ForeignKey(Group,
+                               on_delete=models.CASCADE,
+                               related_name="players")
diff --git a/chronojumpserver-django/chronojump_networks/organizations/tests.py 
b/chronojumpserver-django/chronojump_networks/organizations/tests.py
new file mode 100644
index 0000000..5982e6b
--- /dev/null
+++ b/chronojumpserver-django/chronojump_networks/organizations/tests.py
@@ -0,0 +1,6 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.test import TestCase
+
+# Create your tests here.
diff --git a/chronojumpserver-django/chronojump_networks/organizations/urls.py 
b/chronojumpserver-django/chronojump_networks/organizations/urls.py
new file mode 100644
index 0000000..5ff3cf6
--- /dev/null
+++ b/chronojumpserver-django/chronojump_networks/organizations/urls.py
@@ -0,0 +1,51 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.conf.urls import url, include
+from django.contrib.auth.decorators import login_required
+from django.views.generic import TemplateView
+
+from . import views
+
+app_name = 'organizations'
+urlpatterns = [
+    url(
+        regex=r'^$',
+        view=login_required(TemplateView.as_view(template_name='pages/index.html')),
+        name='index'),
+    url(
+        regex=r'^$',
+        view=views.OrganizationListView.as_view(),
+        name='list'
+    ),
+    url(
+        regex=r'^(?P<id>[\w.@+-]+)/$',
+        view=views.OrganizationDetailView.as_view(),
+        name='detail'
+    ),
+    url(
+        regex=r'^stations/$',
+        view=views.StationListView.as_view(),
+        name='stations'
+    ),
+    url(
+        regex=r'^(?P<organization_id>\d+)/groups/(?P<group_id>\d+)$',
+        view=views.GroupPlayerTemplateView.as_view(),
+        name='group_players_list'
+    ),
+    url(
+        regex=r'^(?P<organization_id>\d+)/gyms/(?P<gym_id>\d+)$',
+        view=views.GymDetailTemplateView.as_view(),
+        name='gym_detail'
+    ),
+    url(
+        regex=r'^login$',
+        view=views.organization_login,
+        name='login'
+    ),
+    url(
+        regex=r'^logout$',
+        view=views.organization_logout,
+        name='logout'
+    ),
+]
diff --git a/chronojumpserver-django/chronojump_networks/organizations/views.py 
b/chronojumpserver-django/chronojump_networks/organizations/views.py
new file mode 100644
index 0000000..465cfd3
--- /dev/null
+++ b/chronojumpserver-django/chronojump_networks/organizations/views.py
@@ -0,0 +1,93 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.contrib.auth import authenticate
+from django.contrib.auth import login as auth_login, logout as auth_logout
+from django.contrib.auth.mixins import LoginRequiredMixin
+from django.shortcuts import render, redirect
+from django.urls import reverse
+from django.views.generic import DetailView, ListView, RedirectView, UpdateView, TemplateView
+from django.utils.translation import ugettext_lazy as _
+from django.utils import translation
+
+from .models import Organization, Station, Group, Gym, Player
+from .forms import UserLoginForm
+from .decorators import check_user_organization
+
+from django import http
+from django.conf import settings
+
+class OrganizationDetailView(LoginRequiredMixin, DetailView):
+    model = Organization
+    slug_field = 'id'
+    slug_url_kwarg = 'id'
+
+
+class OrganizationListView(LoginRequiredMixin, ListView):
+    model = Organization
+    slug_field = 'name'
+    slug_url_kwarg = 'name'
+
+class StationListView(LoginRequiredMixin, ListView):
+    model = Station
+    slug_field = 'name'
+    slug_url_kwarg = 'name'
+
+
+class GroupPlayerTemplateView(LoginRequiredMixin, TemplateView):
+    """ Show the Group and Player List
+    """
+    template_name = 'organizations/groups/group_players_list.html'
+
+    def get_context_data(self, **kwargs):
+        """Pass to the template the Group object"""
+
+        context = super(GroupPlayerTemplateView,self).get_context_data(**kwargs)
+        group_id = int(kwargs['group_id'])
+        context['group'] = Group.objects.get(id=group_id)
+        return context
+
+class GymDetailTemplateView(LoginRequiredMixin, TemplateView):
+    template_name = 'organizations/gyms/gym_detail.html'
+
+    def get_context_data(self, **kwargs):
+        """Pass to the template the Group object"""
+
+        context = super(GymDetailTemplateView,self).get_context_data(**kwargs)
+        gym_id = int(kwargs['gym_id'])
+        context['gym'] = Gym.objects.get(id=gym_id)
+        return context
+
+
+def organization_login(request):
+    """ Login authentication method against the organization """
+    # If user is already authenticated , got to index
+    if request.user.is_authenticated():
+        return redirect('/')
+    # Create user login form with data from post or none if method is get
+    form = UserLoginForm(request.POST or None)
+    if request.method == 'GET':
+        return render(request, 'users/login.html', {'form': form})
+    else:
+        if form.is_valid():
+            username = form.cleaned_data['username']
+            password = form.cleaned_data['password']
+            user = authenticate(username=username, password=password)
+            if user is not None:
+                auth_login(request, user)
+                # Set the language of the User
+                user_language = user.language
+                translation.activate(user_language)
+                request.session[translation.LANGUAGE_SESSION_KEY] = user_language
+                #print(settings.LANGUAGE_CODE)
+                print(translation.get_language())
+                return redirect('/')
+            else:
+                error_msg = _("Invalid username or password")
+        return render(request,
+                'users/login.html',
+                {'form': form, 'error_msg' : error_msg})
+
+def organization_logout(request):
+    auth_logout(request)
+    return redirect('/')
diff --git a/chronojumpserver-django/chronojump_networks/results/__init__.py 
b/chronojumpserver-django/chronojump_networks/results/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/chronojumpserver-django/chronojump_networks/results/admin.py 
b/chronojumpserver-django/chronojump_networks/results/admin.py
new file mode 100644
index 0000000..13be29d
--- /dev/null
+++ b/chronojumpserver-django/chronojump_networks/results/admin.py
@@ -0,0 +1,6 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.contrib import admin
+
+# Register your models here.
diff --git a/chronojumpserver-django/chronojump_networks/results/apps.py 
b/chronojumpserver-django/chronojump_networks/results/apps.py
new file mode 100644
index 0000000..383f243
--- /dev/null
+++ b/chronojumpserver-django/chronojump_networks/results/apps.py
@@ -0,0 +1,8 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.apps import AppConfig
+
+
+class ResultsConfig(AppConfig):
+    name = 'results'
diff --git a/chronojumpserver-django/chronojump_networks/results/migrations/__init__.py 
b/chronojumpserver-django/chronojump_networks/results/migrations/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/chronojumpserver-django/chronojump_networks/results/models.py 
b/chronojumpserver-django/chronojump_networks/results/models.py
new file mode 100644
index 0000000..1dfab76
--- /dev/null
+++ b/chronojumpserver-django/chronojump_networks/results/models.py
@@ -0,0 +1,6 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import models
+
+# Create your models here.
diff --git a/chronojumpserver-django/chronojump_networks/results/tests.py 
b/chronojumpserver-django/chronojump_networks/results/tests.py
new file mode 100644
index 0000000..5982e6b
--- /dev/null
+++ b/chronojumpserver-django/chronojump_networks/results/tests.py
@@ -0,0 +1,6 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.test import TestCase
+
+# Create your tests here.
diff --git a/chronojumpserver-django/chronojump_networks/results/views.py 
b/chronojumpserver-django/chronojump_networks/results/views.py
new file mode 100644
index 0000000..e784a0b
--- /dev/null
+++ b/chronojumpserver-django/chronojump_networks/results/views.py
@@ -0,0 +1,6 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.shortcuts import render
+
+# Create your views here.
diff --git a/chronojumpserver-django/chronojump_networks/static/css/styles-airport.css 
b/chronojumpserver-django/chronojump_networks/static/css/styles-airport.css
new file mode 100644
index 0000000..7c8375e
--- /dev/null
+++ b/chronojumpserver-django/chronojump_networks/static/css/styles-airport.css
@@ -0,0 +1,82 @@
+/*
+* AIRPORT PAGE
+*/
+
+#airportTable {
+    border: none;
+}
+
+#airportTable thead tr th {
+    /*border-bottom: none;*/
+}
+
+#airportTable tbody tr td {
+    /*border-top: none;*/
+}
+
+.playerStationCell {
+
+}
+
+.playerWithActiveTasks {
+    /* Permalink - use to edit and share this gradient: 
http://colorzilla.com/gradient-editor/#00894e+0,006e2e+100 */
+background: #00894e; /* Old browsers */
+background: -moz-linear-gradient(top, #00894e 0%, #006e2e 100%); /* FF3.6-15 */
+background: -webkit-linear-gradient(top, #00894e 0%,#006e2e 100%); /* Chrome10-25,Safari5.1-6 */
+background: linear-gradient(to bottom, #00894e 0%,#006e2e 100%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, 
Safari7+ */
+filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#00894e', 
endColorstr='#006e2e',GradientType=0 ); /* IE6-9 */
+}
+
+#airportTable td.playerName {
+    font-size: 18px;
+    font-weight: bold;
+    text-align: right;
+    vertical-align: middle;
+    border-left: none;
+    border-bottom: none;
+    border-top: none;
+}
+#airportTable th.stationName {
+    text-align: center;
+    background-color: #eee;
+
+}
+
+.carousel-indicators {
+    bottom: 10px;
+}
+
+.carousel-indicators li {
+    border-color: #000;
+}
+
+.carousel-indicators li.active {
+    background-color: gray;
+}
+
+.navbar-text.airport-title {
+    color: #fff;
+    font-size: 1.5em;
+    font-weight: bold;
+    padding-top: 10px;
+}
+
+#datatable_wrapper {
+  margin-top: 20px;
+  padding: 10px;
+  border-radius: 4px 4px 4px 4px;
+  -moz-border-radius: 4px 4px 4px 4px;
+  -webkit-border-radius: 4px 4px 4px 4px;
+  border: 1px solid rgba(240,235,240,1);
+  -webkit-box-shadow: 4px 4px 5px 0px rgba(240,235,240,1);
+  -moz-box-shadow: 4px 4px 5px 0px rgba(240,235,240,1);
+  box-shadow: 4px 4px 5px 0px rgba(240,235,240,1);
+}
+
+td.details-control {
+    background: url('/static/images/details_open.png') no-repeat center center;
+    cursor: pointer;
+}
+tr.shown td.details-control {
+    background: url('/static/images/details_close.png') no-repeat center center;
+}
diff --git a/chronojumpserver-django/chronojump_networks/static/css/styles.css 
b/chronojumpserver-django/chronojump_networks/static/css/styles.css
new file mode 100644
index 0000000..637f9cf
--- /dev/null
+++ b/chronojumpserver-django/chronojump_networks/static/css/styles.css
@@ -0,0 +1,132 @@
+/**
+    Global stylesheet for Chronojump Site
+*/
+
+
+/* Stylesheet from chronojump home page */
+
+body {
+  font-family: 'Open Sans', sans-serif;
+  padding-bottom: 70px;
+  margin-top: 0px;
+}
+
+/* Header Index */
+.header-index {
+  background-color: #0f2351;
+  height: 200px;
+}
+
+.header-index h1, .header-index h4 {
+  color: #fff;
+  font-weight: bold;
+}
+
+body.airport {
+    padding-bottom: 0px;
+}
+
+body.home {
+  margin-top: 0px;
+}
+
+body.login {
+  background-color: #e3e3e3;
+}
+
+/* Buttons */
+.btn-primary {
+    background-color: #0f2351;
+}
+
+.btn-secondary.btn-primary {
+    background-color: #0f2351;
+}
+
+.pagination>.active {
+    background-color: #0f2351;
+}
+
+/* Navbars */
+.navbar-fixed-top {
+  background-color: #0f2351;
+  height: 80px;
+}
+
+.navbar-collapse {
+  background-color: #0f2351;
+}
+
+
+/* Datatables */
+div.datatables_wrapped {
+
+  margin: 20px 0px;
+  padding: 20px 5px;
+  border-radius: 4px 4px 4px 4px;
+  -moz-border-radius: 4px 4px 4px 4px;
+  -webkit-border-radius: 4px 4px 4px 4px;
+  border: 1px solid rgba(240,235,240,1);
+  -webkit-box-shadow: 4px 4px 5px 0px rgba(240,235,240,1);
+  -moz-box-shadow: 4px 4px 5px 0px rgba(240,235,240,1);
+  box-shadow: 4px 4px 5px 0px rgba(240,235,240,1);
+}
+
+
+.footer {
+  background-color: #2b2b2b;
+  color: #ffffff;
+}
+
+.task-link {
+  cursor: pointer;
+}
+
+#results .colResult {
+  color: blue;
+}
+
+.dt-buttons > a.btn {
+    margin-right: 4px;
+    border-radius: 4px;
+
+}
+
+.colAlignRight {
+    text-align: right;
+}
+
+#players td {
+    vertical-align: middle;
+}
+
+#stations td {
+    vertical-align: middle;
+}
+
+#stations tr.selected {
+    font-weight: bold;
+}
+
+.modal-header {
+  background-color: #0f2351;
+  color: #fff;
+}
+
+.modal-header > button.close {
+  color: #fff;
+}
+
+/* Page Header */
+.page-header {
+  border-bottom: 1px solid #0f2351;
+  margin: 10px 5px;
+}
+
+td.details-control {
+    background: url('/static/images/details_open.png') no-repeat center center;
+    cursor: pointer;
+}
+tr.shown td.details-control {
+    background: url('/static/images/details_close.png') no-repeat center center;
+}
diff --git a/chronojumpserver-django/chronojump_networks/static/images/chronojump-logo.png 
b/chronojumpserver-django/chronojump_networks/static/images/chronojump-logo.png
new file mode 100644
index 0000000..e4fbbd4
Binary files /dev/null and b/chronojumpserver-django/chronojump_networks/static/images/chronojump-logo.png 
differ
diff --git a/chronojumpserver-django/chronojump_networks/static/images/details_close.png 
b/chronojumpserver-django/chronojump_networks/static/images/details_close.png
new file mode 100644
index 0000000..9c7d698
Binary files /dev/null and b/chronojumpserver-django/chronojump_networks/static/images/details_close.png 
differ
diff --git a/chronojumpserver-django/chronojump_networks/static/images/details_open.png 
b/chronojumpserver-django/chronojump_networks/static/images/details_open.png
new file mode 100644
index 0000000..c0edf44
Binary files /dev/null and b/chronojumpserver-django/chronojump_networks/static/images/details_open.png differ
diff --git a/chronojumpserver-django/chronojump_networks/static/js/chronojump.js 
b/chronojumpserver-django/chronojump_networks/static/js/chronojump.js
new file mode 100644
index 0000000..58fbfc3
--- /dev/null
+++ b/chronojumpserver-django/chronojump_networks/static/js/chronojump.js
@@ -0,0 +1,40 @@
+/* The Global Javascript for the site goes here */
+
+/* Add csrf token on each Ajax Call on the site */
+function csrfSafeMethod(method) {
+    // these HTTP methods do not require CSRF protection
+    return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
+}
+
+$.ajaxSetup({
+    beforeSend: function(xhr, settings) {
+        if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
+            xhr.setRequestHeader("X-CSRFToken", csrftoken);
+        }
+    }
+});
+
+/* Enable tooltips */
+function enableToolTips() {
+  $('[data-toggle="tooltip"]').tooltip();
+  console.log("Chronojump: Enable tooltips");
+}
+
+/* Enable Remove Button Selection */
+function enableCheckboxSelection(selectClass, buttonClass) {
+  var selector = '.' + selectClass;
+  var button = '.' + buttonClass;
+  $(selector).on('change', function() {
+    var totalChecked = $(selector+':checked').length;
+    if (totalChecked > 0) {
+      // Enable button
+      $(button).removeClass('disabled');
+    } else {
+      // Disable button
+      $(button).addClass('disabled');
+    }
+  });
+}
+
+
+console.log("Chronojump Networks ready");
diff --git a/chronojumpserver-django/chronojump_networks/static/js/tasks.js 
b/chronojumpserver-django/chronojump_networks/static/js/tasks.js
new file mode 100644
index 0000000..b29117c
--- /dev/null
+++ b/chronojumpserver-django/chronojump_networks/static/js/tasks.js
@@ -0,0 +1 @@
+/* Javascript code for task creation */
diff --git a/chronojumpserver-django/chronojump_networks/tasks/__init__.py 
b/chronojumpserver-django/chronojump_networks/tasks/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/chronojumpserver-django/chronojump_networks/tasks/admin.py 
b/chronojumpserver-django/chronojump_networks/tasks/admin.py
new file mode 100644
index 0000000..af0a422
--- /dev/null
+++ b/chronojumpserver-django/chronojump_networks/tasks/admin.py
@@ -0,0 +1,11 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.contrib import admin
+
+from .models import Task
+
+# Register your models here.
+@admin.register(Task)
+class TaskModelAdmin(admin.ModelAdmin):
+    list_display = ( 'ts', 'person', 'station', 'exercise', 'sets', 'nreps' )
diff --git a/chronojumpserver-django/chronojump_networks/tasks/api/__init__.py 
b/chronojumpserver-django/chronojump_networks/tasks/api/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/chronojumpserver-django/chronojump_networks/tasks/api/serializers.py 
b/chronojumpserver-django/chronojump_networks/tasks/api/serializers.py
new file mode 100644
index 0000000..db161db
--- /dev/null
+++ b/chronojumpserver-django/chronojump_networks/tasks/api/serializers.py
@@ -0,0 +1,23 @@
+from rest_framework import serializers
+
+from ..models import Task
+
+class PlayerTaskSerializer(serializers.ModelSerializer):
+    exercise = serializers.StringRelatedField()
+    gym = serializers.StringRelatedField()
+    station = serializers.StringRelatedField()
+
+    class Meta:
+        model = Task
+        fields = [ 'id', 'ts', 'sets', 'nreps', 'load', 'speed', 'gym', 'station', 'exercise']
+
+
+class TaskSerializer(serializers.ModelSerializer):
+
+    class Meta:
+        model = Task
+        fields = [ 'id', 'ts', 'person', 'coach',
+                   'gym', 'station', 'exercise',
+                   'sets', 'nreps', 'load', 'speed',
+                   'percentMaxSpeed', 'lossBySpeed', 'lossByPower',
+                   'comment']
diff --git a/chronojumpserver-django/chronojump_networks/tasks/api/urls.py 
b/chronojumpserver-django/chronojump_networks/tasks/api/urls.py
new file mode 100644
index 0000000..e008266
--- /dev/null
+++ b/chronojumpserver-django/chronojump_networks/tasks/api/urls.py
@@ -0,0 +1,19 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.conf.urls import url
+
+from . import views
+
+urlpatterns = [
+    url(
+        regex=r'^$',
+        view=views.ListCreateAPIView.as_view(),
+        name='tasks'
+    ),
+    url(
+        regex=r'^(?P<task_id>\d+)$',
+        view=views.TaskRetrieveUpdateDestroyAPIView.as_view(),
+        name='tasks'
+    ),
+]
diff --git a/chronojumpserver-django/chronojump_networks/tasks/api/views.py 
b/chronojumpserver-django/chronojump_networks/tasks/api/views.py
new file mode 100644
index 0000000..fa7b373
--- /dev/null
+++ b/chronojumpserver-django/chronojump_networks/tasks/api/views.py
@@ -0,0 +1,52 @@
+from ..models import Task
+from .serializers import TaskSerializer
+
+from django.http import HttpResponse, JsonResponse
+from django.shortcuts import get_object_or_404
+from rest_framework.response import Response
+from rest_framework.generics import ListCreateAPIView, RetrieveUpdateDestroyAPIView
+from rest_framework.mixins import ListModelMixin, CreateModelMixin, DestroyModelMixin
+from rest_framework.permissions import IsAuthenticated
+
+
+class ListCreateAPIView(ListCreateAPIView):
+    permission_classes = (IsAuthenticated, )
+    serializer_class = TaskSerializer
+
+    def get_queryset(self):
+        return Task.objects.all()
+
+    def create(self, request, *args, **kwargs):
+        data = dict(request.data)
+        # TODO: Sure there is a better way to do this
+        o = Task.objects.create(
+            person_id = int(data['person_id'][0]),
+            coach_id = int(data['coach_id'][0]),
+            gym_id = int(data['gym_id'][0]),
+            station_id = int(data['station_id'][0]),
+            exercise_id = int(data['exercise_id'][0]),
+            type = data['type'][0],
+            load = float(data['load'][0]),
+            speed = float(data['speed'][0]),
+            percentMaxSpeed = data['percentMaxSpeed'][0],
+            laterality = data['laterality'][0],
+            sets = int(data['sets'][0]),
+            nreps = int(data['nreps'][0]),
+            lossBySpeed = int(data['lossBySpeed'][0]),
+            lossByPower = int(data['lossByPower'][0]),
+            comment = data['comment'][0]
+        )
+        s = TaskSerializer(o)
+        return Response(s.data)
+
+class TaskRetrieveUpdateDestroyAPIView(RetrieveUpdateDestroyAPIView):
+
+    permission_classes = (IsAuthenticated, )
+    serializer_class = TaskSerializer
+    lookup_field = 'task_id'
+
+    def retrieve(self, request, *args, **kwars):
+        #print(self.kwargs['task_id'])
+        o = get_object_or_404(Task, id=self.kwargs['task_id'])
+        s = TaskSerializer(o)
+        return Response(s.data)
diff --git a/chronojumpserver-django/chronojump_networks/tasks/apps.py 
b/chronojumpserver-django/chronojump_networks/tasks/apps.py
new file mode 100644
index 0000000..226c1a4
--- /dev/null
+++ b/chronojumpserver-django/chronojump_networks/tasks/apps.py
@@ -0,0 +1,8 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.apps import AppConfig
+
+
+class TasksConfig(AppConfig):
+    name = 'chronojump_networks.tasks'
diff --git a/chronojumpserver-django/chronojump_networks/tasks/migrations/0001_initial.py 
b/chronojumpserver-django/chronojump_networks/tasks/migrations/0001_initial.py
new file mode 100644
index 0000000..381decf
--- /dev/null
+++ b/chronojumpserver-django/chronojump_networks/tasks/migrations/0001_initial.py
@@ -0,0 +1,30 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.1 on 2018-04-01 21:53
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    initial = True
+
+    dependencies = [
+        ('organizations', '0005_auto_20180401_2146'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='Task',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, 
verbose_name='ID')),
+                ('type', models.CharField(default='P', max_length=1)),
+                ('ts', models.DateTimeField(auto_now_add=True)),
+                ('person', models.ForeignKey(db_column='personId', 
on_delete=django.db.models.deletion.CASCADE, to='organizations.Player')),
+            ],
+            options={
+                'db_table': 'task',
+            },
+        ),
+    ]
diff --git a/chronojumpserver-django/chronojump_networks/tasks/migrations/0002_auto_20180401_2209.py 
b/chronojumpserver-django/chronojump_networks/tasks/migrations/0002_auto_20180401_2209.py
new file mode 100644
index 0000000..2f55630
--- /dev/null
+++ b/chronojumpserver-django/chronojump_networks/tasks/migrations/0002_auto_20180401_2209.py
@@ -0,0 +1,89 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.1 on 2018-04-01 22:09
+from __future__ import unicode_literals
+
+from django.conf import settings
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('organizations', '0005_auto_20180401_2146'),
+        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+        ('tasks', '0001_initial'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='task',
+            name='coach',
+            field=models.ForeignKey(db_column='coach_id', null=True, 
on_delete=django.db.models.deletion.SET_NULL, related_name='coach_tasks', to=settings.AUTH_USER_MODEL),
+        ),
+        migrations.AddField(
+            model_name='task',
+            name='comment',
+            field=models.CharField(blank=True, max_length=150, null=True),
+        ),
+        migrations.AddField(
+            model_name='task',
+            name='done',
+            field=models.BooleanField(default=False),
+        ),
+        migrations.AddField(
+            model_name='task',
+            name='exercise',
+            field=models.ForeignKey(db_column='exercise_id', null=True, 
on_delete=django.db.models.deletion.CASCADE, related_name='exercise_tasks', to='organizations.Exercise'),
+        ),
+        migrations.AddField(
+            model_name='task',
+            name='gym',
+            field=models.ForeignKey(db_column='gym_id', null=True, 
on_delete=django.db.models.deletion.CASCADE, related_name='gym_tasks', to='organizations.Gym'),
+        ),
+        migrations.AddField(
+            model_name='task',
+            name='laterality',
+            field=models.CharField(choices=[('RL', 'RL - both extremities'), ('R,L', 'R,L - First right, 
then left'), ('R', 'R - Only right extremity'), ('L', 'L - Only left extremity')], default='RL', 
max_length=3),
+        ),
+        migrations.AddField(
+            model_name='task',
+            name='lossByPower',
+            field=models.IntegerField(default=-1),
+        ),
+        migrations.AddField(
+            model_name='task',
+            name='lossBySpeed',
+            field=models.IntegerField(default=-1),
+        ),
+        migrations.AddField(
+            model_name='task',
+            name='nreps',
+            field=models.IntegerField(default=1),
+        ),
+        migrations.AddField(
+            model_name='task',
+            name='percentMaxSpeed',
+            field=models.FloatField(default=-1),
+        ),
+        migrations.AddField(
+            model_name='task',
+            name='sets',
+            field=models.IntegerField(default=1),
+        ),
+        migrations.AddField(
+            model_name='task',
+            name='speed',
+            field=models.FloatField(default=-1),
+        ),
+        migrations.AddField(
+            model_name='task',
+            name='station',
+            field=models.ForeignKey(db_column='station_id', null=True, 
on_delete=django.db.models.deletion.CASCADE, related_name='station_tasks', to='organizations.Station'),
+        ),
+        migrations.AlterField(
+            model_name='task',
+            name='person',
+            field=models.ForeignKey(db_column='personId', on_delete=django.db.models.deletion.CASCADE, 
related_name='player_tasks', to='organizations.Player'),
+        ),
+    ]
diff --git a/chronojumpserver-django/chronojump_networks/tasks/migrations/0003_task_load.py 
b/chronojumpserver-django/chronojump_networks/tasks/migrations/0003_task_load.py
new file mode 100644
index 0000000..ad64d7d
--- /dev/null
+++ b/chronojumpserver-django/chronojump_networks/tasks/migrations/0003_task_load.py
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.1 on 2018-04-02 10:26
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('tasks', '0002_auto_20180401_2209'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='task',
+            name='load',
+            field=models.FloatField(default=-1),
+        ),
+    ]
diff --git a/chronojumpserver-django/chronojump_networks/tasks/migrations/__init__.py 
b/chronojumpserver-django/chronojump_networks/tasks/migrations/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/chronojumpserver-django/chronojump_networks/tasks/models.py 
b/chronojumpserver-django/chronojump_networks/tasks/models.py
new file mode 100644
index 0000000..290026e
--- /dev/null
+++ b/chronojumpserver-django/chronojump_networks/tasks/models.py
@@ -0,0 +1,67 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import models
+from django.utils.translation import ugettext_lazy as _
+
+from chronojump_networks.organizations.models import Player, Gym, Station, Exercise, User
+
+# Create your models here.
+
+class Task(models.Model):
+    LATERALITY_BOTH = 'RL'
+    LATERALITY_FIRST_LEFT_THEN_RIGHT = 'R,L'
+    LATERALITY_LEFT = 'L'
+    LATERALITY_RIGHT = 'R'
+
+    LATERALITY_CHOICES= (
+        (LATERALITY_BOTH, _('RL - both extremities')),
+        (LATERALITY_FIRST_LEFT_THEN_RIGHT, _('R,L - First right, then left')),
+        (LATERALITY_RIGHT, _('R - Only right extremity')),
+        (LATERALITY_LEFT, _('L - Only left extremity'))
+    )
+
+    class Meta:
+        db_table = 'task'
+
+    type = models.CharField(max_length=1, default='P')
+    ts = models.DateTimeField(auto_now_add=True)
+    person = models.ForeignKey(Player,
+                               on_delete = models.CASCADE,
+                               db_column='personId',
+                               related_name='player_tasks')
+    coach = models.ForeignKey(User,
+                              on_delete = models.SET_NULL,
+                              db_column = 'coach_id',
+                              related_name = 'coach_tasks',
+                              null=True)
+
+    gym = models.ForeignKey(Gym,
+                            on_delete = models.CASCADE,
+                            db_column='gym_id',
+                            related_name='gym_tasks',
+                            null=True)
+
+    station = models.ForeignKey(Station,
+                            on_delete = models.CASCADE,
+                            db_column='station_id',
+                            related_name='station_tasks',
+                            null=True)
+
+    exercise = models.ForeignKey(Exercise,
+                            on_delete = models.CASCADE,
+                            db_column='exercise_id',
+                            related_name='exercise_tasks',
+                            null=True)
+
+    sets = models.IntegerField(default = 1)
+    nreps = models.IntegerField(default = 1)
+    speed = models.FloatField(default = -1)
+    load = models.FloatField(default = -1)
+    percentMaxSpeed = models.FloatField(default = -1)
+    lossBySpeed = models.IntegerField(default = -1)
+    lossByPower = models.IntegerField(default = -1)
+    laterality = models.CharField(max_length = 3, choices = LATERALITY_CHOICES,
+                                  default=LATERALITY_BOTH )
+    comment = models.CharField(max_length=150, null=True, blank=True)
+    done = models.BooleanField(default=False)
diff --git a/chronojumpserver-django/chronojump_networks/tasks/tests.py 
b/chronojumpserver-django/chronojump_networks/tasks/tests.py
new file mode 100644
index 0000000..5982e6b
--- /dev/null
+++ b/chronojumpserver-django/chronojump_networks/tasks/tests.py
@@ -0,0 +1,6 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.test import TestCase
+
+# Create your tests here.
diff --git a/chronojumpserver-django/chronojump_networks/tasks/views.py 
b/chronojumpserver-django/chronojump_networks/tasks/views.py
new file mode 100644
index 0000000..e784a0b
--- /dev/null
+++ b/chronojumpserver-django/chronojump_networks/tasks/views.py
@@ -0,0 +1,6 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.shortcuts import render
+
+# Create your views here.
diff --git a/chronojumpserver-django/chronojump_networks/templates/admin/base_site.html 
b/chronojumpserver-django/chronojump_networks/templates/admin/base_site.html
new file mode 100644
index 0000000..88d68d6
--- /dev/null
+++ b/chronojumpserver-django/chronojump_networks/templates/admin/base_site.html
@@ -0,0 +1,9 @@
+{% extends "admin/base.html" %}
+
+{% block title %}{{ title }} | Chronojump Site Admin{% endblock %}
+
+{% block branding %}
+<h1 id="site-name"><a href="{% url 'admin:index' %}">Chronojump Administration</a></h1>
+{% endblock %}
+
+{% block nav-global %}{% endblock %}
diff --git a/chronojumpserver-django/chronojump_networks/templates/base.html 
b/chronojumpserver-django/chronojump_networks/templates/base.html
new file mode 100644
index 0000000..01b8e78
--- /dev/null
+++ b/chronojumpserver-django/chronojump_networks/templates/base.html
@@ -0,0 +1,39 @@
+{% load static i18n %}
+<!doctype html>
+{% get_current_language as LANGUAGE_CODE %}
+<html lang="{{ LANGUAGE_CODE }}">
+  <head>
+    <!-- Required meta tags -->
+    <meta charset="utf-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
+
+    <title>{% block title %}Welcome to Chronojump Networks{% endblock title %}</title>
+
+    {% block css %}
+
+    <!-- Bootstrap CSS -->
+    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"; 
integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
+    <link href="https://fonts.googleapis.com/css?family=Open+Sans"; rel="stylesheet">
+    <link href="https://fonts.googleapis.com/icon?family=Material+Icons"rel="stylesheet";>
+    <link rel="stylesheet" href="{% static 'css/styles.css' %}">
+
+    {% endblock css %}
+
+  </head>
+  <body class="{% block body_class %}{% endblock %}">
+
+    {% block main %}
+    {% endblock main %}
+
+    {% block javascript %}
+
+    <!-- jQuery first, then Popper.js, then Bootstrap JS -->
+    <script src="https://code.jquery.com/jquery-3.3.1.min.js"; 
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
+    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"; 
integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" 
crossorigin="anonymous"></script>
+    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"; 
integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" 
crossorigin="anonymous"></script>
+
+    <script src="{% static 'js/chronojump.js' %}"></script>
+
+    {% endblock %}
+  </body>
+</html>
diff --git a/chronojumpserver-django/chronojump_networks/templates/layout.html 
b/chronojumpserver-django/chronojump_networks/templates/layout.html
new file mode 100644
index 0000000..4376374
--- /dev/null
+++ b/chronojumpserver-django/chronojump_networks/templates/layout.html
@@ -0,0 +1,62 @@
+{% extends "base.html" %}
+{% load static i18n %}
+{% block main %}
+
+<nav class="navbar navbar-expand-lg navbar-dark" style="background-color:#0f2351">
+  <a class="navbar-brand" href="/"><img alt="Brand" src="{% static 'images/chronojump-logo.png' %}" 
height="48px"></a>
+  <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarToggler" 
aria-controls="navbarToggler" aria-expanded="false" aria-label="Toggle navigation">
+    <span class="navbar-toggler-icon"></span>
+  </button>
+  <div class="collapse navbar-collapse" id="navbarToggler">
+    <ul class="navbar-nav mr-auto">
+      <li class="nav-item active">
+        <a class="nav-link" href="/">{% trans 'Home' %} <span class="sr-only">(current)</span></a>
+      </li>
+      <li class="nav-item">
+        <a class="nav-link disabled" href="#">{% trans 'Results' %}</a>
+      </li>
+      <li class="nav-item">
+        <a class="nav-link disabled" href="#">{% trans 'Sprints' %}</a>
+      </li>
+      {% if request.user.groups_by_coach %}
+      <li class="nav-item dropdown active">
+        <a class="nav-link dropdown-toggle" href="#" id="navbarDropdownGroups" data-toggle="dropdown" 
aria-haspopup="true" aria-expanded="false">
+          {% trans 'Groups' %}
+        </a>
+        <div class="dropdown-menu" aria-labelledby="navbarDropdownGroups">
+          <h6 class="dropdown-header">{% trans 'My groups' %}</h6>
+          {% for group in request.user.groups_by_coach.all %}
+          <a class="dropdown-item" href="{% url 'organizations:group_players_list' 
organization_id=user.organization.id group_id=group.group.id %}">{{ group.group.name}}</a>
+          {% endfor %}
+          <div class="dropdown-divider"></div>
+          <a class="dropdown-item" href="#">{% trans 'Create a group' %}</a>
+        </div>
+      </li>
+      {% endif %}
+      {% if request.user.organization.gyms %}
+      <li class="nav-item dropdown active">
+        <a class="nav-link dropdown-toggle" href="#" id="navbarDropdownGyms" data-toggle="dropdown" 
aria-haspopup="true" aria-expanded="false">
+          {% trans 'Gyms' %}
+        </a>
+        <div class="dropdown-menu" aria-labelledby="navbarDropdownGroups">
+          <h6 class="dropdown-header">{% trans 'My gyms' %}</h6>
+          {% for gym in request.user.organization.gyms.all %}
+          <a class="dropdown-item" href="{% url 'organizations:gym_detail' 
organization_id=user.organization.id gym_id=gym.id %}">{{ gym.name}}</a>
+          {% endfor %}
+          <div class="dropdown-divider"></div>
+          <a class="dropdown-item" href="#">{% trans 'Create a gym' %}</a>
+        </div>
+      </li>
+      {% endif %}
+    </ul>
+    <ul class="navbar-nav justify-content-end">
+      <li class="nav-item active"><a class="nav-link" href="#">{% trans 'Hello, '%}{{user.name}}</a></li>
+      <li class="nav-item active"><a class="nav-link" href="{% url 'logout' %}">{% trans 'Close session' 
%}</a></li>
+    </ul>
+  </div>
+</nav>
+<div class="container-fluid">
+{% block content %}
+{% endblock content %}
+</div>
+{% endblock main %}
diff --git 
a/chronojumpserver-django/chronojump_networks/templates/organizations/groups/group_players_list.html 
b/chronojumpserver-django/chronojump_networks/templates/organizations/groups/group_players_list.html
new file mode 100644
index 0000000..327fc6a
--- /dev/null
+++ b/chronojumpserver-django/chronojump_networks/templates/organizations/groups/group_players_list.html
@@ -0,0 +1,603 @@
+{% extends 'layout.html' %}
+{% load static i18n %}
+
+{% block title %}Chronojump Networks | {{user.organization.name}} | {{group.name}}{% endblock %}
+
+{% block css %}
+{{ block.super }}
+<link rel="stylesheet" href="https://cdn.datatables.net/1.10.16/css/dataTables.bootstrap4.min.css";>
+<link rel="stylesheet" href="https://cdn.datatables.net/buttons/1.5.1/css/buttons.bootstrap4.min.css";>
+<!--<link rel="stylesheet" 
href="https://cdn.datatables.net/fixedcolumns/3.2.4/css/fixedColumns.bootstrap4.min.css";>-->
+
+{% endblock %}
+
+{% block content %}
+{% csrf_token %}
+
+<div class="page-header row">
+  <div class="col-sm-9">
+    <img src="/media/{{ user.organization.image }}" class="img-fluid float-left" width="48px" height="48px" 
style="margin-top:12px;margin-right:10px;"/>
+    <h1 class="display-4">{{group.name}}  <small class="text-muted" style="font-size:32px">{% trans 'Players 
and tasks' %}</small></h1>
+  </div>
+  <div class="col-sm-3">
+    <dl class="row" style="margin-top:10px">
+      <dt class="col-sm-4 text-right">{% trans 'Responsible' %}:</dt>
+      <dd class="col-sm-8">{{ group.responsible.name }}</dd>
+      <dt class="col-sm-4 text-right">{% trans 'Gym' %}:</dt>
+      <dd class="col-sm-8">{{ group.gym }}</dd>
+    </dl>
+  </div>
+</div>
+
+<div class="row datatables_wrapped">
+  <div class="col">
+       <table id="players" cellspacing="0" cellpadding="0" class="table table-sm" style="width:100%">
+       </table>
+  </div>
+</div>
+
+
+<!-- Modal Form to add a player -->
+<div class="modal fade" id="addPlayerModal" tabindex="-1" role="dialog" aria-labelledby="{% trans 'Add 
Player to Group' %}" aria-hidden="true">
+  <div class="modal-dialog modal-dialog-centered modal-lg" role="document">
+    <div class="modal-content">
+      <div class="modal-header">
+        <h5 class="modal-title" id="addPlayersModalTitle">{% trans 'Add players to group ' 
%}{{group.name}}</h5>
+        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+          <span aria-hidden="true">&times;</span>
+        </button>
+      </div>
+      <div class="modal-body">
+        <table id="add_players" cellspacing="0" class="table" style="width:100%">
+        </table>
+      </div>
+      <div class="modal-footer">
+        <button type="button" class="btn btn-outline-secondary" data-dismiss="modal">{% trans 'Close' 
%}</button>
+        <button type="button" class="btn btn-outline-primary disabled addPlayerButton">{% trans 'Add 
players' %}</button>
+      </div>
+    </div>
+  </div>
+</div>
+
+<!-- Include Modal Task Form -->
+{% include 'organizations/groups/task_modal_form.html' %}
+
+<!-- Include Multiple Modal Task Form -->
+
+
+{% endblock %}
+
+{% block javascript %}
+{{ block.super }}
+<script src="https://cdn.datatables.net/1.10.16/js/jquery.dataTables.min.js";></script>
+<script src="https://cdn.datatables.net/1.10.16/js/dataTables.bootstrap4.min.js";></script>
+<script src="https://cdn.datatables.net/buttons/1.5.1/js/dataTables.buttons.min.js";></script>
+<script src="https://cdn.datatables.net/buttons/1.5.1/js/buttons.bootstrap4.min.js";></script>
+<!--<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.1.3/jszip.min.js";></script>
+<script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.32/pdfmake.min.js";></script>
+<script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.32/vfs_fonts.js";></script>
+<script src="https://cdn.datatables.net/buttons/1.5.1/js/buttons.print.min.js";></script>-->
+<script src="https://cdn.datatables.net/buttons/1.5.1/js/buttons.html5.min.js";></script>
+<!--<script src="https://cdn.datatables.net/buttons/1.5.1/js/buttons.colVis.min.js";></script>
+<script src="https://cdn.datatables.net/fixedcolumns/3.2.4/js/dataTables.fixedColumns.min.js";></script>-->
+
+<script>
+  var csrftoken = jQuery("[name=csrfmiddlewaretoken]").val();
+
+  $(document).ready(function() {
+    /* Datatable for players in groups */
+    var table_players = $('#players').DataTable({
+      lengthChange: false,
+      "ajax": {
+        "processing": true,
+        "url" : "{% url 'api_organizations:group_players_list' organization_id=user.organization.id 
group_id=group.id %}",
+        "dataSrc": ""
+      },
+      {% if user.id == group.responsible.id %}
+      "order": [ 
+       [3, 'asc']
+      ],
+      {% else %}
+      "order": [ 
+       [2, 'asc']
+      ],
+      {% endif %}
+      "columns": [
+        {% if user.id == group.responsible.id %}
+        {
+                       type: "html",
+                       orderable:false,
+                       render: function(value, type, row) {
+                               return '<input class="selectPlayerCheckbox" type="checkbox" data-player-id="' 
+ row.id + '"/>';
+                       }
+               },
+        {% endif %}
+        { /* Column to show the tasks */
+            "className":      'details-control',
+            "orderable":      false,
+            "data":           null,
+            "defaultContent": ''
+        },
+        {
+                       type: "html",
+                       title: "",
+                       data: 'image',
+                       orderable: false,
+                       render: function(value, type, row) {
+            if (value) {
+                                       var src = value;
+                               } else {
+                                       // Otherwise show the no_image icon
+                                       var src = '/static/images/no_image.png';
+                               }
+                               var html = '<img src="' + src + '" class="img-fluid rounded" width="32px" 
height="32px"/>';
+                               return html;
+                       }
+               },
+        {
+          "data": "number",
+          title: "{% trans 'Number' %}"
+        },
+        {
+          data: "name",
+                       title: "{% trans 'Player name' %}",
+        },
+
+        {
+          "data": "height",
+          title: "{% trans 'Height' %}"
+        },
+        {
+          "data": "weight",
+          title: "{% trans 'Weight' %}"
+        },
+        {
+          "type": "html",
+          orderable: false,
+          render: function(value, type, row) {
+            var html = "";
+            // Single Task Button
+            html += '<button type="button" class="addTaskBtn btn btn-outline-success btn-sm" ';
+            html += 'data-player-id="' + row.id + '" ';
+            html += 'data-player-name="' + row.name + '" ';
+            html += 'data-toggle="tooltip" data-placement="right" ';
+            html += 'title="' + "{% trans 'Add new task to ' %}" + row.name + '">';
+            html += '<i class="material-icons" style="margin-top:3px;font-size:16px;">add</i></button>';
+            // Multiple Tasks
+            html += '&nbsp;<button type="button" class="addMultipleTaskBtn btn btn-outline-warning btn-sm" ';
+            html += 'data-player-id="' + row.id + '" ';
+            html += 'data-player-name="' + row.name + '" ';
+            html += 'data-toggle="tooltip" data-placement="right" ';
+            html += 'title="' + "{% trans 'Add multiple tasks to ' %}" + row.name + '">';
+            html += '<i class="material-icons" style="margin-top:3px;font-size:16px;">plus_one</i></button>';
+            return html;
+          }
+        }
+      ],
+      "dom": "<'row'<'col-sm-6'B><'col-sm-6'f>>rtip",
+      buttons: [
+        {% if user.id == group.responsible.id %}
+               { /* Add Player button */
+          text: "{% trans 'Add players' %}",
+          className: "btn btn-primary",
+                 action: function( e, dt, node, config ) {
+            $('#addPlayerModal').modal('show');
+
+          }
+        },
+        { /* Remove Players Button */
+          text: "{% trans 'Remove players' %}",
+          className: "btn btn-danger disabled removePlayerBtn",
+
+                 action: function( e, dt, node, config ) {
+            var player_ids = [];
+            $.each($('.selectPlayerCheckbox:checked'), function(index, value) {
+              var v = $(value);
+                               player_ids.push(v.attr('data-player-id'));
+
+            });
+            removePlayersFromGroup(player_ids);
+          }
+        }
+        {% endif %}
+      ],
+      initComplete: function() {
+        // Enable the remove player selection the first time data is loaded
+        enablePlayersTableFunctionality();
+      }
+    });
+
+    /* Task child rows */
+    function format ( d ) {
+        // `d` is the original data object for the row
+               if (d.player_tasks.length > 0) {
+                       var html = '<table cellpadding="5" cellspacing="10" style="margin-left:50px;">';
+                       html += "<thead><th></th><th>{% trans 'Gym' %}";
+          html += "<th>{% trans 'Station' %}</th><th>{% trans 'Exercise' %}</th>";
+          html += "<th>{% trans 'Sets' %}</th><th>{% trans 'Repeats' %}</th>";
+          html += "<th>{% trans 'Load' %}</th></th><th>{% trans 'Speed' %}";
+          html +="</th><th></th>"
+                       $.each(d.player_tasks, function(index, task) {
+            console.log(task);
+                               html += '<tbody><tr>';
+                               html += '<td>' + (index + 1) + '</td>';
+            html += '<td>' + task.gym + '</td>';
+                               html += '<td>' + task.station + '</td>';
+                               html += '<td>' + task.exercise + '</td>';
+                               html += '<td class="text-center">' + task.sets + '</td>';
+                               html += '<td class="text-center">' + task.nreps + '</td>';
+            if (task.load >= 0) {
+                                 html += '<td class="text-center">' + task.load + '</td>';
+            } else {
+              html += '<td class="text-center no-value">-</td>';
+            }
+            if (task.speed >= 0) {
+                                 html += '<td class="text-center">' + task.speed + '</td>';
+            } else {
+              html += '<td class="text-center no-value">-</td>';
+            }
+
+                               html += '<td>';
+            html += '<a class="task-link task-modify-link" data-toogle="tooltip" data-placement="right" 
title="' + "{% trans 'Modify this task' %}" +'"';
+                               html += 'data-task-id="' + task.id + '"'
+                               html += 'data-task-type="' + task.type + '">'
+            html += '<i class="material-icons">mode_edit</i></a>';
+            html += '&nbsp;';
+            html += '<a class="task-link task-duplicate-link" data-toogle="tooltip" data-placement="right" 
title="' + "{% trans 'Duplicate this task' %}" +'"';
+                               html += 'data-task-id="' + task.id + '"'
+                               html += 'data-task-type="' + task.type + '">'
+            html += '<i class="material-icons">content_copy</i></a>';
+            html += '&nbsp;';
+            html += '<a class="task-link task-delete-link" data-toogle="tooltip" data-placement="right" 
title="' + "{% trans 'Delete this task' %}" +'"';
+                               html += 'data-task-id="' + task.id + '"'
+                               html += 'data-task-type="' + task.type + '">'
+            html += '<i class="material-icons">delete_sweep</i></a>';
+            html += '</td></tr>';
+                       });
+                       html += "</tbody></table>";
+
+                       return html;
+               } else {
+                       return '<h6 class="text-center font-weight-bold font-italic">' + "{% trans 'Player 
has not tasks' %}" +'</h6>';
+               }
+        /*return '<table cellpadding="5" cellspacing="0" border="0" style="padding-left:50px;">'+
+            '<tr>'+
+                '<td>Full name:</td>'+
+                '<td>'+d.name+'</td>'+
+            '</tr>'+
+            '<tr>'+
+                '<td>Extension number:</td>'+
+                '<td>'+d.extn+'</td>'+
+            '</tr>'+
+            '<tr>'+
+                '<td>Extra info:</td>'+
+                '<td>And any further details here (images etc)...</td>'+
+            '</tr>'+
+        '</table>';*/
+    }
+    // Add event listener for opening and closing details
+    $('#players tbody').on('click', 'td.details-control', function () {
+        var tr = $(this).closest('tr');
+        var row = table_players.row( tr );
+
+        if ( row.child.isShown() ) {
+            // This row is already open - close it
+            row.child.hide();
+            tr.removeClass('shown');
+        }
+        else {
+            // Open this row
+            row.child( format(row.data()) ).show();
+            tr.addClass('shown');
+        }
+    } );
+
+    function enablePlayersTableFunctionality() {
+      // Enanble checkboxes
+      $('.removePlayerBtn').removeClass('disabled').addClass('disabled');
+      enableCheckboxSelection('selectPlayerCheckbox', 'removePlayerBtn');
+
+      // Enabling add task buttons
+      $('.addTaskBtn').on('click', function(){
+        var player = table_players.row($(this).parents('tr')).data();
+
+        // Set the title for new player task
+        var title = "{% trans 'Add new task to '%}" + player.name;
+        $('#taskModalTitle').text(title);
+
+        var player = table_players.row($(this).parents('tr')).data();
+        // newTaskOperation
+        newTaskInitialOperations(player.id);
+        $('#taskModalForm').modal('show');
+      });
+
+    }
+
+    /* Datatable for add players */
+    var add_players_table = $('#add_players').DataTable({
+      lengthChange: false,
+      "ajax": {
+        "processing": true,
+        "url" : "{% url 'api_organizations:group_add_players_list' organization_id=user.organization.id 
group_id=group.id %}",
+        "dataSrc": ""
+      },
+      "columns": [
+        {
+                       type: "html",
+                       orderable:false,
+                       render: function(value, type, row) {
+                               return '<input class="addPlayerCheckbox" type="checkbox" data-player-id="' + 
row.id + '"/>';
+                       }
+               },
+        {
+          "data": "number",
+          title: "{% trans 'Number' %}"
+        },
+        {
+          data: "name",
+                       title: "{% trans 'Player name' %}",
+        }
+      ],
+      "order": [ 
+       [1, 'asc']
+      ],
+      initComplete: function() {
+        /* Called when the table is loaded */
+        enableAddPlayersTableFunctionality();
+
+        // Set the action to add player button
+        $('.addPlayerButton').on('click', function(e) {
+          // Be sure to do something if button is enabled
+          if (!$('.addPlayerButton').hasClass('disabled')) {
+
+            var player_ids = [];
+
+            $.each($('.addPlayerCheckbox:checked'), function(index, value) {
+              var v = $(value);
+                               player_ids.push(v.attr('data-player-id'));
+
+            });
+            // Call the function to add the players via ajax
+            addPlayersToGroup(player_ids);
+            e.preventDefault();
+          }
+        })
+      }
+    });
+
+
+
+    function enableAddPlayersTableFunctionality() {
+      $('.addPlayerButton').removeClass('disabled').addClass('disabled');
+      enableCheckboxSelection('addPlayerCheckbox', 'addPlayerButton');
+    }
+
+
+
+    /* Buttons operation */
+    function removePlayersFromGroup(player_ids) {
+        $.ajax({
+        'url': "{% url 'api_organizations:remove_players_from_group' organization_id=user.organization.id 
group_id=group.id %}",
+        'method': 'DELETE',
+        'data': {
+          'player_ids': player_ids
+        },
+        success:function(data) {
+          console.log("players removed to the group");
+          // Hide AddPlayerModel dialog
+          var totalChecked = $('.selectPlayerCheckbox:checked').length;
+          if (totalChecked == 1) {
+            alert("{% trans 'The player has been removed from group' %}");
+          } else {
+            alert("{% trans 'The players have been removed from the group' %}");
+          }
+          table_players.ajax.reload(enablePlayersTableFunctionality, false);
+          add_players_table.ajax.reload(enableAddPlayersTableFunctionality, false);
+        }
+      });
+    }
+
+    /* Add the players selected */
+    function addPlayersToGroup(player_ids) {
+      $.ajax({
+        'url': "{% url 'api_organizations:group_add_players_list' organization_id=user.organization.id 
group_id=group.id %}",
+        'method': 'POST',
+        'data': {
+          'player_ids': player_ids
+        },
+        success:function(data) {
+          // Hide AddPlayerModel dialog
+          var totalChecked = $('.addPlayerCheckbox:checked').length;
+          if (totalChecked == 1) {
+            alert("{% trans 'The player has been added to the group' %}");
+          } else {
+            alert("{% trans 'The players have been added to the group' %}");
+          }
+          table_players.ajax.reload(enablePlayersTableFunctionality, false);
+          add_players_table.ajax.reload(enableAddPlayersTableFunctionality, false);
+          $('#addPlayerModal').modal('hide');
+        },
+        error: function (request, status, error) {
+            alert(request.responseText);
+        }
+      });
+    }
+
+    /* Source for Tasks */
+
+    /* initials operations for task */
+    function newTaskInitialOperations(player_id) {
+      // Load station from assigned gym to group
+
+      console.log("initial gym is " + "{{ group.gym.name}}");
+      var group_id = {{ group.gym.id }};
+      console.log('Look for gym with id ' + {{ group.gym.id }});
+      $('#gymSelect').val(group_id);
+      // Set the player Id
+      $('#personId').val(player_id);
+      // Set taskId empty representing a new task
+      $('#taskId').val('');
+
+      loadGymStations(group_id);
+    }
+
+    $('#gymSelect').on('change', function() {
+       //Ajax call to retrieve all the stations. Call the function below.
+      var gym_id = $('#gymSelect').val();
+       // Show the stations of this gym
+       loadGymStations(gym_id);
+    });
+
+    /* Load stations from the gym into selectStation control */
+    function loadGymStations(gym_id) {
+      $('#stationSelect').find('option').remove().end();
+
+      $.ajax({
+        'url': "{% url 'api_organizations:gym_stations' organization_id=user.organization.id %}",
+        data: {
+          'gym_id': gym_id
+        },
+        success: function(data) {
+          console.log(data);
+          var count = 0;
+                       $.each(data, function(i, item) {
+            count ++;
+                               $('#stationSelect').append($('<option>', {
+                                       value: item.id,
+                                       text: item.name
+                               }));
+                       })
+          if (count > 0) {
+            $('#stationSelect').removeAttr('disabled');
+            // Load exercises from first station loaded
+            var station_id = $('#stationSelect option:first').val();
+            $('#stationSelect').val(station_id);
+            loadStationExercises(station_id);
+          } else {
+            // Disable task creation
+          }
+        }
+      });
+    }
+
+    $('#stationSelect').on('change', function() {
+       //Ajax call to retrieve all the exercises from a station
+      var station_id = $('#stationSelect').val();
+       // Show the exercises of this station
+       loadStationExercises(station_id);
+    });
+
+    /* Load stations from the gym into selectStation control */
+    function loadStationExercises(station_id) {
+      $('#exerciseSelect').find('option').remove().end();
+
+      $.ajax({
+        'url': "{% url 'api_organizations:station_exercises' organization_id=user.organization.id %}",
+        data: {
+          'station_id': station_id
+        },
+        success: function(data) {
+          console.log(data);
+          var count = 0;
+                       $.each(data, function(i, item) {
+                               count ++;
+                               $('#exerciseSelect').append($('<option>', {
+                                       value: item.id,
+                                       text: item.name
+                               }));
+                       })
+          if (count > 0) {
+            $('#exerciseSelect').removeAttr('disabled');
+            // Load exercises from first station loaded
+            $('#exerciseSelect').val($('#exerciseSelect option:first').val());
+          } else {
+            // Disable task creation
+          }
+        }
+      });
+    }
+
+
+    $('#btnAddModifyTask').on('click', function(e) {
+      e.preventDefault();
+      var task = serializeTask();
+      putTask(task);
+    })
+
+    /* If value is empty set -1 as value */
+    function safe_task_value(selector) {
+
+      var val = $(selector).val();
+
+      if (val != '') {
+        return val;
+      }
+      return -1;
+    }
+
+    /* Get all the values in the form into json object */
+    function serializeTask() {
+      let gym_id = $('#gymSelect').val();
+      let station_id = $('#stationSelect').val();
+      let exercise_id = $('#exerciseSelect').val();
+      let person_id = $('#personId').val();
+      let sets = $('#numSets').val();
+      let nreps = $('#numReps').val();
+      let load = safe_task_value('#taskLoad');
+      var speed = safe_task_value('#taskSpeed');
+      let percentMaxSpeed = safe_task_value('#taskPercentMaxSpeed');
+      let laterality = $('#taskLaterality').val();
+      let comment = $('#taskCoachComment').val();
+      let lossBySpeed = safe_task_value('#taskLossBySpeed');
+      let lossByPower = safe_task_value('#taskLossByPower');
+      let coach_id = {{ user.id }};
+      var task = {
+        'type' : 'S',
+        'person_id': person_id,
+        'gym_id': gym_id,
+        'station_id': station_id,
+        'exercise_id': exercise_id,
+        'sets' : sets,
+        'nreps' : nreps,
+        'load' : load,
+        'speed' : speed,
+        'percentMaxSpeed' : percentMaxSpeed,
+        'laterality': laterality,
+        'comment': comment,
+        'lossByPower': lossByPower,
+        'lossBySpeed': lossBySpeed,
+        'coach_id': 2
+      }
+      console.log(task);
+      return task;
+    }
+
+    function validateTask(task) {
+      return task;
+    }
+
+    function putTask(task) {
+      /* TODO: Add validation */
+      $.ajax({
+        'url': "{% url 'api_tasks:tasks' %}",
+        'method': 'POST',
+        'data': task,
+        success: function(data) {
+          alert("The task has been added");
+          table_players.ajax.reload(enablePlayersTableFunctionality, false);
+          $('#taskModalForm').modal('hide');
+        }
+
+      })
+    }
+
+    // Enable tooltips
+    $(function () {
+      $('[data-toggle="tooltip"]').tooltip();
+      console.log("Enabling the tooltips");
+    })
+
+  }); /* End of Document ready */
+</script>
+
+{% endblock %}
diff --git a/chronojumpserver-django/chronojump_networks/templates/organizations/groups/task_modal_form.html 
b/chronojumpserver-django/chronojump_networks/templates/organizations/groups/task_modal_form.html
new file mode 100644
index 0000000..e6494e2
--- /dev/null
+++ b/chronojumpserver-django/chronojump_networks/templates/organizations/groups/task_modal_form.html
@@ -0,0 +1,254 @@
+{% load static i18n %}
+
+<!-- Modal Form to add a new task -->
+<div id="taskModalForm" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="{% trans 'Add Task' 
%}" aria-hidden="true">
+       <div class="modal-dialog modal-dialog-centered modal-lg" role="document">
+               <div class="modal-content">
+      <div class="modal-header">
+        <h5 class="modal-title" id="taskModalTitle"></h5>
+        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+          <span aria-hidden="true">&times;</span>
+        </button>
+      </div>
+                       <div class="modal-body">
+
+                               <input type="hidden" id="personId" />
+                               <input type="hidden" id="taskId" />
+                               <input type="hidden" id="coachId" value="{{ user.id }}"/>
+
+       <form>
+          <div class="form-row">
+                                               <div class="form-group col-sm-4">
+                                                       <label for="gym">{% trans 'Gym' %}</label>
+                                                       <select name="gym" class="form-control" 
id="gymSelect">
+                                                               {% for gym in user.organization.gyms.all %}
+                                                               <option value={{gym.id}}>{{gym.name}}</option>
+                                                               {% endfor %}
+                                                       </select>
+                                               </div>
+            <div class="form-group col-sm-4">
+                                                       <label for="station">{% trans 'Station' %}</label>
+                                                       <select name="station" class="form-control" 
id="stationSelect">
+              <!-- Load dynamically -->
+                                                       </select>
+                                               </div>
+            <div class="form-group col-sm-4">
+                                                       <label for="exercise">{% trans 'Exercise' %}</label>
+                                                       <select name="exercise" class="form-control" 
id="exerciseSelect">
+              <!-- Load dynamically -->
+                                                       </select>
+                                               </div>
+          </div>
+                                 <hr>
+          <div class="form-row">
+            <div class="form-group col-sm-4">
+              <label for="numSets">{% trans '# Sets' %}</label>
+              <input id="numSets" name="numSets" type="number" class="form-control taskParameter" value="1" 
min="1"></input>
+            </div>
+            <div class="form-group col-sm-4 ">
+              <label for="numReps">{% trans '# Repeats' %}</label>
+              <input id="numReps" name="numReps" type="number" class="form-control taskParameter" value="1" 
min="1"></input>
+            </div>
+            <div class="form-group col-sm-4">
+              <label for="taskLoad">{% trans 'Load (Kg)' %}</label>
+              <input id="taskLoad" name="taskLoad" type="number" class="form-control taskParameter"></input>
+            </div>
+          </div>
+          <div class="form-row">
+            <div class="form-group col-sm-4">
+              <label for="taskMaxSpeed">{% trans 'Max Vm registered (m/s)' %}</label>
+              <input id="taskMaxSpeed" name="taskMaxSpeed" type="number" class="form-control taskParameter" 
disabled readonly></input>
+            </div>
+            <div class="form-group col-sm-4 ">
+              <label for="taskPercentMax">{% trans 'Max Vm registered (%)' %}</label>
+              <input id="taskPercentMaxSpeed" name="taskPercentMaxSpeed" type="number" class="form-control" 
disabled max="100" min="0"></input>
+            </div>
+            <div class="form-group col-sm-4">
+              <label for="taskSpeed">{% trans 'Speed (m/s)' %}</label>
+              <input id="taskSpeed" name="taskSpeed" type="number" class="form-control" min="-1" step="0.1" 
disabled></input>
+            </div>
+          </div>
+          <div class="form-row">
+            <div class="form-group col-sm-4">
+              <label for="taskLossByPower">{% trans 'Loss by power' %}</label>
+              <input id="taskLossByPower" name="taskLossByPower" type="number" class="form-control"></input>
+            </div>
+            <div class="form-group col-sm-4">
+              <label for="taskLossBySpeed">{% trans 'Loss by speed' %}</label>
+              <input id="taskLossBySpeed" name="taskLossBySpeed" type="number" class="form-control"></input>
+            </div>
+            <div class="form-group col-sm-4">
+              <label for="taskLaterality">{% trans 'Laterality' %}</label>
+              <select class="form-control" id="taskLaterality" name="taskLaterality">
+                <option value="RL">{% trans 'RL - both extremities' %}</option>
+                <option value="R,L">{% trans 'R,L - First right, then left' %}</option>
+                <option value="R">{% trans 'R - Only right extremity' %}</option>
+                <option value="L">{% trans 'L - Only left extremity' %}</option>
+              </select>
+            </div>
+          </div>
+          <hr>
+          <div class="form-group">
+            <label for="taskCoachComment">{% trans 'Comments from coach' %}</label>
+            <textarea rows=2 class="form-control" id="taskCoachComment"></textarea>
+          </div>
+        </form>
+
+
+                       </div> <!-- .modal-body -->
+                       <div class="modal-footer">
+                               <button type="button" class="btn btn-outline-secondary" 
data-dismiss="modal">{% trans 'Cancel' %}</button>
+        <button id="btnAddModifyTask" type="button" class="btn btn-outline-primary" >{% trans 'Add task' 
%}</button>
+                       </div>
+               </div>
+               <!-- /.modal-content -->
+       </div>
+       <!-- /.modal-dialog -->
+</div>
+<!--
+<div class="tab-content">
+  <div role="tabpanel" id="singleTask" class="tab-pane fade in active">
+
+    <form class="form-horizontal" style="margin-top: 10px">
+
+        <label for="numReps" class="col-sm-2 control-label"># Repeticions:</label>
+        <div class="col-sm-2">
+          <input id="numReps" name="numReps" type="number" class="form-control" value="1" min="1"></input>
+        </div>
+        <label for="taskLoad" class="col-sm-2 control-label">Carrega (Kg):</label>
+        <div class="col-sm-2">
+          <input id="taskLoad" name="taskLoad" type="number" class="form-control"  ></input>
+        </div>
+      </div>
+
+      <div class="form-group taskParameter">
+
+        <label for="taskMaxSpeed" class="col-sm-2 control-label" style="padding-top:0;margin-top: 
-5px;"></label>
+        <div class="col-sm-2">
+          <input id="taskMaxSpeed" name="taskMaxSpeed" type="number" class="form-control" disabled 
readonly></input>
+        </div>
+        <label for="taskpercentMax" class="col-sm-2 control-label" style="padding-top:0;margin-top: 
-5px;">Max Vm<br>registrada (%):</label>
+        <div class="col-sm-2">
+          <input id="taskpercentMaxSpeed" name="taskpercentMaxSpeed" type="number" class="form-control" 
disabled max="100" min="0"></input>
+        </div>
+        <label for="taskSpeed" class="col-sm-2 control-label">Velocitat (m/s):</label>
+        <div class="col-sm-2">
+          <input id="taskSpeed" name="taskSpeed" type="number" class="form-control" min="-1" step="0.1" 
disabled></input>
+        </div>
+      </div>
+
+      <div class="form-group taskParameter">
+
+        <label for="taskLossByPower" class="col-sm-2 control-label" style="padding-top:0;margin-top: 
-5px;">Perdua per potencia:</label>
+        <div class="col-sm-2">
+          <input id="taskLossByPower" name="taskLossByPower" type="number" class="form-control"></input>
+        </div>
+        <label for="taskLossBySpeed" class="col-sm-2 control-label" style="padding-top:0;margin-top: 
-5px;">Perdua per velocitat:</label>
+        <div class="col-sm-2">
+          <input id="taskLossBySpeed" name="taskLossBySpeed" type="number" class="form-control"></input>
+        </div>
+      </div>
+
+      <div class="form-group taskParameter">
+        <label for="recipient-name" class="col-sm-2 control-label">Lateralitat:</label>
+        <div class="col-sm-10">
+          <select class="form-control" id="taskLaterality" name="taskLaterality">
+            <option value="RL">RL - ambdúes extremitats</option>
+            <option value="R,L">R,L - Primer amb la dreta, després amb l'esquerra</option>
+            <option value="R">R - Només extremitat dreta</option>
+            <option value="L">L - Només extremitat esquerra</option>
+          </select>
+        </div>
+      </div>
+      <div class="form-group">
+        <label for="taskComment" class="control-label col-sm-2">Comentari de l'entrenador:</label>
+        <div class="col-sm-10">
+          <textarea rows=2 class="form-control" id="taskComment"></textarea>
+        </div>
+      </div>
+    </form>
+  </div>
+  <div role="tabpanel" id="macroTask" class="tab-pane fade">
+    <form class="form-horizontal" style="margin-top: 10px">
+      <div class="form-group">
+        <label for="numTasks" class="col-sm-2 control-label taskParameter macroTask"># Tasques:</label>
+        <div class="col-sm-2">
+          <input id="numTasks" name="numTaks" type="number" class="form-control taskParameter 
macroTaskControl" value="1" min="1"></input>
+        </div>
+      </div>
+      <div class="form-group">
+        <label for="numSets2" class="col-sm-2 control-label taskParameter"># Series:</label>
+        <div class="col-sm-2">
+          <input id="numSets2" name="numSets2" type="number" class="form-control taskParameter 
macroTaskControl" value="1" min="1"></input>
+        </div>
+        <label for="numReps2" class="col-sm-2 control-label"># Repeticions:</label>
+        <div class="col-sm-2">
+          <input id="numReps2" name="numReps2" type="number" class="form-control macroTaskControl" value="1" 
min="1"></input>
+        </div>
+        <label for="taskLoad2" class="col-sm-2 control-label">Carrega (Kg):</label>
+        <div class="col-sm-2">
+          <input id="taskLoad2" name="taskLoad2" type="number" class="form-control macroTaskControl"  
</input>
+        </div>
+      </div>
+      <div class="form-group taskParameter">
+
+        <label for="taskMaxSpeed2" class="col-sm-2 control-label" style="padding-top:0;margin-top: 
-5px;">Max Vm<br>registrada (m/s):</label>
+        <div class="col-sm-2">
+          <input id="taskMaxSpeed2" name="taskMaxSpeed2" type="number" class="form-control" disabled 
readonly></input>
+        </div>
+        <label for="taskpercentMaxSpeed2" class="col-sm-2 control-label" style="padding-top:0;margin-top: 
-5px;">Max Vm<br>registrada (%):</label>
+        <div class="col-sm-2">
+          <input id="taskpercentMaxSpeed2" name="taskpercentMaxSpeed2" type="number" class="form-control 
macroTaskControl" disabled max="100" min="0"></input>
+        </div>
+        <label for="taskSpeed2" class="col-sm-2 control-label">Velocitat (m/s):</label>
+        <div class="col-sm-2">
+          <input id="taskSpeed2" name="taskSpeed2" type="number" class="form-control macroTaskControl" 
min="-1" step="0.1" disabled></input>
+        </div>
+      </div>
+      <div class="form-group taskParameter">
+
+        <label for="taskLossByPower2" class="col-sm-2 control-label" style="padding-top:0;margin-top: 
-5px;">Perdua per potencia:</label>
+        <div class="col-sm-2">
+          <input id="taskLossByPower2" name="taskLossByPower2" type="number" class="form-control 
macroTaskControl"></input>
+        </div>
+        <label for="taskLossBySpeed2" class="col-sm-2 control-label" style="padding-top:0;margin-top: 
-5px;">Perdua per velocitat:</label>
+        <div class="col-sm-2">
+          <input id="taskLossBySpeed2" name="taskLossBySpeed2" type="number" class="form-control 
macroTaskControl"></input>
+        </div>
+      </div>
+      <div class="form-group taskParameter">
+        <label for="recipient-name" class="col-sm-2 control-label">Lateralitat:</label>
+        <div class="col-sm-10">
+          <select class="form-control macroTaskControl" id="taskLaterality2" name="taskLaterality2">
+            <option value="RL">RL - ambdúes extremitats</option>
+            <option value="R,L">R,L - Primer amb la dreta, després amb l'esquerra</option>
+            <option value="R">R - Només extremitat dreta</option>
+            <option value="L">L - Només extremitat esquerra</option>
+          </select>
+        </div>
+      </div>
+      <div class="form-group">
+        <div class="col-sm-12">
+
+        </div>
+      </div>
+      <hr/>
+      <table class="table hide" id="tasksTable">
+        <caption>Pots modificar les tasques abans d'afegir-les.</caption>
+        <thead>
+          <tr>
+            <th>#</th>
+            <th>Carrega (Kg)</th>
+            <th>Max Vm registrada (%)</th>
+            <th>Velocitat (m/s)</th>
+            <th>Perdua per potencia</th>
+            <th>Perdua per velocitat</th>
+          </tr>
+        </thead>
+        <tbody>
+
+        </tbody>
+      </table>
+    </form>
+  </div>
+</div>-->
diff --git a/chronojumpserver-django/chronojump_networks/templates/organizations/gyms/gym_detail.html 
b/chronojumpserver-django/chronojump_networks/templates/organizations/gyms/gym_detail.html
new file mode 100644
index 0000000..ef9ca7f
--- /dev/null
+++ b/chronojumpserver-django/chronojump_networks/templates/organizations/gyms/gym_detail.html
@@ -0,0 +1,193 @@
+{% extends 'layout.html' %}
+{% load static i18n %}
+
+{% block title %}Chronojump Networks | {{user.organization.name}} | {{group.name}}{% endblock %}
+
+{% block css %}
+{{ block.super }}
+<link rel="stylesheet" href="https://cdn.datatables.net/1.10.16/css/dataTables.bootstrap4.min.css";>
+<link rel="stylesheet" href="https://cdn.datatables.net/buttons/1.5.1/css/buttons.bootstrap4.min.css";>
+<!--<link rel="stylesheet" 
href="https://cdn.datatables.net/fixedcolumns/3.2.4/css/fixedColumns.bootstrap4.min.css";>-->
+
+{% endblock %}
+
+{% block content %}
+{% csrf_token %}
+
+<div class="page-header row">
+  <div class="col-sm-9">
+    <img src="/media/{{ user.organization.image }}" class="img-fluid float-left" width="48px" height="48px" 
style="margin-top:12px;margin-right:10px;"/>
+    <h1 class="display-4">{{gym.name}}  <small class="text-muted" style="font-size:32px">{% trans 'Stations 
and exercises' %}</small></h1>
+  </div>
+  <div class="col-sm-3">
+    <dl class="row" style="margin-top:10px">
+      <dt class="col-sm-4 text-right">{% trans 'Responsible' %}:</dt>
+      <dd class="col-sm-8">{{ gym.responsible.name }}</dd>
+    </dl>
+  </div>
+</div>
+
+<div class="row datatables_wrapped">
+  <div class="col">
+       <table id="stations" cellspacing="0" cellpadding="0" class="table table-sm" style="width:100%">
+       </table>
+  </div>
+</div>
+
+
+
+{% endblock %}
+
+{% block javascript %}
+{{ block.super }}
+<script src="https://cdn.datatables.net/1.10.16/js/jquery.dataTables.min.js";></script>
+<script src="https://cdn.datatables.net/1.10.16/js/dataTables.bootstrap4.min.js";></script>
+<script src="https://cdn.datatables.net/buttons/1.5.1/js/dataTables.buttons.min.js";></script>
+<script src="https://cdn.datatables.net/buttons/1.5.1/js/buttons.bootstrap4.min.js";></script>
+<script src="https://cdn.datatables.net/buttons/1.5.1/js/buttons.html5.min.js";></script>
+
+<script>
+  var csrftoken = jQuery("[name=csrfmiddlewaretoken]").val();
+
+  $(document).ready(function() {
+    /* Datatable for station and exercises */
+    var table_station = $('#stations').DataTable({
+      "scrollY":        "600px",
+        "scrollCollapse": true,
+        "paging":         false,
+      lengthChange: false,
+      "ajax": {
+        "processing": true,
+        "url" : "{% url 'api_organizations:gym_stations' organization_id=user.organization.id gym_id=gym.id 
%}",
+        "dataSrc": ""
+      },
+      "columns": [
+        {
+          "data": "type",
+          title: "Type",
+          visible: false
+        },
+        {
+          type: "html",
+          orderable: false,
+          render: function(value, type, row) {
+            if (row.exercises.length > 0) {
+              return '<a href="#" class="text-dark show-hide-exercises" data-station-id="'+row.id+'"><i 
class="material-icons">keyboard_arrow_down</i></a>';
+            } else {
+              return '&nbsp;';
+            }
+          },
+          width: 32,
+          className: "align-top"
+        },
+        {
+          "data": "name",
+          title: "{% trans 'Station name' %}",
+          width: 300,
+          className: "align-top"
+        },
+
+        {
+          "data": "exercises",
+          title: "{% trans 'Exercises' %}",
+          type: "html",
+          render: function(value, type, row) {
+            var html = "";
+            console.log(row);
+            if (value.length > 0) {
+              html = '<table class="collapse show" id="collapseExercises-' + row.id +'" style="width:100%">';
+              html += '<thead><th>{% trans "Exercise name" %}</th>';
+              html += '<th>{% trans "% Mass body displaced" %}</th>';
+              html += '</thead><tbody>';
+              $.each(value, function(index, exercise) {
+                html += '<tr><td>'+ exercise.name + '</td><td class="text-right">' + 
exercise.percentBodyMassDisplaced +'</tr>';
+              });
+              html += '</tbody></table>';
+
+            } else {
+              html = '<h6 class="font-weight-bold font-italic">{% trans "Station has not exercises" %}</h6>';
+            }
+            return html;
+          }
+        },
+        {
+          type: 'html',
+          className: 'align-top',
+          render: function(value, type, row) {
+            var html = "";
+            // Single Task Button
+            html += '<button type="button" class="addTaskBtn btn btn-outline-success btn-sm" ';
+            html += 'data-player-id="' + row.id + '" ';
+            html += 'data-player-name="' + row.name + '" ';
+            html += 'data-toggle="tooltip" data-placement="right" ';
+            html += 'title="{% trans "Add new exercise" %}">';
+            html += '<i class="material-icons" style="margin-top:3px;font-size:16px;">add</i></button>';
+            // Multiple Tasks
+            html += '&nbsp;<button type="button" class="addMultipleTaskBtn btn btn-outline-danger btn-sm" ';
+            html += 'data-player-id="' + row.id + '" ';
+            html += 'data-player-name="' + row.name + '" ';
+            html += 'data-toggle="tooltip" data-placement="right" ';
+            html += 'title="{% trans "Disable station" %}">';
+            html += '<i class="material-icons" style="margin-top:3px;font-size:16px;">block</i></button>';
+            return html;
+          }
+        }
+      ],
+      "drawCallback" : function ( settings ) {
+            var api = this.api();
+            var rows = api.rows( {page:'current'} ).nodes();
+            var last=null;
+
+            api.column(0, {page:'current'} ).data().each( function ( group, i ) {
+                if ( last !== group ) {
+                  var group_name = "";
+                  if (group == "I") {
+                    group_name = "{% trans 'Inertial stations' %}";
+                  } else if (group == "G") {
+                    group_name = "{% trans 'Gravitatory stations' %}";
+                  } else if (group == "S" ){
+                    group_name = "{% trans 'Sprint stations' %}";
+                  } else {
+                    group_name = group;
+                  }
+                  $(rows).eq( i ).before(
+
+                      '<tr class="group font-weight-bold"><td colspan="5">'+group_name+'</td></tr>'
+                  );
+
+                  last = group;
+                }
+            } );
+      },
+      "dom": "<'row'<'col-sm-6'B><'col-sm-6'f>>rtip",
+      buttons: [],
+      initComplete: function() {
+        // Enable table functionality
+        enableStationsTableFunctionality();
+      }
+    });
+
+    function enableStationsTableFunctionality() {
+      $('.show-hide-exercises').on('click', function(e) {
+        e.preventDefault();
+        let station_id = $(this).attr('data-station-id');
+        var t = $('#collapseExercises-' + station_id);
+        console.log(t);
+        if (t.hasClass('show')) {
+          // Collapse the table
+          t.collapse('hide');
+          // Change-icon
+          console.log($(this).children(0));
+          $(this).children(0).text = 'keyboard_arrow_up';
+        } else {
+          t.collapse('show');
+          // Change-icon
+          $(this).html = '<i class="material-icons">keyboard_arrow_down</i>';
+        }
+      });
+    }
+
+  }); /* End of Document ready */
+</script>
+
+{% endblock %}
diff --git a/chronojumpserver-django/chronojump_networks/templates/organizations/organization_detail.html 
b/chronojumpserver-django/chronojump_networks/templates/organizations/organization_detail.html
new file mode 100644
index 0000000..1d412a8
--- /dev/null
+++ b/chronojumpserver-django/chronojump_networks/templates/organizations/organization_detail.html
@@ -0,0 +1,25 @@
+{% extends "layout.html" %}
+{% load static %}
+
+{% block title %}Organization: {{ object.name }}{% endblock %}
+
+{% block content %}
+<div class="container">
+
+  <div class="row">
+    <div class="col-sm-12">
+
+      <h2>{{ object.name }}</h2>
+      {% if object.image %}
+        <img src="/media/{{ object.image }}" alt="Logo Club"/>
+      {% endif %}
+      <ul>
+      {% for coach in object.coaches.all %}
+        <li>{{coach.name}}</li>
+      {% endfor %}
+    </ul>
+    </div>
+  </div>
+
+</div>
+{% endblock content %}
diff --git a/chronojumpserver-django/chronojump_networks/templates/organizations/organization_list.html 
b/chronojumpserver-django/chronojump_networks/templates/organizations/organization_list.html
new file mode 100644
index 0000000..dbf1cf6
--- /dev/null
+++ b/chronojumpserver-django/chronojump_networks/templates/organizations/organization_list.html
@@ -0,0 +1,17 @@
+{% extends "base.html" %}
+{% load static i18n %}
+{% block title %}Members{% endblock %}
+
+{% block content %}
+<div class="container">
+  <h2>Organizations</h2>
+
+  <div class="list-group">
+    {% for organization in organization_list %}
+      <a href="{% url 'users:detail' organization.id %}" class="list-group-item">
+        <h4 class="list-group-item-heading">{{ organization.name }}</h4>
+      </a>
+    {% endfor %}
+  </div>
+</div>
+{% endblock content %}
diff --git a/chronojumpserver-django/chronojump_networks/templates/pages/403_csrf.html 
b/chronojumpserver-django/chronojump_networks/templates/pages/403_csrf.html
new file mode 100644
index 0000000..77db8ae
--- /dev/null
+++ b/chronojumpserver-django/chronojump_networks/templates/pages/403_csrf.html
@@ -0,0 +1,9 @@
+{% extends "base.html" %}
+
+{% block title %}Forbidden (403){% endblock %}
+
+{% block content %}
+<h1>Forbidden (403)</h1>
+
+<p>CSRF verification failed. Request aborted.</p>
+{% endblock content %}
diff --git a/chronojumpserver-django/chronojump_networks/templates/pages/404.html 
b/chronojumpserver-django/chronojump_networks/templates/pages/404.html
new file mode 100644
index 0000000..98327cd
--- /dev/null
+++ b/chronojumpserver-django/chronojump_networks/templates/pages/404.html
@@ -0,0 +1,9 @@
+{% extends "base.html" %}
+
+{% block title %}Page not found{% endblock %}
+
+{% block content %}
+<h1>Page not found</h1>
+
+<p>This is not the page you were looking for.</p>
+{% endblock content %}
diff --git a/chronojumpserver-django/chronojump_networks/templates/pages/500.html 
b/chronojumpserver-django/chronojump_networks/templates/pages/500.html
new file mode 100644
index 0000000..21df606
--- /dev/null
+++ b/chronojumpserver-django/chronojump_networks/templates/pages/500.html
@@ -0,0 +1,13 @@
+{% extends "base.html" %}
+
+{% block title %}Server Error{% endblock %}
+
+{% block content %}
+<h1>Ooops!!! 500</h1>
+
+<h3>Looks like something went wrong!</h3>
+
+<p>We track these errors automatically, but if the problem persists feel free to contact us. In the 
meantime, try refreshing.</p>
+{% endblock content %}
+
+
diff --git a/chronojumpserver-django/chronojump_networks/templates/pages/index.html 
b/chronojumpserver-django/chronojump_networks/templates/pages/index.html
new file mode 100644
index 0000000..16afa16
--- /dev/null
+++ b/chronojumpserver-django/chronojump_networks/templates/pages/index.html
@@ -0,0 +1,121 @@
+{% extends "base.html" %}
+{% load static i18n %}
+
+{% block css %}
+
+{{ block.super }}
+<style>
+  .dashboard h2 {
+    margin-top: 10px;
+  }
+
+  .dashboard .buttons {
+    height: 100px;
+  }
+
+  .dashboard .buttons a {
+    height: 100px;
+    padding-top: 30px;
+  }
+</style>
+{% endblock %}
+
+{% block main %}
+<div class="container-fluid header-index">
+
+    <div class="row">
+        <div class="col-md-6" style="margin-top:40px">
+            <img class="img-responsive" src="{% static 'images/chronojump-logo.png' %}" >
+        </div>
+        <div class="col-md-6">
+          <div class="float-right">
+            <ul class="nav">
+              <li class="nav-item active"><a class="nav-link text-white" href="#">{% trans 'Welcome, 
'%}{{user.name}}</a></li>
+              <li class="nav-item active"><a href="{% url 'logout' %}" class="nav-link text-white">{% trans 
'Close session' %}</a></li>
+            </ul>
+          </div>
+          <div style="margin-top:60px">
+            <h1 class="text-center text-uppercase">Chronojump Server</h1>
+            <h4 class="text-center text-uppercase">No more blind training</h4>
+          </div>
+        </div>
+    </div>
+
+</div>
+<div class="container dashboard">
+{% if user.is_organization_member  %}
+    <div class="row" style="margin-top:20px; border-bottom: 1px solid #000;padding-bottom:10px;">
+      <div class="col-md-4" >
+          <img src="/media/{{ user.organization.image }}" class="img-fluid" height="80px" />
+      </div>
+      <div class="col-md-8" >
+          <h1 class="display-4">{{ user.organization.name }}</h1>
+      </div>
+    </div>
+    <!-- Results -->
+    <h2 class="text-center">{% trans 'Player results' %}</h2>
+    <div class="row buttons">
+      <div class="col-sm-6">
+        <a class="btn btn-outline-dark btn-block font-weight-bold text-uppercase" href="#">{% trans 
'Results' %}</a>
+      </div>
+      <div class="col-sm-6">
+        <a class="btn btn-outline-dark btn-block font-weight-bold text-uppercase" href="#">{% trans 
'Sprints' %}</a>
+      </div>
+    </div>
+    {% if user.groups_by_coach %}
+    <h2 class="text-center">{% trans 'My Groups' %}</h2>
+    <div class="row buttons" >
+      {% for group in user.groups_by_coach.all %}
+        <div class="col-sm-6 col-md-4">
+          <a class="btn btn-outline-info btn-block font-weight-bold text-uppercase" href="{% url 
'organizations:group_players_list' organization_id=user.organization.id group_id=group.group.id 
%}">{{group.group.name}}</a>
+        </div>
+      {% endfor %}
+    </div>
+    {% endif %}
+
+    {% if user.organization.gyms %}
+    <h2 class="text-center">{% trans 'My Gyms' %}</h2>
+    <div class="row buttons" >
+        {% for gym in user.organization.gyms.all %}
+        <div class="col-sm-6 col-md-4">
+          <a class="btn btn-outline-warning btn-block font-weight-bold text-uppercase" href="{% url 
'organizations:gym_detail' organization_id=user.organization.id gym_id=gym.id %}">{{gym.name}}</a>
+        </div>
+        {% endfor %}
+    </div>
+    {% endif %}
+
+    {% if user.id == user.organization.responsible.id %}
+    <h2 class="text-center">{% trans 'Organization options' %}</h2>
+    <div class="row buttons" >
+      <div class="col-sm-6 col-md-3">
+        <a class="btn btn-outline-primary btn-block font-weight-bold text-uppercase" href="">{% trans 
'Staff' %}</a>
+      </div>
+        <div class="col-sm-6 col-md-3">
+          <a class="btn btn-outline-primary btn-block font-weight-bold text-uppercase" href="">{% trans 
'Players' %}</a>
+        </div>
+        <div class="col-sm-6 col-md-3">
+          <a class="btn btn-outline-primary btn-block font-weight-bold text-uppercase" href="">{% trans 
'Groups' %}</a>
+        </div>
+        <div class="col-sm-6 col-md-3">
+          <a class="btn btn-outline-primary btn-block font-weight-bold text-uppercase" href="">{% trans 
'Gyms' %}</a>
+        </div>
+    </div>
+    {% endif %}
+
+{% else %}
+    <div class="row">
+      <div class="col-md-12">
+          <div class="alert alert-danger">{% trans 'You are not member of any organization' %}</div>
+      </div>
+    </div>
+{% endif %}
+  </div>
+</div>
+
+<nav class="navbar navbar-default fixed-bottom footer" style="height:40px">
+    <div class="container-fluid" style="margin-top: 10px">
+        <p class="navbar-text navbar-left">{% trans "Chronojump server is a product from Chronojump 
Boscosystem ®" %}</p>
+        <p class="navbar-text navbar-right">{% trans "version 1.0" %}</p>
+    </div>
+</nav>
+{% endblock main %}
diff --git a/chronojumpserver-django/chronojump_networks/templates/users/login.html 
b/chronojumpserver-django/chronojump_networks/templates/users/login.html
new file mode 100644
index 0000000..597e309
--- /dev/null
+++ b/chronojumpserver-django/chronojump_networks/templates/users/login.html
@@ -0,0 +1,31 @@
+{% extends 'base.html' %}
+{% load static i18n %}
+{% load crispy_forms_tags %}
+
+{% block body_class %}login{% endblock %}
+
+{% block main %}
+    <div class="container">
+        <div class="row">
+            <div class="offset-sm-3 col-sm-6" style="margin-top:50px;">
+                <div class="" style="background-color:#fff;;border-radius:15px;padding:10px">
+                    <div style=" margin-bottom: 20px;background-color: #0f2351;padding:-10px">
+                        <img class="img-responsive" src="{% static 'images/chronojump-logo.png' %}" >
+                    </div>
+                    {% if error_msg %}
+                        <div class="alert alert-danger text-center">Error: {{error_msg}}</div>
+                    {% endif %}
+                    <form method="post" enctype="multipart/form-data">
+                      <p class="text-center">{% trans "Enter your username and password" %}</p>
+                      {% csrf_token %}
+                      {{ form|crispy }}
+                      {% if redirect_field_value %}
+                      <input type="hidden" name="{{ redirect_field_name }}" value="{{ redirect_field_value 
}}" />
+                      {% endif %}
+                      <button class="btn btn-primary btn-block" type="submit">{% trans "Login" %}</button>
+                    </form>
+                </div>
+            </div>
+        </div>
+    </div>
+{% endblock main %}
diff --git a/chronojumpserver-django/chronojump_networks/templates/users/user_list.html 
b/chronojumpserver-django/chronojump_networks/templates/users/user_list.html
new file mode 100644
index 0000000..e69de29
diff --git a/chronojumpserver-django/config/__init__.py b/chronojumpserver-django/config/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/chronojumpserver-django/config/settings/__init__.py 
b/chronojumpserver-django/config/settings/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/chronojumpserver-django/config/settings/base.py b/chronojumpserver-django/config/settings/base.py
new file mode 100644
index 0000000..587adf1
--- /dev/null
+++ b/chronojumpserver-django/config/settings/base.py
@@ -0,0 +1,239 @@
+"""
+Django settings for chronojump_networks project.
+
+Generated by 'django-admin startproject' using Django 1.11.11.
+
+For more information on this file, see
+https://docs.djangoproject.com/en/1.11/topics/settings/
+
+For the full list of settings and their values, see
+https://docs.djangoproject.com/en/1.11/ref/settings/
+"""
+
+
+import environ
+
+ROOT_DIR = environ.Path(__file__) - 3  # (cj1/config/settings/base.py - 3 = cj1/)
+APPS_DIR = ROOT_DIR.path('chronojump_networks')
+
+env = environ.Env()
+
+READ_DOT_ENV_FILE = env.bool('DJANGO_READ_DOT_ENV_FILE', default=False)
+if READ_DOT_ENV_FILE:
+    # OS environment variables take precedence over variables from .env
+    env.read_env(str(ROOT_DIR.path('.env')))
+
+# GENERAL
+# ------------------------------------------------------------------------------
+# https://docs.djangoproject.com/en/dev/ref/settings/#debug
+DEBUG = env.bool('DJANGO_DEBUG', False)
+# Local time zone. Choices are
+# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
+# though not all of them may be available with every OS.
+# In Windows, this must be set to your system time zone.
+TIME_ZONE = 'UTC'
+# https://docs.djangoproject.com/en/dev/ref/settings/#language-code
+
+# https://docs.djangoproject.com/en/dev/ref/settings/#site-id
+SITE_ID = 1
+# https://docs.djangoproject.com/en/dev/ref/settings/#use-i18n
+USE_I18N = True
+# https://docs.djangoproject.com/en/dev/ref/settings/#use-l10n
+USE_L10N = True
+# https://docs.djangoproject.com/en/dev/ref/settings/#use-tz
+USE_TZ = True
+
+from django.utils.translation import gettext_lazy as _
+
+LANGUAGE_CODE = 'en'
+
+LANGUAGES = (
+    ('en', _('English')),
+    ('ca', _('Catalan')),
+    ('es', _('Spanish')),
+    ('fr', _('French'))
+)
+
+LOCALE_PATHS = [
+    str(ROOT_DIR.path('locale'))
+]
+
+
+# DATABASES
+# ------------------------------------------------------------------------------
+# https://docs.djangoproject.com/en/dev/ref/settings/#databases
+DATABASES = {
+    'default': env.db('DATABASE_URL'),
+}
+DATABASES['default']['ATOMIC_REQUESTS'] = True
+
+# URLS
+# ------------------------------------------------------------------------------
+# https://docs.djangoproject.com/en/dev/ref/settings/#root-urlconf
+ROOT_URLCONF = 'config.urls'
+# https://docs.djangoproject.com/en/dev/ref/settings/#wsgi-application
+WSGI_APPLICATION = 'config.wsgi.application'
+
+# APPS
+# ------------------------------------------------------------------------------
+DJANGO_APPS = [
+    'django.contrib.auth',
+    'django.contrib.contenttypes',
+    'django.contrib.sessions',
+    'django.contrib.sites',
+    'django.contrib.messages',
+    'django.contrib.staticfiles',
+    # 'django.contrib.humanize', # Handy template tags
+    'django.contrib.admin',
+]
+
+THIRD_PARTY_APPS = [
+    'crispy_forms',
+    'rest_framework',
+]
+
+LOCAL_APPS = [
+    'chronojump_networks.organizations.apps.OrganizationsConfig',
+    'chronojump_networks.tasks.apps.TasksConfig'
+
+]
+# https://docs.djangoproject.com/en/dev/ref/settings/#installed-apps
+INSTALLED_APPS = DJANGO_APPS + THIRD_PARTY_APPS + LOCAL_APPS
+
+# MIGRATIONS
+# ------------------------------------------------------------------------------
+# https://docs.djangoproject.com/en/dev/ref/settings/#migration-modules
+MIGRATION_MODULES = {}
+
+# AUTHENTICATION
+# ------------------------------------------------------------------------------
+# https://docs.djangoproject.com/en/dev/ref/settings/#authentication-backends
+AUTHENTICATION_BACKENDS = [
+    'django.contrib.auth.backends.ModelBackend',
+]
+# https://docs.djangoproject.com/en/dev/ref/settings/#auth-user-model
+AUTH_USER_MODEL = 'organizations.User'
+# https://docs.djangoproject.com/en/dev/ref/settings/#login-redirect-url
+LOGIN_REDIRECT_URL = 'organization:users:redirect'
+# https://docs.djangoproject.com/en/dev/ref/settings/#login-url
+LOGIN_URL = 'login'
+
+# https://docs.djangoproject.com/en/dev/ref/settings/#auth-password-validators
+AUTH_PASSWORD_VALIDATORS = [
+    {
+        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
+    },
+    {
+        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
+    },
+    {
+        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
+    },
+    {
+        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
+    },
+]
+
+# MIDDLEWARE
+# ------------------------------------------------------------------------------
+# https://docs.djangoproject.com/en/dev/ref/settings/#middleware
+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',
+    'django.contrib.messages.middleware.MessageMiddleware',
+    'django.middleware.clickjacking.XFrameOptionsMiddleware',
+]
+
+# STATIC
+# ------------------------------------------------------------------------------
+# https://docs.djangoproject.com/en/dev/ref/settings/#static-root
+STATIC_ROOT = str(ROOT_DIR('staticfiles'))
+# https://docs.djangoproject.com/en/dev/ref/settings/#static-url
+STATIC_URL = '/static/'
+# https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/#std:setting-STATICFILES_DIRS
+STATICFILES_DIRS = [
+    str(APPS_DIR.path('static')),
+]
+# https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/#staticfiles-finders
+STATICFILES_FINDERS = [
+    'django.contrib.staticfiles.finders.FileSystemFinder',
+    'django.contrib.staticfiles.finders.AppDirectoriesFinder',
+]
+
+# MEDIA
+# ------------------------------------------------------------------------------
+# https://docs.djangoproject.com/en/dev/ref/settings/#media-root
+MEDIA_ROOT = str(APPS_DIR('media'))
+# https://docs.djangoproject.com/en/dev/ref/settings/#media-url
+MEDIA_URL = '/media/'
+
+# TEMPLATES
+# ------------------------------------------------------------------------------
+# https://docs.djangoproject.com/en/dev/ref/settings/#templates
+TEMPLATES = [
+    {
+        # https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-TEMPLATES-BACKEND
+        'BACKEND': 'django.template.backends.django.DjangoTemplates',
+        # https://docs.djangoproject.com/en/dev/ref/settings/#template-dirs
+        'DIRS': [
+            str(APPS_DIR.path('templates')),
+        ],
+        'OPTIONS': {
+            # https://docs.djangoproject.com/en/dev/ref/settings/#template-debug
+            'debug': DEBUG,
+            # https://docs.djangoproject.com/en/dev/ref/settings/#template-loaders
+            # https://docs.djangoproject.com/en/dev/ref/templates/api/#loader-types
+            'loaders': [
+                'django.template.loaders.filesystem.Loader',
+                'django.template.loaders.app_directories.Loader',
+            ],
+            # https://docs.djangoproject.com/en/dev/ref/settings/#template-context-processors
+            'context_processors': [
+                'django.template.context_processors.debug',
+                'django.template.context_processors.request',
+                'django.contrib.auth.context_processors.auth',
+                'django.template.context_processors.i18n',
+                'django.template.context_processors.media',
+                'django.template.context_processors.static',
+                'django.template.context_processors.tz',
+                'django.contrib.messages.context_processors.messages',
+            ],
+        },
+    },
+]
+
+# http://django-crispy-forms.readthedocs.io/en/latest/install.html#template-packs
+CRISPY_TEMPLATE_PACK = 'bootstrap4'
+
+# FIXTURES
+# ------------------------------------------------------------------------------
+# https://docs.djangoproject.com/en/dev/ref/settings/#fixture-dirs
+FIXTURE_DIRS = (
+    str(APPS_DIR.path('fixtures')),
+)
+
+# ADMIN
+# ------------------------------------------------------------------------------
+# Django Admin URL regex.
+ADMIN_URL = r'^admin/'
+# https://docs.djangoproject.com/en/dev/ref/settings/#admins
+ADMINS = [
+    ("""Marcos Venteo""", 'mventeo gmail com'),
+]
+# https://docs.djangoproject.com/en/dev/ref/settings/#managers
+MANAGERS = ADMINS
+
+
+# Rest Framework
+# ------------------------------------------------------------------------------
+CSRF_USE_SESSIONS=True  # Store the CSRF in Session is better than in a cookie
+
+REST_FRAMEWORK = {
+    'DEFAULT_PERMISSION_CLASSES': (
+        'rest_framework.permissions.IsAdminUser',
+    ),
+}
diff --git a/chronojumpserver-django/config/settings/local.py 
b/chronojumpserver-django/config/settings/local.py
new file mode 100644
index 0000000..4c2c99d
--- /dev/null
+++ b/chronojumpserver-django/config/settings/local.py
@@ -0,0 +1,57 @@
+from .base import *  # noqa
+from .base import env
+
+# GENERAL
+# ------------------------------------------------------------------------------
+# https://docs.djangoproject.com/en/dev/ref/settings/#debug
+DEBUG = env.bool('DJANGO_DEBUG', default=True)
+# https://docs.djangoproject.com/en/dev/ref/settings/#secret-key
+SECRET_KEY = env('DJANGO_SECRET_KEY', 
default='frkS4wP89VDVwgwMutBoAnajychwzhxvcRYLCrtBbUjdVsas4lLba8tq9hUFfREU')
+# https://docs.djangoproject.com/en/dev/ref/settings/#allowed-hosts
+ALLOWED_HOSTS = [
+    "localhost",
+    "0.0.0.0",
+    "127.0.0.1",
+]
+
+# CACHES
+# ------------------------------------------------------------------------------
+# https://docs.djangoproject.com/en/dev/ref/settings/#caches
+CACHES = {
+    'default': {
+        'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
+        'LOCATION': ''
+    }
+}
+
+# TEMPLATES
+# ------------------------------------------------------------------------------
+# https://docs.djangoproject.com/en/dev/ref/settings/#templates
+TEMPLATES[0]['OPTIONS']['debug'] = DEBUG  # noqa F405
+
+
+# django-debug-toolbar
+# ------------------------------------------------------------------------------
+# https://django-debug-toolbar.readthedocs.io/en/latest/installation.html#prerequisites
+INSTALLED_APPS += ['debug_toolbar']  # noqa F405
+# https://django-debug-toolbar.readthedocs.io/en/latest/installation.html#middleware
+MIDDLEWARE += ['debug_toolbar.middleware.DebugToolbarMiddleware']  # noqa F405
+# https://django-debug-toolbar.readthedocs.io/en/latest/configuration.html#debug-toolbar-config
+DEBUG_TOOLBAR_CONFIG = {
+    'DISABLE_PANELS': [
+        'debug_toolbar.panels.redirects.RedirectsPanel',
+    ],
+    'SHOW_TEMPLATE_CONTEXT': True,
+}
+
+INTERNAL_IPS = ['127.0.0.1', '10.0.2.2']
+import socket
+import os
+if os.environ.get('USE_DOCKER') == 'yes':
+    hostname, _, ips = socket.gethostbyname_ex(socket.gethostname())
+    INTERNAL_IPS += [ip[:-1] + '1' for ip in ips]
+
+# django-extensions
+# ------------------------------------------------------------------------------
+# https://django-extensions.readthedocs.io/en/latest/installation_instructions.html#configuration
+INSTALLED_APPS += ['django_extensions']  # noqa F405
diff --git a/chronojumpserver-django/config/urls.py b/chronojumpserver-django/config/urls.py
new file mode 100644
index 0000000..6c40dd5
--- /dev/null
+++ b/chronojumpserver-django/config/urls.py
@@ -0,0 +1,38 @@
+from django.conf import settings
+from django.conf.urls import url, include
+from django.conf.urls.static import static
+from django.contrib import admin
+from django.contrib.auth.decorators import login_required
+from django.views.generic import TemplateView
+from django.views import defaults as default_views
+
+from chronojump_networks.organizations import views
+
+urlpatterns = [
+    url(r'^$', login_required(TemplateView.as_view(template_name='pages/index.html')), name='index'),
+    url(settings.ADMIN_URL, admin.site.urls),
+    # User management
+    #url(r'^users/', include('chronojump_networks.users.urls', namespace='users')),
+    url(r'^organizations/', include('chronojump_networks.organizations.urls', namespace='organizations')),
+    url(r'^api/v1/organizations/', include('chronojump_networks.organizations.api.urls', 
namespace='api_organizations')),
+    url(r'^api/v1/tasks/', include('chronojump_networks.tasks.api.urls', namespace='api_tasks')),
+    url(r'^login$', views.organization_login, name='login'),
+    url(r'^logout$', views.organization_logout, name='logout'),
+    url(r'^i18n/', include('django.conf.urls.i18n')),
+] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
+
+
+if settings.DEBUG:
+    # This allows the error pages to be debugged during development, just visit
+    # these url in browser to see how these error pages look like.
+    urlpatterns += [
+        url(r'^400/$', default_views.bad_request, kwargs={'exception': Exception('Bad Request!')}),
+        url(r'^403/$', default_views.permission_denied, kwargs={'exception': Exception('Permission 
Denied')}),
+        url(r'^404/$', default_views.page_not_found, kwargs={'exception': Exception('Page not Found')}),
+        url(r'^500/$', default_views.server_error),
+    ]
+    if 'debug_toolbar' in settings.INSTALLED_APPS:
+        import debug_toolbar
+        urlpatterns = [
+            url(r'^__debug__/', include(debug_toolbar.urls)),
+        ] + urlpatterns
diff --git a/chronojumpserver-django/config/wsgi.py b/chronojumpserver-django/config/wsgi.py
new file mode 100644
index 0000000..13524ce
--- /dev/null
+++ b/chronojumpserver-django/config/wsgi.py
@@ -0,0 +1,16 @@
+"""
+WSGI config for chronojump_networks project.
+
+It exposes the WSGI callable as a module-level variable named ``application``.
+
+For more information on this file, see
+https://docs.djangoproject.com/en/1.11/howto/deployment/wsgi/
+"""
+
+import os
+
+from django.core.wsgi import get_wsgi_application
+
+os.environ.setdefault("DJANGO_SETTINGS_MODULE", "chronojump_networks.settings")
+
+application = get_wsgi_application()
diff --git a/chronojumpserver-django/locale/es/LC_MESSAGES/django.po 
b/chronojumpserver-django/locale/es/LC_MESSAGES/django.po
new file mode 100644
index 0000000..3d2bceb
--- /dev/null
+++ b/chronojumpserver-django/locale/es/LC_MESSAGES/django.po
@@ -0,0 +1,335 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2018-04-02 09:09+0000\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL li org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: chronojump_networks/organizations/api/permissions.py:5
+msgid "You are not a valid coach for this group. This will be notify"
+msgstr ""
+
+#: chronojump_networks/organizations/decorators.py:19
+msgid "The user does not belongs to this organization."
+msgstr ""
+
+#. Translators: Username for login form
+#: chronojump_networks/organizations/forms.py:14
+msgid "Username"
+msgstr "Usuario"
+
+#. Translators: Password for login form
+#: chronojump_networks/organizations/forms.py:21
+msgid "Password"
+msgstr "Contraseña"
+
+#: chronojump_networks/organizations/models.py:25 config/settings/base.py:51
+msgid "Spanish"
+msgstr ""
+
+#: chronojump_networks/organizations/models.py:26 config/settings/base.py:50
+msgid "Catalan"
+msgstr ""
+
+#: chronojump_networks/organizations/models.py:27 config/settings/base.py:52
+msgid "French"
+msgstr ""
+
+#: chronojump_networks/organizations/models.py:28 config/settings/base.py:49
+msgid "English"
+msgstr ""
+
+#: chronojump_networks/organizations/models.py:36
+msgid "Name of User"
+msgstr ""
+
+#: chronojump_networks/organizations/models.py:99
+msgid "Coach"
+msgstr ""
+
+#: chronojump_networks/organizations/models.py:100
+msgid "Coach Lead"
+msgstr ""
+
+#: chronojump_networks/organizations/models.py:152
+msgid "Sprint"
+msgstr ""
+
+#: chronojump_networks/organizations/models.py:153
+msgid "Inertial"
+msgstr ""
+
+#: chronojump_networks/organizations/models.py:154
+msgid "Gravitatory"
+msgstr ""
+
+#: chronojump_networks/organizations/views.py:80
+msgid "Invalid username or password"
+msgstr ""
+
+#: chronojump_networks/tasks/models.py:18
+#: chronojump_networks/templates/organizations/task_modal_form.html:82
+msgid "RL - both extremities"
+msgstr ""
+
+#: chronojump_networks/tasks/models.py:19
+#: chronojump_networks/templates/organizations/task_modal_form.html:83
+msgid "R,L - First right, then left"
+msgstr ""
+
+#: chronojump_networks/tasks/models.py:20
+#: chronojump_networks/templates/organizations/task_modal_form.html:84
+msgid "R - Only right extremity"
+msgstr ""
+
+#: chronojump_networks/tasks/models.py:21
+#: chronojump_networks/templates/organizations/task_modal_form.html:85
+msgid "L - Only left extremity"
+msgstr ""
+
+#: chronojump_networks/templates/layout.html:13
+msgid "Home"
+msgstr ""
+
+#: chronojump_networks/templates/layout.html:16
+#: chronojump_networks/templates/pages/index.html:59
+msgid "Results"
+msgstr ""
+
+#: chronojump_networks/templates/layout.html:19
+#: chronojump_networks/templates/pages/index.html:62
+msgid "Sprints"
+msgstr ""
+
+#: chronojump_networks/templates/layout.html:22
+msgid "Tasks"
+msgstr "Tareas"
+
+#: chronojump_networks/templates/layout.html:27
+#: chronojump_networks/templates/pages/index.html:97
+msgid "Groups"
+msgstr "Grupos"
+
+#: chronojump_networks/templates/layout.html:30
+msgid "My groups"
+msgstr "Mis grupos"
+
+#: chronojump_networks/templates/layout.html:35
+msgid "Create a group"
+msgstr "Crear nuevo grupo"
+
+#: chronojump_networks/templates/layout.html:41
+msgid "Hello, "
+msgstr "Hola, "
+
+#: chronojump_networks/templates/layout.html:42
+#: chronojump_networks/templates/pages/index.html:34
+msgid "Close session"
+msgstr "Cerrar sesión"
+
+#: chronojump_networks/templates/organizations/group_players_list.html:20
+msgid "Players and tasks"
+msgstr "Jugadores y tareas"
+
+#: chronojump_networks/templates/organizations/group_players_list.html:24
+msgid "Responsible"
+msgstr "Responsable"
+
+#: chronojump_networks/templates/organizations/group_players_list.html:26
+#: chronojump_networks/templates/organizations/task_modal_form.html:21
+msgid "Gym"
+msgstr "Gimnasio"
+
+#: chronojump_networks/templates/organizations/group_players_list.html:41
+msgid "Add Player to Group"
+msgstr "Añadir jugadores al grupo"
+
+#: chronojump_networks/templates/organizations/group_players_list.html:45
+msgid "Add players to group "
+msgstr "Añadir jugadores al grupo"
+
+#: chronojump_networks/templates/organizations/group_players_list.html:55
+msgid "Close"
+msgstr "Cerrar"
+
+#: chronojump_networks/templates/organizations/group_players_list.html:56
+#: chronojump_networks/templates/organizations/group_players_list.html:175
+msgid "Add players"
+msgstr "Añadir jugadores"
+
+#: chronojump_networks/templates/organizations/group_players_list.html:133
+#: chronojump_networks/templates/organizations/group_players_list.html:241
+msgid "Number"
+msgstr "Dorsal"
+
+#: chronojump_networks/templates/organizations/group_players_list.html:137
+#: chronojump_networks/templates/organizations/group_players_list.html:245
+#, fuzzy
+#| msgid "Username"
+msgid "Player name"
+msgstr "Usuario"
+
+#: chronojump_networks/templates/organizations/group_players_list.html:142
+msgid "Height"
+msgstr "Altura"
+
+#: chronojump_networks/templates/organizations/group_players_list.html:146
+msgid "Weight"
+msgstr "Peso"
+
+#: chronojump_networks/templates/organizations/group_players_list.html:158
+#: chronojump_networks/templates/organizations/group_players_list.html:214
+msgid "Add new task to "
+msgstr "Añadir nueva tarea a "
+
+#: chronojump_networks/templates/organizations/group_players_list.html:165
+msgid "Add multiple tasks to "
+msgstr "Añadir múltiple tareas a "
+
+#: chronojump_networks/templates/organizations/group_players_list.html:183
+msgid "Remove players"
+msgstr "Quitar jugadores"
+
+#: chronojump_networks/templates/organizations/group_players_list.html:297
+msgid "The player has been removed from group"
+msgstr ""
+
+#: chronojump_networks/templates/organizations/group_players_list.html:299
+msgid "The players have been removed from the group"
+msgstr ""
+
+#: chronojump_networks/templates/organizations/group_players_list.html:319
+msgid "The player has been added to the group"
+msgstr ""
+
+#: chronojump_networks/templates/organizations/group_players_list.html:321
+msgid "The players have been added to the group"
+msgstr ""
+
+#: chronojump_networks/templates/organizations/task_modal_form.html:4
+#, fuzzy
+#| msgid "Tasks"
+msgid "Add Task"
+msgstr "Tareas"
+
+#: chronojump_networks/templates/organizations/task_modal_form.html:29
+msgid "Station"
+msgstr ""
+
+#: chronojump_networks/templates/organizations/task_modal_form.html:35
+msgid "Exercise"
+msgstr ""
+
+#: chronojump_networks/templates/organizations/task_modal_form.html:44
+msgid "# Sets"
+msgstr ""
+
+#: chronojump_networks/templates/organizations/task_modal_form.html:48
+msgid "# Repeats"
+msgstr ""
+
+#: chronojump_networks/templates/organizations/task_modal_form.html:52
+msgid "Load (Kg)"
+msgstr ""
+
+#: chronojump_networks/templates/organizations/task_modal_form.html:58
+msgid "Max Vm registered (m/s)"
+msgstr ""
+
+#: chronojump_networks/templates/organizations/task_modal_form.html:62
+#, python-format
+msgid "Max Vm registered (%%)"
+msgstr ""
+
+#: chronojump_networks/templates/organizations/task_modal_form.html:66
+msgid "Speed (m/s)"
+msgstr ""
+
+#: chronojump_networks/templates/organizations/task_modal_form.html:72
+msgid "Loss by power"
+msgstr ""
+
+#: chronojump_networks/templates/organizations/task_modal_form.html:76
+msgid "Loss by speed"
+msgstr ""
+
+#: chronojump_networks/templates/organizations/task_modal_form.html:80
+msgid "Laterality"
+msgstr ""
+
+#: chronojump_networks/templates/organizations/task_modal_form.html:91
+msgid "Comments from coach"
+msgstr ""
+
+#: chronojump_networks/templates/organizations/task_modal_form.html:99
+msgid "Cancel"
+msgstr ""
+
+#: chronojump_networks/templates/organizations/task_modal_form.html:100
+msgid "Add task"
+msgstr ""
+
+#: chronojump_networks/templates/pages/index.html:33
+msgid "Welcome, "
+msgstr ""
+
+#: chronojump_networks/templates/pages/index.html:56
+msgid "Player results"
+msgstr "Resultado de jugadores"
+
+#: chronojump_networks/templates/pages/index.html:66
+msgid "My Groups"
+msgstr "Mis grupos"
+
+#: chronojump_networks/templates/pages/index.html:77
+msgid "My Gyms"
+msgstr "Mis gimnasios"
+
+#: chronojump_networks/templates/pages/index.html:88
+msgid "Organization options"
+msgstr "Opciones de la organización"
+
+#: chronojump_networks/templates/pages/index.html:91
+msgid "Staff"
+msgstr "Miembros"
+
+#: chronojump_networks/templates/pages/index.html:94
+msgid "Players"
+msgstr "Jugadores"
+
+#: chronojump_networks/templates/pages/index.html:100
+msgid "Gyms"
+msgstr ""
+
+#: chronojump_networks/templates/pages/index.html:108
+msgid "You are not member of any organization"
+msgstr ""
+
+#: chronojump_networks/templates/pages/index.html:116
+msgid "Chronojump server is a product from Chronojump Boscosystem ®"
+msgstr ""
+
+#: chronojump_networks/templates/pages/index.html:117
+msgid "version 1.0"
+msgstr ""
+
+#: chronojump_networks/templates/users/login.html:19
+msgid "Enter your username and password"
+msgstr "Introduce tu usuario y contraseña"
+
+#: chronojump_networks/templates/users/login.html:25
+msgid "Login"
+msgstr "Acceder"
diff --git a/chronojumpserver-django/manage.py b/chronojumpserver-django/manage.py
new file mode 100755
index 0000000..4ab9300
--- /dev/null
+++ b/chronojumpserver-django/manage.py
@@ -0,0 +1,22 @@
+#!/usr/bin/env python
+import os
+import sys
+
+if __name__ == "__main__":
+    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings.local')
+    try:
+        from django.core.management import execute_from_command_line
+    except ImportError:
+        # The above import may fail for some other reason. Ensure that the
+        # issue is really that Django is missing to avoid masking other
+        # exceptions on Python 2.
+        try:
+            import django
+        except ImportError:
+            raise ImportError(
+                "Couldn't import Django. Are you sure it's installed and "
+                "available on your PYTHONPATH environment variable? Did you "
+                "forget to activate a virtual environment?"
+            )
+        raise
+    execute_from_command_line(sys.argv)
diff --git a/chronojumpserver/__init__.py b/chronojumpserver/__init__.py
index 7424f46..19a6ab1 100755
--- a/chronojumpserver/__init__.py
+++ b/chronojumpserver/__init__.py
@@ -7,7 +7,8 @@ import click
 from flask import Flask, send_from_directory
 from flask_login import LoginManager, current_user
 from flask_babel import Babel, refresh, gettext, request
-
+from flask_admin import Admin
+from flask_admin.contrib.sqla import ModelView
 import ConfigParser
 import os
 
@@ -19,6 +20,8 @@ config.read('/etc/chronojump.conf')
 
 app = Flask(__name__)
 
+# Administration
+admin = Admin(app, name='Chronojump Server Administration', template_mode='bootstrap3')
 
 login_manager = LoginManager()
 login_manager.init_app(app)
@@ -98,7 +101,7 @@ def shutdown_session(exception=None):
 from chronojumpserver.database import init_db
 init_db()
 
-from chronojumpserver.models import User, Language
+from chronojumpserver.models import User, Language, Person
 # To retrieve the user from session
 @login_manager.user_loader
 def load_user(user_id):
@@ -124,3 +127,8 @@ def generate_string(eval_ctx, localized_value):
         return ""
     else:
         return Markup("\"" + localized_value + "\"").unescape()
+
+
+# Administration models
+admin.add_view(ModelView(User, db_session))
+admin.add_view(ModelView(Person, db_session))
diff --git a/chronojumpserver/models.py b/chronojumpserver/models.py
index dd4c876..3def127 100755
--- a/chronojumpserver/models.py
+++ b/chronojumpserver/models.py
@@ -348,7 +348,7 @@ class Task(Base):
     def __repr__(self):
         """Representation of the task."""
         # For the moment show only task
-        return '<Task %r>' % self.description
+        return '<Task %r>' % ""
 
 
 class ResultEncoder(Base):
diff --git a/chronojumpserver/templates/groups_and_players.html 
b/chronojumpserver/templates/groups_and_players.html
new file mode 100644
index 0000000..8d24bef
--- /dev/null
+++ b/chronojumpserver/templates/groups_and_players.html
@@ -0,0 +1,19 @@
+{% extends 'layout.html' %}
+{% block head %} {{ super() }}
+<link href="{{ url_for('assets', filename='DataTables/media/css/dataTables.bootstrap.min.css') }}" 
rel="stylesheet" />
+{% endblock %}
+
+{% block content %}
+
+<div class="page-header">
+       <h1>{{_('Groups and Players')}}</h1>
+</div>
+
+<!-- /.modal -->
+{% endblock %}
+
+{% block script %} {{ super() }}
+<script src="{{ url_for('assets', filename='DataTables/media/js/jquery.dataTables.min.js') }}"></script>
+<script src="{{ url_for('assets', filename='DataTables/media/js/dataTables.bootstrap.min.js') }}"></script>
+
+{% endblock %}
diff --git a/chronojumpserver/views.py b/chronojumpserver/views.py
index b21fd1f..27c6120 100755
--- a/chronojumpserver/views.py
+++ b/chronojumpserver/views.py
@@ -268,3 +268,10 @@ def login():
 def logout():
     logout_user()
     return redirect(url_for('login'))
+
+
+# Networks changes
+@app.route("/group-players")
+@login_required
+def show_groups_and_players():
+    return render_template('groups_and_players.html')
diff --git a/compose/local/django/start.sh b/compose/local/django/start.sh
new file mode 100644
index 0000000..69210e8
--- /dev/null
+++ b/compose/local/django/start.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+python manage.py migrate
+python manage.py compilemessages
+python manage.py runserver 0.0.0.0:8000
diff --git a/compose/local/flask/chronojump.conf.template b/compose/local/flask/chronojump.conf.template
new file mode 100644
index 0000000..4c6d0f8
--- /dev/null
+++ b/compose/local/flask/chronojump.conf.template
@@ -0,0 +1,20 @@
+[api]
+debug=True
+port=8080
+version=1.2.3
+backtraces_directory=/tmp
+chronojump_stable_version=1.2.3
+photos_dir=/source/chronojumpserver/static/images/photos
+mono_executables_dir=/source/chronojumpserver/rfid-csharp
+
+[db]
+server=db
+name=chronojump
+user=chronojump
+password=chronojump
+
+[club]
+name=FC Barcelona
+
+[security]
+secret_key=Thisisaweakexampleofsecretkey
diff --git a/compose/local/flask/start.sh b/compose/local/flask/start.sh
new file mode 100644
index 0000000..1d9a4ce
--- /dev/null
+++ b/compose/local/flask/start.sh
@@ -0,0 +1,2 @@
+#!/bin/sh
+flask run --host 0.0.0.0
diff --git a/compose/production/django/entrypoint.sh b/compose/production/django/entrypoint.sh
new file mode 100644
index 0000000..476e89b
--- /dev/null
+++ b/compose/production/django/entrypoint.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+
+cmd="$@"
+
+export DATABASE_URL="mysql://${MYSQL_USER}:${MYSQL_PASSWORD}@${MYSQL_HOSTNAME}:3306/${MYSQL_DATABASE}"
+
+exec $cmd
diff --git a/local.yml b/local.yml
new file mode 100755
index 0000000..18436af
--- /dev/null
+++ b/local.yml
@@ -0,0 +1,50 @@
+version: '2'
+
+services:
+   db:
+     image: mysql:5.7
+     volumes:
+       - db_data:/var/lib/mysql
+     env_file:
+       - ./.envs/.local/.mysql
+
+   mysql_django:
+     image: mysql:5.7
+     volumes:
+       - db_data_django:/var/lib/mysql
+     env_file:
+       - ./.envs/.local/.mysql-django
+
+   django:
+     build:
+       context: .
+       dockerfile: ./compose/local/django/Dockerfile
+     volumes:
+       - ./chronojumpserver-django:/app
+     depends_on:
+       - mysql_django
+     ports:
+       - "8000:8000"
+     env_file:
+       - ./.envs/.local/.django
+       - ./.envs/.local/.mysql-django
+     command: /start.sh
+   flask:
+     build:
+       context: .
+       dockerfile: ./compose/local/flask/Dockerfile
+     volumes:
+         - .:/source
+     depends_on:
+       - db
+     ports:
+       - "5000:5000"
+     env_file:
+       - ./.envs/.local/.flask
+       - ./.envs/.local/.mysql
+     command: /start.sh
+
+
+volumes:
+    db_data:
+    db_data_django:
diff --git a/requirements/base.txt b/requirements/base.txt
new file mode 100644
index 0000000..37eaf23
--- /dev/null
+++ b/requirements/base.txt
@@ -0,0 +1,26 @@
+aniso8601==1.2.1
+appdirs==1.4.3
+click==6.7
+itsdangerous==0.24
+Jinja2==2.7.3
+MarkupSafe==0.23
+mysql==0.0.1
+MySQL-python==1.2.5
+packaging==16.8
+PyMySQL==0.7.11
+pyparsing==2.2.0
+python-dateutil==2.6.0
+pytz==2017.2
+six==1.10.0
+SQLAlchemy==1.1.10
+Werkzeug==0.9.6
+
+
+# Flask
+# ------------------------------------------------------------------------------
+Flask==0.12.2
+Flask-Autodoc==0.1.1
+Flask-SQLAlchemy==2.2
+Flask-WTF==0.14.2
+flask-login
+Flask-Babel
diff --git a/requirements/django/base.txt b/requirements/django/base.txt
new file mode 100644
index 0000000..167b052
--- /dev/null
+++ b/requirements/django/base.txt
@@ -0,0 +1,18 @@
+environ==1.0
+MySQL-python==1.2.5
+pytz==2018.3  # https://github.com/stub42/pytz
+awesome-slugify==1.6.5  # https://github.com/dimka665/awesome-slugify
+Pillow==5.0.0  # https://github.com/python-pillow/Pillow
+argon2-cffi==18.1.0  # https://github.com/hynek/argon2_cffi
+
+# Django
+# ------------------------------------------------------------------------------
+django==1.11.1  # https://www.djangoproject.com/
+django-environ==0.4.4  # https://github.com/joke2k/django-environ
+django-model-utils==3.1.1  # https://github.com/jazzband/django-model-utils
+django-crispy-forms==1.7.2  # https://github.com/django-crispy-forms/django-crispy-forms
+django-redis==4.9.0  # https://github.com/niwinz/django-redis
+
+# Django REST Framework
+djangorestframework==3.7.7  # https://github.com/encode/django-rest-framework
+coreapi==2.3.3  # https://github.com/core-api/python-client
diff --git a/requirements/django/local.txt b/requirements/django/local.txt
new file mode 100644
index 0000000..c724814
--- /dev/null
+++ b/requirements/django/local.txt
@@ -0,0 +1,25 @@
+-r ./base.txt
+
+Werkzeug==0.14.1  # https://github.com/pallets/werkzeug
+ipdb==0.11  # https://github.com/gotcha/ipdb
+Sphinx==1.7.2  # https://github.com/sphinx-doc/sphinx
+
+# Testing
+# ------------------------------------------------------------------------------
+pytest==3.5.0  # https://github.com/pytest-dev/pytest
+pytest-sugar==0.9.1  # https://github.com/Frozenball/pytest-sugar
+
+# Code quality
+# ------------------------------------------------------------------------------
+flake8==3.5.0  # https://github.com/PyCQA/flake8
+coverage==4.5.1  # https://github.com/nedbat/coveragepy
+
+# Django
+# ------------------------------------------------------------------------------
+factory-boy==2.10.0  # https://github.com/FactoryBoy/factory_boy
+django-test-plus==1.0.22  # https://github.com/revsys/django-test-plus
+
+django-debug-toolbar==1.9.1  # https://github.com/jazzband/django-debug-toolbar
+django-extensions==2.0.6  # https://github.com/django-extensions/django-extensions
+django-coverage-plugin==1.5.0  # https://github.com/nedbat/django_coverage_plugin
+pytest-django==3.1.2  # https://github.com/pytest-dev/pytest-django
diff --git a/requirements/local.txt b/requirements/local.txt
new file mode 100644
index 0000000..4953a6c
--- /dev/null
+++ b/requirements/local.txt
@@ -0,0 +1,5 @@
+-r ./base.txt
+
+# Flask-Admin
+#------------------------------------------------------------------------------
+Flask-Admin==1.5.0
diff --git a/requirements/production.txt b/requirements/production.txt
new file mode 100644
index 0000000..db167e2
--- /dev/null
+++ b/requirements/production.txt
@@ -0,0 +1,4 @@
+-r ./base.txt
+
+virtualenv==15.1.0
+gunicorn==0.14.5


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]