Skip to content

Commit

Permalink
feat(Activités des structures): Ajout du choix du périmètre d'interve…
Browse files Browse the repository at this point in the history
…ntion aux niveaux des activités (#1457)
  • Loading branch information
SebastienReuiller authored Oct 21, 2024
1 parent a06e89a commit 8dc6f66
Show file tree
Hide file tree
Showing 13 changed files with 542 additions and 66 deletions.
4 changes: 2 additions & 2 deletions lemarche/siaes/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -740,7 +740,7 @@ class SiaeActivityAdmin(admin.ModelAdmin):
search_fields = ["id", "siae__id", "siae__name"]
search_help_text = "Cherche sur les champs : ID, Structure (ID, Nom)"

autocomplete_fields = ["siae", "sectors", "location"]
autocomplete_fields = ["siae", "sectors", "locations"]
readonly_fields = ["created_at", "updated_at"]

fieldsets = (
Expand All @@ -759,7 +759,7 @@ class SiaeActivityAdmin(admin.ModelAdmin):
(
"Localisation et périmètre d'intervention",
{
"fields": ("location", "geo_range", "geo_range_custom_distance"),
"fields": ("locations", "geo_range", "geo_range_custom_distance"),
},
),
("Dates", {"fields": ("created_at", "updated_at")}),
Expand Down
7 changes: 7 additions & 0 deletions lemarche/siaes/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@
GEO_RANGE_REGION = "REGION"
GEO_RANGE_CUSTOM = "CUSTOM"
GEO_RANGE_COUNTRY = "COUNTRY"
GEO_RANGE_ZONES = "ZONES"

GEO_RANGE_CHOICES = (
(GEO_RANGE_COUNTRY, "France entière"),
Expand All @@ -88,6 +89,12 @@
(GEO_RANGE_CUSTOM, "Distance en kilomètres"),
)

ACTIVITIES_GEO_RANGE_CHOICES = (
(GEO_RANGE_COUNTRY, "France entière"),
(GEO_RANGE_CUSTOM, "Distance en kilomètres"),
(GEO_RANGE_ZONES, "Zone(s) d'intervention personnalisée(s)"),
)

SOURCE_ASP = "ASP"
SOURCE_GEIQ = "GEIQ"
SOURCE_EA_EATT = "EA_EATT"
Expand Down
18 changes: 17 additions & 1 deletion lemarche/siaes/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import factory.fuzzy
from factory.django import DjangoModelFactory

from lemarche.sectors.factories import SectorGroupFactory
from lemarche.siaes import constants as siae_constants
from lemarche.siaes.models import (
Siae,
Expand Down Expand Up @@ -69,13 +70,28 @@ class SiaeActivityFactory(DjangoModelFactory):
class Meta:
model = SiaeActivity

presta_type = factory.List([factory.fuzzy.FuzzyChoice([key for (key, value) in siae_constants.PRESTA_CHOICES])])
class Params:
with_country_perimeter = factory.Trait(geo_range=siae_constants.GEO_RANGE_COUNTRY)
with_custom_distance_perimeter = factory.Trait(
geo_range=siae_constants.GEO_RANGE_CUSTOM,
geo_range_custom_distance=factory.fuzzy.FuzzyInteger(1, 100),
)
with_zones_perimeter = factory.Trait(geo_range=siae_constants.GEO_RANGE_ZONES)

sector_group = factory.SubFactory(SectorGroupFactory)

presta_type = factory.List([factory.fuzzy.FuzzyChoice([key for (key, _) in siae_constants.PRESTA_CHOICES])])

@factory.post_generation
def sectors(self, create, extracted, **kwargs):
if extracted:
self.sectors.add(*extracted)

@factory.post_generation
def locations(self, create, extracted, **kwargs):
if extracted:
self.locations.add(*extracted)


class SiaeOfferFactory(DjangoModelFactory):
class Meta:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Generated by Django 4.2.15 on 2024-10-07 14:03

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("perimeters", "0005_alter_perimeter_post_codes"),
("siaes", "0076_siaeactivity"),
]

operations = [
migrations.RemoveField(
model_name="siaeactivity",
name="location",
),
migrations.AddField(
model_name="siaeactivity",
name="locations",
field=models.ManyToManyField(
blank=True, related_name="siae_activities", to="perimeters.perimeter", verbose_name="Localisations"
),
),
migrations.AlterField(
model_name="siaeactivity",
name="geo_range",
field=models.CharField(
blank=True,
choices=[
("COUNTRY", "France entière"),
("CUSTOM", "Distance en kilomètres"),
("ZONES", "Zone(s) d'intervention personnalisée(s)"),
],
db_index=True,
max_length=20,
verbose_name="Périmètre d'intervention",
),
),
]
33 changes: 6 additions & 27 deletions lemarche/siaes/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -1428,25 +1428,19 @@ class SiaeActivity(models.Model):
null=True,
db_index=True,
)
location: Perimeter = models.ForeignKey(
to="perimeters.Perimeter",
verbose_name="Localisation",
related_name="siae_activities",
on_delete=models.DO_NOTHING,
blank=True,
null=True,
locations = models.ManyToManyField(
"perimeters.Perimeter", verbose_name="Localisations", related_name="siae_activities", blank=True
)
geo_range = models.CharField(
verbose_name="Périmètre d'intervention",
max_length=20,
choices=siae_constants.GEO_RANGE_CHOICES,
choices=siae_constants.ACTIVITIES_GEO_RANGE_CHOICES,
blank=True,
db_index=True,
)
geo_range_custom_distance = models.IntegerField(
verbose_name="Distance en kilomètres (périmètre d'intervention)", blank=True, null=True
)

created_at = models.DateTimeField(verbose_name="Date de création", default=timezone.now)
updated_at = models.DateTimeField(verbose_name="Date de modification", auto_now=True)

Expand All @@ -1463,28 +1457,13 @@ def presta_type_display(self) -> str:
def geo_range_pretty_display(self):
if self.geo_range == siae_constants.GEO_RANGE_COUNTRY:
return self.get_geo_range_display()
elif self.geo_range == siae_constants.GEO_RANGE_REGION:
return f"{self.get_geo_range_display().lower()} ({self.siae.region})"
elif self.geo_range == siae_constants.GEO_RANGE_DEPARTMENT:
return f"{self.get_geo_range_display().lower()} ({self.siae.department})"
elif self.geo_range == siae_constants.GEO_RANGE_ZONES:
return f"{self.get_geo_range_display()} : {', '.join(self.locations.values_list('name', flat=True))}"
elif self.geo_range == siae_constants.GEO_RANGE_CUSTOM:
if self.geo_range_custom_distance:
return f"{self.geo_range_custom_distance} km"
return f"{self.geo_range_custom_distance} km de {self.siae.city}"
return "non disponible"

@property
def geo_range_pretty_title(self):
if self.geo_range == siae_constants.GEO_RANGE_COUNTRY:
return self.geo_range_pretty_display
elif self.geo_range == siae_constants.GEO_RANGE_REGION:
return self.siae.region
elif self.geo_range == siae_constants.GEO_RANGE_DEPARTMENT:
return self.siae.get_department_display()
elif self.geo_range == siae_constants.GEO_RANGE_CUSTOM:
if self.geo_range_custom_distance:
return f"{self.geo_range_pretty_display} de {self.siae.city}"
return self.geo_range_pretty_display


class SiaeOffer(models.Model):
name = models.CharField(verbose_name="Nom", max_length=255)
Expand Down
13 changes: 3 additions & 10 deletions lemarche/static/js/siae_activity_delete.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
document.addEventListener('alpine:init', function () {
Alpine.data('activityItem', () => ({
siaeSlug: null,
siaeActivityId: null,
siaeActivityNameDisplay: null,

initOptions(siaeSlug, siaeActivityId, siaeActivityNameDisplay) {
this.siaeSlug = siaeSlug;
initOptions(siaeActivityId, siaeActivityNameDisplay) {
this.siaeActivityId = siaeActivityId;
this.siaeActivityNameDisplay = siaeActivityNameDisplay;
},
Expand All @@ -20,13 +18,8 @@ document.addEventListener('alpine:init', function () {
if (modal.querySelector('#siae-activity-name-display')) {
modal.querySelector('#siae-activity-name-display').textContent = this.siaeActivityNameDisplay;
}

let formActionUrl = new URL(modalForm.getAttribute('data-action'));
formActionUrl.pathname = formActionUrl.pathname
.replace('siae-slug-to-replace', encodeURIComponent(this.siaeSlug))
.replace('siae-activity-id-to-replace', encodeURIComponent(this.siaeActivityId));

modalForm.setAttribute('action', formActionUrl.toString());
let formActionUrl = escapeHtml(modalForm.getAttribute('data-action'));
modalForm.setAttribute('action', formActionUrl.replace('siae-activity-id-to-replace', this.siaeActivityId.replace(/\D/g, '')));

const modalDialog = document.getElementById(modalID);
dsfr(modalDialog).modal.disclose();
Expand Down
22 changes: 9 additions & 13 deletions lemarche/static/js/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ window.addEventListener('DOMContentLoaded', function () {
initSuperBadges();

// some elements have their url in data-url attribute
$(document).on("click", ".with-data-url", function(e) {
$(document).on("click", ".with-data-url", function (e) {
window.location.href = $(this).data("url");
});
});
Expand Down Expand Up @@ -57,13 +57,6 @@ let toggleInputElement = (toggle, element, required = undefined) => {
}
}

const initModalMessages = () => {
var elements = document.getElementsByClassName('modal-message-alert');
for (var i = 0; i < elements.length; i++) {
OpenBootstrapModal(elements[i]);
}
}

const initSuperBadges = () => {
$('.super-badge-badge').each(function (element) {
$(this).tooltip(
Expand Down Expand Up @@ -103,8 +96,11 @@ const initSuperBadges = () => {
})
}

function OpenBootstrapModal(elmt) {
setTimeout(function () {
$(elmt).modal('show');
}, 1000);
}
function escapeHtml(unsafe) {
return unsafe
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&#039;");
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ <h3 id="siae_activity_delete_modal_title" class="fr-modal__title">Supprimer</h3>
<div class="fr-modal__footer">
<div class="fr-btns-group fr-btns-group--right fr-btns-group--inline-reverse fr-btns-group--inline-lg">
<form method="post"
data-action="{% url 'dashboard_siaes:siae_edit_activities_delete' siae.slug|default:'siae-slug-to-replace' activity.id|default:'siae-activity-id-to-replace' %}">
data-action="{% url 'dashboard_siaes:siae_edit_activities_delete' siae.slug 'siae-activity-id-to-replace' %}">
{% csrf_token %}
<button class="fr-btn fr-btn--icon-left" type="submit">Confirmer</button>
</form>
Expand Down
63 changes: 58 additions & 5 deletions lemarche/templates/dashboard/siae_edit_activities_create.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<div class="fr-container">
<div class="fr-grid-row">
<div class="fr-col-12">
<form method="POST" action="">
<form method="post" action="">
{% csrf_token %}
{% if form.non_field_errors %}
<section class="fr-my-4v fr-input-group fr-input-group--error">
Expand Down Expand Up @@ -54,7 +54,11 @@ <h3 class="fr-callout__title fr-text--sm">
<div class="fr-grid-row fr-grid-row--gutters">
<div class="fr-col-12 fr-col-lg-8">
{% dsfr_form_field form.geo_range %}
{% dsfr_form_field form.geo_range_custom_distance %}
<div id="geo_range_custom_distance_wrapper">{% dsfr_form_field form.geo_range_custom_distance %}</div>
<div id="geo_range_locations_wrapper" class="fr-input-group">
{{ form.locations }}
{{ current_locations|json_script:"current-locations" }}
</div>
</div>
<div class="fr-col-12 fr-col-lg-4">
<div class="fr-callout fr-p-4v">
Expand All @@ -67,7 +71,7 @@ <h3 class="fr-callout__title fr-text--sm">
</div>
</div>
</div>
<div class="fr-grid-row fr-grid-row--gutters fr-mt-3v fr-mt-lg-5v">
<div class="fr-grid-row fr-grid-row--gutters fr-my-3v fr-my-lg-5v">
<div class="fr-col-12 fr-col-lg-8">
<ul class="fr-mt-2v fr-btns-group fr-btns-group--right fr-btns-group--inline-reverse fr-btns-group--inline-sm fr-btns-group--icon-left">
<li>
Expand All @@ -89,10 +93,11 @@ <h3 class="fr-callout__title fr-text--sm">
{% endblock content %}
{% block extra_js %}
<script type="text/javascript"
src="{% static 'js/siae_geo_range_field.js' %}"></script>
src="{% static 'js/perimeter_autocomplete_field.js' %}"></script>
<script type="text/javascript">
// dynamic sector display based on sector group selection
document.addEventListener('DOMContentLoaded', function() {
// -------------------------------------------------------------------
// dynamic sector display based on sector group selection
let sectorGroupSelect = document.getElementById('id_sector_group');
let sectorGroupSelectOptions = sectorGroupSelect.children;
let sectorRadios = document.querySelectorAll('#checkboxes-id_sectors input[type="checkbox"][name="sectors"]');
Expand Down Expand Up @@ -135,6 +140,54 @@ <h3 class="fr-callout__title fr-text--sm">
showSectorsOfSelectedSectorGroup(event.target.value);
}
})
// -------------------------------------------------------------------


// -------------------------------------------------------------------
// init locations autocomplete form fields
const LOCATION_AUTOCOMPLETE_ID = 'id_locations';
const LOCATION_AUTOCOMPLETE_CONTAINER_SELECTOR = '#dir_form_locations';
const LOCATION_SELECTED_CONTAINER_SELECTOR = '#locations-selected';
const LOCATION_HIDDEN_INPUT_SELECTOR_PREFIX = 'hiddenLocation';
const LOCATION_CURRENT_ID = 'current-locations';
const locationsAutoComplete = new PerimetersMultiAutocomplete(LOCATION_AUTOCOMPLETE_ID, LOCATION_AUTOCOMPLETE_CONTAINER_SELECTOR, LOCATION_SELECTED_CONTAINER_SELECTOR, LOCATION_HIDDEN_INPUT_SELECTOR_PREFIX, LOCATION_CURRENT_ID);
locationsAutoComplete.init();
// -------------------------------------------------------------------


// -------------------------------------------------------------------
// geo range custom distance input
let geoRangeCustomDistanceInput = document.getElementById('id_geo_range_custom_distance');
let geoRangeCustomDistanceInputGroup = document.getElementById('geo_range_custom_distance_wrapper');
let geoRangeLocationsInputGroup = document.getElementById('geo_range_locations_wrapper');

function toggleGeoRangeFieldsAccordingToRadio(value) {
geoRangeLocationsInputGroup.style.display = 'none';
geoRangeCustomDistanceInputGroup.style.display = 'none';
geoRangeCustomDistanceInput.disabled = true;

if (value === 'CUSTOM') {
geoRangeCustomDistanceInput.disabled = false;
geoRangeCustomDistanceInputGroup.style.display = 'block';
} else if (value === 'ZONES') {
geoRangeLocationsInputGroup.style.display = 'block';
}
}

let geoRangeRadios = document.querySelectorAll('input[type=radio][name="geo_range"]');
// init
geoRangeLocationsInputGroup.style.display = 'none';
geoRangeCustomDistanceInputGroup.style.display = 'none';
geoRangeRadios.forEach(radio => {
if (radio.checked) {
toggleGeoRangeFieldsAccordingToRadio(radio.value);
}
});
// on change
geoRangeRadios.forEach(radio => radio.addEventListener('change', () => {
toggleGeoRangeFieldsAccordingToRadio(radio.value);
}));
// -------------------------------------------------------------------
});
</script>
{% endblock extra_js %}
4 changes: 1 addition & 3 deletions lemarche/templates/siaes/_siae_activity_card.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ <h4>{{ activity.sector_group }}</h4>
</p>
<p>
<span class="fr-icon-map-pin-2-line" aria-hidden="true"></span>
<span class="fr-sr-only">Intervient sur :</span>{{ activity.geo_range_pretty_title }}
<span class="fr-icon-road-map-line fr-ml-2w" aria-hidden="true"></span>
<span>{{ activity.geo_range_pretty_display }}</span>
</p>
</div>
Expand All @@ -32,7 +30,7 @@ <h4>{{ activity.sector_group }}</h4>
<button id="siae-activity-delete-modal-btn"
class="fr-btn fr-btn--sm fr-btn--tertiary-no-outline fr-icon-delete-line"
x-data="activityItem"
x-init="initOptions('{{ activity.siae.slug }}','{{ activity.id }}','{{ activity.sector_group|escapejs }}')"
x-init="initOptions('{{ activity.id }}','{{ activity.sector_group|escapejs }}')"
@click="remove"
title="Supprimer l'activité">
<i class="ri-delete-bin-line ri-xl"></i>
Expand Down
Loading

0 comments on commit 8dc6f66

Please sign in to comment.