aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrea Lepori <aleporia@gmail.com>2023-07-24 18:31:02 +0200
committerAndrea Lepori <aleporia@gmail.com>2023-07-24 18:31:03 +0200
commit0de1f0a309c62a9e6dd9eb48e38b32c552e09c6c (patch)
treeabf8cbe64e242ffd7d29bfc9ae733531cee72891
parentimprove index show multiple peoples (diff)
downloadscout-subs-0de1f0a309c62a9e6dd9eb48e38b32c552e09c6c.tar.gz
scout-subs-0de1f0a309c62a9e6dd9eb48e38b32c552e09c6c.zip
create new persons and edit
-rw-r--r--accounts/templates/accounts/user_edit.html592
-rw-r--r--accounts/urls.py1
-rw-r--r--accounts/views.py399
-rw-r--r--client/templates/client/index.html14
-rw-r--r--templates/registration/base_admin.html4
-rw-r--r--templates/registration/base_client.html4
-rw-r--r--version.txt2
7 files changed, 1009 insertions, 7 deletions
diff --git a/accounts/templates/accounts/user_edit.html b/accounts/templates/accounts/user_edit.html
new file mode 100644
index 0000000..21e3ed8
--- /dev/null
+++ b/accounts/templates/accounts/user_edit.html
@@ -0,0 +1,592 @@
+{% extends 'registration/base_client.html' %}
+{% load static %}
+
+{% block title %}Modifica persona{% endblock %}
+
+{% block breadcrumb %}
+ <a class="breadcrumb hide-on-med-and-down">Persona</a>
+{% endblock %}
+
+{% block content %}
+<div class="tap-target {{color}}" data-target="home_btn">
+ <div class="tap-target-content">
+ <h5 style="color:white">Continua l'attivazione</h5>
+ <p style="color:white">Usa questo pulsante per tornare alla home e continuare il processo d'attivazione</p>
+ </div>
+</div>
+
+<form action="{% url 'edit_user' code=ucode %}?saved=true" method="post" id="form1" enctype="multipart/form-data">
+<div id="personal" class="row">
+ <div class="col l8 offset-l2 s12">
+ <div class="card-panel">
+ <div class="row">
+ <div class="col 12">
+ <input type="hidden" name="action" id="action">
+ <input type="hidden" name="delete_vac" id="delete_vac">
+ <input type="hidden" name="delete_health" id="delete_health">
+ {% csrf_token %}
+ <div class="row">
+ <div class="input-field col l4 s12">
+ <input name="first_name" value="{{first_name}}" id="first_name" type="text" {{validation_dic.first_name|safe}} {{midata_disable}}>
+ <label for="first_name">Nome</label>
+ <span class="helper-text" data-error="Campo richiesto"></span>
+ </div>
+ <div class="input-field col l4 s12">
+ <input name="last_name" value="{{last_name}}" id="last_name" type="text" {{validation_dic.last_name|safe}} {{midata_disable}}>
+ <label for="last_name">Cognome</label>
+ <span class="helper-text" data-error="Campo richiesto"></span>
+ </div>
+ <div class="input-field col l4 s12">
+ <input name="birth_date" value="{{birth_date}}" id="birth_date" type="text" {{validation_dic.birth_date|safe}} {{midata_disable}}>
+ <label for="birth_date">Data di nascita</label>
+ <span class="helper-text" data-error="Campo richiesto"></span>
+ </div>
+ </div>
+ <div class="row">
+ <div class="input-field col l4 s12">
+ <select name="branca" disabled>
+ <option value="" disabled {{branca_default}}>Nessuna</option>
+ <option value="diga" {{branca_castorini}}>Castorini</option>
+ <option value="muta" {{branca_lupetti}}>Lupetti</option>
+ <option value="reparto" {{branca_esploratori}}>Esploratori</option>
+ <option value="posto" {{branca_pionieri}}>Pionieri</option>
+ <option value="clan" {{branca_rover}}>Rover</option>
+ </select>
+ <label>Branca (campo non modificabile)</label>
+ </div>
+ <div class="input-field col l4 s12">
+ <input value="{{parent_name}}" name="parent_name" id="parent_name" type="text" {{validation_dic.parent_name|safe}}>
+ <label for="parent_name">Nome dei genitori</label>
+ <span class="helper-text" data-error="Campo richiesto"></span>
+ </div>
+ <div class="input-field col l4 s12">
+ <input value="{{avs_number}}" name="avs_number" id="avs_number" type="text" placeholder="756.1234.5678.90" {{validation_dic.avs_number|safe}}>
+ <label for="avs_number" data-error="wrong">Numero AVS</label>
+ <span class="helper-text" data-error="Campo richiesto"></span>
+ </div>
+ <div class="input-field col l4 s12">
+ <input value="{{via}}" name="via" id="via" type="text" {{validation_dic.via|safe}} {{midata_disable}}>
+ <label for="via">Via e numero</label>
+ <span class="helper-text" data-error="Campo richiesto"></span>
+ </div>
+ <div class="input-field col l4 s12">
+ <input value="{{cap}}" name="cap" id="cap" type="text" {{validation_dic.cap|safe}} {{midata_disable}}>
+ <label for="cap">CAP</label>
+ <span class="helper-text" data-error="Campo richiesto"></span>
+ </div>
+ <div class="input-field col l4 s12">
+ <input value="{{country}}" name="country" id="country" type="text" {{validation_dic.country|safe}} {{midata_disable}}>
+ <label for="country">Comune</label>
+ <span class="helper-text" data-error="Campo richiesto"></span>
+ </div>
+ <div class="input-field col l4 s12">
+ <input value="{{nationality}}" name="nationality" id="nationality" type="text" {{validation_dic.nationality|safe}}>
+ <label for="nationality">Nazionalit&agrave;</label>
+ <span class="helper-text" data-error="Campo richiesto"></span>
+ </div>
+ <div class="input-field col l4 s12">
+ <input value="{{phone}}" name="phone" id="phone" type="text" {{validation_dic.phone|safe}}>
+ <label for="phone">Numero di cellulare</label>
+ <span class="helper-text" data-error="Campo richiesto"></span>
+ </div>
+ <div class="input-field col l4 s12">
+ <input value="{{home_phone}}" name="home_phone" id="home_phone" type="text" {{validation_dic.home_phone|safe}}>
+ <label for="home_phone">Telefono di casa</label>
+ </div>
+ <div class="input-field col l8 s12">
+ <input value="{{school}}" name="school" id="school" type="text" {{validation_dic.school|safe}}>
+ <label for="school">Scuola frequentata (o professione)</label>
+ </div>
+ <div class="input-field col l4 s12">
+ <input value="{{year}}" name="year" id="year" type="text" {{validation_dic.year|safe}}>
+ <label for="year">Classe scolastica</label>
+ </div>
+ </div>
+ <div class="fixed-action-btn">
+ <a class="btn-floating btn-large {{color}}" onclick="send('save')">
+ <i class="large material-icons">save</i>
+ </a>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+</div>
+
+<div id="medic" class="row">
+ <div class="col l8 offset-l2 s12">
+ <div class="card-panel">
+ <div class="row">
+ <div class="col s12">
+ <h6>Persona di contatto in caso di necessit&agrave;</h6>
+ </div>
+ </div>
+ <div class="row">
+ <div class="input-field col l6 s12">
+ <input name="emer_name" value="{{emer_name}}" id="emer_name" type="text" {{validation_dic.emer_name|safe}}>
+ <label for="emer_name">Nome e cognome</label>
+ <span class="helper-text" data-error="Campo richiesto"></span>
+ </div>
+ <div class="input-field col l3 s12">
+ <input name="emer_relative" value="{{emer_relative}}" id="emer_relative" type="text" {{validation_dic.emer_relative|safe}}>
+ <label for="emer_releative">Parentela</label>
+ <span class="helper-text" data-error="Campo richiesto"></span>
+ </div>
+ <div class="input-field col l3 s12">
+ <input name="cell_phone" value="{{cell_phone}}" id="cellphone" type="text" {{validation_dic.cell_phone|safe}}>
+ <label for="cell_phone">Cellulare</label>
+ <span class="helper-text" data-error="Campo richiesto"></span>
+ </div>
+ <div class="input-field col l9 s12">
+ <input value="{{address}}" name="address" id="address" type="text" {{validation_dic.address|safe}}>
+ <label for="address">Indirizzo completo</label>
+ <span class="helper-text" data-error="Campo richiesto"></span>
+ </div>
+ <div class="input-field col l3 s12">
+ <input value="{{emer_phone}}" name="emer_phone" id="emer_phone" type="text" {{validation_dic.emer_phone|safe}}>
+ <label for="emer_phone">Telefono di casa</label>
+ </div>
+ </div>
+ <div class="row">
+ <div class="col s12">
+ <h6>Assicurazione</h6>
+ </div>
+ </div>
+ <div class="row">
+ <div class="input-field col l4 s12">
+ <input value="{{health_care}}" name="health_care" id="health_care" type="text" {{validation_dic.health_care|safe}}>
+ <label for="health_care">Cassa Malati</label>
+ <span class="helper-text" data-error="Campo richiesto"></span>
+ </div>
+ <div class="input-field col l4 s12">
+ <input value="{{injuries}}" name="injuries" id="injuries" type="text" {{validation_dic.injuries|safe}}>
+ <label for="injuries">Infortuni</label>
+ <span class="helper-text" data-error="Campo richiesto"></span>
+ </div>
+ <div class="input-field col l4 s12">
+ <input value="{{rc}}" name="rc" id="rc" type="text" {{validation_dic.rc|safe}}>
+ <label for="rc">Responsabilit&agrave; civile</label>
+ <span class="helper-text" data-error="Campo richiesto"></span>
+ </div>
+ </div>
+ <div class="row">
+ <div class="switch col s12">
+ &Egrave; sostenitore REGA&nbsp;&nbsp;
+ <label>
+ No
+ <input name="rega" type="checkbox" {{rega_check}}>
+ <span class="lever"></span>
+ Si
+ </label>
+ </div>
+ </div>
+ <div class="row">
+ <div class="col s12">
+ <h6>Medico di famiglia</h6>
+ </div>
+ <div class="input-field col l6 s12">
+ <input value="{{medic_name}}" name="medic_name" id="medic_name" type="text" {{validation_dic.medic_name|safe}}>
+ <label for="medic_name">Nome e cognome</label>
+ <span class="helper-text" data-error="Campo richiesto"></span>
+ </div>
+ <div class="input-field col l6 s12">
+ <input value="{{medic_phone}}" name="medic_phone" id="medic_phone" type="text" {{validation_dic.medic_phone|safe}}>
+ <label for="medic_phone">Telefono studio</label>
+ <span class="helper-text" data-error="Campo richiesto"></span>
+ </div>
+ <div class="input-field col l12 s12">
+ <input value="{{medic_address}}" name="medic_address" id="medic_address" type="text" {{validation_dic.medic_address|safe}}>
+ <label for="medic_address">Indirizzo completo</label>
+ <span class="helper-text" data-error="Campo richiesto"></span>
+ </div>
+ </div>
+ <div class="row">
+ <div class="col s12">
+ <h6>Scheda medica personale</h6>
+ </div>
+ <div class="input-field col s12">
+ <input value="{{sickness}}" name="sickness" id="sickness" type="text" data-length="250">
+ <label for="sickness">Principali malattie avute</label>
+ </div>
+ <div class="input-field col l8 s12">
+ <input value="{{vaccine}}" name="vaccine" id="vaccine" type="text" data-length="250">
+ <label for="vaccine">Vacinazioni fatte</label>
+ </div>
+ <div class="input-field col l4 s12">
+ <label for="tetanus_date">Ultima vacinazione contro il tetano</label>
+ <input value="{{tetanus_date}}" name="tetanus_date" id="tetanus_date" type="text" class="datepicker">
+ </div>
+ <div class="input-field col s12">
+ <input value="{{allergy}}" name="allergy" id="allergy" type="text" data-length="250">
+ <label for="allergy">Allergie particolari/Intolleraze alimentari</label>
+ </div>
+ <div class="switch col s12">
+ Deve assumere regolarmente medicamenti&nbsp;&nbsp;
+ <label>
+ No
+ <input name="drugs_bool" type="checkbox" {{drugs_check}}>
+ <span class="lever"></span>
+ Si
+ </label>
+ </div>
+ <div class="col s12">
+ <div class="card {{color}}">
+ <div class="card-content">
+ <p style="color:white"><b>In caso dovesse assumere farmaci, avvisare comunque i capi</b></p>
+ </div>
+ </div>
+ </div>
+ <div class="input-field col s12">
+ <input value="{{drugs}}" name="drugs" id="drugs" type="text" data-length="250">
+ <label for="drugs">Se s&igrave; quali, in che dosi e prescrizioni</label>
+ </div>
+ <div class="switch col s12">
+ Informazioni particolari sullo stato di salute: (postumi di operazioni, incidenti, malattie, disturbi fisici)&nbsp;&nbsp;
+ <label>
+ No
+ <input name="misc_bool" type="checkbox" {{misc_check}}>
+ <span class="lever"></span>
+ Si
+ </label>
+ </div>
+ <div class="input-field col s12">
+ <input value="{{misc}}" name="misc" id="misc" type="text" data-length="250">
+ <label for="misc">Se s&igrave; quali</label>
+ </div>
+ </div>
+ <div class="row">
+ <div class="col s12">
+ <h6>Allegati</h6>
+ </div>
+ <div class="col s12">
+ <div class="card">
+ <div class="card-content">
+ Certificato di vacinazione
+ <div class="file-field input-field">
+ <div class="btn {{color}}">
+ <span><i class="material-icons left">file_upload</i>File</span>
+ <input type="file" name="vac_certificate" id="vac_certificate" multiple>
+ </div>
+ <div class="file-path-wrapper">
+ <input id="vac_file" value="{{vac_certificate}}" class="file-path" type="text" placeholder="Certificato di vacinazione">
+ </div>
+ </div>
+ {% if vac_certificate != ''%}
+ <a class="btn {{color}}" onclick="send('download_vac')"><i class="material-icons left">file_download</i>Download</a>
+ <a class="btn {{color}}" onclick="delete_vac()"><i class="material-icons left">delete</i><span>Elimina</span></a>
+ {% endif %}
+ </div>
+ </div>
+ </div>
+ <div class="col s12">
+ <div class="card">
+ <div class="card-content">
+ Tessera cassa malati
+ <div class="file-field input-field">
+ <div class="btn {{color}}">
+ <span><i class="material-icons left">file_upload</i>File</span>
+ <input type="file" name="health_care_certificate" id="health_care_certificate" multiple>
+ </div>
+ <div class="file-path-wrapper">
+ <input id="health_care_file" value="{{health_care_certificate}}" class="file-path" type="text" placeholder="Tessera cassa malati">
+ </div>
+ </div>
+ {% if health_care_certificate != ''%}
+ <a class="btn {{color}}" onclick="send('download_health')"><i class="material-icons left">file_download</i>Download</a>
+ <a class="btn {{color}}" onclick="delete_health()"><i class="material-icons left">delete</i><span>Elimina</span></a>
+ {% endif %}
+ </div>
+ </div>
+ </div>
+ </div>
+ <div class="fixed-action-btn">
+ <a class="btn-floating btn-large {{color}}" onclick="send('save')">
+ <i class="large material-icons">save</i>
+ </a>
+ </div>
+ </div>
+ </div>
+</div>
+</form>
+{% endblock %}
+
+{% block script %}
+function send(id) {
+ $('#form1').trigger('reinitialize.areYouSure');
+ var form = document.getElementById('form1');
+ var action = document.getElementById('action');
+ action.setAttribute('value', id);
+ $(':disabled').each(function(e) {
+ $(this).removeAttr('disabled');
+ })
+ form.submit();
+}
+
+function delete_vac() {
+ var action = document.getElementById('delete_vac');
+ var text = document.getElementById('vac_file');
+ action.setAttribute('value', 'vac');
+ text.setAttribute('value', '');
+}
+
+function delete_health() {
+ var action = document.getElementById('delete_health');
+ var text = document.getElementById('health_care_file');
+ action.setAttribute('value', 'health');
+ text.setAttribute('value', '');
+}
+
+var elem = $('.tabs')
+var options = {
+ yearRange:100,
+ format:'dd mmmm yyyy',
+ i18n: {
+ months: [ 'gennaio', 'febbraio', 'marzo', 'aprile', 'maggio', 'giugno', 'luglio', 'agosto', 'settembre', 'ottobre', 'novembre', 'dicembre' ],
+ monthsShort: [ 'gen', 'feb', 'mar', 'apr', 'mag', 'giu', 'lug', 'ago', 'set', 'ott', 'nov', 'dic' ],
+ weekdays: [ 'domenica', 'lunedì', 'martedì', 'mercoledì', 'giovedì', 'venerdì', 'sabato' ],
+ weekdaysShort: [ 'dom', 'lun', 'mar', 'mer', 'gio', 'ven', 'sab' ],
+ weekdaysAbbrev: [ 'D', 'L', 'M', 'M', 'G', 'V', 'S' ],
+ today: 'Oggi',
+ clear: 'Cancella',
+ close: 'Chiudi',
+ firstDay: 1,
+ format: 'dddd d mmmm yyyy',
+ formatSubmit: 'yyyy/mm/dd',
+ labelMonthNext: 'Mese successivo',
+ labelMonthPrev: 'Mese precedente',
+ labelMonthSelect: 'Seleziona un mese',
+ labelYearSelect: 'Seleziona un anno'
+ }
+}
+
+$(document).ready(function() {
+ $('input#sickness, input#vaccine, input#allergy, input#drugs, input#misc').characterCounter();
+ $('.datepicker').datepicker(options);
+ $('select').formSelect();
+ $('.tap-target').tapTarget();
+ {% for error in errors %}
+ M.toast({html: '{{ error }}', classes: 'orange'})
+ {% endfor %}
+ {% if ok_message %}
+ M.toast({html: '{{ ok_message }}', classes: 'green'})
+ {% endif %}
+ {% if home_tooltip %}
+ $('.tap-target').tapTarget('open');
+ {% endif %}
+ document.getElementById("vac_certificate").onchange = function() {
+ for (i=0; i < this.files.length; i++) {
+ if(this.files[i].size > 1048576*10) {
+ M.toast({html: 'Il file è troppo grande. Grandezza massima 10MB', classes: 'orange'});
+ this.value = "";
+ break;
+ }
+ }
+ };
+
+ document.getElementById("health_care_certificate").onchange = function() {
+ for (i=0; i < this.files.length; i++) {
+ if(this.files[i].size > 1048576*10) {
+ M.toast({html: 'Il file è troppo grande. Grandezza massima 10MB', classes: 'orange'});
+ this.value = "";
+ break;
+ }
+ }
+ };
+
+});
+
+/*!
+ * jQuery Plugin: Are-You-Sure (Dirty Form Detection)
+ * https://github.com/codedance/jquery.AreYouSure/
+ *
+ * Copyright (c) 2012-2014, Chris Dance and PaperCut Software http://www.papercut.com/
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * Author: chris.dance@papercut.com
+ * Version: 1.9.0
+ * Date: 13th August 2014
+ */
+(function($) {
+
+ $.fn.areYouSure = function(options) {
+
+ var settings = $.extend(
+ {
+ 'message' : 'You have unsaved changes!',
+ 'dirtyClass' : 'dirty',
+ 'change' : null,
+ 'silent' : false,
+ 'addRemoveFieldsMarksDirty' : false,
+ 'fieldEvents' : 'change keyup propertychange input',
+ 'fieldSelector': ":input:not(input[type=submit]):not(input[type=button])"
+ }, options);
+
+ var getValue = function($field) {
+ if ($field.hasClass('ays-ignore')
+ || $field.hasClass('aysIgnore')
+ || $field.attr('data-ays-ignore')
+ || $field.attr('name') === undefined) {
+ return null;
+ }
+
+ if ($field.is(':disabled')) {
+ return 'ays-disabled';
+ }
+
+ var val;
+ var type = $field.attr('type');
+ if ($field.is('select')) {
+ type = 'select';
+ }
+
+ switch (type) {
+ case 'checkbox':
+ case 'radio':
+ val = $field.is(':checked');
+ break;
+ case 'select':
+ val = '';
+ $field.find('option').each(function(o) {
+ var $option = $(this);
+ if ($option.is(':selected')) {
+ val += $option.val();
+ }
+ });
+ break;
+ default:
+ val = $field.val();
+ }
+
+ return val;
+ };
+
+ var storeOrigValue = function($field) {
+ $field.data('ays-orig', getValue($field));
+ };
+
+ var checkForm = function(evt) {
+
+ var isFieldDirty = function($field) {
+ var origValue = $field.data('ays-orig');
+ if (undefined === origValue) {
+ return false;
+ }
+ return (getValue($field) != origValue);
+ };
+
+ var $form = ($(this).is('form'))
+ ? $(this)
+ : $(this).parents('form');
+
+ // Test on the target first as it's the most likely to be dirty
+ if (isFieldDirty($(evt.target))) {
+ setDirtyStatus($form, true);
+ return;
+ }
+
+ $fields = $form.find(settings.fieldSelector);
+
+ if (settings.addRemoveFieldsMarksDirty) {
+ // Check if field count has changed
+ var origCount = $form.data("ays-orig-field-count");
+ if (origCount != $fields.length) {
+ setDirtyStatus($form, true);
+ return;
+ }
+ }
+
+ // Brute force - check each field
+ var isDirty = false;
+ $fields.each(function() {
+ var $field = $(this);
+ if (isFieldDirty($field)) {
+ isDirty = true;
+ return false; // break
+ }
+ });
+
+ setDirtyStatus($form, isDirty);
+ };
+
+ var initForm = function($form) {
+ var fields = $form.find(settings.fieldSelector);
+ $(fields).each(function() { storeOrigValue($(this)); });
+ $(fields).unbind(settings.fieldEvents, checkForm);
+ $(fields).bind(settings.fieldEvents, checkForm);
+ $form.data("ays-orig-field-count", $(fields).length);
+ setDirtyStatus($form, false);
+ };
+
+ var setDirtyStatus = function($form, isDirty) {
+ var changed = isDirty != $form.hasClass(settings.dirtyClass);
+ $form.toggleClass(settings.dirtyClass, isDirty);
+
+ // Fire change event if required
+ if (changed) {
+ if (settings.change) settings.change.call($form, $form);
+
+ if (isDirty) $form.trigger('dirty.areYouSure', [$form]);
+ if (!isDirty) $form.trigger('clean.areYouSure', [$form]);
+ $form.trigger('change.areYouSure', [$form]);
+ }
+ };
+
+ var rescan = function() {
+ var $form = $(this);
+ var fields = $form.find(settings.fieldSelector);
+ $(fields).each(function() {
+ var $field = $(this);
+ if (!$field.data('ays-orig')) {
+ storeOrigValue($field);
+ $field.bind(settings.fieldEvents, checkForm);
+ }
+ });
+ // Check for changes while we're here
+ $form.trigger('checkform.areYouSure');
+ };
+
+ var reinitialize = function() {
+ initForm($(this));
+ }
+
+ if (!settings.silent && !window.aysUnloadSet) {
+ window.aysUnloadSet = true;
+ $(window).bind('beforeunload', function() {
+ $dirtyForms = $("form").filter('.' + settings.dirtyClass);
+ if ($dirtyForms.length == 0) {
+ return;
+ }
+ // Prevent multiple prompts - seen on Chrome and IE
+ if (navigator.userAgent.toLowerCase().match(/msie|chrome/)) {
+ if (window.aysHasPrompted) {
+ return;
+ }
+ window.aysHasPrompted = true;
+ window.setTimeout(function() {window.aysHasPrompted = false;}, 900);
+ }
+ return settings.message;
+ });
+ }
+
+ return this.each(function(elem) {
+ if (!$(this).is('form')) {
+ return;
+ }
+ var $form = $(this);
+
+ $form.submit(function() {
+ $form.removeClass(settings.dirtyClass);
+ });
+ $form.bind('reset', function() { setDirtyStatus($form, false); });
+ // Add a custom events
+ $form.bind('rescan.areYouSure', rescan);
+ $form.bind('reinitialize.areYouSure', reinitialize);
+ $form.bind('checkform.areYouSure', checkForm);
+ initForm($form);
+ });
+ };
+})(jQuery);
+$('form').areYouSure();
+
+{% endblock %} \ No newline at end of file
diff --git a/accounts/urls.py b/accounts/urls.py
index b35796b..57a649d 100644
--- a/accounts/urls.py
+++ b/accounts/urls.py
@@ -6,6 +6,7 @@ urlpatterns = [
path('signup/', views.signup, name='signup'),
path('login/', views.CustomLoginView.as_view(), name='login'),
path('personal/', views.personal, name='personal'),
+ path('edit/<int:code>', views.edit, name='edit_user'),
path('terms/', views.terms, name='terms'),
path('oauth_login/', views.oauth_login, name='oauth_login'),
path('auth/', views.auth, name='auth'),
diff --git a/accounts/views.py b/accounts/views.py
index 8ea48f2..35dca92 100644
--- a/accounts/views.py
+++ b/accounts/views.py
@@ -755,6 +755,405 @@ def personal_wrapper(request, errors):
return render(request, 'accounts/index.html', context)
+@login_required
+def edit(request, code):
+ errors = []
+ context = {}
+ ok_message = ""
+ personal_active = "active"
+ medic_active = ""
+ settings_active = ""
+ # additional user information
+ if (code == 0):
+ # generate code
+ while (True):
+ code = randint(100000, 999999)
+ if len(UserCode.objects.filter(code=code)) == 0:
+ break
+ medic = MedicalData()
+ medic.save()
+ userCode = UserCode(user=request.user, code=code, medic=medic)
+ userCode.save()
+
+ usercode = UserCode.objects.filter(user=request.user, code=code)
+
+ if (len(usercode) == 0):
+ # code is not authorised for this user
+ return
+
+ usercode = usercode[0]
+
+ # medical info
+ medic = usercode.medic
+ # values for multiple choice box
+ # TODO remove multiple choice
+ branca_default = ""
+ branca_castorini = ""
+ branca_lupetti = ""
+ branca_esploratori = ""
+ branca_pionieri = ""
+ branca_rover = ""
+
+ # variables for validation
+ validation_dic = {}
+ required_fields = ["first_name", "last_name", "parent_name", "via", "cap", "country", "nationality", "phone", "avs_number", "emer_name", "emer_relative", "cell_phone", "address", "health_care", "injuries", "rc", "medic_name", "medic_phone", "medic_address"]
+ personal_fields = ["first_name", "last_name", "parent_name", "via", "cap", "country", "nationality", "phone", "avs_number"]
+ medic_fields = ["emer_name", "emer_relative", "cell_phone", "address", "health_care", "injuries", "rc", "medic_name", "medic_phone", "medic_address"]
+
+ if request.method == "POST":
+ # requested download
+ if request.POST['action'] == "download_vac":
+ if medic.vac_certificate != None:
+ filename = os.path.basename(medic.vac_certificate.name)
+ filename = filename[filename.find("_")+1:]
+ if filename.rfind('.') != -1:
+ filename = filename[:filename.rfind('.')]
+ filename = filename + ".jpg"
+
+ # encode in JPEG
+ im = Image.open(medic.vac_certificate.file)
+ im_io = BytesIO()
+ im.save(im_io, 'JPEG', quality=90)
+ im_io.seek(0)
+ return FileResponse(im_io, as_attachment=True, filename=filename)
+
+ elif request.POST['action'] == "download_health":
+ if medic.health_care_certificate != None:
+ filename = os.path.basename(medic.health_care_certificate.name)
+ filename = filename[filename.find("_")+1:]
+ if filename.rfind('.') != -1:
+ filename = filename[:filename.rfind('.')]
+ filename = filename + ".jpg"
+
+ # encode in JPEG
+ im = Image.open(medic.health_care_certificate.file)
+ im_io = BytesIO()
+ im.save(im_io, 'JPEG', quality=90)
+ im_io.seek(0)
+ return FileResponse(im_io, as_attachment=True, filename=filename)
+
+ elif request.POST['action'] == "password":
+ # get form object
+ if request.user.has_usable_password():
+ form2 = PasswordChangeForm(data=request.POST, user=request.user)
+ else:
+ form2 = SetPasswordForm(data=request.POST, user=request.user)
+
+ # if form is valid and terms were accepted save user
+ if form2.is_valid():
+ form2.save()
+ ok_message = "Password modificata con successo"
+ personal_active = ""
+ settings_active = "active"
+ else:
+ personal_active = ""
+ settings_active = "active"
+ for field in form2.errors.as_data().values():
+ for err in field:
+ if err.code == "password_mismatch":
+ errors.append("Le due password non sono uguali")
+ elif err.code == "password_too_similar":
+ errors.append("La password è troppo simile all'username")
+ elif err.code == "password_too_short":
+ errors.append("La password è troppo corta")
+ elif err.code == "password_too_common":
+ errors.append("La password è troppo comune")
+ elif err.code == "password_entirely_numeric":
+ errors.append("La password deve contenere lettere")
+ elif err.code == "password_incorrect":
+ errors.append("La password attuale è incorretta")
+
+ else:
+ # set all attributes
+ usercode.first_name = request.POST["first_name"]
+ usercode.last_name = request.POST["last_name"]
+ usercode.parent_name = request.POST["parent_name"]
+ usercode.via = request.POST["via"]
+ usercode.cap = request.POST["cap"]
+ usercode.country = request.POST["country"]
+ usercode.nationality = request.POST["nationality"]
+ usercode.born_date = dateparser.parse(request.POST["birth_date"])
+ usercode.home_phone = request.POST["home_phone"]
+ usercode.phone = request.POST["phone"]
+ usercode.school = request.POST["school"]
+ usercode.avs_number = request.POST["avs_number"]
+
+ if request.POST["year"].isdigit():
+ usercode.year = request.POST["year"]
+ else:
+ errors.append("L'anno scolastico deve essere un numero")
+
+ usercode.save()
+
+ medic.emer_name = request.POST["emer_name"]
+ medic.emer_relative = request.POST["emer_relative"]
+ medic.cell_phone = request.POST["cell_phone"]
+ medic.address = request.POST["address"]
+ medic.emer_phone = request.POST["emer_phone"]
+ medic.health_care = request.POST["health_care"]
+ medic.injuries = request.POST["injuries"]
+ medic.rc = request.POST["rc"]
+ medic.rega = "rega" in request.POST
+ medic.medic_name = request.POST["medic_name"]
+ medic.medic_phone = request.POST["medic_phone"]
+ medic.medic_address = request.POST["medic_address"]
+ medic.sickness = request.POST["sickness"]
+ medic.vaccine = request.POST["vaccine"]
+ medic.tetanus_date = dateparser.parse(request.POST["tetanus_date"])
+ medic.allergy = request.POST["allergy"]
+ medic.drugs_bool = "drugs_bool" in request.POST
+ medic.drugs = request.POST["drugs"]
+ medic.misc_bool = "misc_bool" in request.POST
+ medic.misc = request.POST["misc"]
+ medic.save()
+
+ missing_fields = False
+ missing_personal_field = False
+
+ if request.POST["birth_date"] == "" or request.POST["birth_date"] == "01 Gennaio 1970" or request.POST["birth_date"] == "None":
+ validation_dic["birth_date"] = 'class="datepicker validate invalid" required="" aria-required="true"'
+ missing_fields = True
+ missing_personal_field = True
+ else:
+ validation_dic["birth_date"] = 'class="datepicker validate" required="" aria-required="true"'
+
+ for i in required_fields:
+ if request.POST[i] == "":
+ missing_fields = True
+ if i in personal_fields:
+ missing_personal_field = True
+ validation_dic[i] = 'class="validate invalid" required="" aria-required="true"'
+ else:
+ validation_dic[i] = 'class="validate" required="" aria-required="true"'
+
+ if missing_fields:
+ errors.append("Alcuni campi richiesti non sono stati compilati")
+ if not missing_personal_field:
+ personal_active = ""
+ medic_active = "active"
+
+ # if "branca" in request.POST:
+ # if request.POST["branca"] != "":
+ # request.user.groups.clear()
+ # request.user.groups.add(
+ # Group.objects.get(name=request.POST["branca"]))
+
+ # check if user uploaded a file
+ if "vac_certificate" in request.FILES:
+ files = request.FILES.getlist('vac_certificate')
+ name = files[0].name
+ try:
+ # if multiple files concatenate pictures
+ im = Image.new("RGB", (0, 0), (255, 255, 255))
+ for f in files:
+ if f.name.endswith(".pdf") or f.name.endswith(".PDF"):
+ images = convert_from_bytes(f.read())
+ for i in images:
+ dst = Image.new('RGB', (max(im.width, i.width), im.height + i.height), (255, 255, 255))
+ dst.paste(im, (0, 0))
+ dst.paste(i, (0, im.height))
+ im = dst
+ else:
+ i = Image.open(f)
+ dst = Image.new('RGB', (max(im.width, i.width), im.height + i.height), (255, 255, 255))
+ dst.paste(im, (0, 0))
+ dst.paste(i, (0, im.height))
+ im = dst
+
+ im_io = BytesIO()
+ # resize image if larger than max value
+ if im.height > 16383:
+ im = im.resize((round(im.width/im.height*16383), 16383))
+ # compress image in WEBP
+ im.save(im_io, 'WEBP', quality=50, method=4)
+ medic.vac_certificate.save(
+ request.user.username+"_"+name, im_io)
+ medic.save()
+ except UnidentifiedImageError:
+ errors.append("Il certificato delle vaccinazioni non è un immagine valida")
+ except PDFPageCountError:
+ errors.append("Il certificato delle vaccinazioni non è un pdf valido")
+ except PDFSyntaxError:
+ errors.append("Il certificato delle vaccinazioni non è un pdf valido")
+ except IOError:
+ errors.append("Il certificato delle vaccinazioni è un immagine troppo grande")
+
+ if "health_care_certificate" in request.FILES:
+ files = request.FILES.getlist('health_care_certificate')
+ name = files[0].name
+ try:
+ # if multiple files concatenate pictures
+ im = Image.new("RGB", (0, 0), (255, 255, 255))
+ for f in files:
+ if f.name.endswith(".pdf") or f.name.endswith(".PDF"):
+ images = convert_from_bytes(f.read())
+ for i in images:
+ dst = Image.new('RGB', (max(im.width, i.width), im.height + i.height), (255, 255, 255))
+ dst.paste(im, (0, 0))
+ dst.paste(i, (0, im.height))
+ im = dst
+ else:
+ i = Image.open(f)
+ dst = Image.new('RGB', (max(im.width, i.width), im.height + i.height), (255, 255, 255))
+ dst.paste(im, (0, 0))
+ dst.paste(i, (0, im.height))
+ im = dst
+
+ im_io = BytesIO()
+ # resize image if larger than max value
+ if im.height > 16383:
+ im = im.resize((round(im.width/im.height*16383), 16383))
+ # compress image in WEBP
+ im.save(im_io, 'WEBP', quality=50, method=4)
+ medic.health_care_certificate.save(
+ request.user.username+"_"+name, im_io)
+ medic.save()
+ except UnidentifiedImageError:
+ errors.append("La tessera della cassa malati non è un immagine valida")
+ except PDFPageCountError:
+ errors.append("La tessera della cassa malati non è un pdf valido")
+ except PDFSyntaxError:
+ errors.append("La tessera della cassa malati non è un pdf valido")
+ except IOError:
+ errors.append("La tessera della cassa malati è un immagine troppo grande")
+
+ # user requested file delete
+ if request.POST["delete_vac"] == 'vac':
+ medic.vac_certificate = None
+ medic.save()
+
+ if request.POST["delete_health"] == 'health':
+ medic.health_care_certificate = None
+ medic.save()
+
+ # if there wasn't any error redirect to clear POST
+ if len(errors) == 0:
+ return HttpResponseRedirect(request.get_full_path())
+
+ else:
+ # no post, create empty validation
+ validation_dic["birth_date"] = 'class="datepicker validate" required="" aria-required="true"'
+ for i in required_fields:
+ validation_dic[i] = 'class="validate" required="" aria-required="true"'
+
+ # check if user is in a group and set multiple choice to that
+ if len(request.user.groups.values_list('name', flat=True)) == 0:
+ branca_default = "selected"
+ else:
+ parent_group = request.user.groups.values_list('name', flat=True)[0]
+ if parent_group == "diga":
+ branca_castorini = "selected"
+ elif parent_group == "muta":
+ branca_lupetti = "selected"
+ elif parent_group == "reparto":
+ branca_esploratori = "selected"
+ elif parent_group == "posto":
+ branca_pionieri = "selected"
+ elif parent_group == "clan":
+ branca_rover = "selected"
+ else:
+ branca_default = "selected"
+
+ # set checkbox status
+ rega = ""
+ if medic.rega:
+ rega = "checked='checked'"
+ drugs = ""
+ if medic.drugs_bool:
+ drugs = "checked='checked'"
+ misc = ""
+ if medic.misc_bool:
+ misc = "checked='checked'"
+
+ # set file name for uploaded files
+ if (medic.vac_certificate != None):
+ vac_name = os.path.basename(medic.vac_certificate.name)
+ vac_name = vac_name[vac_name.find("_")+1:]
+ else:
+ vac_name = ''
+
+ if (medic.health_care_certificate != None):
+ card_name = os.path.basename(medic.health_care_certificate.name)
+ card_name = card_name[card_name.find("_")+1:]
+ else:
+ card_name = ''
+
+ # check if user is connected with midata
+ midata_user = (usercode.midata_id > 0)
+ midata_disable = ""
+
+ # get user info from midata
+ if midata_user:
+ midata_disable = " readonly disabled"
+ if not copy_from_midata(request, usercode):
+ return HttpResponseRedirect(request.get_full_path())
+
+ usable_password = request.user.has_usable_password()
+
+ # check if user has saved the form
+ home_tooltip = False
+ if "saved" in request.GET:
+ # show tooltip only if user is not approved and there are no errors
+ home_tooltip = (not request.user.has_perm("client.approved")) and (len(errors) == 0)
+
+ # fill context
+ context = {
+ 'ucode': code,
+ 'validation_dic': validation_dic,
+ 'first_name': usercode.first_name,
+ 'last_name': usercode.last_name,
+ 'parent_name': usercode.parent_name,
+ 'via': usercode.via,
+ 'cap': usercode.cap,
+ 'country': usercode.country,
+ 'nationality': usercode.nationality,
+ 'birth_date': usercode.born_date,
+ 'home_phone': usercode.home_phone,
+ 'phone': usercode.phone,
+ 'school': usercode.school,
+ 'year': usercode.year,
+ 'avs_number': usercode.avs_number,
+ 'branca_default': branca_default,
+ 'branca_castorini': branca_castorini,
+ 'branca_lupetti': branca_lupetti,
+ 'branca_esploratori': branca_esploratori,
+ 'branca_pionieri': branca_pionieri,
+ 'branca_rover': branca_rover,
+ 'emer_name': medic.emer_name,
+ 'emer_relative': medic.emer_relative,
+ 'cell_phone': medic.cell_phone,
+ 'address': medic.address,
+ 'emer_phone': medic.emer_phone,
+ 'health_care': medic.health_care,
+ 'injuries': medic.injuries,
+ 'rc': medic.rc,
+ 'rega_check': rega,
+ 'medic_name': medic.medic_name,
+ 'medic_phone': medic.medic_phone,
+ 'medic_address': medic.medic_address,
+ 'sickness': medic.sickness,
+ 'vaccine': medic.vaccine,
+ 'tetanus_date': medic.tetanus_date,
+ 'allergy': medic.allergy,
+ 'drugs_check': drugs,
+ 'drugs': medic.drugs,
+ 'misc_check': misc,
+ 'misc': medic.misc,
+ 'health_care_certificate': card_name,
+ 'vac_certificate': vac_name,
+ 'errors': errors,
+ 'ok_message': ok_message,
+ 'midata_user': midata_user,
+ 'midata_disable': midata_disable,
+ 'usable_password': usable_password,
+ 'personal_active': personal_active,
+ 'medic_active': medic_active,
+ 'settings_active': settings_active,
+ 'midata_enabled': MIDATA_ENABLED,
+ 'home_tooltip': home_tooltip,
+ }
+
+ return render(request, 'accounts/user_edit.html', context)
# simple terms page, only static html
def terms(request):
diff --git a/client/templates/client/index.html b/client/templates/client/index.html
index 0b0b25c..0350311 100644
--- a/client/templates/client/index.html
+++ b/client/templates/client/index.html
@@ -36,6 +36,8 @@
<div class="card-content">
<span class="card-title">
{{data.0.first_name}} {{data.0.last_name}}
+ <a href="{% url "edit_user" code=data.0.code %}" class="btn-flat"><i class="material-icons">edit</i></a>
+ <a href="" class="btn-flat"><i class="material-icons">delete</i></a>
<div style="font-size: 0.5em; line-height: normal;">{{data.0.born_date}}</div>
</span>
<a id="add" class="btn-floating halfway-fab btn-large {{color}}" href="{% url 'create'%}"><i class="material-icons">add</i></a>
@@ -434,18 +436,22 @@
{% endfor %}
{% else %}
<div class="row">
- <div class="col l4 offset-l4 m8 offset-m2 s12">
+ <div class="col s12">
<div class="card">
<div class="card-content">
- <p>Il tuo utente non contiene nessuna persona fisica. Per creare una nuova persona aggiungerla
- dal profilo utente. Seleziona il proprio nome in alto a destra e in seguito "Gestione account".
- Torna in seguito su questa pagina per creare una nuova iscrizione.
+ <p>Il tuo utente non contiene nessuna persona fisica. Per creare una nuova persona utilizzare
+ il pulsante qua sotto. Una volta creata tornare in seguito su questa pagina per creare una nuova iscrizione.
</p>
</div>
</div>
</div>
</div>
{% endif %}
+<div class="row">
+ <div class="col s12">
+ <a href="{% url "edit_user" code=0 %}" class="btn waves-effect waves-light {{color}}">Crea una nuova persona <i class="material-icons right">add</i></a>
+ </div>
+</div>
{% endblock %}
{% block script %}
diff --git a/templates/registration/base_admin.html b/templates/registration/base_admin.html
index 9f78b43..1f484e6 100644
--- a/templates/registration/base_admin.html
+++ b/templates/registration/base_admin.html
@@ -110,7 +110,7 @@
<li class="userswitcher" data-target='userswitcher'><a href="#">{{ user.username }}</a></li>
{% endif %}
<ul id='userswitcher' class='dropdown-content'>
- <li><a href="{% url 'personal' %}"><i class="material-icons">person</i>Gestione account</a></li>
+ <li><a href="{% url 'personal' %}"><i class="material-icons">person</i>Impostazioni</a></li>
{% if user.is_staff or perms.client.staff %}
<li><a href="{% url 'server' %}"><i class="material-icons">build</i>Pannello Admin</a></li>
{% endif %}
@@ -119,6 +119,7 @@
{% endif %}
<li><a onclick="switcher_submit('logout')"><i class="material-icons">exit_to_app</i>Logout</a></li>
+ <!--
<li class="divider" tabindex="-1"></li>
<li class="divider" tabindex="-1"></li>
<li class="divider" tabindex="-1"></li>
@@ -133,6 +134,7 @@
<li class="divider" tabindex="-1"></li>
<li class="divider" tabindex="-1"></li>
<li class="divider" tabindex="-1"></li>
+ -->
<li><a href="{% url 'about' %}">Informazioni sul prodotto</a></li>
</ul>
</ul>
diff --git a/templates/registration/base_client.html b/templates/registration/base_client.html
index ad2fadc..357197a 100644
--- a/templates/registration/base_client.html
+++ b/templates/registration/base_client.html
@@ -126,7 +126,7 @@
<li class="userswitcher" data-target='userswitcher'><a href="#">{{ user.username }}</a></li>
{% endif %}
<ul id='userswitcher' class='dropdown-content'>
- <li><a href="{% url 'personal' %}"><i class="material-icons">person</i>Gestione account</a></li>
+ <li><a href="{% url 'personal' %}"><i class="material-icons">person</i>Impostazioni</a></li>
{% if user.is_staff or perms.client.staff %}
<li><a href="{% url 'server' %}"><i class="material-icons">build</i>Pannello Admin</a></li>
{% endif %}
@@ -135,6 +135,7 @@
{% endif %}
<li><a onclick="switcher_submit('logout')"><i class="material-icons">exit_to_app</i>Logout</a></li>
+ <!--
<li class="divider" tabindex="-1"></li>
<li class="divider" tabindex="-1"></li>
<li class="divider" tabindex="-1"></li>
@@ -149,6 +150,7 @@
<li class="divider" tabindex="-1"></li>
<li class="divider" tabindex="-1"></li>
<li class="divider" tabindex="-1"></li>
+ -->
<li><a href="{% url 'about' %}">Informazioni sul prodotto</a></li>
</ul>
</ul>
diff --git a/version.txt b/version.txt
index 5fe012e..b80d385 100644
--- a/version.txt
+++ b/version.txt
@@ -1,2 +1,2 @@
version=0.6
-rev=27
+rev=28