]> git.atlas4tour.it Git - pia_atlas.git/commitdiff
- Implementazione funzionalità
authorCostantino <Costantino@DESKTOP-NSVPNBA>
Fri, 30 Sep 2022 15:33:55 +0000 (17:33 +0200)
committerCostantino <Costantino@DESKTOP-NSVPNBA>
Fri, 30 Sep 2022 15:33:55 +0000 (17:33 +0200)
25 files changed:
.idea/misc.xml
.idea/socoin_atlas.iml
requirements.txt
sistema/datatables.py [new file with mode: 0644]
sistema/forms.py
sistema/models.py
sistema/templates/add_mod_localita.html [new file with mode: 0644]
sistema/templates/add_mod_tipologia.html [new file with mode: 0644]
sistema/templates/base.html
sistema/templates/home.html
sistema/templates/localita_list.html [new file with mode: 0644]
sistema/templates/multimedia_list.html [new file with mode: 0644]
sistema/templates/percorsi_list.html [new file with mode: 0644]
sistema/templates/poi_list.html [new file with mode: 0644]
sistema/templates/tipo_multimedia_list.html [new file with mode: 0644]
sistema/urls.py
sistema/views.py
socoin_atlas/settings.py
utenti/datatables.py [new file with mode: 0644]
utenti/forms.py
utenti/templates/admin_list.html [new file with mode: 0644]
utenti/templates/clienti_list.html [new file with mode: 0644]
utenti/templates/tour_operator_list.html [new file with mode: 0644]
utenti/urls.py
utenti/views.py

index ec83ff998036e2d2bfc49cbce7d3cc49f09891d4..d28790de07edb35c6cca22cd03eb28b8454e328a 100644 (file)
@@ -1,4 +1,4 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <project version="4">
-  <component name="ProjectRootManager" version="2" project-jdk-name="Python 3.7 (socoin_atlas)" project-jdk-type="Python SDK" />
+  <component name="ProjectRootManager" version="2" project-jdk-name="Python 3.7 (pia_atlas)" project-jdk-type="Python SDK" />
 </project>
\ No newline at end of file
index f89b1a889d6c9ce4d8070ff8bceec92f54755348..a312c3aab382f77006378fb8bd673b1eb2064314 100644 (file)
@@ -16,7 +16,7 @@
     <content url="file://$MODULE_DIR$">
       <excludeFolder url="file://$MODULE_DIR$/env" />
     </content>
-    <orderEntry type="inheritedJdk" />
+    <orderEntry type="jdk" jdkName="Python 3.7 (pia_atlas)" jdkType="Python SDK" />
     <orderEntry type="sourceFolder" forTests="false" />
   </component>
   <component name="TemplatesService">
index 379775177efb73a0818aae608a4844dc8b5ede0b..bff547c68811ffc8d28aca733f5cd6cda7b9efdb 100644 (file)
@@ -4,7 +4,7 @@ django-braces==1.15.0
 django-crispy-forms==1.14.0
 djangorestframework==3.14.0
 djangorestframework-simplejwt==5.2.0
-mysqlclient==2.1.1
+#mysqlclient==2.1.1
 PyJWT==2.5.0
 pytz==2022.2.1
 sqlparse==0.4.3
