Skip to content
This repository has been archived by the owner on Jun 24, 2024. It is now read-only.

Commit

Permalink
Merge branch 'release/3.5.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexandreJunod committed Feb 21, 2024
2 parents 9483ece + bef7ad7 commit a58ebeb
Show file tree
Hide file tree
Showing 41 changed files with 602 additions and 89 deletions.
3 changes: 2 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
# COMPOSE_FILE=docker-compose.yml:docker-compose.thumbor.yml
COMPOSE_FILE=docker-compose.yml:docker-compose.dev.yml
COMPOSE_PATH_SEPARATOR=:

# If you don't want to run the migration script at production startup, set to "true"
DISABLE_MIGRATION_SCRIPT_ON_PRODUCTION=false
# If you don't want to clear public schema, set to "false"
CLEAR_PUBLIC_SCHEMA_ON_FIXTURIZE=true
# The django application container
Expand Down
1 change: 1 addition & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ services:
- /var/run/docker.sock:/var/run/docker.sock
environment:
ENV: PROD
DISABLE_MIGRATION_SCRIPT_ON_PRODUCTION:
CLEAR_PUBLIC_SCHEMA_ON_FIXTURIZE:
DJANGO_DOCKER_PORT:
STATIC_URL:
Expand Down
13 changes: 11 additions & 2 deletions entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,19 @@ set -e
# If not will, the container will fail and restart.
python3 manage.py shell -c "import django; django.db.connection.ensure_connection();"

# On PROD, we run migrations on startup.
# On PROD, we run migrations at startup unless explicitly disabled.
# If disabled, this command must be run manually for the application to function correctly after a model update.
if [ "$ENV" == "PROD" ] && [ "${DISABLE_MIGRATION_SCRIPT_ON_PRODUCTION}" != "true" ]; then
python3 manage.py migrate
fi

# On PROD, we always collect statics
if [ "$ENV" == "PROD" ]; then
scripts/migrate.sh
python3 manage.py collectstatic --no-input
fi

python3 manage.py update_integrator_permissions
python3 manage.py compilemessages -l fr

# Run the command
exec $@
3 changes: 3 additions & 0 deletions geocity/apps/accounts/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -690,6 +690,7 @@ class Meta:
"sites",
"expeditor_email",
"expeditor_name",
"reply_to_email",
"custom_signature",
"link",
"archive_link",
Expand Down Expand Up @@ -774,6 +775,7 @@ class AdministrativeEntityAdmin(IntegratorFilterMixin, admin.ModelAdmin):
"sites",
"expeditor_email",
"expeditor_name",
"reply_to_email",
"custom_signature",
"link",
"archive_link",
Expand Down Expand Up @@ -847,6 +849,7 @@ def __new__(cls, *args, **kwargs):
"sortable_str",
"expeditor_name",
"expeditor_email",
"reply_to_email",
"ofs_id",
"get_tags",
"get_is_single_form",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,6 @@ def handle(self, *args, **options):
for integrator_group in integrator_groups:
integrator_group.permissions.set(get_integrator_permissions())

self.stdout.write("Update of integrator permissions sucessful.")
self.stdout.write("Update of integrator permissions successful.")
except CommandError:
self.stdout.write("ERROR: Error while updating integrator permissions!")
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Generated by Django 4.2.9 on 2024-02-13 10:17

import django.core.validators
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("accounts", "0015_alter_siteprofile_integrator"),
]

