feat: allow technicians and observers to access mobile home via query parameter and session state
This commit is contained in:
parent
6d2de3a7c8
commit
27ab3a8c1b
6 changed files with 63 additions and 13 deletions
|
|
@ -153,8 +153,8 @@
|
||||||
<i class="bi bi-arrow-left fs-4"></i>
|
<i class="bi bi-arrow-left fs-4"></i>
|
||||||
</a>
|
</a>
|
||||||
{% elif mobile_view or is_mobile %}
|
{% elif mobile_view or is_mobile %}
|
||||||
<a href="{% url 'mobile:mobile_index' %}" class="nav-link" style="color: white;">
|
<a href="{% url 'mobile:mobile_index' %}?home=1" class="nav-link" style="color: white;" title="{% translate 'Accueil' %}">
|
||||||
<i class="bi bi-house fs-3" title="Home"></i>
|
<i class="bi bi-house fs-3"></i>
|
||||||
</a>
|
</a>
|
||||||
{% else %}
|
{% else %}
|
||||||
<a href="/" class="nav-link" style="color: white;">
|
<a href="/" class="nav-link" style="color: white;">
|
||||||
|
|
|
||||||
|
|
@ -188,11 +188,22 @@
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
transition: none !important;
|
||||||
|
}
|
||||||
|
.maplibregl-marker {
|
||||||
|
transition: none !important;
|
||||||
|
}
|
||||||
|
.asset-map-marker i {
|
||||||
|
display: inline-flex;
|
||||||
transition: transform 0.15s ease;
|
transition: transform 0.15s ease;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
.asset-map-marker:hover i, .asset-map-marker:active i {
|
||||||
|
transform: scale(1.2);
|
||||||
}
|
}
|
||||||
.asset-map-marker:hover, .asset-map-marker:active {
|
.asset-map-marker:hover, .asset-map-marker:active {
|
||||||
transform: scale(1.15);
|
|
||||||
z-index: 5;
|
z-index: 5;
|
||||||
|
box-shadow: 0 4px 10px rgba(0,0,0,0.4);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Volet inférieur (Bottom Sheet) pour prévisualisation */
|
/* Volet inférieur (Bottom Sheet) pour prévisualisation */
|
||||||
|
|
@ -714,7 +725,7 @@
|
||||||
mapMoveTimeout = setTimeout(() => {
|
mapMoveTimeout = setTimeout(() => {
|
||||||
if (currentView !== 'map') return;
|
if (currentView !== 'map') return;
|
||||||
fetchAndRenderAssets(true); // fromMapMove = true -> synchronise carte et liste
|
fetchAndRenderAssets(true); // fromMapMove = true -> synchronise carte et liste
|
||||||
}, 350);
|
}, 200);
|
||||||
});
|
});
|
||||||
|
|
||||||
map.on('load', () => {
|
map.on('load', () => {
|
||||||
|
|
|
||||||
|
|
@ -226,8 +226,8 @@
|
||||||
<nav class="navbar navbar-expand-lg navbar-custom">
|
<nav class="navbar navbar-expand-lg navbar-custom">
|
||||||
<div class="container-fluid d-flex justify-content-between align-items-center">
|
<div class="container-fluid d-flex justify-content-between align-items-center">
|
||||||
{% block upleft %}
|
{% block upleft %}
|
||||||
<a href="{% url 'mobile:mobile_index' %}" class="nav-link navbar-upleft" style="color: white;">
|
<a href="{% url 'mobile:mobile_index' %}?home=1" class="nav-link navbar-upleft" style="color: white;" title="{% translate 'Accueil' %}">
|
||||||
<i class="bi bi-house fs-3" title="Home"></i>
|
<i class="bi bi-house fs-3"></i>
|
||||||
</a>
|
</a>
|
||||||
{% endblock upleft %}
|
{% endblock upleft %}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -65,6 +65,35 @@ class MobileIndexViewTests(TestCase):
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
self.assertTrue(response.context["can_add_structures_repair"])
|
self.assertTrue(response.context["can_add_structures_repair"])
|
||||||
|
|
||||||
|
def test_technician_can_access_home_with_home_param_and_see_assets(self):
|
||||||
|
"""Technicians are redirected initially, but can access the home page via ?home=1 or subsequent navigation."""
|
||||||
|
technician_role, _ = Role.objects.get_or_create(name="technician")
|
||||||
|
self.user_config.roles.add(technician_role)
|
||||||
|
|
||||||
|
thematic = Thematic.objects.create(code="signalisation", name_fr="Signalisation", name_nl="Signalisatie")
|
||||||
|
UserThematics.objects.create(
|
||||||
|
user_config=self.user_config,
|
||||||
|
thematic=thematic,
|
||||||
|
can_view_assets=True,
|
||||||
|
can_view_interventions=True
|
||||||
|
)
|
||||||
|
|
||||||
|
# 1. Initial access without ?home redirects to interventions
|
||||||
|
response = self.client.get(reverse("mobile:mobile_index"))
|
||||||
|
self.assertEqual(response.status_code, 302)
|
||||||
|
self.assertEqual(response.url, "/mobile/interventions/")
|
||||||
|
|
||||||
|
# 2. Access with ?home=1 allows viewing the home page
|
||||||
|
response = self.client.get(reverse("mobile:mobile_index") + "?home=1")
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
self.assertTrue(response.context["can_view_assets"])
|
||||||
|
self.assertContains(response, reverse("mobile:mobile_assets_index"))
|
||||||
|
self.assertContains(response, reverse("mobile:interventions_index_mobile"))
|
||||||
|
|
||||||
|
# 3. Subsequent access in the same session without ?home also stays on home
|
||||||
|
response = self.client.get(reverse("mobile:mobile_index"))
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
|
||||||
|
|
||||||
class MobileStockPermissionTests(TestCase):
|
class MobileStockPermissionTests(TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
|
|
||||||
|
|
@ -40,13 +40,23 @@ def index(request):
|
||||||
user_config = None
|
user_config = None
|
||||||
try:
|
try:
|
||||||
user_config = UserConfig.objects.get(user=request.user)
|
user_config = UserConfig.objects.get(user=request.user)
|
||||||
# Vérifie si l'utilisateur n'a qu'un seul rôle et que c'est 'technician'
|
|
||||||
roles = list(user_config.roles.values_list('name', flat=True))
|
roles = list(user_config.roles.values_list('name', flat=True))
|
||||||
if len(roles) == 1 and roles[0] == 'technician':
|
|
||||||
return redirect('/mobile/interventions/')
|
# Les techniciens (et observateurs) sont redirigés directement sur leur page de travail
|
||||||
# Vérifie si l'utilisateur n'a qu'un seul rôle et que c'est 'observer'
|
# lors de leur arrivée initiale dans la session (/mobile/), mais peuvent accéder à la page d'accueil ensuite
|
||||||
if len(roles) == 1 and roles[0] == 'observer':
|
# (ex: clic sur l'icône Accueil ?home=1, navigation interne depuis la session, etc.)
|
||||||
return redirect('/mobile/observations/')
|
wants_home = request.GET.get('home') == '1' or request.session.get('mobile_home_visited', False)
|
||||||
|
if not wants_home:
|
||||||
|
# Vérifie si l'utilisateur n'a qu'un seul rôle et que c'est 'technician'
|
||||||
|
if len(roles) == 1 and roles[0] == 'technician':
|
||||||
|
request.session['mobile_home_visited'] = True
|
||||||
|
return redirect('/mobile/interventions/')
|
||||||
|
# Vérifie si l'utilisateur n'a qu'un seul rôle et que c'est 'observer'
|
||||||
|
if len(roles) == 1 and roles[0] == 'observer':
|
||||||
|
request.session['mobile_home_visited'] = True
|
||||||
|
return redirect('/mobile/observations/')
|
||||||
|
else:
|
||||||
|
request.session['mobile_home_visited'] = True
|
||||||
|
|
||||||
except UserConfig.DoesNotExist:
|
except UserConfig.DoesNotExist:
|
||||||
# If no user config exists, return unauthorized (403)
|
# If no user config exists, return unauthorized (403)
|
||||||
|
|
|
||||||
|
|
@ -115,7 +115,7 @@
|
||||||
<a href="{% url 'mobile:notifications_settings_mobile' %}" class="btn btn-outline-secondary btn-sm" title="{% translate 'Paramètres' %}">
|
<a href="{% url 'mobile:notifications_settings_mobile' %}" class="btn btn-outline-secondary btn-sm" title="{% translate 'Paramètres' %}">
|
||||||
<i class="bi bi-gear"></i>
|
<i class="bi bi-gear"></i>
|
||||||
</a>
|
</a>
|
||||||
<a href="{% url 'mobile:mobile_index' %}" class="btn btn-outline-secondary btn-sm">
|
<a href="{% url 'mobile:mobile_index' %}?home=1" class="btn btn-outline-secondary btn-sm">
|
||||||
<i class="bi bi-house me-1"></i>{% translate "Accueil" %}
|
<i class="bi bi-house me-1"></i>{% translate "Accueil" %}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue