Compare commits

..

1 Commits

Author SHA1 Message Date
Yann Weber 2393f93660 manager: make agenda's groups foldable (#85616)
gitea/chrono/pipeline/head There was a failure building this commit Details
2024-04-03 10:34:36 +02:00
6 changed files with 138 additions and 15 deletions

View File

@ -19,5 +19,5 @@ from django.urls import path
from . import api_views
urlpatterns = [
path('', api_views.preferences, name='api-user-preferences'),
path('save', api_views.save_preference, name='api-user-preferences'),
]

View File

@ -18,21 +18,37 @@ import json
from django.core.exceptions import PermissionDenied
from django.http import HttpResponse
from django.utils.translation import gettext_lazy as _
from django.views.decorators.csrf import csrf_exempt
from . import models
@csrf_exempt
def preferences(request):
def save_preference(request):
'''Save a user preference
Given a JSON with a single boolean value identified by a str, save the
key <-> value association in UserPreference
'''
if not request.user:
raise PermissionDenied()
user_pref, _ = models.UserPreferences.objects.get_or_create(user=request.user)
user_pref, created = models.UserPreferences.objects.get_or_create(user=request.user)
if not user_pref:
raise PermissionDenied()
if len(request.body) > 1000:
return HttpResponse(b'Payload too large', status_code=400)
return HttpResponse(_('Payload is too large').encode(), status=400)
bad_fmt_response = HttpResponse(_('Bad format').encode(), status=400)
try:
prefs = json.loads(request.body)
except json.DecodeError:
return HttpResponse(b'Bad format')
user_pref.update_preferences(prefs)
return HttpResponse('')
except json.JSONDecodeError:
return bad_fmt_response
if not isinstance(prefs, dict) or len(prefs) != 1:
return bad_fmt_response
name, value = list(prefs.items())[0]
if not isinstance(name, str) or not isinstance(value, bool):
return bad_fmt_response
user_pref.update_preference(name, value)
return HttpResponse(b'', status=204)

View File

@ -24,11 +24,8 @@ class UserPreferences(models.Model):
preferences = models.JSONField(_('Preferences'), default=dict)
def get_preference(self, name):
return self.preferences.get(name)
return self.preferences.get(name) or False
def get_preferences(self, prefix):
return {k: v for k, v in self.preferences.items() if k.startswith(prefix)}
def update_preferences(self, preferences):
self.preferences.update(preferences)
def update_preference(self, name, value):
self.preferences.update({name: value})
self.save()

View File

@ -6,7 +6,7 @@ $(function() {
if (old_folded == new_folded) { return; }
var pref_message = Object();
pref_message[mu.target.dataset.sectionFoldedPrefName] = new_folded;
fetch('/api/user_preferences/', {
fetch('/api/user_preferences/save', {
method: 'POST',
credentials: 'include',
headers: {'Accept': 'application/json', 'Content-Type': 'application/json'},

View File

@ -0,0 +1,80 @@
import json
import pytest
from django.urls import reverse
from chrono.apps.user_preferences.models import UserPreferences
from tests.utils import login
pytestmark = pytest.mark.django_db
def test_user_preferences_api_ok(app, admin_user):
UserPreferences.objects.all().delete()
login(app)
fake_id = 'fake-id-1'
url = reverse('api-user-preferences')
app.post_json(url, params={fake_id: True}, status=204)
user_pref = UserPreferences.objects.get(user=admin_user)
assert user_pref
assert fake_id in user_pref.preferences
assert user_pref.preferences[fake_id] is True
app.post_json(url, params={fake_id: False}, status=204)
user_pref = UserPreferences.objects.get(user=admin_user)
assert user_pref
assert fake_id in user_pref.preferences
assert user_pref.preferences[fake_id] is False
fake_id2 = 'fake-id-2'
app.post_json(url, params={fake_id2: False}, status=204)
user_pref = UserPreferences.objects.get(user=admin_user)
assert user_pref
assert fake_id in user_pref.preferences
assert fake_id2 in user_pref.preferences
assert user_pref.preferences[fake_id] is False
assert user_pref.preferences[fake_id2] is False
app.post_json(url, params={fake_id2: False}, status=204)
user_pref = UserPreferences.objects.get(user=admin_user)
assert user_pref
assert fake_id in user_pref.preferences
assert fake_id2 in user_pref.preferences
assert user_pref.preferences[fake_id] is False
assert user_pref.preferences[fake_id2] is False
app.post_json(url, params={fake_id2: True}, status=204)
user_pref = UserPreferences.objects.get(user=admin_user)
assert user_pref
assert fake_id in user_pref.preferences
assert fake_id2 in user_pref.preferences
assert user_pref.preferences[fake_id] is False
assert user_pref.preferences[fake_id2] is True
@pytest.mark.parametrize(
'bad_body',
(
json.dumps({'fake-id-1': True, 'fake-id-2': False}),
json.dumps({'fake-id-1': 'true'}),
json.dumps({'fake-id-1': 1}),
'{\'fake-id-1\': true',
),
)
def test_user_preferences_api_invalid(app, admin_user, bad_body):
login(app)
url = reverse('api-user-preferences')
app.post(url, params=bad_body, status=400)
def test_user_preferences_api_large_payload(app, admin_user):
login(app)
url = reverse('api-user-preferences')
app.post(url, params='a' * 1024, status=400)
app.post_json(url, params={'b' * 1024: True}, status=400)

View File

@ -0,0 +1,30 @@
import pytest
from django.template import Context, Template
from chrono.apps.user_preferences.models import UserPreferences
from chrono.manager.templatetags.chrono import get_preference
from tests.utils import login
pytestmark = pytest.mark.django_db
def context(user):
return Context({'user': user})
def test_manager_templatetags_get_preference(app, simple_user):
login(app, 'user', 'user')
t = Template('{% load chrono %}{% if user|get_preference:\'fake-id-1\' %}OK{% else %}KO{% endif %}')
res = t.render(context(simple_user))
assert res == 'KO'
user_prefs, created = UserPreferences.objects.get_or_create(user=simple_user)
user_prefs.update_preference('fake-id-1', False)
res = t.render(context(simple_user))
assert res == 'KO'
user_prefs.update_preference('fake-id-1', True)
res = t.render(context(simple_user))
assert res == 'OK'