operations = [
migrations.AddField(
model_name="administrativeentity",
name="reply_to_email",
field=models.CharField(
blank=True,
help_text="Permet de définir une adresse email de réponse autre que celle de l'expéditeur des notifications",
max_length=255,
validators=[
django.core.validators.RegexValidator(
message="Le format de l'adresse email n'est pas valable.",
regex="^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,63}$",
)
],
verbose_name="Adresse email de réponse",
),
),
]
12 changes: 12 additions & 0 deletions geocity/apps/accounts/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,18 @@ class AdministrativeEntity(models.Model):
)
],
)
reply_to_email = models.CharField(
_("Adresse email de réponse"),
max_length=255,
blank=True,
validators=[
RegexValidator(
regex=r"^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,63}$",
message="Le format de l'adresse email n'est pas valable.",
)
],
help_text="Permet de définir une adresse email de réponse autre que celle de l'expéditeur des notifications",
)
is_single_form_submissions = models.BooleanField(
_("Autoriser uniquement un objet par demande"),
default=True,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
{% load i18n %}
{% autoescape off %}
{% blocktranslate %}Bonjour {{ user.get_full_name }}{% endblocktranslate %},
{% load i18n %}{% autoescape off %}{% blocktranslate %}Bonjour {{ user.get_full_name }}{% endblocktranslate %},

{% translate "Nous devons simplement vérifier votre adresse e-mail avant que vous puissiez accéder à Geocity." %}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
{% load i18n %}
{% autoescape off %}
{% blocktranslate %}Bonjour {{ user.get_full_name }}{% endblocktranslate %},
{% load i18n %}{% autoescape off %}{% blocktranslate %}Bonjour {{ user.get_full_name }}{% endblocktranslate %},

{% translate "Pour votre information, quelqu'un a tenté de créer un compte Geocity avec votre adresse e-mail." %}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
{% load i18n %}{% autoescape off %}
{% translate "Bonjour," %}
{% load i18n %}{% autoescape off %}{% translate "Bonjour" %} {{ user.get_full_name }},

{% translate "Une demande de réinitialisation de mot de passe a été demandée." %}

{% translate "Veuillez vous rendre sur cette page et choisir un nouveau mot de passe :" %}
{% translate "Veuillez vous rendre sur cette page et choisir un nouveau mot de passe:" %}
{% block reset_link %}
{{ protocol }}://{{ domain }}{% url 'password_reset_confirm' uidb64=uid token=token %}
{% endblock %}
Expand All @@ -12,5 +11,6 @@
{% translate "Avec nos meilleures salutations," %}
{% translate "L'application de gestion des demandes" %}


{% translate "Ceci est un e-mail automatique, veuillez ne pas y répondre." %}
{% endautoescape %}
14 changes: 7 additions & 7 deletions geocity/apps/core/static/css/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -456,35 +456,35 @@ th.actions {

.status0 {
/* STATUS_DRAFT */
color: #DADBDF;
color: #dadbdf;
}
.status1 {
/* STATUS_SUBMITTED_FOR_VALIDATION */
color: #F88C52;
color: #f88c52;
}
.status2 {
/* STATUS_APPROVED */
color: #008c6f;
}
.status3 {
/* STATUS_PROCESSING */
color: #2FA4A2;
color: #d075e7;
}
.status4 {
/* STATUS_AWAITING_SUPPLEMENT */
color: #BD5947;
color: #bd5947;
}
.status5 {
/* STATUS_AWAITING_VALIDATION */
color: #4285B0;
color: #4285b0;
}
.status6 {
/* STATUS_REJECTED */
color: #DB5033;
color: #db5033;
}
.status7 {
/* STATUS_RECEIVED */
color: #A0B46F;
color: #a0b46f;
}

/* TRANSACTION STATUSES */
Expand Down
2 changes: 2 additions & 0 deletions geocity/apps/core/static/js/admin/display.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ document.addEventListener('DOMContentLoaded', () => {
document.getElementsByClassName('field-wms_layers')[0].classList.remove('display-none')
document.getElementsByClassName('field-wms_layers_order')[0].classList.remove('display-none')
document.getElementsByClassName('field-can_have_multiple_ranges')[0].classList.remove('display-none')
document.getElementsByClassName('field-geo_step_help_text')[0].classList.remove('display-none')
}

if (state == 2) {
Expand All @@ -15,6 +16,7 @@ document.addEventListener('DOMContentLoaded', () => {
document.getElementsByClassName('field-wms_layers')[0].classList.add('display-none')
document.getElementsByClassName('field-wms_layers_order')[0].classList.add('display-none')
document.getElementsByClassName('field-can_have_multiple_ranges')[0].classList.add('display-none')
document.getElementsByClassName('field-geo_step_help_text')[0].classList.add('display-none')
}
}

Expand Down
14 changes: 14 additions & 0 deletions geocity/apps/core/static/js/admin/form.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,18 @@ document.addEventListener('DOMContentLoaded', () => {

maxSubmissions.addEventListener('input', hideMaxSubmissions);
hideMaxSubmissions();

const validationDocument = document.getElementById('id_validation_document');
const validationDocumentRequiredFor = document.getElementById('id_validation_document_required_for').closest('.form-group.field-validation_document_required_for');

function hideValidationDocument() {
if (!validationDocument.checked) {
validationDocumentRequiredFor.style.display = 'none';
} else {
validationDocumentRequiredFor.style.display = 'block';
}
}

validationDocument.addEventListener('input', hideValidationDocument);
hideValidationDocument();
});
24 changes: 24 additions & 0 deletions geocity/apps/core/static/js/admin/form_field.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,15 @@ document.addEventListener('DOMContentLoaded', function() {
const regexLabelElement = regexRowElement.querySelector('label');
const isRegexPatternVisible = inputType === 'regex';

const minimumDateElement = document.getElementById('id_minimum_date');
const minimumDateRowElement = minimumDateElement.closest('.form-group');
const minimumDateLabelElement = minimumDateRowElement.querySelector('label');
const isMinimumDateVisible = inputType === 'date';
const maximumDateElement = document.getElementById('id_maximum_date');
const maximumDateRowElement = maximumDateElement.closest('.form-group');
const maximumDateLabelElement = maximumDateRowElement.querySelector('label');
const isMaximumDateVisible = inputType === 'date';

const lineNumberForTextareaElement = document.getElementById('id_line_number_for_textarea');
const lineNumberForTextareaRowElement = lineNumberForTextareaElement.closest('.form-group');
const lineNumberForTextareaLabelElement = lineNumberForTextareaRowElement.querySelector('label');
Expand Down Expand Up @@ -94,6 +103,13 @@ document.addEventListener('DOMContentLoaded', function() {
regexRowElement.classList.add(hiddenClass);
regexLabelElement.classList.remove(requiredClass);

minimumDateElement.removeAttribute('required');
minimumDateRowElement.classList.add(hiddenClass);
minimumDateLabelElement.classList.remove(requiredClass);
maximumDateElement.removeAttribute('required');
maximumDateRowElement.classList.add(hiddenClass);
maximumDateLabelElement.classList.remove(requiredClass);

lineNumberForTextareaElement.removeAttribute('required');
lineNumberForTextareaRowElement.classList.add(hiddenClass);
lineNumberForTextareaLabelElement.classList.remove(requiredClass);
Expand Down Expand Up @@ -137,6 +153,14 @@ document.addEventListener('DOMContentLoaded', function() {
regexRowElement.classList.remove(hiddenClass);
regexLabelElement.classList.add(requiredClass);
}
else if (isMinimumDateVisible || isMaximumDateVisible) {
minimumDateElement.setAttribute('required', '');
minimumDateRowElement.classList.remove(hiddenClass);
minimumDateLabelElement.classList.add(requiredClass);
maximumDateElement.setAttribute('required', '');
maximumDateRowElement.classList.remove(hiddenClass);
maximumDateLabelElement.classList.add(requiredClass);
}
else if (isLineNumberForTextareaVisible) {
lineNumberForTextareaElement.setAttribute('required', '');
lineNumberForTextareaRowElement.classList.remove(hiddenClass);
Expand Down
6 changes: 6 additions & 0 deletions geocity/apps/core/static/js/submission_submit.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,9 @@ checkbox.addEventListener("click", () => {
button.toggleAttribute("disabled");
}
});

let formNumber = document.querySelector("[data-geo-time-role='formNumber']");

if (formNumber.textContent == "1") {
formNumber.style.display = "none";
}
39 changes: 31 additions & 8 deletions geocity/apps/forms/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ class Meta:
}
),
"quick_access_slug": forms.TextInput(),
"validation_document_required_for": forms.RadioSelect(),
}
help_texts = {
"wms_layers": "URL pour la ou les couches WMS utiles à la saisie de la demande pour ce type d'objet",
Expand Down Expand Up @@ -220,7 +221,8 @@ class FormAdmin(SortableAdminMixin, IntegratorFilterMixin, admin.ModelAdmin):
"requires_payment",
"requires_online_payment",
"payment_settings",
"requires_validation_document",
"validation_document",
"get_validation_document_required_for",
"disable_validation_by_validators",
"is_anonymous",
"notify_services",
Expand All @@ -235,7 +237,6 @@ class FormAdmin(SortableAdminMixin, IntegratorFilterMixin, admin.ModelAdmin):
"publication_enabled",
"permanent_publication_enabled",
"max_submissions_nb_submissions",
"get_max_submissions_message",
"agenda_visible",
]
list_filter = ["administrative_entities"]
Expand Down Expand Up @@ -283,7 +284,8 @@ class FormAdmin(SortableAdminMixin, IntegratorFilterMixin, admin.ModelAdmin):
_("Validation et nombre max."),
{
"fields": (
"requires_validation_document",
"validation_document",
"validation_document_required_for",
"default_validation_text",
"disable_validation_by_validators",
"max_submissions",
Expand All @@ -307,6 +309,7 @@ class FormAdmin(SortableAdminMixin, IntegratorFilterMixin, admin.ModelAdmin):
"geometry_types",
"wms_layers",
"wms_layers_order",
"geo_step_help_text",
)
},
),
Expand Down Expand Up @@ -381,12 +384,18 @@ def max_submissions_nb_submissions(self, obj):
max_submissions_nb_submissions.admin_order_field = "max_submissions"
max_submissions_nb_submissions.short_description = _("Nombre maximum de demandes")

def get_max_submissions_message(self, obj):
return obj.max_submissions_message if obj.max_submissions else "-"
def get_validation_document_required_for(self, obj):
return (
obj.get_validation_document_required_for_display()
if obj.validation_document
else "-"
)

get_max_submissions_message.admin_order_field = "max_submissions_message"
get_max_submissions_message.short_description = _(
"Message lorsque le nombre maximal est atteint"
get_validation_document_required_for.admin_order_field = (
"validation_document_required_for"
)
get_validation_document_required_for.short_description = _(
"Document de validation obligatoire pour"
)

def get_queryset(self, request):
Expand Down Expand Up @@ -538,6 +547,18 @@ def clean_allowed_file_types(self):

return self.cleaned_data["allowed_file_types"]

def clean_maximum_date(self):
minimum_date = self.cleaned_data.get("minimum_date")
maximum_date = self.cleaned_data.get("maximum_date")

if minimum_date is not None and maximum_date is not None:
if minimum_date >= maximum_date:
raise forms.ValidationError(
_("La date maximale doit être ultérieure à la date minimale.")
)

return maximum_date

class Media:
js = ("js/admin/form_field.js",)

Expand Down Expand Up @@ -663,6 +684,8 @@ class FieldAdmin(IntegratorFilterMixin, admin.ModelAdmin):
"store_geometry_for_address_field",
"map_widget_configuration",
"allowed_file_types",
"minimum_date",
"maximum_date",
"integrator",
"form_list",
)
Expand Down
Loading

0 comments on commit a58ebeb

Please sign in to comment.