[chronojump-server] Added a user_detail page



commit 5195f6b4b2b4b05f8ac4c47d132522250087f965
Author: Max Ros i Morejon <mros33 gmail com>
Date:   Thu Jul 11 16:22:26 2019 +0200

    Added a user_detail page

 .../organizations/api/serializers.py               |   5 +
 .../chronojump_networks/organizations/api/urls.py  |   5 +
 .../chronojump_networks/organizations/api/views.py |  20 ++-
 .../chronojump_networks/organizations/urls.py      |   5 +
 .../chronojump_networks/organizations/views.py     |  21 ++-
 .../chronojump_networks/templates/layout.html      |   2 +-
 .../chronojump_networks/templates/pages/index.html |   2 +-
 .../templates/users/user_detail.html               | 145 +++++++++++++++++++++
 .../templates/users/user_list.html                 |   0
 9 files changed, 197 insertions(+), 8 deletions(-)
---
diff --git a/chronojumpserver-django/chronojump_networks/organizations/api/serializers.py 
b/chronojumpserver-django/chronojump_networks/organizations/api/serializers.py
index 81d57b5..256fd09 100644
--- a/chronojumpserver-django/chronojump_networks/organizations/api/serializers.py
+++ b/chronojumpserver-django/chronojump_networks/organizations/api/serializers.py
@@ -9,6 +9,11 @@ class UserSerializer(serializers.ModelSerializer):
         model = User
         fields = [ 'id', 'name']
         
+class UserAllSerializer(serializers.ModelSerializer):
+    class Meta:
+        model = User
+        fields = [ 'id', 'email', 'firstname', 'secondname', 'language' ]
+        
 class GymTableSerializer(serializers.ModelSerializer):
     responsible = UserSerializer(many=False)
     class Meta:
diff --git a/chronojumpserver-django/chronojump_networks/organizations/api/urls.py 
b/chronojumpserver-django/chronojump_networks/organizations/api/urls.py
index 4555e7e..5f38830 100644
--- a/chronojumpserver-django/chronojump_networks/organizations/api/urls.py
+++ b/chronojumpserver-django/chronojump_networks/organizations/api/urls.py
@@ -66,6 +66,11 @@ urlpatterns = [
         view=views.PlayerGroupsListView.as_view(),
         name='player_groups'
     ),