diff --git a/sistema/datatables.py b/sistema/datatables.py
new file mode 100644 (file)
index 0000000..90f0e27
--- /dev/null
@@ -0,0 +1,193 @@
+from django_datatables_view.base_datatable_view import BaseDatatableView
+from django.utils.html import escape
+from django.db.models import Q
+
+from sistema.models import Localita, Multimedia, TipologiaMultimedia, Percorso, PointOfInterest, Feedback
+
+
+class LocalitaDatatables(BaseDatatableView):
+    model = Localita
+    columns = ['id', 'descrizione', 'provincia', 'cap', 'regione', 'mod', 'del']
+    order_columns = ['id', 'descrizione', 'provincia', 'cap', 'regione', '', '']
+
+    def get_initial_queryset(self):
+        return self.model.objects.filter(is_active=True)
+
+    def render_column(self, row, column):
+        if column == 'id':
+            return escape('{0}'.format(row.pk))
+        if column == 'descrizione':
+            return escape('{0}'.format(row.descrizione))
+        if column == 'provincia':
+            return escape('{0}'.format(row.provincia))
+        if column == 'cap':
+            return escape('{0}'.format(row.cap))
+        if column == 'regione':
+            return escape('{0}'.format(row.regione))
+        if column == 'mod':
+            return '<a class="btn btn-sm btn-primary" href="/mod_localita/%s/" ><i class="fas fa-edit"></i></a>' % row.pk
+        if column == 'del':
+            return '<button class="btn btn-sm btn-danger" onclick="DeleteLocalita(%s)"><i class="fas fa-trash"></i></button>' % row.pk
+        else:
+            return super(LocalitaDatatables, self).render_column(row, column)
+
+    def filter_queryset(self, qs):
+        search = self.request.GET.get('search[value]', None)
+        if search:
+            qs = qs.filter(Q(descrizione__icontains=search) | Q(provincia__icontains=search)
+                           | Q(cap__icontains=search) | Q(regione__icontains=search))
+        return qs
+
+
+class MultimediaDatatables(BaseDatatableView):
+    model = Multimedia
+    columns = ['id', 'tipologia', 'nome', 'descrizione', 'testo', 'mod', 'del']
+    order_columns = ['id', 'tipologia', 'nome', 'descrizione', 'testo', 'mod', 'del']
+
+    def get_initial_queryset(self):
+        return self.model.objects.filter(is_active=True)
+
+    def render_column(self, row, column):
+        if column == 'id':
+            return escape('{0}'.format(row.pk))
+        if column == 'tipologia':
+            return escape('{0}'.format(row.tipologia.nome))
+        if column == 'nome':
+            return escape('{0}'.format(row.provincia))
+        if column == 'descrizione':
+            return escape('{0}'.format(row.descrizione))
+        if column == 'testo':
+            return escape('{0}'.format(row.testo))
+        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
+        else:
+            return super(MultimediaDatatables, self).render_column(row, column)
+
+    def filter_queryset(self, qs):
+        search = self.request.GET.get('search[value]', None)
+        if search:
+            qs = qs.filter(Q(descrizione__icontains=search) | Q(nome__icontains=search)
+                           | Q(tipologia__nome__icontains=search))
+        return qs
+
+
+class TipoMultimediaDatatables(BaseDatatableView):
+    model = TipologiaMultimedia
+    columns = ['id', 'nome', 'mod', 'del']
+    order_columns = ['id', 'nome', 'mod', 'del']
+
+    def get_initial_queryset(self):
+        return self.model.objects.filter(is_active=True)
+
+    def render_column(self, row, column):
+        if column == 'id':
+            return escape('{0}'.format(row.pk))
+        if column == 'nome':
+            return escape('{0}'.format(row.nome))
+        if column == 'mod':
+            return '<a class="btn btn-sm btn-primary" href="/mod_tipo_multimedia/%s/" ><i class="fas fa-edit"></i></a>' % row.pk
+        if column == 'del':
+            return '<button class="btn btn-sm btn-danger" onclick="DeleteTipologia(%s)"><i class="fas fa-trash"></i></button>' % row.pk
+        else:
+            return super(TipoMultimediaDatatables, self).render_column(row, column)
+
+    def filter_queryset(self, qs):
+        search = self.request.GET.get('search[value]', None)
+        if search:
+            qs = qs.filter(Q(nome__icontains=search))
+        return qs
+
+
+class PercorsoDatatables(BaseDatatableView):
+    model = Percorso
+    columns = ['id', 'nome', 'descrizione', 'testo', 'mod', 'del']
+    order_columns = ['id', 'nome', 'descrizione', 'testo', 'mod', 'del']
+
+    def get_initial_queryset(self):
+        return self.model.objects.filter(is_active=True)
+
+    def render_column(self, row, column):
+        if column == 'id':
+            return escape('{0}'.format(row.pk))
+        if column == 'nome':
+            return escape('{0}'.format(row.nome))
+        if column == 'descrizione':
+            return escape('{0}'.format(row.descrizione))
+        if column == 'testo':
+            return escape('{0}'.format(row.testo))
+        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
+        else:
+            return super(PercorsoDatatables, self).render_column(row, column)
+
+    def filter_queryset(self, qs):
+        search = self.request.GET.get('search[value]', None)
+        if search:
+            qs = qs.filter(Q(nome__icontains=search) | Q(descrizione__icontains=search) | Q(testo__icontains=search))
+        return qs
+
+
+class PoiDatatables(BaseDatatableView):
+    model = PointOfInterest
+    columns = ['id', 'nome', 'lat', 'long', 'mod', 'del']
+    order_columns = ['id', 'nome', 'lat', 'long', 'mod', 'del']
+
+    def get_initial_queryset(self):
+        return self.model.objects.filter(is_active=True)
+
+    def render_column(self, row, column):
+        if column == 'id':
+            return escape('{0}'.format(row.pk))
+        if column == 'nome':
+            return escape('{0}'.format(row.nome))
+        if column == 'lat':
+            return escape('{0}'.format(row.lat))
+        if column == 'long':
+            return escape('{0}'.format(row.long))
+        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
+        else:
+            return super(PoiDatatables, self).render_column(row, column)
+
+    def filter_queryset(self, qs):
+        search = self.request.GET.get('search[value]', None)
+        if search:
+            qs = qs.filter(Q(nome__icontains=search) | Q(lat__icontains=search) | Q(long__icontains=search))
+        return qs
+
+
+class FeedbackDatatables(BaseDatatableView):
+    model = Feedback
+    columns = ['id', 'utente', 'valutazione', 'commento', 'mod', 'del']
+    order_columns = ['id', 'utente', 'valutazione', 'commento', 'mod', 'del']
+
+    def get_initial_queryset(self):
+        return self.model.objects.filter(is_active=True)
+
+    def render_column(self, row, column):
+        if column == 'id':
+            return escape('{0}'.format(row.pk))
+        if column == 'utente':
+            return escape('{0}'.format(row.utente.username))
+        if column == 'valutazione':
+            return escape('{0}'.format(row.valutazione))
+        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
+        else:
+            return super(FeedbackDatatables, self).render_column(row, column)
+
+    def filter_queryset(self, qs):
+        search = self.request.GET.get('search[value]', None)
+        if search:
+            qs = qs.filter(Q(utente__icontains=search) | Q(valutazione__icontains=search))
+        return qs
\ No newline at end of file
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..df266eac6e2c3008003a80c200db160ef02c0fef 100644 (file)
@@ -0,0 +1,48 @@
+from django.contrib.auth.forms import *
+
+from sistema.models import Localita, TipologiaMultimedia
+
+
+class LocalitaForm(forms.ModelForm):
+    class Meta:
+        model = Localita
+        exclude = ('is_active',)
+
+    descrizione = forms.CharField(
+        label="Nome",
+        max_length=255,
+        widget=forms.TextInput(attrs={'class': 'form-control', 'form': 'localita_form'})
+    )
+
+    provincia = forms.CharField(
+        label="Provincia",
+        max_length=20,
+        widget=forms.TextInput(attrs={'class': 'form-control', 'form': 'localita_form'})
+    )
+
+    cap = forms.CharField(
+        label="Cap",
+        max_length=10,
+        widget=forms.TextInput(attrs={'class': 'form-control', 'form': 'localita_form'})
+    )
+
+    regione = forms.CharField(
+        label="Regione",
+        max_length=50,
+        widget=forms.TextInput(attrs={'class': 'form-control', 'form': 'localita_form'})
+    )
+
+    def __init__(self, *args, **kwargs):
+        super().__init__(*args, **kwargs)
+
+
+class TipoMultimediaForm(forms.ModelForm):
+    class Meta:
+        model = TipologiaMultimedia
+        exclude = ('is_active',)
+
+    nome = forms.CharField(
+        label="Nome tipologia",
+        max_length=255,
+        widget=forms.TextInput(attrs={'class': 'form-control', 'form': 'tipo_multimedia_form'})
+    )
\ No newline at end of file
index ec42a5dd079bd3ed3cd802fbd366625feacb6ee6..a6f9a9815241e13dabb66344b0e9da365477dedd 100644 (file)
@@ -5,9 +5,9 @@ from django.utils import timezone
 
 class Localita(models.Model):
     descrizione = models.CharField(max_length=255, null=False)
-    provincia = models.CharField(max_length=5, null=True, blank=True)
-    cap = models.CharField(max_length=5, null=True, blank=True)
-    regione = models.CharField(max_length=5, null=True, blank=True)
+    provincia = models.CharField(max_length=50, null=True, blank=True)
+    cap = models.CharField(max_length=10, null=True, blank=True)
+    regione = models.CharField(max_length=50, null=True, blank=True)
     is_active = models.BooleanField(default=True)
 
 
@@ -16,28 +16,33 @@ class Gestisce(models.Model):
     localita = models.ForeignKey(Localita, on_delete=models.DO_NOTHING)
     data_inizio = models.DateTimeField(auto_now_add=False, default=timezone.now, null=True, blank=True)
     data_fine = models.DateTimeField(null=True, blank=True)
