]> git.atlas4tour.it Git - pia_atlas.git/commitdiff
- Serializer
authorCostantino Vitale <costantino.vitale@dyrecta.com>
Thu, 13 Oct 2022 15:41:57 +0000 (17:41 +0200)
committerCostantino Vitale <costantino.vitale@dyrecta.com>
Thu, 13 Oct 2022 15:41:57 +0000 (17:41 +0200)
- Implementazione API

api/urls.py
api/views.py
sistema/datatables.py
sistema/models.py
sistema/templates/add_mod_percorso.html
sistema/templates/base.html
sistema/urls.py
sistema/views.py

index d566f9623b068252fe632f7613db15c314179c37..28a75d7f853839dc35669b1a9c9908861758ecdd 100644 (file)
@@ -2,10 +2,14 @@ from django.contrib import admin
 from django.urls import path, include
 from django.contrib.auth import views as auth_views
 
-from api.views import Login_v2, RegistrationAPI, ListaPercorsiAPI
+from api.views import Login_v2, RegistrationAPI, ListaPercorsiAPI, DetailPercorsoAPI, DetailPoiAPI, SendFeedbackAPI
 
 urlpatterns = [
     path('api-login/', Login_v2.as_view(), name='api_login'),
     path('api-registration/', RegistrationAPI.as_view(), name='api_registration'),
     path('lista_percorsi/', ListaPercorsiAPI.as_view(), name='lista_percorsi'),
+    path('detail_percorso/', DetailPercorsoAPI.as_view(), name='detail_percorso'),
+    path('detail_poi/', DetailPoiAPI.as_view(), name='detail_poi'),
+
+    path('send_feedback/', SendFeedbackAPI.as_view(), name='send_feedback'),
 ]
index 03dc0eefdb2ed6ba8f5853720e6c129b6a11b55c..8bc2904bd7a2afb008d1080dd1dbe70e87336c8e 100644 (file)
@@ -1,3 +1,4 @@
+from django.contrib.auth.models import User
 from django.http import JsonResponse
 from django.shortcuts import render
 from django.utils.translation import ugettext as _
@@ -12,9 +13,8 @@ from rest_framework_simplejwt.tokens import RefreshToken
 from rest_framework_simplejwt.views import TokenViewBase
 from rest_framework_simplejwt.exceptions import AuthenticationFailed
 
-from sistema.models import Percorso, PercorsoSerializer
-from socoin_atlas import settings
-from utenti.mixins import AuthorizationRequiredMixin
+from sistema.models import Percorso, PercorsoSerializer, Tappa, TappaSerializer, Feedback, FeedbackSerializer, \
+    PointOfInterest, PoiSerializer, Multimedia, MultimediaSerializer
 
 
 class TokenObtainLoginSerializer(serializers.Serializer):
@@ -136,4 +136,111 @@ class ListaPercorsiAPI(APIView):
         if error:
             return Response({'errors': errors, 'error': error, 'data': '', 'messages': ['KO']})
         else:
-            return Response({'errors': errors, 'error': error, 'data': percorsi_serialize.data, 'messages': ['OK']})
\ No newline at end of file
+            return Response({'errors': errors, 'error': error, 'data': percorsi_serialize.data, 'messages': ['OK']})
+
+
+class DetailPercorsoAPI(APIView):
+    def get(self, request):
+        errors = []
+        error = False
+        data = []
+
+        id_percorso = request.data['id_percorso']
+
+        if id_percorso:
+
+            filter = Percorso.objects.filter(id=int(id_percorso), is_active=True)
+
+            if filter:
+                percorsi_serialize = PercorsoSerializer(filter, many=True)
+
+                tappe = Tappa.objects.filter(percorso=filter.first(), is_active=True)
+                tappe_list = TappaSerializer(tappe, many=True)
+
+                feedback = Feedback.objects.filter(percorso=filter.first(), is_active=True)
+                feedback_list = FeedbackSerializer(feedback, many=True)
+
+                data.append({
+                    'percorso': percorsi_serialize.data,
+                    'tappe': tappe_list.data,
+                    'feedback': feedback_list.data
+                })
+
+                return Response({'errors': errors, 'error': error, 'data': data, 'messages': ['OK']})
+            else:
+                return Response({'errors': 'Percorso non presente', 'error': True, 'data': '', 'messages': ['']})
+
+        else:
+            return Response({'errors': 'ID percorso non inviato', 'error': True, 'data': '', 'messages': ['']})
+
+
+class DetailPoiAPI(APIView):
+    def get(self, request):
+        errors = []
+        error = False
+        data = []
+
+        id_poi = request.data['id_poi']
+
+        if id_poi:
+
+            filter = PointOfInterest.objects.filter(id=int(id_poi), is_active=True)
+
+            if filter:
+                poi_serialize = PoiSerializer(filter, many=True)
+
+                multimedia = Multimedia.objects.filter(poi=filter.first(), is_active=True)
+                multimedia_list = MultimediaSerializer(multimedia, many=True)
+
+                data.append({
+                    'poi': poi_serialize.data,
+                    'multimedia': multimedia_list.data,
+                })
+
+                return Response({'errors': errors, 'error': error, 'data': data, 'messages': ['OK']})
+            else:
+                return Response({'errors': 'Punto di interesse non presente', 'error': True, 'data': '', 'messages': ['']})
+
+        else:
+            return Response({'errors': 'ID punto di interesse  non inviato', 'error': True, 'data': '', 'messages': ['']})
+
+
+class SendFeedbackAPI(APIView):
+    def post(self, request):
+        errors = []
+        error = False
+        data = []
+
+        id_utente = request.data['pk_utente']
+        id_percorso = request.data['percorso']
+        valutazione = request.data['valutazione']
+        commento = request.data['commento']
+
+        if id_utente and id_percorso and valutazione:
+
+            utente = User.objects.get(pk=int(id_utente))
+            if utente:
+
+                percorso = Percorso.objects.get(pk=int(id_percorso))
+                if percorso:
+
+                    try:
+                        Feedback.objects.create(
+                            utente=utente,
+                            percorso=percorso,
+                            valutazione=int(valutazione),
+                            commento=commento
+                        )
+                        return Response({'errors': errors, 'error': error, 'data': data, 'messages': ['OK']})
+
+                    except Exception as e:
+                        return Response(
+                            {'errors': str(e), 'error': True, 'data': '', 'messages': ['']})
+                else:
+                    return Response(
+                        {'errors': 'Percorso non trovato a sistema', 'error': True, 'data': '', 'messages': ['KO']})
+            else:
+                return Response({'errors': 'Utente non trovato a sistema', 'error': True, 'data': '', 'messages': ['KO']})
+        else:
+            return Response(
+                {'errors': 'Assicurati che le informazioni relative all\'utente, percorso e valutazione siano state inviate', 'error': True, 'data': '', 'messages': ['KO']})
index 7c56e7fe7eb411be290c549ecfb965ec9f5efb05..db187965944055dc9fb240415af545ec92e03177 100644 (file)
@@ -151,7 +151,7 @@ class PoiDatatables(BaseDatatableView):
         if column == 'mod':
             return '<a class="btn btn-sm btn-primary" href="/mod_poi/%s/" ><i class="fas fa-edit"></i></a>' % row.pk
         if column == 'del':
-            return '<a class="btn btn-sm btn-danger" href="DeletePoi(%s)" ><i class="fas fa-trash"></i></a>' % row.pk
+            return '<button class="btn btn-sm btn-danger" onclick="DeletePoi(%s)" ><i class="fas fa-trash"></i></button>' % row.pk
         else:
             return super(PoiDatatables, self).render_column(row, column)
 
@@ -164,8 +164,8 @@ class PoiDatatables(BaseDatatableView):
 
 class FeedbackDatatables(BaseDatatableView):
     model = Feedback
-    columns = ['id', 'utente', 'valutazione', 'commento', 'mod', 'del']
-    order_columns = ['id', 'utente', 'valutazione', 'commento', 'mod', 'del']
+    columns = ['id', 'utente', 'valutazione', 'commento', 'del']
+    order_columns = ['id', 'utente', 'valutazione', 'commento', 'del']
 
     def get_initial_queryset(self):
         return self.model.objects.filter(is_active=True)
@@ -176,13 +176,14 @@ class FeedbackDatatables(BaseDatatableView):
         if column == 'utente':
             return escape('{0}'.format(row.utente.username))
         if column == 'valutazione':
-            return escape('{0}'.format(row.valutazione))
+            value = ''
+            for i in range(0, int(row.valutazione)):
+                value += '<i class="fa-solid fa-star"></i>'
+            return f'{value}'
         if column == 'commento':
             return escape('{0}'.format(row.commento))
-        if column == 'mod':
-            return '<a class="btn btn-sm btn-primary" href="#" ><i class="fas fa-edit"></i></a>' #% row.pk
         if column == 'del':