+    url(
+        regex=r'^(?P<organization_id>\d+)/users/(?P<user_id>\d+)$',
+        view=views.UserUpdateView.as_view(),
+        name='update_user'
+    ),
     url(
         regex=r'^register_rfid/$',
         view=views.register_rfid,
diff --git a/chronojumpserver-django/chronojump_networks/organizations/api/views.py 
b/chronojumpserver-django/chronojump_networks/organizations/api/views.py
index abdcf7a..c5909f1 100644
--- a/chronojumpserver-django/chronojump_networks/organizations/api/views.py
+++ b/chronojumpserver-django/chronojump_networks/organizations/api/views.py
@@ -2,7 +2,7 @@ import os
 import subprocess
 from ..models import Player, GroupPlayer, Group, Station, Gym, Exercise, RFIDHistory, OrganizationStaff, User
 from ..decorators import check_user_organization
-from .serializers import PlayerSerializer, StationSerializer, ExerciseSerializer, GymStationsSerializer, 
GroupSerializer, GroupTableSerializer, UserSerializer, GymTableSerializer
+from .serializers import PlayerSerializer, StationSerializer, ExerciseSerializer, GymStationsSerializer, 
GroupSerializer, GroupTableSerializer, UserSerializer, UserAllSerializer, GymTableSerializer
 
 from django.core.files.storage import default_storage
 from django.core.files.base import ContentFile
@@ -11,7 +11,7 @@ from django.conf import settings
 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.generics import GenericAPIView, ListAPIView, ListCreateAPIView, DestroyAPIView, 
RetrieveUpdateDestroyAPIView, RetrieveAPIView
 from rest_framework.mixins import ListModelMixin, CreateModelMixin, DestroyModelMixin
 from rest_framework.permissions import IsAuthenticated
 
@@ -301,6 +301,22 @@ class PlayerGroupsListView(ListCreateAPIView):
             resp_n = [r.name for r in resp]
             setattr(group, 'responsible_name', resp_n[0])
         return groups
+    
+class UserUpdateView(RetrieveAPIView):
+    permission_classes = (IsAuthenticated, )
+    serializer_class = UserAllSerializer
+    queryset = ''
+    
+    def put(self, request, *args, **kwars):
+        print "Update user"
+        data = dict(request.data)
+        o = User.objects.get(id=int(data['id'][0]))
+        o.first_name = str(data['firstname'][0].encode('utf-8'))
+        o.last_name = str(data['secondname'][0].encode('utf-8'))
+        o.email = str(data['email'][0].encode('utf-8'))
+        o.language = str(data['language'][0])
+        o.save()
+        return JsonResponse({}, status=200, safe=False)
 
 def register_rfid(request):
     """Call an external program to read rfid and return the value read."""
diff --git a/chronojumpserver-django/chronojump_networks/organizations/urls.py 
b/chronojumpserver-django/chronojump_networks/organizations/urls.py
index be97359..634d947 100644
--- a/chronojumpserver-django/chronojump_networks/organizations/urls.py
+++ b/chronojumpserver-django/chronojump_networks/organizations/urls.py
@@ -53,6 +53,11 @@ urlpatterns = [
         view=views.GymDetailTemplateView.as_view(),
         name='gym_detail'
     ),
+    url(
+        regex=r'^(?P<organization_id>\d+)/users/(?P<user_id>\d+)$',
+        view=views.UserDetailTemplateView.as_view(),
+        name='user_page'
+    ),
     url(
         regex=r'^login$',
         view=views.organization_login,
diff --git a/chronojumpserver-django/chronojump_networks/organizations/views.py 
b/chronojumpserver-django/chronojump_networks/organizations/views.py
index 088e1cf..fd67171 100644
--- a/chronojumpserver-django/chronojump_networks/organizations/views.py
+++ b/chronojumpserver-django/chronojump_networks/organizations/views.py
@@ -10,7 +10,7 @@ from django.views.generic import DetailView, ListView, RedirectView, UpdateView,
 from django.utils.translation import ugettext_lazy as _
 from django.utils import translation
 
-from .models import Organization, Station, Group, Gym, Player
+from .models import Organization, Station, Group, Gym, Player, User
 from .forms import UserLoginForm
 from .decorators import check_user_organization
 
@@ -51,7 +51,7 @@ class GymDetailTemplateView(LoginRequiredMixin, TemplateView):
     template_name = 'organizations/gyms/gym_detail.html'
 
     def get_context_data(self, **kwargs):
-        """Pass to the template the Group object"""
+        """Pass to the template the Gym object"""
 
         context = super(GymDetailTemplateView,self).get_context_data(**kwargs)
         gym_id = int(kwargs['gym_id'])
@@ -64,14 +64,27 @@ class PlayerListTemplateView(LoginRequiredMixin, TemplateView):
     template_name = 'organizations/players/players_list.html'
 
 class GroupListTemplateView(LoginRequiredMixin, TemplateView):
-    """ Show the Player List
+    """ Show the Group List
     """
     template_name = 'organizations/groups/groups_list.html'
     
 class GymListTemplateView(LoginRequiredMixin, TemplateView):
-    """ Show the Player List
+    """ Show the Gym List
     """
     template_name = 'organizations/gyms/gyms_list.html'
+    
+class UserDetailTemplateView(LoginRequiredMixin, TemplateView):
+    """ Show the User details
+    """
+    template_name = 'users/user_detail.html'
+    
+    def get_context_data(self, **kwargs):
+        """Pass to the template the User object"""
+
+        context = super(UserDetailTemplateView,self).get_context_data(**kwargs)
+        user_id = int(kwargs['user_id'])
+        context['user'] = User.objects.get(id=user_id)
+        return context
 
 #
 # Login methods and views
diff --git a/chronojumpserver-django/chronojump_networks/templates/layout.html 
b/chronojumpserver-django/chronojump_networks/templates/layout.html
index 81f4584..3d32f6a 100644
--- a/chronojumpserver-django/chronojump_networks/templates/layout.html
+++ b/chronojumpserver-django/chronojump_networks/templates/layout.html
@@ -56,7 +56,7 @@
       {% endif %}
     </ul>
     <ul class="navbar-nav justify-content-end">
-      <li class="nav-item active"><a class="nav-link">{% trans 'Hello, '%}{{user.name}}</a></li>
+      <li class="nav-item active"><a class="nav-link" href="{% url 'organizations:user_page' 
organization_id=user.organization.id user_id=user.id %}">{% 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>
diff --git a/chronojumpserver-django/chronojump_networks/templates/pages/index.html 
b/chronojumpserver-django/chronojump_networks/templates/pages/index.html
index a13328d..254feb0 100644
--- a/chronojumpserver-django/chronojump_networks/templates/pages/index.html
+++ b/chronojumpserver-django/chronojump_networks/templates/pages/index.html
@@ -30,7 +30,7 @@
         <div class="col-md-6">
           <div class="float-right">
             <ul class="nav">
-              <li class="nav-item active"><a class="nav-link text-white">{% trans 'Welcome, 
'%}{{user.name}}</a></li>
+              <li class="nav-item active"><a href="{% url 'organizations:user_page' 
organization_id=user.organization.id user_id=user.id %}" class="nav-link text-white">{% 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>
diff --git a/chronojumpserver-django/chronojump_networks/templates/users/user_detail.html 
b/chronojumpserver-django/chronojump_networks/templates/users/user_detail.html
new file mode 100644
index 0000000..6afc70b
--- /dev/null
+++ b/chronojumpserver-django/chronojump_networks/templates/users/user_detail.html
@@ -0,0 +1,145 @@
+{% 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-8">
+    {% if user.organization.image %}
+        <img src="{{MEDIA_URL}}{{ user.organization.image }}" class="img-fluid float-left" width="48px" 
height="48px" style="margin-top:12px;margin-right:10px;" />
+    {% else %}
+        <img src="{% static 'images/logo_club.png' %}" class="img-fluid float-left" width="48px" 
height="48px" style="margin-top:12px;margin-right:10px;" />
+    {% endif %}
+    <h1 class="display-4">{{user.name}} </h1>
+    <h1 class="display-4"> <small class="text-muted" style="font-size:32px">{% trans 'Details' 
%}</small></h1>
+  </div>
+  <div class="col-sm-4">
+    <dl class="row" style="margin-top:10px">
+      <dt class="col-sm-4 text-right">{% trans 'Organization' %}:</dt>
+      <dd class="col-sm-8">{{ user.organization.name }}</dd>
+    </dl>
+    <dl class="row" style="margin-top:10px">
+      <dt class="col-sm-4 text-right">{% trans 'Username' %}:</dt>
+      <dd class="col-sm-8">{{ user.username }}</dd>
+    </dl>
+    <!--<div class="row" style="margin-top:10px">
+      <div class="col" style="margin-left:50px">
+        <button id="btnPas" type="button" class="btn btn-outline-secondary">{% trans 'Change password' 
%}</button> 
+      </div>
+    </div>-->
+  </div>
+</div>
+
+<div class="container">
+  <div class="row" style="margin-bottom:20px">
+    <div class="col-sm-12">
+        <label for="email">{% trans 'Email' %}</label>
+        <input name="email" class="form-control" id="email" type="text" value="{{user.email}}">
+    </div>
+  </div>
+  <div class="row" style="margin-bottom:20px">
+    <div class="col-sm-6">
+        <label for="firstname">{% trans 'First name' %}</label>
+        <input name="firstname" class="form-control" id="firstname" type="text" value="{{user.first_name}}">
+    </div>
+    <div class="col-sm-6">
+        <label for="secondname">{% trans 'Second name' %}</label>
+        <input name="secondname" class="form-control" id="secondname" type="text" value="{{user.last_name}}">
+    </div>
+  </div>
+  <div class="row" style="margin-bottom:20px">
+    <div class="col-sm-4">
+        <label for="language">{% trans 'Language' %}</label>
+        <select name="language" class="form-control" id="language">
+            <option value="en">{% trans 'English' %}</option>
+            <option value="es">{% trans 'Spanish' %}</option>
+            <option value="fr">{% trans 'French' %}</option>
+            <option value="ca">{% trans 'Catalan' %}</option>
+        </select>
+    </div>
+    <div class="col-sm-4">
+        <label for="isstaff">{% trans 'Staff' %}</label>
+        <input name="isstaff" class="form-control" id="isstaff" type="text" value="{{user.is_staff}}" 
disabled readonly>
+    </div>
+    <div class="col-sm-4">
+        <button id="btnSave" type="button" class="btn btn-outline-primary" 
style="bottom:0;left:0;position:absolute;">{% trans 'Save changes' %}</button>
+    </div>
+  </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();
+  var lgc = false;
+
+    $(document).ready(function() {
+        var lg = "{{user.language}}";
+        $('#language').val(lg);
+        
+        $('#btnSave').on('click', function(e) {
+            e.preventDefault();
+            var user = serializeUser();
+            $.ajax({
+                'url': "{% url 'api_organizations:update_user' organization_id=user.organization.id 
user_id=user.id %}",
+                'method': 'PUT',
+                'data': user,
+                success: function(data) {
+                    if(lgc) {
+                        alert("{% trans 'The user has been updated. You will have to re-login in order to 
see the language changed.' %}");
+                    } else {
+                        alert("{% trans 'The user has been updated' %}");
+                    }
+                },
+                error: function(request, status, error) { 
+                    alert(request.responseText);
+                }
+
+            });
+        });
+        
+        $('#language').on('change', function() {
+            lgc = true;
+        });
+        
+        /* Get all the values in the form into json object */
+        function serializeUser() {
+        let id = {{user.id}};
+        let email = $('#email').val();
+        let firstname = $('#firstname').val();
+        let secondname = $('#secondname').val();
+        let language = $('#language').val();
+        var user = {
+            'id': id,
+            'email': email, 
+            'firstname': firstname,
+            'secondname' : secondname,
+            'language': language
+        }
+        console.log(user);
+        return user;
+        }
+        
+    });
+</script>
+
+{% endblock %}


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