+    is_active = models.BooleanField(default=True)
 
 
 class Percorso(models.Model):
     nome = models.CharField(max_length=255, null=False)
     descrizione = models.CharField(max_length=255, null=False)
     testo = models.TextField(max_length=255, null=False)
+    is_active = models.BooleanField(default=True)
 
 
 class PointOfInterest(models.Model):
     nome = models.CharField(max_length=255, null=False)
     lat = models.FloatField()
     long = models.FloatField()
+    is_active = models.BooleanField(default=True)
 
 
 class Tappa(models.Model):
     percorso = models.ForeignKey(Percorso, on_delete=models.DO_NOTHING)
     poi = models.ForeignKey(PointOfInterest, on_delete=models.DO_NOTHING)
     ordine = models.IntegerField()
+    is_active = models.BooleanField(default=True)
 
 
 class TipologiaMultimedia(models.Model):
     nome = models.CharField(max_length=255, null=False)
+    is_active = models.BooleanField(default=True)
 
 
 class Multimedia(models.Model):
@@ -46,9 +51,12 @@ class Multimedia(models.Model):
     nome = models.CharField(max_length=255, null=False)
     descrizione = models.CharField(max_length=255, null=False)
     testo = models.TextField(max_length=255, null=False)
+    is_active = models.BooleanField(default=True)
 
 
 class Feedback(models.Model):
     utente = models.ForeignKey(User, on_delete=models.DO_NOTHING)
     percorso = models.ForeignKey(Percorso, on_delete=models.DO_NOTHING)
     valutazione = models.IntegerField()
+    commento = models.TextField(max_length=255, null=True, blank=True)
+    is_active = models.BooleanField(default=True)
diff --git a/sistema/templates/add_mod_localita.html b/sistema/templates/add_mod_localita.html
new file mode 100644 (file)
index 0000000..4db31d8
--- /dev/null
@@ -0,0 +1,44 @@
+{% extends 'base.html' %}
+{% load static %}
+{% load crispy_forms_tags %}
+{% block content %}
+
+    <div class="row">
+        <div class="col-12 col-md-12 col-lg-12">
+            <h1 class="line-bolle"><i class="fa-solid fa-tree-city clr-bolle mr-2" aria-hidden="true"></i> Gestione località </h1>
+            <div class="card">
+                <div class="card-header">
+                    {% if form.instance.pk %}
+                    <h4 class="clr-config">Modifica la località #{{ form.instance.pk }}</h4>
+                    {% else %}
+                    <h4 class="clr-config">Registra una nuova località nel sistema</h4>
+                    {% endif %}
+                </div>
+
+                <div class="card-body">
+                    <form method="POST" id="localita_form" action="{% url 'sistema:localita' %}">{% csrf_token %}
+                        {% if form.instance.pk %}
+                            <input type="hidden" name="mod" form="localita_form">
+                            <input type="hidden" name="pk" value="{{ form.instance.pk }}" form="localita_form">
+                        {% endif %}
+                            {{form | crispy }}
+                            <br>
+                        <div class="card-footer text-right">
+                            <button class="btn btn-primary" type="button" onclick="javascript:this.form.submit();"><i class="fas fa-save" aria-hidden="true"></i> Salva
+                            </button>
+                        </div>
+
+                    </form>
+                </div>
+
+            </div>
+        </div>
+    </div>
+
+
+    <script>
+
+    </script>
+
+
+{% endblock %}
\ No newline at end of file
diff --git a/sistema/templates/add_mod_tipologia.html b/sistema/templates/add_mod_tipologia.html
new file mode 100644 (file)
index 0000000..f66fed5
--- /dev/null
@@ -0,0 +1,44 @@
+{% extends 'base.html' %}
+{% load static %}
+{% load crispy_forms_tags %}
+{% block content %}
+
+    <div class="row">
+        <div class="col-12 col-md-12 col-lg-12">
+            <h1 class="line-bolle"><i class="fa-solid fa-cogs clr-bolle mr-2" aria-hidden="true"></i> Tipologia multimedia </h1>
+            <div class="card">
+                <div class="card-header">
+                    {% if form.instance.pk %}
+                    <h4 class="clr-config">Modifica la tipologia #{{ form.instance.pk }}</h4>
+                    {% else %}
+                    <h4 class="clr-config">Registra una nuova tipologia di multimedia nel sistema</h4>
+                    {% endif %}
+                </div>
+
+                <div class="card-body">
+                    <form method="POST" id="tipo_multimedia_form" action="{% url 'sistema:tipo_multimedia' %}">{% csrf_token %}
+                        {% if form.instance.pk %}
+                            <input type="hidden" name="mod" form="tipo_multimedia_form">
+                            <input type="hidden" name="pk" value="{{ form.instance.pk }}" form="tipo_multimedia_form">
+                        {% endif %}
+                            {{form | crispy }}
+                            <br>
+                        <div class="card-footer text-right">
+                            <button class="btn btn-primary" type="button" onclick="javascript:this.form.submit();"><i class="fas fa-save" aria-hidden="true"></i> Salva
+                            </button>
+                        </div>
+
+                    </form>
+                </div>
+
+            </div>
+        </div>
+    </div>
+
+
+    <script>
+
+    </script>
+
+
+{% endblock %}
\ No newline at end of file
index caf29b5326faa5fec064f2b370a8c281251b9e14..5b94b5075b3418667d4c5e503e698b73230cd7cb 100644 (file)
                 </div>
                 <ul class="sidebar-menu mt-3">
                     <li class="dropdown voce_menu active" id="home">
-                        <a href="#" class="nav-link color-home">
+                        <a href="{% url 'sistema:home' %}" class="nav-link color-home">
                             <i class="fa-solid fa-house"></i><span>Home</span></a>
                     </li>
 
-                    <li class="menu-header">Piattaforma</li>
-                    <li class="dropdown voce_menu" id="clienti-fornitori-menu">
-                        <a href="#" class="nav-link color-clients">
-                            <i class="fa-solid fa-people-carry-box"></i><span>Clienti / Fornitori</span></a>
+                    <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="#" class="nav-link color-dipendenti">
-                            <i class="fa-solid fa-users"></i><span>Dipendenti</span></a>
+                        <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>
+                            <li><a class="nav-link" href="#">Multimedia</a></li>
+                        </ul>
+                    </li>
+
+                    <li class="dropdown voce_menu" id="poi-menu">
+                        <a href="#" class="nav-link color-listini">
+                            <i class="fa-solid fa-route"></i><span>Percorsi</span></a>
                     </li>
                 </ul>
             </aside>