-            return '<a class="btn btn-sm btn-danger" href="#" ><i class="fas fa-trash"></i></a>' #% row.pk
+            return '<button class="btn btn-sm btn-danger" onclick="DeactivateFeedback(%s)" ><i class="fas fa-trash"></i></button>' % row.pk
         else:
             return super(FeedbackDatatables, self).render_column(row, column)
 
index fe5d3ca049bd38dd655a268073a835e0a56b3ab5..e0830445c46689268b4b9573a98d60f2d7e593a6 100644 (file)
@@ -39,12 +39,6 @@ class Percorso(models.Model):
     is_active = models.BooleanField(default=True)
 
 
-class PercorsoSerializer(serializers.ModelSerializer):
-    class Meta:
-        model = Percorso
-        fields = ('id', 'nome', 'descrizione', 'testo')
-
-
 class Tappa(models.Model):
     percorso = models.ForeignKey(Percorso, on_delete=models.DO_NOTHING)
     poi = models.ForeignKey(PointOfInterest, on_delete=models.DO_NOTHING)
@@ -106,3 +100,27 @@ class Feedback(models.Model):
     valutazione = models.IntegerField()
     commento = models.TextField(max_length=255, null=True, blank=True)
     is_active = models.BooleanField(default=True)
+
+
+class PercorsoSerializer(serializers.ModelSerializer):
+    class Meta:
+        model = Percorso
+        fields = ('id', 'nome', 'descrizione', 'testo')
+
+
+class FeedbackSerializer(serializers.ModelSerializer):
+    class Meta:
+        model = Feedback
+        fields = ('id', 'utente', 'percorso', 'valutazione', 'commento')
+
+
+class PoiSerializer(serializers.ModelSerializer):
+    class Meta:
+        model = PointOfInterest
+        fields = ('id', 'nome', 'lat', 'long', )
+
+
+class MultimediaSerializer(serializers.ModelSerializer):
+    class Meta:
+        model = Multimedia
+        fields = ('id', 'nome', 'tipologia__nome', 'media', 'nome', 'descrizione', 'testo')
\ No newline at end of file
index b17fe89baec1380f86416cea5ffee73f8eff359f..934a19d4756337d50d9dd8b8666590286edf3e02 100644 (file)
                         </div>
                     </div>
                 </div>
-                     <div class="card-footer text-right">
-                        <button class="btn-sm btn-success" type="button" onclick="saveItinerary()">Salva</button>
+                 <div class="card-footer text-right">
+                    <button class="btn-sm btn-success" type="button" onclick="saveItinerary()">Salva</button>
+                </div>
+            </div>
+
+            <div class="card">
+                <div class="card-header">
+                    <h4 class="clr-config">Feedback degli utenti</h4>
+                </div>
+                <div class="card-body">
+                    <div class="row">
+                        <div class="table-responsive">
+                            <table id="feedback-table"
+                                   class="table table-sm table-bordered table-striped dataTables_wrapper dt-bootstrap4 no-footer" style="width: 100% !important;">
+                                <thead>
+                                <tr>
+                                    <th>#</th>
+                                    <th>Utente</th>
+                                    <th>Valutazione</th>
+                                    <th>Commento</th>
+                                    <th></th>
+                                </tr>
+                                </thead>
+                                <tbody>
+                                </tbody>
+                            </table>
+                        </div>
                     </div>
+                </div>
             </div>
+
         </div>
     </div>
 
 
     <script>
+
         var list_tappe = [];
         var selected_items = []
 
 
         $(document).ready(function () {
+            $('#feedback-table').dataTable({
+                processing: true,
+                serverSide: true,
+                ajax: {
+                    "url": "{% url 'sistema:feedback_datatables' %}",
+                    "type": 'GET',
+                },
+                language: {
+                    url: "//cdn.datatables.net/plug-ins/1.10.20/i18n/Italian.json"
+                },
+                columnDefs: [
+                        {"targets": 4, "orderable": false, "width": "5%"},
+                ],
+                "order": []
+            });
+
             updateSelect();
 
             {% if associated_tappe %}
 
         });
 
