Compare commits

..

No commits in common. "b49db390805674949a3a6b6bcd90600ac7ebea1f" and "cbd36f110af81dea4f1222190cfa8f8bb4bb7d88" have entirely different histories.

8 changed files with 154 additions and 148 deletions

View File

@ -3,36 +3,8 @@ upstream note{
server unix:///var/www/note_kfet/note_kfet.sock; # file socket
}
# Redirect HTTP to nk20 HTTPS
server {
listen 80 default_server;
listen [::]:80 default_server;
location / {
return 301 https://nk20-beta.crans.org$request_uri;
}
}
# Redirect all HTTPS to nk20 HTTPS
server {
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
location / {
return 301 https://nk20-beta.crans.org$request_uri;
}
ssl_certificate /etc/letsencrypt/live/nk20-beta.crans.org/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/nk20-beta.crans.org/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
}
# configuration of the server
server {
listen 443 ssl;
listen [::]:443 ssl;
# the port your site will be served on
# the domain name it will serve for
server_name nk20-beta.crans.org; # substitute your machine's IP address or FQDN
@ -56,8 +28,23 @@ server {
include /var/www/note_kfet/uwsgi_params; # the uwsgi_params file you installed
}
listen 443 ssl;
ssl_certificate /etc/letsencrypt/live/nk20-beta.crans.org/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/nk20-beta.crans.org/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
}
server {
if ($host = nk20-beta.crans.org) {
return 301 https://$host$request_uri;
}
listen 80;
server_name nk20-beta.crans.org;
return 404;
}

View File

@ -20,19 +20,6 @@ class CustomAuthenticationForm(AuthenticationForm):
)
class UserForm(forms.ModelForm):
def _get_validation_exclusions(self):
# Django usernames can only contain letters, numbers, @, ., +, - and _.
# We want to allow users to have uncommon and unpractical usernames:
# That is their problem, and we have normalized aliases for us.
return super()._get_validation_exclusions() + ["username"]
class Meta:
model = User
fields = ('first_name', 'last_name', 'username', 'email',)
class ProfileForm(forms.ModelForm):
"""
A form for the extras field provided by the :model:`member.Profile` model.

View File

@ -26,7 +26,7 @@ from permission.models import Role
from permission.views import ProtectQuerysetMixin
from wei.models import WEIClub
from .forms import ProfileForm, ClubForm, MembershipForm, CustomAuthenticationForm, UserForm
from .forms import ProfileForm, ClubForm, MembershipForm, CustomAuthenticationForm
from .models import Club, Membership
from .tables import ClubTable, UserTable, MembershipTable
@ -47,10 +47,9 @@ class UserUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
Update the user information.
"""
model = User
form_class = UserForm
fields = ['first_name', 'last_name', 'username', 'email']
template_name = 'member/profile_update.html'
context_object_name = 'user_object'
profile_form = ProfileForm
def get_context_data(self, **kwargs):