index 97bab53461ec9f4c0a96cac96dacc208e458c34f..b3bc64afe4143ab2b29f6d6b0bc61581c5ed5408 100644 (file)
@@ -1,5 +1,5 @@
 {% extends 'base.html' %}
 {% load static %}
 {% block content %}
-    CIAO
+    CIAO, {{ request.session.roles }}
 {% endblock %}
\ No newline at end of file
diff --git a/sistema/templates/localita_list.html b/sistema/templates/localita_list.html
new file mode 100644 (file)
index 0000000..1e597f1
--- /dev/null
@@ -0,0 +1,105 @@
+{% extends 'base.html' %}
+{% load static %}
+{% block content %}
+    <div class="row">
+        <div class="col-12">
+            <h1 class="line-bolle"><i class="fa-solid fa-tree-city clr-bolle mr-2" aria-hidden="true"></i> Gestione località </h1>
+
+            <div class="card">
+                <div class="card-header justify-content-between">
+                    <h4 class="clr-bolle">Lista località</h4>
+                    <a href="{% url 'sistema:localita' %}">
+                       <button class="btn-sm btn-primary"><i class="fa-solid fa-plus"></i>  Aggiungi una nuova località</button>
+                    </a>
+                </div>
+
+                <div class="card-body">
+                    <div class="row">
+                        <div class="table-responsive">
+                            <table id="localita-table"
+                                   class="table table-sm table-bordered table-striped dataTables_wrapper dt-bootstrap4 no-footer" style="width: 100% !important;">
+                                <thead>
+                                <tr>
+                                    <th>#</th>
+                                    <th>Nome</th>
+                                    <th>Provincia</th>
+                                    <th>Cap</th>
+                                    <th>Regione</th>
+                                    <th></th>
+                                    <th></th>
+                                </tr>
+                                </thead>
+                                <tbody>
+                                </tbody>
+                            </table>
+                        </div>
+                    </div>
+                </div>
+            </div>
+
+        </div>
+    </div>
+
+    <script>
+        $(document).ready(function () {
+            $('#localita-table').dataTable({
+                processing: true,
+                serverSide: true,
+                ajax: {
+                    "url": "{% url 'sistema:localita_datatables' %}",
+                    "type": 'GET',
+                },
+                language: {
+                    url: "//cdn.datatables.net/plug-ins/1.10.20/i18n/Italian.json"
+                },
+                columnDefs: [
+                        {"targets": 5, "orderable": false, "width": "5%"},
+                        {"targets": 6, "orderable": false, "width": "5%"},
+                ],
+                "order": []
+            });
+        });
+
+        function DeleteLocalita(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:localita' %}',
+                        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'
+                    )
+                }
+            });
+        }
+
+    </script>
+{% endblock %}
\ No newline at end of file
diff --git a/sistema/templates/multimedia_list.html b/sistema/templates/multimedia_list.html
new file mode 100644 (file)
index 0000000..3b909ef
--- /dev/null
@@ -0,0 +1,63 @@
+{% extends 'base.html' %}
+{% load static %}
+{% block content %}
+    <div class="row">
+        <div class="col-12">
+            <h1 class="line-bolle"><i class="fa-solid fa-photo-film clr-bolle mr-2" aria-hidden="true"></i> Gestione multimedia </h1>
+
+            <div class="card">
+                <div class="card-header justify-content-between">
+                    <h4 class="clr-bolle">Lista multimedia</h4>
+                    <a href="#">
+                       <button class="btn-sm btn-primary"><i class="fa-solid fa-plus"></i>  Aggiungi una multimedia</button>
+                    </a>
+                </div>
+
+                <div class="card-body">
+                    <div class="row">
+                        <div class="table-responsive">
+                            <table id="multimedia-table"
+                                   class="table table-sm table-bordered table-striped dataTables_wrapper dt-bootstrap4 no-footer" style="width: 100% !important;">
+                                <thead>
+                                <tr>
+                                    <th>#</th>
+                                    <th>Tipologia</th>
+                                    <th>Nome</th>
+                                    <th>Descrizione</th>
+                                    <th>Testo</th>
+                                    <th></th>
+                                    <th></th>
+                                </tr>
+                                </thead>
+                                <tbody>
+                                </tbody>
+                            </table>
+                        </div>
+                    </div>
+                </div>
+            </div>
+
+        </div>
+    </div>
+
+    <script>
+        $(document).ready(function () {
+            $('#multimedia-table').dataTable({
+                processing: true,
+                serverSide: true,
+                ajax: {
+                    "url": "{% url 'utenti:user_datatables' %}",
+                    "type": 'GET',
+                },
+                language: {
+                    url: "//cdn.datatables.net/plug-ins/1.10.20/i18n/Italian.json"
+                },
+                columnDefs: [
+                        {"targets": 5, "orderable": false},
+                        {"targets": 6, "orderable": false},
+                ],
+                "order": []
+            });
+        });
+    </script>
+{% endblock %}
\ No newline at end of file
diff --git a/sistema/templates/percorsi_list.html b/sistema/templates/percorsi_list.html
new file mode 100644 (file)
index 0000000..566549b
--- /dev/null
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>Title</title>
+</head>
+<body>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/sistema/templates/poi_list.html b/sistema/templates/poi_list.html
new file mode 100644 (file)
index 0000000..42fb6da
--- /dev/null
@@ -0,0 +1,104 @@
+{% extends 'base.html' %}
+{% load static %}
+{% block content %}
+    <div class="row">
+        <div class="col-12">
+            <h1 class="line-bolle"><i class="fa-solid fa-location-dot clr-bolle mr-2" aria-hidden="true"></i> Gestione punti di interesse </h1>
+
+            <div class="card">
+                <div class="card-header justify-content-between">
+                    <h4 class="clr-bolle">Lista punti di interesse</h4>
+                    <a href="{% url 'sistema:poi' %}">
+                       <button class="btn-sm btn-primary"><i class="fa-solid fa-plus"></i>  Aggiungi una nuovo punto di interesse</button>
+                    </a>
+                </div>
+
+                <div class="card-body">
+                    <div class="row">
+                        <div class="table-responsive">
+                            <table id="poi-table"
+                                   class="table table-sm table-bordered table-striped dataTables_wrapper dt-bootstrap4 no-footer" style="width: 100% !important;">
+                                <thead>
+                                <tr>
+                                    <th>#</th>
+                                    <th>Nome</th>
+                                    <th>Latitudine</th>
+                                    <th>Longitudine</th>
+                                    <th></th>
+                                    <th></th>
+                                </tr>
+                                </thead>
+                                <tbody>
+                                </tbody>
+                            </table>
+                        </div>
+                    </div>
+                </div>
+            </div>
+
+        </div>
+    </div>
+
+    <script>
+        $(document).ready(function () {
+            $('#poi-table').dataTable({
+                processing: true,
+                serverSide: true,
+                ajax: {
+                    "url": "{% url 'sistema:poi_datatables' %}",
+                    "type": 'GET',
+                },
+                language: {
+                    url: "//cdn.datatables.net/plug-ins/1.10.20/i18n/Italian.json"
+                },
+                columnDefs: [
+                        {"targets": 4, "orderable": false, "width": "5%"},
+                        {"targets": 5, "orderable": false, "width": "5%"},
+                ],
+                "order": []
+            });
+        });
+
+        function DeletePoi(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:poi' %}',
+                        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'
+                    )
+                }
+            });
+        }
+
+    </script>
+{% endblock %}
\ No newline at end of file
diff --git a/sistema/templates/tipo_multimedia_list.html b/sistema/templates/tipo_multimedia_list.html
new file mode 100644 (file)
index 0000000..2002b6f
--- /dev/null
@@ -0,0 +1,102 @@
+{% extends 'base.html' %}
+{% load static %}
+{% block content %}
+    <div class="row">
+        <div class="col-12">
+            <h1 class="line-bolle"><i class="fa-solid fa-cogs clr-bolle mr-2" aria-hidden="true"></i> Gestione tipologia multimedia </h1>
+
+            <div class="card">
+                <div class="card-header justify-content-between">
+                    <h4 class="clr-bolle">Lista tipologie di multimedia</h4>
+                    <a href="{% url 'sistema:tipo_multimedia' %}">
+                       <button class="btn-sm btn-primary"><i class="fa-solid fa-plus"></i>  Aggiungi una nuova tipologia</button>
+                    </a>
+                </div>
+
+                <div class="card-body">
+                    <div class="row">
+                        <div class="table-responsive">
+                            <table id="tipo_multimedia-table"
+                                   class="table table-sm table-bordered table-striped dataTables_wrapper dt-bootstrap4 no-footer" style="width: 100% !important;">
+                                <thead>
+                                <tr>
+                                    <th>#</th>
+                                    <th>Nome</th>
+                                    <th></th>
+                                    <th></th>
+                                </tr>
+                                </thead>
+                                <tbody>
+                                </tbody>
+                            </table>
+                        </div>
+                    </div>
+                </div>
+            </div>
+
+        </div>
+    </div>
+
+    <script>
+        $(document).ready(function () {
+            $('#tipo_multimedia-table').dataTable({
+                processing: true,
+                serverSide: true,
+                ajax: {
+                    "url": "{% url 'sistema:tipo_multimedia_datatables' %}",
+                    "type": 'GET',
+                },
+                language: {
+                    url: "//cdn.datatables.net/plug-ins/1.10.20/i18n/Italian.json"
+                },
+                columnDefs: [
+                        {"targets": 2, "orderable": false, "width": "5%"},
+                        {"targets": 3, "orderable": false, "width": "5%"},
+                ],
+                "order": []
+            });
+        });
+
+        function DeleteTipologia(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:tipo_multimedia' %}',
+                        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'
+                    )
+                }
+            });
+        }
+
+    </script>
+{% endblock %}
\ No newline at end of file
index 2b04ed4f4b03457307f0210ca8bd7d2b0c8b3944..625b6aa804fd19fc13e5567a8f563d15cbee8188 100644 (file)
@@ -1,7 +1,39 @@
 from django.urls import path
 