+        function DeactivateFeedback(pk){
+            Swal.fire({
+                title: "Sei sicuro?",
+                text: "Una volta eliminata non sarà più possibile accedere all'informazione!",
+                icon: "warning",
+                showCancelButton: true,
+                confirmButtonColor: '#3085d6',
+                cancelButtonColor: '#d33',
+                confirmButtonText: 'Conferma',
+                cancelButtonText: 'Annulla',
+            }).then((willDelete) => {
+                if (willDelete.value) {
+                    $.ajax({
+                        type: 'GET',
+                        data: {
+                            'pk': pk,
+                            'method': 'del',
+                        },
+                        url: '{% url 'sistema:feedback' %}',
+                        success: function (response) {
+                            Swal.fire("Fatto!", response.response, "success")
+                                .then((value) => {
+                                    location.reload();
+                                });
+                        },
+                        error: () => {
+                            Swal.fire("Attenzione!", response.response, "error")
+                        }
+                    })
+                } else if (
+                    willDelete.dismiss === Swal.DismissReason.cancel
+                ) {
+                    Swal.fire(
+                        'Annullato',
+                        'Rimozione annullata.',
+                        'error'
+                    )
+                }
+            });
+        }
+
         function getListSelected(){
             selected_items = []
             $('#sortlist').children('li').each(function () {
index 66f806cedabdd69bff41bdddd525a9e07c4fd10b..77fa0575c77356446bdf7fa140bd615a8f24591e 100644 (file)
                             <i class="fa-solid fa-house"></i><span>Home</span></a>
                     </li>
 
-                    <li class="menu-header">Sistema</li>
-
-                    <li class="dropdown">
-                        <a href="#" class="menu-toggle nav-link has-dropdown color-clients">
-                            <i class="fa-solid fa-users"></i><span>Utenti</span></a>
-
-                        <ul class="dropdown-menu" id="menu-drop">
-                            <li><a class="nav-link" href="{% url 'utenti:admin_list' %}">Amministratori</a></li>
-                            <li><a class="nav-link" href="{% url 'utenti:touroperator_list' %}">Tour operator</a></li>
-                            <li><a class="nav-link" href="{% url 'utenti:clienti_list' %}">Clienti</a></li>
-                        </ul>
-
-                    </li>
-
-                    <li class="dropdown voce_menu" id="dipendenti-menu">
-                        <a href="{% url 'sistema:localita_list' %}" class="nav-link color-dipendenti">
-                            <i class="fa-solid fa-tree-city"></i><span>Località</span></a>
-                    </li>
-
-                    <li class="dropdown">
-                        <a href="#" class="menu-toggle nav-link has-dropdown color-config">
-                            <i class="fa-solid fa-location-dot"></i><span>Punti di interesse</span></a>
-
-                        <ul class="dropdown-menu" id="menu-drop">
-                            <li><a class="nav-link" href="{% url 'sistema:poi_list' %}">Lista punti di interesse</a></li>
-                            <li><a class="nav-link" href="{% url 'sistema:tipo_multimedia_list' %}">Tipologia multimedia</a></li>
-                        </ul>
-                    </li>
+                    {% if 'CLIENTE' not in request.session.roles %}
+                        <li class="menu-header">Sistema</li>
+
+                        <li class="dropdown">
+                            <a href="#" class="menu-toggle nav-link has-dropdown color-clients">
+                                <i class="fa-solid fa-users"></i><span>Utenti</span></a>
+
+                            <ul class="dropdown-menu" id="menu-drop">
+                                {% if 'TOUR_OPERATOR' not in request.session.roles %}
+                                    <li><a class="nav-link" href="{% url 'utenti:admin_list' %}">Amministratori</a></li>
+                                {% endif %}
+                                <li><a class="nav-link" href="{% url 'utenti:touroperator_list' %}">Tour operator</a></li>
+                                <li><a class="nav-link" href="{% url 'utenti:clienti_list' %}">Clienti</a></li>
+                            </ul>
+
+                        </li>
+
+                        <li class="dropdown voce_menu" id="dipendenti-menu">
+                            <a href="{% url 'sistema:localita_list' %}" class="nav-link color-dipendenti">
+                                <i class="fa-solid fa-tree-city"></i><span>Località</span></a>
+                        </li>
+
+                        <li class="dropdown">
+                            <a href="#" class="menu-toggle nav-link has-dropdown color-config">
+                                <i class="fa-solid fa-location-dot"></i><span>Punti di interesse</span>
+                            </a>
+
+                            <ul class="dropdown-menu" id="menu-drop">
+                                <li><a class="nav-link" href="{% url 'sistema:poi_list' %}">Lista punti di interesse</a></li>
+                                <li><a class="nav-link" href="{% url 'sistema:tipo_multimedia_list' %}">Tipologia multimedia</a></li>
+                            </ul>
+                        </li>
+                    {% endif %}
 
                     <li class="dropdown voce_menu" id="poi-menu">
                         <a href="{% url 'sistema:percorsi_list' %}" class="nav-link color-listini">
                             <i class="fa-solid fa-route"></i><span>Percorsi</span></a>
                     </li>
+
                 </ul>
             </aside>
         </div>
index 346874f884e8a8f04565a3a762830a222b21d554..928a187755b0b7bea8040253ce72d520485b06ff 100644 (file)
@@ -3,7 +3,7 @@ from django.urls import path
 from sistema.datatables import LocalitaDatatables, MultimediaDatatables, TipoMultimediaDatatables, PercorsoDatatables, \
     PoiDatatables, FeedbackDatatables, GestisceLocalitaDatatables
 from sistema.views import Home, LocalitaListView, MultimediaListView, PuntiInteresseListView, \
-    TipologiaMultimediaListView, PercorsiListView, LocalitaView, TipoMultimediaView, PoiView, PercorsoView
+    TipologiaMultimediaListView, PercorsiListView, LocalitaView, TipoMultimediaView, PoiView, PercorsoView, FeedbackView
 
 urlpatterns = [
     path('', Home.as_view(), name='home'),
@@ -40,4 +40,7 @@ urlpatterns = [
     ## PERCORSO ##
     path('percorso/', PercorsoView.as_view(), name='percorso'),
     path('mod_percorso/<int:pk>/', PercorsoView.as_view(), name='mod_percorso'),
+
+    ## FEEDBACK ##
+    path('feedback/', FeedbackView.as_view(), name='feedback'),
 ]
index f05a09a53f43b8ac7a6edfb0266da37302099515..f50e3552166c67c8ed43ee091b699ff402b85f55 100644 (file)
@@ -10,7 +10,8 @@ from django.views.generic import TemplateView
 from rest_framework import status
 
 from sistema.forms import LocalitaForm, TipoMultimediaForm, PoiForm, PercorsoForm, MultimediaForm
-from sistema.models import Localita, TipologiaMultimedia, PointOfInterest, Percorso, Tappa, TappaSerializer, Multimedia
+from sistema.models import Localita, TipologiaMultimedia, PointOfInterest, Percorso, Tappa, TappaSerializer, Multimedia, \
+    Feedback, FeedbackSerializer
 from utenti.mixins import CustomLoginRequiredMixin
 
 
@@ -274,7 +275,8 @@ class PercorsoView(View):#PermissionRequiredMixin
         elif 'pk' in kwargs:
             return render(request, 'add_mod_percorso.html', {'poi_list': PointOfInterest.objects.filter(is_active=True).values('id', 'nome'),
                                                              'form': PercorsoForm(instance=Percorso.objects.get(pk=int(self.kwargs['pk']))),
-                                                             'associated_tappe': Tappa.objects.filter(percorso_id=int(self.kwargs['pk'])).values('poi__id', 'poi__nome', 'is_partenza', 'is_arrivo', 'is_tappa')})
+                                                             'associated_tappe': Tappa.objects.filter(percorso_id=int(self.kwargs['pk'])).values('poi__id', 'poi__nome', 'is_partenza', 'is_arrivo', 'is_tappa'),
+                                                             'feedback': Feedback.objects.filter(percorso_id=int(self.kwargs['pk']), is_active=True)})
         else:
             return render(request, 'add_mod_percorso.html', {'poi_list': PointOfInterest.objects.filter(is_active=True).values('id', 'nome'),
                                                              'form': PercorsoForm()})
@@ -286,3 +288,18 @@ class PercorsoView(View):#PermissionRequiredMixin
             self.add_percorso(request)
 
         return redirect(reverse('sistema:percorsi_list'))
+
+
+
+class FeedbackView(View):#PermissionRequiredMixin
+    #permission_required = [settings.TOUR_OPERATOR_GROUPS, settings.ADMIN_GROUPS]
+
+    def del_feedback(self, request):
+        feedback = Feedback.objects.get(pk=int(request.GET.get('pk')))
+        feedback.is_active = False
+        feedback.save()
+
+    def get(self, request, *args, **kwargs):
+        if request.GET.get('method') == 'del':
+            self.del_feedback(request)
+            return JsonResponse({'response': 'Feedback eliminato con successo'}, status=status.HTTP_200_OK)
\ No newline at end of file