View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-07-29 22:54+0200\n"
"POT-Creation-Date: 2020-07-29 10:56+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -186,12 +186,12 @@ msgstr ""
msgid "Type"
msgstr ""
#: apps/activity/tables.py:77 apps/member/forms.py:105
#: apps/activity/tables.py:77 apps/member/forms.py:92
#: apps/registration/forms.py:64 apps/treasury/forms.py:120
msgid "Last name"
msgstr ""
#: apps/activity/tables.py:79 apps/member/forms.py:110
#: apps/activity/tables.py:79 apps/member/forms.py:97
#: apps/registration/forms.py:69 apps/treasury/forms.py:122
#: templates/note/transaction_form.html:126
msgid "First name"
@ -279,35 +279,35 @@ msgstr ""
msgid "member"
msgstr ""
#: apps/member/forms.py:59 apps/member/views.py:78
#: apps/member/forms.py:46 apps/member/views.py:77
msgid "An alias with a similar name already exists."
msgstr ""
#: apps/member/forms.py:84 apps/registration/forms.py:44
#: apps/member/forms.py:71 apps/registration/forms.py:44
msgid "Inscription paid by Société Générale"
msgstr ""
#: apps/member/forms.py:86 apps/registration/forms.py:46
#: apps/member/forms.py:73 apps/registration/forms.py:46
msgid "Check this case is the Société Générale paid the inscription."
msgstr ""
#: apps/member/forms.py:91 apps/registration/forms.py:51
#: apps/member/forms.py:78 apps/registration/forms.py:51
msgid "Credit type"
msgstr ""
#: apps/member/forms.py:92 apps/registration/forms.py:52
#: apps/member/forms.py:79 apps/registration/forms.py:52
msgid "No credit"
msgstr ""
#: apps/member/forms.py:94
#: apps/member/forms.py:81
msgid "You can credit the note of the user."
msgstr ""
#: apps/member/forms.py:98 apps/registration/forms.py:57
#: apps/member/forms.py:85 apps/registration/forms.py:57
msgid "Credit amount"
msgstr ""
#: apps/member/forms.py:115 apps/registration/forms.py:74
#: apps/member/forms.py:102 apps/registration/forms.py:74
#: apps/treasury/forms.py:124 templates/note/transaction_form.html:132
msgid "Bank"
msgstr ""
@ -509,7 +509,7 @@ msgstr ""
msgid "fee"
msgstr ""
#: apps/member/models.py:303 apps/member/views.py:528 apps/wei/views.py:770
#: apps/member/models.py:303 apps/member/views.py:527 apps/wei/views.py:770
msgid "User is not a member of the parent club"
msgstr ""
@ -518,7 +518,7 @@ msgstr ""
msgid "The role {role} does not apply to the club {club}."
msgstr ""
#: apps/member/models.py:321 apps/member/views.py:537
#: apps/member/models.py:321 apps/member/views.py:536
msgid "User is already a member of the club"
msgstr ""
@ -539,45 +539,45 @@ msgstr ""
msgid "Renew"
msgstr ""
#: apps/member/views.py:65 apps/registration/forms.py:23
#: apps/member/views.py:64 apps/registration/forms.py:23
msgid "This address must be valid."
msgstr ""
#: apps/member/views.py:68 templates/member/profile_info.html:47
#: apps/member/views.py:67 templates/member/profile_info.html:47
#: templates/registration/future_profile_detail.html:48
#: templates/wei/weimembership_form.html:130
msgid "Update Profile"
msgstr ""
#: apps/member/views.py:184
#: apps/member/views.py:183
msgid "Search user"
msgstr ""
#: apps/member/views.py:523 apps/wei/views.py:761
#: apps/member/views.py:522 apps/wei/views.py:761
msgid ""
"This user don't have enough money to join this club, and can't have a "
"negative balance."
msgstr ""
#: apps/member/views.py:541
#: apps/member/views.py:540
msgid "The membership must start after {:%m-%d-%Y}."
msgstr ""
#: apps/member/views.py:546
#: apps/member/views.py:545
msgid "The membership must begin before {:%m-%d-%Y}."
msgstr ""
#: apps/member/views.py:563 apps/member/views.py:565 apps/member/views.py:567
#: apps/member/views.py:562 apps/member/views.py:564 apps/member/views.py:566
#: apps/registration/views.py:290 apps/registration/views.py:292
#: apps/registration/views.py:294
msgid "This field is required."
msgstr ""
#: apps/note/admin.py:122 apps/note/models/transactions.py:106
#: apps/note/admin.py:120 apps/note/models/transactions.py:106
msgid "source"
msgstr ""
#: apps/note/admin.py:130 apps/note/admin.py:172
#: apps/note/admin.py:128 apps/note/admin.py:170
#: apps/note/models/transactions.py:55 apps/note/models/transactions.py:119
msgid "destination"
msgstr ""
@ -761,7 +761,7 @@ msgstr ""
#: apps/note/models/transactions.py:228
#: templates/activity/activity_entry.html:13 templates/base.html:99
#: templates/note/transaction_form.html:15
#: templates/note/transaction_form.html:19
#: templates/note/transaction_form.html:140
msgid "Transfer"
msgstr ""
@ -780,11 +780,11 @@ msgstr ""
#: apps/note/models/transactions.py:277
#: templates/activity/activity_entry.html:17
#: templates/note/transaction_form.html:20
#: templates/note/transaction_form.html:24
msgid "Credit"
msgstr ""
#: apps/note/models/transactions.py:277 templates/note/transaction_form.html:24
#: apps/note/models/transactions.py:277 templates/note/transaction_form.html:28
msgid "Debit"
msgstr ""
@ -1522,7 +1522,7 @@ msgid "Guests list"
msgstr ""
#: templates/activity/activity_entry.html:22
#: templates/note/transaction_form.html:29
#: templates/note/transaction_form.html:33
msgid "Entries"
msgstr ""
@ -1707,7 +1707,7 @@ msgstr ""
msgid "Consum"
msgstr ""
#: templates/note/conso_form.html:39 templates/note/transaction_form.html:57
#: templates/note/conso_form.html:39 templates/note/transaction_form.html:61
#: templates/note/transaction_form.html:76
msgid "Name or alias..."
msgstr ""
@ -1736,12 +1736,12 @@ msgstr ""
msgid "Recent transactions history"
msgstr ""
#: templates/note/transaction_form.html:51
msgid "Select emitters"
#: templates/note/transaction_form.html:15
msgid "Gift"
msgstr ""
#: templates/note/transaction_form.html:60
msgid "I am the emitter"
#: templates/note/transaction_form.html:55
msgid "Select emitters"
msgstr ""
#: templates/note/transaction_form.html:70