-from sistema.views import Home
+from sistema.datatables import LocalitaDatatables, MultimediaDatatables, TipoMultimediaDatatables, PercorsoDatatables, \
+    PoiDatatables, FeedbackDatatables
+from sistema.views import Home, LocalitaListView, MultimediaListView, PuntiInteresseListView, \
+    TipologiaMultimediaListView, PercorsiListView, LocalitaView, TipoMultimediaView, PoiView
 
 urlpatterns = [
-    path('home/', Home.as_view(), name='home'),
+    path('', Home.as_view(), name='home'),
+
+    ## TEMPLATEVIEWS ##
+    path('localita_list/', LocalitaListView.as_view(), name='localita_list'),
+    path('multimedia_list/', MultimediaListView.as_view(), name='multimedia_list'),
+    path('poi_list/', PuntiInteresseListView.as_view(), name='poi_list'),
+    path('tipo_multimedia_list/', TipologiaMultimediaListView.as_view(), name='tipo_multimedia_list'),
+    path('percorsi_list/', PercorsiListView.as_view(), name='percorsi_list'),
+
+    ## DATATABLES ##
+    path('localita_datatables/', LocalitaDatatables.as_view(), name='localita_datatables'),
+    path('multimedia_datatables/', MultimediaDatatables.as_view(), name='multimedia_datatables'),
+    path('tipo_multimedia_datatables/', TipoMultimediaDatatables.as_view(), name='tipo_multimedia_datatables'),
+    path('percorso_datatables/', PercorsoDatatables.as_view(), name='percorso_datatables'),
+    path('poi_datatables/', PoiDatatables.as_view(), name='poi_datatables'),
+    path('feedback_datatables/', FeedbackDatatables.as_view(), name='feedback_datatables'),
+
+    ## LOCALITA ##
+    path('localita/', LocalitaView.as_view(), name='localita'),
+    path('mod_localita/<int:pk>/', LocalitaView.as_view(), name='mod_localita'),
+
+    ## TIPOLOGIA MODALITA ##
+    path('tipo_multimedia/', TipoMultimediaView.as_view(), name='tipo_multimedia'),
+    path('mod_tipo_multimedia/<int:pk>/', TipoMultimediaView.as_view(), name='mod_tipo_multimedia'),
+
+    ## PUNTO DI INTERESSE ##
+    path('poi/', PoiView.as_view(), name='poi'),
+    path('mod_poi/<int:pk>/', PoiView.as_view(), name='mod_poi'),
+
+
 ]
index 02645f11e79a01dcfe0bd3085ca8f5037300e8c6..67cce9d08fc4df2f01a4f734a958f1faa1aceea5 100644 (file)
@@ -1,9 +1,183 @@
-from django.shortcuts import render
+from django.contrib import messages
+from django.http import JsonResponse
+from django.shortcuts import render, redirect
+from django.urls import reverse
 from django.views import View
+from django.views.generic import TemplateView
+from rest_framework import status
 
+from sistema.forms import LocalitaForm, TipoMultimediaForm
+from sistema.models import Localita, TipologiaMultimedia
 from utenti.mixins import CustomLoginRequiredMixin
 
 
