mirror of
https://gitlab.crans.org/bde/nk20
synced 2025-09-06 19:13:54 +02:00
Compare commits
3 Commits
phone_inpu
...
fd8cd0ff4e
Author | SHA1 | Date | |
---|---|---|---|
|
fd8cd0ff4e | ||
|
dde1baa25c | ||
|
7a7ee47e0b |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -48,7 +48,6 @@ backups/
|
|||||||
env/
|
env/
|
||||||
venv/
|
venv/
|
||||||
db.sqlite3
|
db.sqlite3
|
||||||
shell.nix
|
|
||||||
|
|
||||||
# ansibles customs host
|
# ansibles customs host
|
||||||
ansible/host_vars/*.yaml
|
ansible/host_vars/*.yaml
|
||||||
|
@@ -10,7 +10,6 @@ from django.contrib.auth.forms import AuthenticationForm
|
|||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
from django.forms import CheckboxSelectMultiple
|
from django.forms import CheckboxSelectMultiple
|
||||||
from phonenumber_field.formfields import PhoneNumberField
|
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from note.models import NoteSpecial, Alias
|
from note.models import NoteSpecial, Alias
|
||||||
@@ -46,11 +45,6 @@ class ProfileForm(forms.ModelForm):
|
|||||||
A form for the extras field provided by the :model:`member.Profile` model.
|
A form for the extras field provided by the :model:`member.Profile` model.
|
||||||
"""
|
"""
|
||||||
# Remove widget=forms.HiddenInput() if you want to use report frequency.
|
# Remove widget=forms.HiddenInput() if you want to use report frequency.
|
||||||
phone_number = PhoneNumberField(
|
|
||||||
widget=forms.TextInput(attrs={"type": "tel", "class": "form-control"}),
|
|
||||||
required=False
|
|
||||||
)
|
|
||||||
|
|
||||||
report_frequency = forms.IntegerField(required=False, initial=0, label=_("Report frequency"))
|
report_frequency = forms.IntegerField(required=False, initial=0, label=_("Report frequency"))
|
||||||
|
|
||||||
last_report = forms.DateTimeField(required=False, disabled=True, label=_("Last report date"))
|
last_report = forms.DateTimeField(required=False, disabled=True, label=_("Last report date"))
|
||||||
@@ -78,12 +72,7 @@ class ProfileForm(forms.ModelForm):
|
|||||||
if not self.instance.section or (("department" in self.changed_data
|
if not self.instance.section or (("department" in self.changed_data
|
||||||
or "promotion" in self.changed_data) and "section" not in self.changed_data):
|
or "promotion" in self.changed_data) and "section" not in self.changed_data):
|
||||||
self.instance.section = self.instance.section_generated
|
self.instance.section = self.instance.section_generated
|
||||||
instance = super().save(commit=False)
|
return super().save(commit)
|
||||||
if instance.phone_number:
|
|
||||||
instance.phone_number = instance.phone_number.as_e164
|
|
||||||
if commit:
|
|
||||||
instance.save()
|
|
||||||
return instance
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Profile
|
model = Profile
|
||||||
|
@@ -10,7 +10,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
|||||||
{{ title }}
|
{{ title }}
|
||||||
</h3>
|
</h3>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<form method="post" id="profile-form">
|
<form method="post">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
{{ form | crispy }}
|
{{ form | crispy }}
|
||||||
{{ profile_form | crispy }}
|
{{ profile_form | crispy }}
|
||||||
@@ -20,46 +20,4 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
|||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block extrajavascript %}
|
|
||||||
<!-- intl-tel-input CSS/JS -->
|
|
||||||
<script>
|
|
||||||
(() => {
|
|
||||||
const input = document.querySelector("input[name='phone_number']");
|
|
||||||
const form = document.querySelector("#profile-form");
|
|
||||||
|
|
||||||
if (!input || !form) {
|
|
||||||
console.error("Input phone_number ou form introuvable.");
|
|
||||||
}
|
|
||||||
|
|
||||||
const iti = window.intlTelInput(input, {
|
|
||||||
initialCountry: "auto",
|
|
||||||
nationalMode: false,
|
|
||||||
autoPlaceholder: "off",
|
|
||||||
geoIpLookup: callback => {
|
|
||||||
fetch("https://ipapi.co/json")
|
|
||||||
.then(res => res.json())
|
|
||||||
.then(data => callback(data.country_code))
|
|
||||||
.catch(() => callback("fr"));
|
|
||||||
},
|
|
||||||
loadUtils: () => import("https://cdn.jsdelivr.net/npm/intl-tel-input@25.5.2/build/js/utils.js"),
|
|
||||||
});
|
|
||||||
|
|
||||||
form.addEventListener("submit", function(e){
|
|
||||||
if (!input.value.trim()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const number = iti.getNumber(intlTelInput.utils.numberFormat.E164);
|
|
||||||
if (number) {
|
|
||||||
input.value = number;
|
|
||||||
form.submit();
|
|
||||||
} else {
|
|
||||||
e.preventDefault();
|
|
||||||
input.focus();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
})();
|
|
||||||
</script>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
@@ -11,7 +11,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
|||||||
{{ title }}
|
{{ title }}
|
||||||
</h3>
|
</h3>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<form id="registration-form" method="post">
|
<form method="post">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
{{ form|crispy }}
|
{{ form|crispy }}
|
||||||
{{ membership_form|crispy }}
|
{{ membership_form|crispy }}
|
||||||
@@ -22,46 +22,6 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block extrajavascript %}
|
{% block extrajavascript %}
|
||||||
<!-- intl-tel-input CSS/JS -->
|
|
||||||
<script>
|
|
||||||
(() => {
|
|
||||||
const input = document.querySelector("input[name='emergency_contact_phone']");
|
|
||||||
const form = document.querySelector("#registration-form");
|
|
||||||
|
|
||||||
if (!input || !form) {
|
|
||||||
console.error("Input phone_number ou form introuvable.");
|
|
||||||
}
|
|
||||||
|
|
||||||
const iti = window.intlTelInput(input, {
|
|
||||||
initialCountry: "auto",
|
|
||||||
nationalMode: false,
|
|
||||||
autoPlaceholder: "off",
|
|
||||||
geoIpLookup: callback => {
|
|
||||||
fetch("https://ipapi.co/json")
|
|
||||||
.then(res => res.json())
|
|
||||||
.then(data => callback(data.country_code))
|
|
||||||
.catch(() => callback("fr"));
|
|
||||||
},
|
|
||||||
loadUtils: () => import("https://cdn.jsdelivr.net/npm/intl-tel-input@25.5.2/build/js/utils.js"),
|
|
||||||
});
|
|
||||||
|
|
||||||
form.addEventListener("submit", function(e){
|
|
||||||
if (!input.value.trim()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const number = iti.getNumber(intlTelInput.utils.numberFormat.E164);
|
|
||||||
if (number) {
|
|
||||||
input.value = number;
|
|
||||||
form.submit();
|
|
||||||
} else {
|
|
||||||
e.preventDefault();
|
|
||||||
input.focus();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
})();
|
|
||||||
</script>
|
|
||||||
|
|
||||||
{% if not object.membership %}
|
{% if not object.membership %}
|
||||||
<script>
|
<script>
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
|
@@ -305,8 +305,8 @@ PIC_WIDTH = 200
|
|||||||
PIC_RATIO = 1
|
PIC_RATIO = 1
|
||||||
|
|
||||||
# Custom phone number format
|
# Custom phone number format
|
||||||
PHONENUMBER_DB_FORMAT = 'E164'
|
PHONENUMBER_DB_FORMAT = 'NATIONAL'
|
||||||
PHONENUMBER_DEFAULT_REGION = None
|
PHONENUMBER_DEFAULT_REGION = 'FR'
|
||||||
|
|
||||||
# We add custom information to CAS, in order to give a normalized name to other services
|
# We add custom information to CAS, in order to give a normalized name to other services
|
||||||
CAS_AUTH_CLASS = 'member.auth.CustomAuthUser'
|
CAS_AUTH_CLASS = 'member.auth.CustomAuthUser'
|
||||||
|
@@ -29,8 +29,6 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
|||||||
<link rel="stylesheet" href="{% static "bootstrap4/css/bootstrap.min.css" %}">
|
<link rel="stylesheet" href="{% static "bootstrap4/css/bootstrap.min.css" %}">
|
||||||
<link rel="stylesheet" href="{% static "font-awesome/css/font-awesome.min.css" %}">
|
<link rel="stylesheet" href="{% static "font-awesome/css/font-awesome.min.css" %}">
|
||||||
<link rel="stylesheet" href="{% static "css/custom.css" %}">
|
<link rel="stylesheet" href="{% static "css/custom.css" %}">
|
||||||
|
|
||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/intl-tel-input@25.5.2/build/css/intlTelInput.css">
|
|
||||||
|
|
||||||
{# JQuery, Bootstrap and Turbolinks JavaScript #}
|
{# JQuery, Bootstrap and Turbolinks JavaScript #}
|
||||||
<script src="{% static "jquery/jquery.min.js" %}"></script>
|
<script src="{% static "jquery/jquery.min.js" %}"></script>
|
||||||
@@ -43,8 +41,6 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
|||||||
{# Translation in javascript files #}
|
{# Translation in javascript files #}
|
||||||
<script src="{% static "js/jsi18n/"|add:LANGUAGE_CODE|add:".js" %}"></script>
|
<script src="{% static "js/jsi18n/"|add:LANGUAGE_CODE|add:".js" %}"></script>
|
||||||
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/intl-tel-input@25.5.2/build/js/intlTelInput.min.js"></script>
|
|
||||||
|
|
||||||
{# If extra ressources are needed for a form, load here #}
|
{# If extra ressources are needed for a form, load here #}
|
||||||
{% if form.media %}
|
{% if form.media %}
|
||||||
{{ form.media }}
|
{{ form.media }}
|
||||||
|
@@ -19,7 +19,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
|||||||
{% endblocktrans %}
|
{% endblocktrans %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<form method="post" id="profile_form">
|
<form method="post">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
{{ form|crispy }}
|
{{ form|crispy }}
|
||||||
{{ profile_form|crispy }}
|
{{ profile_form|crispy }}
|
||||||
@@ -31,45 +31,3 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block extrajavascript %}
|
|
||||||
<!-- intl-tel-input CSS/JS -->
|
|
||||||
<script>
|
|
||||||
(() => {
|
|
||||||
const input = document.querySelector("input[name='phone_number']");
|
|
||||||
const form = document.querySelector("#profile_form");
|
|
||||||
|
|
||||||
if (!input || !form) {
|
|
||||||
console.error("Input phone_number ou form introuvable.");
|
|
||||||
}
|
|
||||||
|
|
||||||
const iti = window.intlTelInput(input, {
|
|
||||||
initialCountry: "auto",
|
|
||||||
nationalMode: false,
|
|
||||||
autoPlaceholder: "off",
|
|
||||||
geoIpLookup: callback => {
|
|
||||||
fetch("https://ipapi.co/json")
|
|
||||||
.then(res => res.json())
|
|
||||||
.then(data => callback(data.country_code))
|
|
||||||
.catch(() => callback("fr"));
|
|
||||||
},
|
|
||||||
loadUtils: () => import("https://cdn.jsdelivr.net/npm/intl-tel-input@25.5.2/build/js/utils.js"),
|
|
||||||
});
|
|
||||||
|
|
||||||
form.addEventListener("submit", function(e){
|
|
||||||
if (!input.value.trim()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const number = iti.getNumber(intlTelInput.utils.numberFormat.E164);
|
|
||||||
if (number) {
|
|
||||||
input.value = number;
|
|
||||||
form.submit();
|
|
||||||
} else {
|
|
||||||
e.preventDefault();
|
|
||||||
input.focus();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
})();
|
|
||||||
</script>
|
|
||||||
{% endblock %}
|
|
34
shell-static.nix
Executable file
34
shell-static.nix
Executable file
@@ -0,0 +1,34 @@
|
|||||||
|
# This is a workaround meant for use with the nix package manager. If you don't know what it is or don't use it, please ignore this file.
|
||||||
|
#
|
||||||
|
# The nk20 javascript static location are hardcoded for imperative system.
|
||||||
|
# This make ./manage.py collectstatic hard to use with nixos.
|
||||||
|
#
|
||||||
|
# A workaround is to enter a FHSUserEnv with the static placed under /share/javascript/<static>.
|
||||||
|
# This emulate a debian like system and enable collecting static normally with ./manage.py collectstatics.
|
||||||
|
# The regular shell.nix should be enough for other configurations.
|
||||||
|
#
|
||||||
|
# Warning, you are still supposed to use pip package with a venv !
|
||||||
|
{ pkgs ? import <nixpkgs> {} }:
|
||||||
|
(pkgs.buildFHSUserEnv {
|
||||||
|
name = "pipzone";
|
||||||
|
targetPkgs = pkgs: (with pkgs;
|
||||||
|
let
|
||||||
|
fhs-static = stdenv.mkDerivation {
|
||||||
|
name = "fhs-static";
|
||||||
|
buildCommand = ''
|
||||||
|
mkdir -p $out/share/javascript/bootstrap4
|
||||||
|
mkdir -p $out/share/javascript/jquery
|
||||||
|
ln -s ${python39Packages.xstatic-bootstrap}/lib/python3.9/site-packages/xstatic/pkg/bootstrap/data/* $out/share/javascript/bootstrap4
|
||||||
|
ln -s ${python39Packages.xstatic-jquery}/lib/python3.9/site-packages/xstatic/pkg/jquery/data/* $out/share/javascript/jquery
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
in [
|
||||||
|
fhs-static
|
||||||
|
python39
|
||||||
|
gettext
|
||||||
|
python39Packages.pip
|
||||||
|
python39Packages.virtualenv
|
||||||
|
python39Packages.setuptools
|
||||||
|
]);
|
||||||
|
runScript = "bash";
|
||||||
|
}).env
|
23
shell.nix
Executable file
23
shell.nix
Executable file
@@ -0,0 +1,23 @@
|
|||||||
|
# This is meant for use with the nix package manager. If you don't know what it is or don't use it, please ignore this file.
|
||||||
|
#
|
||||||
|
# This shell.nix contains all dependencies require to create a venv and pip install -r requirements.txt.
|
||||||
|
#
|
||||||
|
# Please check shell-static.nix for running ./manage.py collectstatics.
|
||||||
|
{ pkgs ? import <nixpkgs> {} }:
|
||||||
|
pkgs.mkShell {
|
||||||
|
buildInputs = with pkgs; [
|
||||||
|
python39
|
||||||
|
python39Packages.pip
|
||||||
|
python39Packages.setuptools
|
||||||
|
gettext
|
||||||
|
|
||||||
|
];
|
||||||
|
shellHook = ''
|
||||||
|
# Tells pip to put packages into $PIP_PREFIX instead of the usual locations.
|
||||||
|
# See https://pip.pypa.io/en/stable/user_guide/#environment-variables.
|
||||||
|
export PIP_PREFIX=$(pwd)/_build/pip_packages
|
||||||
|
export PYTHONPATH="$PIP_PREFIX/${pkgs.python39.sitePackages}:$PYTHONPATH"
|
||||||
|
export PATH="$PIP_PREFIX/bin:$PATH"
|
||||||
|
unset SOURCE_DATE_EPOCH
|
||||||
|
'';
|
||||||
|
}
|
Reference in New Issue
Block a user