View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-07-29 22:54+0200\n"
"POT-Creation-Date: 2020-07-29 10:56+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -187,12 +187,12 @@ msgstr "supprimer"
msgid "Type"
msgstr "Type"
#: apps/activity/tables.py:77 apps/member/forms.py:105
#: apps/activity/tables.py:77 apps/member/forms.py:92
#: apps/registration/forms.py:64 apps/treasury/forms.py:120
msgid "Last name"
msgstr "Nom de famille"
#: apps/activity/tables.py:79 apps/member/forms.py:110
#: apps/activity/tables.py:79 apps/member/forms.py:97
#: apps/registration/forms.py:69 apps/treasury/forms.py:122
#: templates/note/transaction_form.html:126
msgid "First name"
@ -280,35 +280,35 @@ msgstr "journaux de modifications"
msgid "member"
msgstr "adhérent"
#: apps/member/forms.py:59 apps/member/views.py:78
#: apps/member/forms.py:46 apps/member/views.py:77
msgid "An alias with a similar name already exists."
msgstr "Un alias avec un nom similaire existe déjà."
#: apps/member/forms.py:84 apps/registration/forms.py:44
#: apps/member/forms.py:71 apps/registration/forms.py:44
msgid "Inscription paid by Société Générale"
msgstr "Inscription payée par la Société générale"
#: apps/member/forms.py:86 apps/registration/forms.py:46
#: apps/member/forms.py:73 apps/registration/forms.py:46
msgid "Check this case is the Société Générale paid the inscription."
msgstr "Cochez cette case si la Société Générale a payé l'inscription."
#: apps/member/forms.py:91 apps/registration/forms.py:51
#: apps/member/forms.py:78 apps/registration/forms.py:51
msgid "Credit type"
msgstr "Type de rechargement"
#: apps/member/forms.py:92 apps/registration/forms.py:52
#: apps/member/forms.py:79 apps/registration/forms.py:52
msgid "No credit"
msgstr "Pas de rechargement"
#: apps/member/forms.py:94
#: apps/member/forms.py:81
msgid "You can credit the note of the user."
msgstr "Vous pouvez créditer la note de l'utisateur avant l'adhésion."
#: apps/member/forms.py:98 apps/registration/forms.py:57
#: apps/member/forms.py:85 apps/registration/forms.py:57
msgid "Credit amount"
msgstr "Montant à créditer"
#: apps/member/forms.py:115 apps/registration/forms.py:74
#: apps/member/forms.py:102 apps/registration/forms.py:74
#: apps/treasury/forms.py:124 templates/note/transaction_form.html:132
msgid "Bank"
msgstr "Banque"
@ -514,7 +514,7 @@ msgstr "l'adhésion finit le"
msgid "fee"
msgstr "cotisation"
#: apps/member/models.py:303 apps/member/views.py:528 apps/wei/views.py:770
#: apps/member/models.py:303 apps/member/views.py:527 apps/wei/views.py:770
msgid "User is not a member of the parent club"
msgstr "L'utilisateur n'est pas membre du club parent"
@ -523,7 +523,7 @@ msgstr "L'utilisateur n'est pas membre du club parent"
msgid "The role {role} does not apply to the club {club}."
msgstr "Le rôle {role} ne s'applique pas au club {club}."
#: apps/member/models.py:321 apps/member/views.py:537
#: apps/member/models.py:321 apps/member/views.py:536
msgid "User is already a member of the club"
msgstr "L'utilisateur est déjà membre du club"
@ -544,21 +544,21 @@ msgstr "adhésions"
msgid "Renew"
msgstr "Renouveler"
#: apps/member/views.py:65 apps/registration/forms.py:23
#: apps/member/views.py:64 apps/registration/forms.py:23
msgid "This address must be valid."
msgstr "Cette adresse doit être valide."
#: apps/member/views.py:68 templates/member/profile_info.html:47
#: apps/member/views.py:67 templates/member/profile_info.html:47
#: templates/registration/future_profile_detail.html:48
#: templates/wei/weimembership_form.html:130
msgid "Update Profile"
msgstr "Modifier le profil"
#: apps/member/views.py:184
#: apps/member/views.py:183
msgid "Search user"
msgstr "Chercher un utilisateur"
#: apps/member/views.py:523 apps/wei/views.py:761
#: apps/member/views.py:522 apps/wei/views.py:761
msgid ""
"This user don't have enough money to join this club, and can't have a "
"negative balance."
@ -566,25 +566,25 @@ msgstr ""
"Cet utilisateur n'a pas assez d'argent pour rejoindre ce club et ne peut pas "
"avoir un solde négatif."
#: apps/member/views.py:541
#: apps/member/views.py:540
msgid "The membership must start after {:%m-%d-%Y}."
msgstr "L'adhésion doit commencer après le {:%d/%m/%Y}."
#: apps/member/views.py:546
#: apps/member/views.py:545
msgid "The membership must begin before {:%m-%d-%Y}."
msgstr "L'adhésion doit commencer avant le {:%d/%m/%Y}."
#: apps/member/views.py:563 apps/member/views.py:565 apps/member/views.py:567
#: apps/member/views.py:562 apps/member/views.py:564 apps/member/views.py:566
#: apps/registration/views.py:290 apps/registration/views.py:292
#: apps/registration/views.py:294
msgid "This field is required."
msgstr "Ce champ est requis."
#: apps/note/admin.py:122 apps/note/models/transactions.py:106
#: apps/note/admin.py:120 apps/note/models/transactions.py:106
msgid "source"
msgstr "source"
#: apps/note/admin.py:130 apps/note/admin.py:172
#: apps/note/admin.py:128 apps/note/admin.py:170
#: apps/note/models/transactions.py:55 apps/note/models/transactions.py:119
msgid "destination"
msgstr "destination"
@ -771,7 +771,7 @@ msgstr ""
#: apps/note/models/transactions.py:228
#: templates/activity/activity_entry.html:13 templates/base.html:99
#: templates/note/transaction_form.html:15
#: templates/note/transaction_form.html:19
#: templates/note/transaction_form.html:140
msgid "Transfer"
msgstr "Virement"
@ -790,11 +790,11 @@ msgstr "banque"
#: apps/note/models/transactions.py:277
#: templates/activity/activity_entry.html:17
#: templates/note/transaction_form.html:20
#: templates/note/transaction_form.html:24
msgid "Credit"
msgstr "Crédit"
#: apps/note/models/transactions.py:277 templates/note/transaction_form.html:24
#: apps/note/models/transactions.py:277 templates/note/transaction_form.html:28
msgid "Debit"
msgstr "Débit"
@ -1577,7 +1577,7 @@ msgid "Guests list"
msgstr "Liste des invités"
#: templates/activity/activity_entry.html:22
#: templates/note/transaction_form.html:29
#: templates/note/transaction_form.html:33
msgid "Entries"
msgstr "Entrées"
@ -1769,7 +1769,7 @@ msgstr "Il n'y a pas d'utilisateur trouvé avec cette entrée."
msgid "Consum"
msgstr "Consommer"
#: templates/note/conso_form.html:39 templates/note/transaction_form.html:57
#: templates/note/conso_form.html:39 templates/note/transaction_form.html:61
#: templates/note/transaction_form.html:76
msgid "Name or alias..."
msgstr "Pseudo ou alias ..."
@ -1798,14 +1798,14 @@ msgstr "Consommations doubles"
msgid "Recent transactions history"
msgstr "Historique des transactions récentes"
#: templates/note/transaction_form.html:51
#: templates/note/transaction_form.html:15
msgid "Gift"
msgstr "Don"
#: templates/note/transaction_form.html:55
msgid "Select emitters"
msgstr "Sélection des émetteurs"
#: templates/note/transaction_form.html:60
msgid "I am the emitter"
msgstr "Je suis l'émetteur"
#: templates/note/transaction_form.html:70
msgid "Select receivers"
msgstr "Sélection des destinataires"
@ -1951,8 +1951,8 @@ msgid ""
"permission mask?"
msgstr ""
"Vous êtes connecté en tant que %(username)s, mais vous n'avez le droit "
"d'accéder à cette page. Voulez-vous essayer avec un autre compte, ou avec un "
"masque de permissions plus fort ?"
"d'accéder à cette page. Voulez-vous essayer avec un autre compte, ou avec "
"un masque de permissions plus fort ?"
#: templates/registration/login.html:23
msgid "Forgotten your password or username?"