-class Home(View):#CustomLoginRequiredMixin
+class LocalitaListView(TemplateView):
+    template_name = 'localita_list.html'
+
+
+class PuntiInteresseListView(TemplateView):
+    template_name = 'poi_list.html'
+
+
+class TipologiaMultimediaListView(TemplateView):
+    template_name = 'tipo_multimedia_list.html'
+
+
+class MultimediaListView(TemplateView):
+    template_name = 'multimedia_list.html'
+
+
+class PercorsiListView(TemplateView):
+    template_name = 'percorsi_list.html'
+
+
+class Home(View):  # CustomLoginRequiredMixin
     def get(self, request):
         return render(request, 'home.html', {})
+
+
+class LocalitaView(View):
+    def add_localita(self, request):
+        form = LocalitaForm(request.POST)
+        if form.is_valid():
+            form.save()
+
+            messages.add_message(request, messages.INFO, 'Nuova località inserita con successo.')
+        else:
+            errors = ''
+            for err in form.errors.as_data():
+                errors += '<li>' + err + '</li>'
+            messages.add_message(request, messages.ERROR, 'Errore nell\'inserimento della località. Controlla il form.')
+
+    def mod_localita(self, request):
+        form = LocalitaForm(request.POST, instance=Localita.objects.get(pk=int(self.request.POST.get('pk'))))
+        if form.is_valid():
+            form.save()
+
+            messages.add_message(request, messages.INFO, 'Località aggiornata con successo.')
+        else:
+            errors = ''
+            for err in form.errors.as_data():
+                errors += '<li>' + err + '</li>'
+            messages.add_message(request, messages.ERROR, 'Errore nell\'aggiornamento della località. Controlla il form.')
+
+    def del_localita(self, request):
+        localita = Localita.objects.get(pk=int(request.GET.get('pk')))
+        localita.is_active = False
+        localita.save()
+
+    def get(self, request, *args, **kwargs):
+        if request.GET.get('method') == 'del':
+            self.del_localita(request)
+
+            return JsonResponse({'response': 'Località eliminata con successo'}, status=status.HTTP_200_OK)
+        elif 'pk' in kwargs:
+            return render(request, 'add_mod_localita.html', {'form': LocalitaForm(instance=Localita.objects.get(pk=int(self.kwargs['pk'])))})
+        else:
+            return render(request, 'add_mod_localita.html', {'form': LocalitaForm()})
+
+    def post(self, request, *args, **kwargs):
+        if 'mod' in request.POST:
+            self.mod_localita(request)
+        else:
+            self.add_localita(request)
+
+        return redirect(reverse('sistema:localita_list'))
+
+
+class TipoMultimediaView(View):
+    def add_tipologia(self, request):
+        form = TipoMultimediaForm(request.POST)
+        if form.is_valid():
+            form.save()
+
+            messages.add_message(request, messages.INFO, 'Nuova tipologia inserita con successo.')
+        else:
+            errors = ''
+            for err in form.errors.as_data():
+                errors += '<li>' + err + '</li>'
+            messages.add_message(request, messages.ERROR, 'Errore nell\'inserimento della tipologia. Controlla il form.')
+
+    def mod_tipologia(self, request):
+        form = TipoMultimediaForm(request.POST, instance=TipologiaMultimedia.objects.get(pk=int(self.request.POST.get('pk'))))
+        if form.is_valid():
+            form.save()
+
+            messages.add_message(request, messages.INFO, 'Tipologia aggiornata con successo.')
+        else:
+            errors = ''
+            for err in form.errors.as_data():
+                errors += '<li>' + err + '</li>'
+            messages.add_message(request, messages.ERROR, 'Errore nell\'aggiornamento della tipologia. Controlla il form.')
+
+    def del_tipologia(self, request):
+        tipologia = TipologiaMultimedia.objects.get(pk=int(request.GET.get('pk')))
+        tipologia.is_active = False
+        tipologia.save()
+
+    def get(self, request, *args, **kwargs):
+        if request.GET.get('method') == 'del':
+            self.del_tipologia(request)
+
+            return JsonResponse({'response': 'Tipologia eliminata con successo'}, status=status.HTTP_200_OK)
+        elif 'pk' in kwargs:
+            return render(request, 'add_mod_tipologia.html', {'form': TipoMultimediaForm(instance=TipologiaMultimedia.objects.get(pk=int(self.kwargs['pk'])))})
+        else:
+            return render(request, 'add_mod_tipologia.html', {'form': TipoMultimediaForm()})
+
+    def post(self, request, *args, **kwargs):
+        if 'mod' in request.POST:
+            self.mod_tipologia(request)
+        else:
+            self.add_tipologia(request)
+
+        return redirect(reverse('sistema:tipo_multimedia_list'))
+
+
+class PoiView(View):
+    def add_poi(self, request):
+        form = TipoMultimediaForm(request.POST)
+        if form.is_valid():
+            form.save()
+
+            messages.add_message(request, messages.INFO, 'Nuova punto di interesse inserito con successo.')
+        else:
+            errors = ''
+            for err in form.errors.as_data():
+                errors += '<li>' + err + '</li>'
+            messages.add_message(request, messages.ERROR, 'Errore nell\'inserimento del punto di interesse. Controlla il form.')
+
+    def mod_poi(self, request):
+        form = TipoMultimediaForm(request.POST, instance=TipologiaMultimedia.objects.get(pk=int(self.request.POST.get('pk'))))
+        if form.is_valid():
+            form.save()
+
+            messages.add_message(request, messages.INFO, 'Punto di interesse aggiornata con successo.')
+        else:
+            errors = ''
+            for err in form.errors.as_data():
+                errors += '<li>' + err + '</li>'
+            messages.add_message(request, messages.ERROR, 'Errore nell\'aggiornamento del punto di interesse. Controlla il form.')
+
+    def del_poi(self, request):
+        tipologia = TipologiaMultimedia.objects.get(pk=int(request.GET.get('pk')))
+        tipologia.is_active = False
+        tipologia.save()
+
+    def get(self, request, *args, **kwargs):
+        if request.GET.get('method') == 'del':
+            self.del_poi(request)
+
+            return JsonResponse({'response': 'Punto di interesse eliminato con successo'}, status=status.HTTP_200_OK)
+        elif 'pk' in kwargs:
+            return render(request, 'add_mod_tipologia.html', {'form': TipoMultimediaForm(instance=TipologiaMultimedia.objects.get(pk=int(self.kwargs['pk'])))})
+        else:
+            return render(request, 'add_mod_tipologia.html', {'form': TipoMultimediaForm()})
+
+    def post(self, request, *args, **kwargs):
+        if 'mod' in request.POST:
+            self.mod_poi(request)
+        else:
+            self.add_poi(request)
+
+        return redirect(reverse('sistema:tipo_multimedia_list'))
\ No newline at end of file
index 3e954069b0f92baf0bf2f894c5f2e3f930da1a08..f7d5f67a77b1d8279c29604a01bb1f59a131412d 100644 (file)
@@ -90,7 +90,7 @@ DATABASES = {
         'ENGINE': 'django.db.backends.mysql',
         'NAME': 'socoin_atlas',
         'USER': 'root',
-        'PASSWORD': "password",
+        'PASSWORD': "",
         'HOST': '127.0.0.1',  # Or an IP Address that your DB is hosted on
         'PORT': '3306',
         'AUTOCOMMIT': True,
@@ -146,6 +146,6 @@ STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]
 DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
 
 
-CLIENTI_GROUPS = 'CLIENTI'
+CLIENTI_GROUPS = 'CLIENTE'
 TOUR_OPERATOR_GROUPS = 'TOUR_OPERATOR'
 ADMIN_GROUPS = 'ADMIN'
\ No newline at end of file
diff --git a/utenti/datatables.py b/utenti/datatables.py
new file mode 100644 (file)
index 0000000..8f6d0a8
--- /dev/null
@@ -0,0 +1,52 @@
+from django.contrib.auth.models import User
+from django_datatables_view.base_datatable_view import BaseDatatableView
+from django.utils.html import escape
+from django.db.models import Q
+
+from socoin_atlas import settings
+
+
+class UserDatatables(BaseDatatableView):
+    model = User
+    columns = ['id', 'first_name', 'last_name', 'username', 'email', 'last_login', 'mod', 'del']
+    order_columns = ['id', 'first_name', 'last_name', 'username', 'email', 'last_login', '', '']
+
+    def get_initial_queryset(self):
+        role = self.request.GET.get('role')
+
+        if role:
+            if role == settings.ADMIN_GROUPS:
+                return self.model.objects.filter(groups__name=settings.ADMIN_GROUPS, is_active=True)
+            elif role == settings.TOUR_OPERATOR_GROUPS:
+                return self.model.objects.filter(groups__name=settings.TOUR_OPERATOR_GROUPS, is_active=True)
+            elif role == settings.CLIENTI_GROUPS:
+                return self.model.objects.filter(groups__name=settings.CLIENTI_GROUPS, is_active=True)
+            else:
+                return self.model.objects.none()
+
+    def render_column(self, row, column):
+        if column == 'id':
+            return escape('{0}'.format(row.pk))
+        if column == 'first_name':
+            return escape('{0}'.format(row.first_name))
+        if column == 'last_name':
+            return escape('{0}'.format(row.last_name))
+        if column == 'username':
+            return escape('{0}'.format(row.username))
+        if column == 'email':
+            return escape('{0}'.format(row.email) or '')
+        if column == 'last_login':
+            return escape('{0}'.format(row.last_login or ''))
+        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
+        else:
+            return super(UserDatatables, self).render_column(row, column)
+
+    def filter_queryset(self, qs):
+        search = self.request.GET.get('search[value]', None)
+        if search:
+            qs = qs.filter(Q(first_name__icontains=search) | Q(last_name__icontains=search)
+                           | Q(username__icontains=search) | Q(email__icontains=search))
+        return qs
\ No newline at end of file
index 74ed065998d16b88325b168cb3d7700811f78030..22c4b1d5800b1d3506b8ecda2c659d334edd38bd 100644 (file)
@@ -11,7 +11,7 @@ class FormLogin(forms.Form):
 class RegistrationForm(UserCreationForm):
     class Meta:
         model = User
-        fields = ['username', 'first_name', 'last_name', 'password1', 'password2']
+        fields = ['username', 'first_name', 'last_name', 'email', 'password1', 'password2']
 
     def save(self, commit=True):
         user = super().save(commit=False)