View File

@ -223,9 +223,7 @@ function autoCompleteNote(field_id, note_list_id, notes, notes_display, alias_pr
// When the user type "Enter", the first alias is clicked
field.keypress(function (event) {
console.log(notes);
if (event.originalEvent.charCode === 13 && notes.length > 0) {
console.log(42);
let li_obj = field.parent().find("ul li").first();
displayNote(notes[0], li_obj.text(), user_note_field, profile_pic_field);
li_obj.trigger("click");

View File

@ -71,6 +71,16 @@ $(document).ready(function() {
let source = $("#source_note");
let dest = $("#dest_note");
$("#type_gift").click(function() {
$("#special_transaction_div").addClass('d-none');
source.attr('disabled', true);
source.val(username);
source.tooltip('hide');
$("#source_note_list").addClass('d-none');
dest.attr('disabled', false);
$("#dest_note_list").removeClass('d-none');
});
$("#type_transfer").click(function() {
$("#special_transaction_div").addClass('d-none');
source.attr('disabled', false);
@ -121,11 +131,13 @@ $(document).ready(function() {
dest.val(type);
});
// Ensure we begin in transfer mode. Removing these lines may cause problems when reloading.
let type_transfer = $("#type_transfer"); // Default mode
type_transfer.removeAttr('checked');
// Ensure we begin in gift mode. Removing these lines may cause problems when reloading.
let type_gift = $("#type_gift"); // Default mode
type_gift.removeAttr('checked');
$("#type_transfer").removeAttr('checked');
$("#type_credit").removeAttr('checked');
$("#type_debit").removeAttr('checked');
$("label[for='type_gift']").attr('class', 'btn btn-sm btn-outline-primary');
$("label[for='type_transfer']").attr('class', 'btn btn-sm btn-outline-primary');
$("label[for='type_credit']").attr('class', 'btn btn-sm btn-outline-primary');
$("label[for='type_debit']").attr('class', 'btn btn-sm btn-outline-primary');
@ -133,39 +145,62 @@ $(document).ready(function() {
if (location.hash)
$("#type_" + location.hash.substr(1)).click();
else
type_transfer.click();
type_gift.click();
location.hash = "";
$("#source_me").click(function() {
// Shortcut to set the current user as the only emitter
reset();
let source_note = $("#source_note");
source_note.focus();
source_note.val(username);
let event = jQuery.Event("keyup");
event.originalEvent = {charCode: 0};
source_note.trigger(event);
console.log(sources.length);
let fill_note = function() {
if (sources.length === 0) {
setTimeout(fill_note, 100);
return;
}
event = jQuery.Event("keypress");
event.originalEvent = {charCode: 13};
source_note.trigger(event);
source_note.tooltip('hide');
source_note.val('');
$("#dest_note").focus();
};
fill_note();
});
});
$("#btn_transfer").click(function() {
if ($("#type_transfer").is(':checked')) {
if ($("#type_gift").is(':checked')) {
dests_notes_display.forEach(function (dest) {
$.post("/api/note/transaction/transaction/",
{
"csrfmiddlewaretoken": CSRF_TOKEN,
"quantity": dest.quantity,
"amount": 100 * $("#amount").val(),
"reason": $("#reason").val(),
"valid": true,
"polymorphic_ctype": TRANSFER_POLYMORPHIC_CTYPE,
"resourcetype": "Transaction",
"source": user_id,
"destination": dest.note.id,
"destination_alias": dest.name
}).done(function () {
addMsg("Le transfert de "
+ pretty_money(dest.quantity * 100 * $("#amount").val()) + " de votre note "
+ " vers la note " + dest.name + " a été fait avec succès !", "success");
reset();
}).fail(function () { // do it again but valid = false
$.post("/api/note/transaction/transaction/",
{
"csrfmiddlewaretoken": CSRF_TOKEN,
"quantity": dest.quantity,
"amount": 100 * $("#amount").val(),
"reason": $("#reason").val(),
"valid": false,
"invalidity_reason": "Solde insuffisant",
"polymorphic_ctype": TRANSFER_POLYMORPHIC_CTYPE,
"resourcetype": "Transaction",
"source": user_id,
"destination": dest.note.id,
"destination_alias": dest.name
}).done(function () {
addMsg("Le transfert de "
+ pretty_money(dest.quantity * 100 * $("#amount").val()) + " de votre note "
+ " vers la note " + dest.name + " a échoué : Solde insuffisant", "danger");
reset();
}).fail(function (err) {
addMsg("Le transfert de "
+ pretty_money(dest.quantity * 100 * $("#amount").val()) + " de votre note "
+ " vers la note " + dest.name + " a échoué : " + err.responseText, "danger");
reset();
});
});
});
}
else if ($("#type_transfer").is(':checked')) {
sources_notes_display.forEach(function (source) {
dests_notes_display.forEach(function (dest) {
$.post("/api/note/transaction/transaction/",

View File

@ -10,7 +10,11 @@ SPDX-License-Identifier: GPL-2.0-or-later
<div class="row">
<div class="col-xl-12">
<div class="btn-group btn-group-toggle" style="width: 100%; padding: 0 0 2em 0" data-toggle="buttons">
<label for="type_transfer" class="btn btn-sm btn-outline-primary active">
<label for="type_gift" class="btn btn-sm btn-outline-primary active">
<input type="radio" name="transaction_type" id="type_gift" checked>
{% trans "Gift" %}
</label>
<label for="type_transfer" class="btn btn-sm btn-outline-primary">
<input type="radio" name="transaction_type" id="type_transfer">
{% trans "Transfer" %}
</label>
@ -55,10 +59,6 @@ SPDX-License-Identifier: GPL-2.0-or-later
</ul>
<div class="card-body">
<input class="form-control mx-auto d-block" type="text" id="source_note" placeholder="{% trans "Name or alias..." %}" />
<hr>
<button class="form-control mx-auto d-block btn btn-secondary" id="source_me">
{% trans "I am the emitter" %}
</button>
</div>
</div>
</div>