diff --git a/utenti/templates/admin_list.html b/utenti/templates/admin_list.html
new file mode 100644 (file)
index 0000000..d275f31
--- /dev/null
@@ -0,0 +1,65 @@
+{% extends 'base.html' %}
+{% load static %}
+{% block content %}
+    <div class="row">
+        <div class="col-12">
+            <h1 class="line-bolle"><i class="fa-solid fa-crown clr-bolle mr-2" aria-hidden="true"></i> Gestione amministratori</h1>
+
+            <div class="card">
+                <div class="card-header justify-content-between">
+                    <h4 class="clr-bolle">Lista amministratori</h4>
+                    <a href="#">
+                       <button class="btn-sm btn-primary"><i class="fa-solid fa-plus"></i>  Aggiungi un admin</button>
+                    </a>
+                </div>
+
+                <div class="card-body">
+                    <div class="row">
+                        <div class="table-responsive">
+                            <table id="admin-table"
+                                   class="table table-sm table-bordered table-striped dataTables_wrapper dt-bootstrap4 no-footer" style="width: 100% !important;">
+                                <thead>
+                                <tr>
+                                    <th>#</th>
+                                    <th>Nome</th>
+                                    <th>Cognome</th>
+                                    <th>Username</th>
+                                    <th>Email</th>
+                                    <th>Ultimo accesso</th>
+                                    <th></th>
+                                    <th></th>
+                                </tr>
+                                </thead>
+                                <tbody>
+                                </tbody>
+                            </table>
+                        </div>
+                    </div>
+                </div>
+            </div>
+
+        </div>
+    </div>
+
+    <script>
+        $(document).ready(function () {
+            $('#admin-table').dataTable({
+                processing: true,
+                serverSide: true,
+                ajax: {
+                    "url": "{% url 'utenti:user_datatables' %}",
+                    "type": 'GET',
+                    "data": {'role': 'ADMIN' },
+                },
+                language: {
+                    url: "//cdn.datatables.net/plug-ins/1.10.20/i18n/Italian.json"
+                },
+                columnDefs: [
+                        {"targets": 6, "orderable": false},
+                        {"targets": 7, "orderable": false},
+                ],
+                "order": []
+            });
+        });
+    </script>
+{% endblock %}
\ No newline at end of file
diff --git a/utenti/templates/clienti_list.html b/utenti/templates/clienti_list.html
new file mode 100644 (file)
index 0000000..05d2695
--- /dev/null
@@ -0,0 +1,65 @@
+{% extends 'base.html' %}
+{% load static %}
+{% block content %}
+    <div class="row">
+        <div class="col-12">
+            <h1 class="line-bolle"><i class="fa-solid fa-user clr-bolle mr-2" aria-hidden="true"></i> Gestione clienti</h1>
+
+            <div class="card">
+                <div class="card-header justify-content-between">
+                    <h4 class="clr-bolle">Lista clienti</h4>
+                    <a href="#">
+                       <button class="btn-sm btn-primary"><i class="fa-solid fa-plus"></i>  Aggiungi un nuovo cliente</button>
+                    </a>
+                </div>
+
+                <div class="card-body">
+                    <div class="row">
+                        <div class="table-responsive">
+                            <table id="cliente-table"
+                                   class="table table-sm table-bordered table-striped dataTables_wrapper dt-bootstrap4 no-footer" style="width: 100% !important;">
+                                <thead>
+                                <tr>
+                                    <th>#</th>
+                                    <th>Nome</th>
+                                    <th>Cognome</th>
+                                    <th>Username</th>
+                                    <th>Email</th>
+                                    <th>Ultimo accesso</th>
+                                    <th></th>
+                                    <th></th>
+                                </tr>
+                                </thead>
+                                <tbody>
+                                </tbody>
+                            </table>
+                        </div>
+                    </div>
+                </div>
+            </div>
+
+        </div>
+    </div>
+
+    <script>
+        $(document).ready(function () {
+            $('#cliente-table').dataTable({
+                processing: true,
+                serverSide: true,
+                ajax: {
+                    "url": "{% url 'utenti:user_datatables' %}",
+                    "type": 'GET',
+                    "data": {'role': 'CLIENTE' },
+                },
+                language: {
+                    url: "//cdn.datatables.net/plug-ins/1.10.20/i18n/Italian.json"
+                },
+                columnDefs: [
+                        {"targets": 6, "orderable": false},
+                        {"targets": 7, "orderable": false},
+                ],
+                "order": []
+            });
+        });
+    </script>
+{% endblock %}
\ No newline at end of file
diff --git a/utenti/templates/tour_operator_list.html b/utenti/templates/tour_operator_list.html
new file mode 100644 (file)
index 0000000..79a3890
--- /dev/null
@@ -0,0 +1,65 @@
+{% extends 'base.html' %}
+{% load static %}
+{% block content %}
+    <div class="row">
+        <div class="col-12">
+            <h1 class="line-bolle"><i class="fa-solid fa-handshake-angle clr-bolle mr-2" aria-hidden="true"></i> Gestione tour operator</h1>
+
+            <div class="card">
+                <div class="card-header justify-content-between">
+                    <h4 class="clr-bolle">Lista tour operator</h4>
+                    <a href="#">
+                       <button class="btn-sm btn-primary"><i class="fa-solid fa-plus"></i>  Aggiungi un nuovo tour operator</button>
+                    </a>
+                </div>
+
+                <div class="card-body">
+                    <div class="row">
+                        <div class="table-responsive">
+                            <table id="tour_operator-table"
+                                   class="table table-sm table-bordered table-striped dataTables_wrapper dt-bootstrap4 no-footer" style="width: 100% !important;">
+                                <thead>
+                                <tr>
+                                    <th>#</th>
+                                    <th>Nome</th>
+                                    <th>Cognome</th>
+                                    <th>Username</th>
+                                    <th>Email</th>
+                                    <th>Ultimo accesso</th>
+                                    <th></th>
+                                    <th></th>
+                                </tr>
+                                </thead>
+                                <tbody>
+                                </tbody>
+                            </table>
+                        </div>
+                    </div>
+                </div>
+            </div>
+
+        </div>
+    </div>
+
+    <script>
+        $(document).ready(function () {
+            $('#tour_operator-table').dataTable({
+                processing: true,
+                serverSide: true,
+                ajax: {
+                    "url": "{% url 'utenti:user_datatables' %}",
+                    "type": 'GET',
+                    "data": {'role': 'TOUR_OPERATOR' },
+                },
+                language: {
+                    url: "//cdn.datatables.net/plug-ins/1.10.20/i18n/Italian.json"
+                },
+                columnDefs: [
+                        {"targets": 6, "orderable": false},
+                        {"targets": 7, "orderable": false},
+                ],
+                "order": []
+            });
+        });
+    </script>
+{% endblock %}
\ No newline at end of file
index cb3104e142dca8aa83c2476e53fbc0fea2f79a54..7a3fd5acd7ebe302f932d5cbd567b55769f237ac 100644 (file)
@@ -3,7 +3,8 @@ from django.contrib import admin
 
 from django.contrib.auth import views as auth_views
 
-from utenti.views import Autentication, Logout, Register
+from utenti.datatables import UserDatatables
+from utenti.views import Autentication, Logout, Register, AdminListView, TourOperatorListView, ClientiListView
 
 urlpatterns = [
     path('accounts/', include('django.contrib.auth.urls')),
@@ -15,4 +16,13 @@ urlpatterns = [
     path('reset/done/', auth_views.PasswordResetCompleteView.as_view(template_name='registration/custom_password_reset_complete.html'),name='password_reset_complete'),
     path('register/', Register.as_view(), name='register'),
 
+    ## TEMPLATEVIEWS ##
+    path('admin_list/', AdminListView.as_view(), name='admin_list'),
+    path('touroperator_list/', TourOperatorListView.as_view(), name='touroperator_list'),
+    path('clienti_list/', ClientiListView.as_view(), name='clienti_list'),
+
+    ## DATATABLES ##
+    path('user_datatables/', UserDatatables.as_view(), name='user_datatables'),
+
+
 ]
\ No newline at end of file
index 9c22438af4600cadaf8932990e1d54d6ac97db03..7eea356ea019b5ea9a09fe4d5b64010c1cf5d1a8 100644 (file)
@@ -3,6 +3,7 @@ from django.shortcuts import render, redirect
 from django.views import View
 from django.contrib import messages
 from django.contrib.auth import login, authenticate, logout
+from django.views.generic import TemplateView
 
 from utenti.forms import FormLogin, RegistrationForm
 
@@ -62,9 +63,26 @@ class Register(View):
             form.save()
             return redirect('utenti:login')
         else:
-            messages.error(request, 'Please correct form and try again')
+            errors = ''
+            for err in form.errors.as_data():
+                errors += '<li>' + err + '</li>'
+
+            messages.error(request, errors)
             form = RegistrationForm()
 
+            return redirect('utenti:register')
+
+
+class AdminListView(TemplateView):
+    template_name = 'admin_list.html'
+
+
+class TourOperatorListView(TemplateView):
+    template_name = 'tour_operator_list.html'
+
+
+class ClientiListView(TemplateView):
+    template_name = 'clienti_list.html'
 
 # from braces.views import GroupRequiredMixin
 # class SomeProtectedView(GroupRequiredMixin, TemplateView):