accrete 0.0.142__py3-none-any.whl → 0.0.144__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. accrete/contrib/log/admin.py +1 -1
  2. accrete/contrib/system_mail/tasks.py +4 -5
  3. accrete/contrib/ui/__init__.py +16 -14
  4. accrete/contrib/ui/filter.py +22 -13
  5. accrete/contrib/ui/response.py +540 -0
  6. accrete/contrib/ui/static/css/accrete.css +69 -12
  7. accrete/contrib/ui/static/css/accrete.css.map +1 -1
  8. accrete/contrib/ui/static/css/accrete.scss +370 -300
  9. accrete/contrib/ui/templates/ui/content.html +0 -0
  10. accrete/contrib/ui/templates/ui/content_right.html +2 -2
  11. accrete/contrib/ui/templates/ui/detail.html +11 -0
  12. accrete/contrib/ui/templates/ui/filter/filter.html +5 -5
  13. accrete/contrib/ui/templates/ui/filter/query_tags.html +1 -1
  14. accrete/contrib/ui/templates/ui/form_error.html +1 -1
  15. accrete/contrib/ui/templates/ui/layout.html +69 -64
  16. accrete/contrib/ui/templates/ui/list.html +21 -19
  17. accrete/contrib/ui/templates/ui/list_update.html +9 -3
  18. accrete/contrib/ui/templates/ui/message.html +1 -1
  19. accrete/contrib/ui/templates/ui/modal.html +41 -32
  20. accrete/contrib/ui/templates/ui/table_row_update.html +2 -2
  21. accrete/contrib/ui/templates/ui/templatetags/field.html +19 -6
  22. accrete/contrib/ui/templates/ui/widgets/model_search_select.html +7 -7
  23. accrete/contrib/ui/templates/ui/widgets/model_search_select_multi.html +3 -3
  24. accrete/contrib/ui/templatetags/ui.py +24 -2
  25. accrete/contrib/user/templates/user/password_forgotten.html +1 -0
  26. accrete/contrib/user/templates/user/user_preferences.html +43 -0
  27. accrete/contrib/user/views.py +36 -37
  28. accrete/migrations/0008_alter_member_access_groups_and_more.py +23 -0
  29. accrete/utils/__init__.py +1 -0
  30. accrete/utils/forms.py +48 -28
  31. accrete/utils/views.py +1 -2
  32. accrete/views.py +2 -3
  33. {accrete-0.0.142.dist-info → accrete-0.0.144.dist-info}/METADATA +2 -2
  34. {accrete-0.0.142.dist-info → accrete-0.0.144.dist-info}/RECORD +36 -34
  35. accrete/contrib/ui/context.py +0 -123
  36. accrete/contrib/ui/static/css/.sass-cache/15adf1eed05371361b08787c918a7f18fc15be79/accrete.scssc +0 -0
  37. accrete/contrib/ui/utils.py +0 -77
  38. accrete/contrib/user/templates/user/user_form.html +0 -58
  39. {accrete-0.0.142.dist-info → accrete-0.0.144.dist-info}/WHEEL +0 -0
  40. {accrete-0.0.142.dist-info → accrete-0.0.144.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,43 @@
1
+ {#{% extends 'ui/layout.html' %}#}
2
+ {% load i18n %}
3
+ {% load partials %}
4
+ {% load ui %}
5
+
6
+ {% partialdef header %}
7
+ {% if not user.is_managed %}
8
+ <button class="button is-light" hx-get="{% url 'user:change_password' %}" hx-swap="none">
9
+ <span>{% translate 'Change Password' %}</span>
10
+ </button>
11
+ <button class="button is-light" hx-get="{% url 'user:change_email' %}" hx-swap="none">
12
+ <span>{% translate 'Change E-Mail' %}</span>
13
+ </button>
14
+ {% endif %}
15
+ {% endpartialdef %}
16
+
17
+ {% partialdef data %}
18
+ <section class="box">
19
+ <form id="user-form" hx-post="{% url 'user:detail' %}" hx-trigger="change changed" hx-select="#user-form" hx-swap="outerHTML" hx-select-oob="#navbar-user-name">
20
+ {% csrf_token %}
21
+ <div class="columns">
22
+ <div class="column">
23
+ {% include 'ui/form_error.html' %}
24
+ </div>
25
+ </div>
26
+ <div class="columns m-0">
27
+ <div class="column is-6">
28
+ {% translate 'Username' as username %}
29
+ {{ form.username|wrap_label:username }}
30
+ {{ form.first_name|wrap_label }}
31
+ {{ form.last_name|wrap_label }}
32
+ </div>
33
+ <div class="column is-6">
34
+ {% if not user.is_managed %}
35
+ {{ user|wrap_model_field:'email' }}
36
+ {% endif %}
37
+ {{ form.language_code|wrap_label }}
38
+ {{ form.theme|wrap_label }}
39
+ </div>
40
+ </div>
41
+ </form>
42
+ </section>
43
+ {% endpartialdef %}
@@ -40,21 +40,21 @@ def user_detail(request):
40
40
  initial={'language_code': request.user.language_code},
41
41
  instance=request.user
42
42
  )
43
- ctx = ui.Context(
44
- title=_('User Preferences'),
45
- extra=dict(
46
- user=request.user,
47
- form=form
48
- )
49
- ).dict()
43
+ refresh = False
50
44
  if request.method == 'POST':
51
45
  form = save_form(UserForm(request.POST, instance=request.user))
52
- ctx.update(form=form)
53
46
  if form.is_saved:
54
- res = render(request, 'user/user_form.html', ctx)
55
- res.headers['HX-Refresh'] = 'true'
56
- return res
57
- return render(request, 'user/user_form.html', ctx)
47
+ refresh = True
48
+ res = ui.WindowResponse(
49
+ title=str(_('User Preferences')),
50
+ overview_template='user/user_preferences.html#data',
51
+ header_template='user/user_preferences.html#header',
52
+ context=dict(user=request.user, form=form),
53
+ is_centered=True
54
+ ).response(request, replace_body=False)
55
+ if refresh:
56
+ res.headers['HX-Refresh'] = 'true'
57
+ return res
58
58
 
59
59
 
60
60
  @login_required()
@@ -62,15 +62,7 @@ def user_change_password(request):
62
62
  if request.user.is_managed:
63
63
  return HttpResponseForbidden()
64
64
  form = ChangePasswordForm(instance=request.user)
65
- ctx = ui.ModalContext(
66
- title=_('Change Password'),
67
- modal_id='change-password',
68
- blocking=True,
69
- extra=dict(
70
- form=form,
71
- user=request.user
72
- )
73
- ).dict()
65
+ update = bool(request.method == 'POST')
74
66
  if request.method == 'POST':
75
67
  form = save_form(ChangePasswordForm(request.POST, instance=request.user))
76
68
  if form.is_saved:
@@ -79,9 +71,13 @@ def user_change_password(request):
79
71
  resolve_url('user:detail')
80
72
  + f'?{request.GET.urlencode()}'
81
73
  )
82
- ctx.update(form=form)
83
- return ui.modal_response(request, 'user/change_password.html', ctx, update=True)
84
- return render(request, 'user/change_password.html', ctx)
74
+ return ui.ModalResponse(
75
+ title=str(_('Change Password')),
76
+ modal_id='change-password',
77
+ template='user/change_password.html',
78
+ is_update=update,
79
+ context=dict(form=form, user=request.user)
80
+ ).response(request)
85
81
 
86
82
 
87
83
  @login_required()
@@ -89,19 +85,22 @@ def user_change_email(request):
89
85
  if request.user.is_managed:
90
86
  return HttpResponseForbidden()
91
87
  form = ChangeEmailForm(instance=request.user)
92
- ctx = ui.ModalContext(
93
- title=_('Change E-Mail'),
94
- modal_id='change-email',
95
- blocking=True,
96
- extra=dict(
97
- form=form,
98
- user=request.user
99
- )
100
- ).dict()
88
+ update = bool(request.method == 'POST')
101
89
  if request.method == 'POST':
102
90
  form = save_form(ChangeEmailForm(request.POST, instance=request.user))
103
91
  if form.is_saved:
104
- return redirect('user:detail')
105
- ctx.update(form=form)
106
- return ui.modal_response(request, 'user/change_email.html', ctx, update=True)
107
- return render(request, 'user/change_email.html', ctx)
92
+ return redirect(
93
+ resolve_url('user:detail')
94
+ + f'?{request.GET.urlencode()}'
95
+ )
96
+ return ui.ModalResponse(
97
+ title=str(_('Change E-Mail')),
98
+ modal_id='change-email',
99
+ template='user/change_email.html',
100
+ is_update=update,
101
+ context=dict(form=form, user=request.user)
102
+ ).response(request)
103
+
104
+
105
+ def password_forgotten(request):
106
+ return render(request, 'user/')
@@ -0,0 +1,23 @@
1
+ # Generated by Django 5.2.1 on 2025-05-24 09:10
2
+
3
+ from django.db import migrations, models
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ('accrete', '0007_accessgroup_description'),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.AlterField(
14
+ model_name='member',
15
+ name='access_groups',
16
+ field=models.ManyToManyField(blank=True, through='accrete.MemberAccessGroupRel', through_fields=('member', 'access_group'), to='accrete.accessgroup'),
17
+ ),
18
+ migrations.AlterField(
19
+ model_name='tenant',
20
+ name='access_groups',
21
+ field=models.ManyToManyField(blank=True, through='accrete.TenantAccessGroupRel', through_fields=('tenant', 'access_group'), to='accrete.accessgroup'),
22
+ ),
23
+ ]
accrete/utils/__init__.py CHANGED
@@ -1,5 +1,6 @@
1
1
  from . import dates
2
2
  from .forms import (
3
+ FormResult,
3
4
  save_form,
4
5
  save_forms,
5
6
  inline_vals_from_post,
accrete/utils/forms.py CHANGED
@@ -1,79 +1,99 @@
1
1
  import re
2
2
  import logging
3
3
  from uuid import uuid4
4
- from typing import Type
4
+ from typing import Type, Any
5
+ from dataclasses import dataclass, field
5
6
  from django.db import transaction
6
7
  from django.forms import BaseFormSet, Form, ModelForm
7
8
 
8
9
  _logger = logging.getLogger(__name__)
9
10
 
10
11
 
11
- def save_form(form: [Form|ModelForm], commit=True, reraise=False) -> [Form | ModelForm]:
12
+ @dataclass
13
+ class FormResult:
14
+
15
+ form: Form | ModelForm
16
+ is_saved: bool = False
17
+ save_error: str | None = None
18
+ save_error_id: str | None = None
19
+ res: Any = None # return value of form.save()
20
+ inline_formsets: list = field(default_factory=list)
21
+
22
+ def __getattr__(self, item):
23
+ return getattr(self.form, item)
24
+
25
+ def __getitem__(self, item):
26
+ return self.form.__getitem__(item)
27
+
28
+
29
+ def save_form(
30
+ form: Form | ModelForm,
31
+ *,
32
+ commit: bool = True,
33
+ check_changed: bool = False,
34
+ reraise: bool = False
35
+ ) -> FormResult:
12
36
  if not hasattr(form, 'save'):
13
37
  raise AttributeError('Form must have method "save" implemented.')
14
- form.is_saved = False
15
- form.save_error = None
16
- form.save_error_id = None
17
- form.res = None
38
+ result = FormResult(form=form)
39
+ changed = not check_changed or form.has_changed()
18
40
  try:
19
41
  if form.is_valid():
20
- with transaction.atomic():
21
- form.res = form.save(commit=commit)
22
- form.is_saved = True
42
+ if changed:
43
+ with transaction.atomic():
44
+ result.res = form.save(commit=commit)
45
+ result.is_saved = True
23
46
  except Exception as e:
24
- form.save_error = repr(e)
47
+ result.save_error = repr(e)
25
48
  error_id = str(uuid4())[:8]
26
49
  _logger.exception(f'{error_id}: {e}')
27
- form.save_error_id = error_id
50
+ result.save_error_id = error_id
28
51
  if reraise:
29
52
  raise e
30
- return form
53
+ return result
31
54
 
32
55
 
33
- def save_forms(form, inline_formsets: list = None, commit=True, reraise: bool = False) -> [Form | ModelForm]:
56
+ def save_forms(form, inline_formsets: list = None, commit=True, reraise: bool = False) -> FormResult:
34
57
 
35
58
  def handle_error(error):
36
- form.save_error = repr(error)
59
+ result.save_error = repr(error)
37
60
  error_id = str(uuid4())[:8]
38
61
  _logger.exception(f'{error_id}: {error}')
39
- form.save_error_id = error_id
62
+ result.save_error_id = error_id
40
63
 
41
64
  if not hasattr(form, 'save'):
42
65
  raise AttributeError('Form must have method "save" implemented.')
43
66
 
44
- form.is_saved = False
45
- form.save_error = None
46
- form.save_error_id = None
47
- form.res = None
48
- form.inline_forms = inline_formsets
67
+ result = FormResult(form=form)
68
+ result.inline_forms = inline_formsets
49
69
 
50
70
  try:
51
71
  form.is_valid()
52
72
  inlines_valid = all([
53
- inline_formset.is_valid() for inline_formset in inline_formsets
73
+ inline_formset.is_valid() for inline_formset in result.inline_formsets
54
74
  ])
55
75
  except Exception as e:
56
76
  handle_error(e)
57
77
  if reraise:
58
78
  raise e
59
- return form
79
+ return result
60
80
 
61
81
  if not form.is_valid() or not inlines_valid:
62
- return form
82
+ return result
63
83
 
64
84
  try:
65
85
  with transaction.atomic():
66
- form.res = form.save(commit=commit)
67
- for inline_formset in inline_formsets:
86
+ result.res = form.save(commit=commit)
87
+ for inline_formset in result.inline_formsets:
68
88
  inline_formset.save(commit=commit)
69
89
  except Exception as e:
70
90
  handle_error(e)
71
91
  if reraise:
72
92
  raise e
73
- return form
93
+ return result
74
94
 
75
- form.is_saved = True
76
- return form
95
+ result.is_saved = True
96
+ return result
77
97
 
78
98
 
79
99
  def inline_vals_from_post(post: dict, prefix: str) -> list[dict]:
accrete/utils/views.py CHANGED
@@ -134,8 +134,7 @@ def cast_param(params: dict, param: str, cast_to: Callable, default):
134
134
 
135
135
 
136
136
  def method_not_allowed(method: str, allowed: list[str]) -> HttpResponseNotAllowed | None:
137
- if method not in allowed:
138
- return HttpResponseNotAllowed(allowed)
137
+ return None if method in allowed else HttpResponseNotAllowed(allowed)
139
138
 
140
139
 
141
140
  def render_templates(
accrete/views.py CHANGED
@@ -24,16 +24,15 @@ class TenantRequiredMixin(LoginRequiredMixin):
24
24
  MEMBER_GROUPS: list[str | tuple[str]] = []
25
25
 
26
26
  def dispatch(self, request, *args, **kwargs):
27
- res = super().dispatch(request, *args, **kwargs)
28
27
  if not self.get_tenant():
29
28
  return self.handle_tenant_not_set()
30
29
  if self.request.user.is_superuser:
31
- return res
30
+ return super().dispatch(request, *args, **kwargs)
32
31
  if not self.check_tenant_group():
33
32
  return self.handle_tenant_group_not_set()
34
33
  if not self.check_member_group():
35
34
  return self.handle_member_group_not_set()
36
- return res
35
+ return super().dispatch(request, *args, **kwargs)
37
36
 
38
37
  def handle_tenant_not_set(self):
39
38
  return redirect(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: accrete
3
- Version: 0.0.142
3
+ Version: 0.0.144
4
4
  Summary: Django Shared Schema Multi Tenant
5
5
  Author-email: Benedikt Jilek <benedikt.jilek@pm.me>
6
6
  License: Copyright (c) 2025 Benedikt Jilek
@@ -31,7 +31,7 @@ Classifier: Operating System :: OS Independent
31
31
  Classifier: Programming Language :: Python :: 3
32
32
  Classifier: Topic :: Internet :: WWW/HTTP
33
33
  Requires-Python: >=3.10
34
- Requires-Dist: django>=5.1
34
+ Requires-Dist: django>=5.2
35
35
  Provides-Extra: contrib
36
36
  Requires-Dist: celery>=5.3.4; extra == 'contrib'
37
37
  Requires-Dist: django-celery-beat; extra == 'contrib'
@@ -12,7 +12,7 @@ accrete/storage.py,sha256=Jp3oE_uPMqgarjS_G49KDFrR2eSe4XuIJK9oAF_QBxk,1288
12
12
  accrete/tenant.py,sha256=vfalmdfDsjYbl-ol3RqvsTC-YnuQs0JuSC7o85UInG0,2289
13
13
  accrete/tests.py,sha256=Agltbzwwh5htvq_Qi9vqvxutzmg_GwgPS_N19xJZRlw,7197
14
14
  accrete/urls.py,sha256=goDFR-yhOlLLy7AMi9pmh2aBkxdtZtwXNg6mwI2zPhU,227
15
- accrete/views.py,sha256=JNv1T9Bv_eay5LcPauoSSeyga7ftNIZg9xdPSOQPUnI,5862
15
+ accrete/views.py,sha256=O8VytX3LtDizhWla_uRdXUiRnfGbgs9Z4xtubwqIOA4,5883
16
16
  accrete/contrib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
17
  accrete/contrib/country/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
18
  accrete/contrib/country/admin.py,sha256=0dAcFPfC8c80fhKKOL26-5Wl1uWXBYrkUJEjo2sEkk4,329
@@ -23,7 +23,7 @@ accrete/contrib/country/migrations/0002_auto_20250219_1759.py,sha256=hSP0WEErHHJ
23
23
  accrete/contrib/country/migrations/0003_alter_country_options.py,sha256=0reOOdHuApMA5pw4ga6BW63TCG2U1i8T8oSug7EjUXw,428
24
24
  accrete/contrib/country/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
25
25
  accrete/contrib/log/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
26
- accrete/contrib/log/admin.py,sha256=xeuLk1GdU_M0rZR8SQUzcMeWvV9ud0hz_LJmaut5eJE,1211
26
+ accrete/contrib/log/admin.py,sha256=g-wdWF2O62rR0e_rLSgof_z8m42Qqv5VBrl_sFB0qlo,1212
27
27
  accrete/contrib/log/apps.py,sha256=O0Cje3MmpxPToJVgO195lBg0tRCy9Ou87-ntcdGBKM0,369
28
28
  accrete/contrib/log/config.py,sha256=vRzPVbiUfpo5NGtgiJv5mEKR_h3qsYI_brxjni6-Z-Y,132
29
29
  accrete/contrib/log/helper.py,sha256=n5QXPf4Lo8NvxDaJifZs4QVNJdiNyr17e_z26QT9V-U,2514
@@ -55,21 +55,20 @@ accrete/contrib/system_mail/admin.py,sha256=9hXwwfZn446juyRoBOygLWm12X6N9waRC-1L
55
55
  accrete/contrib/system_mail/apps.py,sha256=yIWgsa5GV8NPOJBtDZQJljSZ5v_mOP6VJrTfo_HkLF8,169
56
56
  accrete/contrib/system_mail/forms.py,sha256=AQlQW0hW3KM5cU-y02DWb7HlCD4pcJAD7L5UZmqmnTc,750
57
57
  accrete/contrib/system_mail/models.py,sha256=mTx8YAtyyrUE2B8iKQDyJVsUqN1EGHg8XKgdoWibZ9g,880
58
- accrete/contrib/system_mail/tasks.py,sha256=W3q40AxcjGFt7wtuvblQ_WFYIaipYF-WWkDYGvbkYhQ,1326
58
+ accrete/contrib/system_mail/tasks.py,sha256=Q9KLh_exm_KTr7ZfyNJ6KPGh5P-Nkipf0tScWRyzZUQ,1330
59
59
  accrete/contrib/system_mail/tests.py,sha256=mrbGGRNg5jwbTJtWWa7zSKdDyeB4vmgZCRc2nk6VY-g,60
60
60
  accrete/contrib/system_mail/views.py,sha256=xc1IQHrsij7j33TUbo-_oewy3vs03pw_etpBWaMYJl0,63
61
61
  accrete/contrib/system_mail/migrations/0001_initial.py,sha256=6cwkkRXGjXvwXoMjjgmWmcPyXSTlUbhW1vMiHObk9MQ,1074
62
62
  accrete/contrib/system_mail/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
63
- accrete/contrib/ui/__init__.py,sha256=ziSWIhoBk2EhnkG7gGhMKSLSlgLICPm-M2RxdWAjrn0,300
63
+ accrete/contrib/ui/__init__.py,sha256=DTl4vnTWdYTdChIPv--iYzRGAKi9uVx6NGxrF36iO6Q,365
64
64
  accrete/contrib/ui/admin.py,sha256=suMo4x8I3JBxAFBVIdE-5qnqZ6JAZV0FESABHOSc-vg,63
65
65
  accrete/contrib/ui/apps.py,sha256=E0ao2ox6PQ3ldfeR17FXJUUJuGiWjm2DPCxHbPXGzls,152
66
- accrete/contrib/ui/context.py,sha256=7FBNcPG77dU7asMomiRACP1bypE3lbsHXdg90MXbjf4,2616
67
- accrete/contrib/ui/filter.py,sha256=zLTWWSvsfvwBMNWgpZqP2kRKXCVW_50mhTQyJA36ywo,13323
66
+ accrete/contrib/ui/filter.py,sha256=WWELsSZF-v7FxAWw1gGvYHFBB0BhmQWuWacI_joTKas,13703
68
67
  accrete/contrib/ui/middleware.py,sha256=QprWR8FXK9iMPIvLQAeYASaUJSW0uD9BHoYroMKrph0,1560
69
68
  accrete/contrib/ui/models.py,sha256=Vjc0p2XbAPgE6HyTF6vll98A4eDhA5AvaQqsc4kQ9AQ,57
69
+ accrete/contrib/ui/response.py,sha256=vsSr4P3icnGflHv9zCfozlYUPESwtEEiugFAYUKQn9M,15482
70
70
  accrete/contrib/ui/tests.py,sha256=mrbGGRNg5jwbTJtWWa7zSKdDyeB4vmgZCRc2nk6VY-g,60
71
71
  accrete/contrib/ui/urls.py,sha256=5XUfK85HYWYf7oopMoJEEYmQ6pNgHgZBErBEn97pBt4,337
72
- accrete/contrib/ui/utils.py,sha256=CyDqwIUAOhZQ-p0MCEjWzk-qEYI1jn_NBBL-D7Oi63w,2193
73
72
  accrete/contrib/ui/views.py,sha256=5VUbP0jgMcLMv9-3AKxkV315RA0qXuw5PmTRejPc0Yg,1136
74
73
  accrete/contrib/ui/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
75
74
  accrete/contrib/ui/static/bulma/LICENSE,sha256=--fY7Bi3Lt7RXXnKc9pe756OJY9fGv-D5OmT5pdSJ5w,1080
@@ -168,12 +167,11 @@ accrete/contrib/ui/static/bulma/versions/bulma-no-dark-mode.scss,sha256=1tXoYLlK
168
167
  accrete/contrib/ui/static/bulma/versions/bulma-no-helpers-prefixed.scss,sha256=NRrD7Euz_mfDI02D92a63M6H4UhArjhWy3g5DIhQr5o,366
169
168
  accrete/contrib/ui/static/bulma/versions/bulma-no-helpers.scss,sha256=gyRiEug6frpDJEaxZ7VybdApnmNS5R5A9Zn1R0yWLJg,335
170
169
  accrete/contrib/ui/static/bulma/versions/bulma-prefixed.scss,sha256=cDhte1VyFupdjYFXpUyQb7wGB8aUKDGYuKluZCY5CtA,133
171
- accrete/contrib/ui/static/css/accrete.css,sha256=uvPIU2FvJFnFwyvISjhrHVDC1OV9H1MsDU9id4HZiJg,6862
172
- accrete/contrib/ui/static/css/accrete.css.map,sha256=UFEDkXkiYpwyBsk0N3SVaAx316bMz0SPsGUUibpbfag,3887
173
- accrete/contrib/ui/static/css/accrete.scss,sha256=ZuIwivXkinl4vPJTTy1J48yYXON5YjLLpUBOgCYgomg,7205
170
+ accrete/contrib/ui/static/css/accrete.css,sha256=C5GVDuOcSiCVczvpvIzGAmpZQ7_VFbU-0Z_CQ_RtDGE,8208
171
+ accrete/contrib/ui/static/css/accrete.css.map,sha256=r0fiRbfcq57rvMPOC3RZvz7DGKiglLzC2fs5Y8-cHGw,4802
172
+ accrete/contrib/ui/static/css/accrete.scss,sha256=lVgtZx6HsInVdV0LVO0JVijoS6wBupi4GiPhRpQvQ4I,8261
174
173
  accrete/contrib/ui/static/css/fa.css,sha256=wiz7ZSCn_btzhjKDQBms9Hx4sSeUYsDrTLg7roPstac,102641
175
174
  accrete/contrib/ui/static/css/icons.css,sha256=5550KHsaayeEtRaUdf0h7esQhyec-_5ZfecZ_sOC6v0,6334
176
- accrete/contrib/ui/static/css/.sass-cache/15adf1eed05371361b08787c918a7f18fc15be79/accrete.scssc,sha256=COJYmUzNErZkHzYxo3GVAqn7leI8NHOyD_YSii9XjHU,71246
177
175
  accrete/contrib/ui/static/icons/Logo.svg,sha256=hGZuxrAa-LRpFavFiF8Lnc7X9OQcqmb6Xl_dxx-27hM,1861
178
176
  accrete/contrib/ui/static/icons/accrete.svg,sha256=CWHJKIgk3hxL7xIaFSz2j1cK-eF1TroCbjcF58bgOIs,1024
179
177
  accrete/contrib/ui/static/js/alpine-3.14.9.js,sha256=tgDjY9mdlURNtUrL-y3v_smueSqpmgkim82geOW1VkM,44758
@@ -197,28 +195,30 @@ accrete/contrib/ui/templates/django/forms/widgets/input.html,sha256=FCLULKMx0eNl
197
195
  accrete/contrib/ui/templates/django/forms/widgets/select.html,sha256=uSfDpOQox2mEKDm9LWJ6jg5rCa3jCbHHTcmOadFLlBg,455
198
196
  accrete/contrib/ui/templates/django/forms/widgets/text.html,sha256=MSmLlQc7PsPoDLVtTOOiWNprrsPriNr712yFxaHyDIo,47
199
197
  accrete/contrib/ui/templates/django/forms/widgets/textarea.html,sha256=c9BTedqb3IkXLyVYd0p9pR8DFnsXCNGoxVBWZTk_Fic,278
200
- accrete/contrib/ui/templates/ui/content_right.html,sha256=3DQqbjAafaLtWUTGcBTCzObQEII35DVLfWQ6i6KDh6Y,379
198
+ accrete/contrib/ui/templates/ui/content.html,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
199
+ accrete/contrib/ui/templates/ui/content_right.html,sha256=aOFjbtXjjlqwmHpGoEpAUz6LtLGSTM6mX_RAO5-aM6k,380
200
+ accrete/contrib/ui/templates/ui/detail.html,sha256=2yVoJ5rsRKCUoId2NC7ds8l5q1z6Nl7VlLA3bSsxXMM,295
201
201
  accrete/contrib/ui/templates/ui/favicon.html,sha256=ZSK6qDGV4Cexgt0VA3KOHYN100yZHOFjfOiFZVudWg0,90
202
- accrete/contrib/ui/templates/ui/form_error.html,sha256=uPfIkK9OMpy5H147AxVxNAhG6dKBa9Wq64_f4tk5UU8,379
203
- accrete/contrib/ui/templates/ui/layout.html,sha256=yDcZYMUdT3ZaqXPC1qg2Lme_dBnBUG2ZzGyrG0V6ces,13174
204
- accrete/contrib/ui/templates/ui/list.html,sha256=o0YGM2O4SUlFcP5jMwdEOXVTCuEfanvd77yH7OBRRws,2208
205
- accrete/contrib/ui/templates/ui/list_update.html,sha256=mLQTCgkKfVI5jrgei-Upc1u87iXL0Q63uLzXHPwMyeo,110
206
- accrete/contrib/ui/templates/ui/message.html,sha256=3LPe1D5tmEhan7Ldrwy3MsK6cL1uZSKt6aDYQNtNVHc,732
207
- accrete/contrib/ui/templates/ui/modal.html,sha256=2HwmqcUvGqWfKpuKO1EOfr5F1Lcwn7eChbu3XbrxvYg,2233
202
+ accrete/contrib/ui/templates/ui/form_error.html,sha256=WWqfFWyJ_LCzm5IkxXztn23GFak5wyM2HZcmiZ3Eq9s,417
203
+ accrete/contrib/ui/templates/ui/layout.html,sha256=r3ZylKY2iPK8HwNcRPSzuJ4dfEQKQMGFCu7CBBE9gUg,13674
204
+ accrete/contrib/ui/templates/ui/list.html,sha256=xyEUYwQKcj-65CO5Te8ixQcUoUj_bh4nmN9cpHaO9uM,2437
205
+ accrete/contrib/ui/templates/ui/list_update.html,sha256=uHwdVQFGwDq0wEbZ6jtSnII6G7xLruivIlOX5dVGlz8,274
206
+ accrete/contrib/ui/templates/ui/message.html,sha256=dQnPNkHIrrOzelXCTO8CLWG5ufmxJ8MuWp66YLZbmro,773
207
+ accrete/contrib/ui/templates/ui/modal.html,sha256=3FzvnFVWvwRQ_r1-2qd9N5wYIOh6_oYDDp7uk6XoJPE,3481
208
208
  accrete/contrib/ui/templates/ui/oob.html,sha256=lZHIBBYclefbGkKguS1A7vrtOhODJizbSRaGAAHDvG8,267
209
209
  accrete/contrib/ui/templates/ui/table.html,sha256=u6JJz1FykuljZiiC2hL83hy8RbMeXcSH8xuU1ji2SHc,3939
210
- accrete/contrib/ui/templates/ui/table_row_update.html,sha256=_7tKQlCXxczguYQ-6rkZRwukYBswsh3J2cwT4ke_sQM,445
211
- accrete/contrib/ui/templates/ui/filter/filter.html,sha256=RBYzmgQmgWKjVNrtZo9L98IW23vWLKSDQrZRb88VxrQ,758
210
+ accrete/contrib/ui/templates/ui/table_row_update.html,sha256=Jvt0wlq4btlIRk1RoSv467nT0MUBn7OwC1EbzawDej4,409
211
+ accrete/contrib/ui/templates/ui/filter/filter.html,sha256=GOTXouHH4RSCFsIzg1UPFAcmKaNNxTPmRj5Bx9K1m4o,759
212
212
  accrete/contrib/ui/templates/ui/filter/query_input.html,sha256=Qg_41fODXMgL534ohktb0QOxNzAEbaeBzAajJCEK7Pg,2035
213
213
  accrete/contrib/ui/templates/ui/filter/query_operator.html,sha256=h4WWLDnse6DK5Rb_0TTb0wqWxhvY_g3qjwx8_eENMuI,569
214
214
  accrete/contrib/ui/templates/ui/filter/query_params.html,sha256=wCkyZ9oSK_ivraNiL-UAY_9TflYw5EspnHHm6V6uOzk,9548
215
- accrete/contrib/ui/templates/ui/filter/query_tags.html,sha256=QSdM5w8UduT89x4S1ttdmzECBBnR-JipKOsf7rBCfL4,1562
216
- accrete/contrib/ui/templates/ui/templatetags/field.html,sha256=xQGixZBcgRfQVkRDDOcQVvz2blPia_h0sS6Deatgbkc,198
217
- accrete/contrib/ui/templates/ui/widgets/model_search_select.html,sha256=bk6m38_u_hbudQoXqzGunGUhvHRphVDlfKjkdcB9rEs,2748
218
- accrete/contrib/ui/templates/ui/widgets/model_search_select_multi.html,sha256=ojj3n6kAAWL-O8-dqGX2nqFWnPpLlbVvAyiZytSuq10,4599
215
+ accrete/contrib/ui/templates/ui/filter/query_tags.html,sha256=ooeIwIwvhT0fG5SMAuLoMquTVUmYf5n50DM-3gC_iAo,1567
216
+ accrete/contrib/ui/templates/ui/templatetags/field.html,sha256=njmCBUBpLQsSu1r740PMXuh5gNfjDxI6Lmo_dm4JTqw,776
217
+ accrete/contrib/ui/templates/ui/widgets/model_search_select.html,sha256=AUlWN2gKhHk_tWP1-KGel5ifaRMTF60MUtgbap7CGQ4,2938
218
+ accrete/contrib/ui/templates/ui/widgets/model_search_select_multi.html,sha256=NV_PWH8-3TqSfJT2l4aN3TOCFyYWxxtCQ9sh6X8gML0,4686
219
219
  accrete/contrib/ui/templates/ui/widgets/model_search_select_options.html,sha256=4Wky0XkYWZlIKXTXzGjJkJTX3H9rhjXTY1hYai3Q3TA,242
220
220
  accrete/contrib/ui/templatetags/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
221
- accrete/contrib/ui/templatetags/ui.py,sha256=_aKZoLwH_AcDszy3a3lehQsTg9zDaNeMmbSnjFK2wpM,4220
221
+ accrete/contrib/ui/templatetags/ui.py,sha256=cWWgzjQKgcxy6uAJZlIJzeP-O3oqFjbrCZrZdnxNUVk,4924
222
222
  accrete/contrib/ui/widgets/__init__.py,sha256=W_y10jfu37lygp4frXuKFSGec97gpNbWskG6DMhTKtY,69
223
223
  accrete/contrib/ui/widgets/search_select.py,sha256=zKmOt54QsxUobNkDNEA2ut3pPAl8a5DqmEpcfam1l1I,3762
224
224
  accrete/contrib/user/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -230,7 +230,7 @@ accrete/contrib/user/middleware.py,sha256=qblcujwJsthopagyT-hPFq4HsMyGt-VvqZw5TQ
230
230
  accrete/contrib/user/models.py,sha256=8vgDZ2Jf-aFOC12W1vKObaK9FJUwcuWwQWqAi2hXQZg,6257
231
231
  accrete/contrib/user/tests.py,sha256=mrbGGRNg5jwbTJtWWa7zSKdDyeB4vmgZCRc2nk6VY-g,60
232
232
  accrete/contrib/user/urls.py,sha256=_fBa--3NfyYN10Td7PGHpetJYy42SMqTyCCXhgynkEQ,407
233
- accrete/contrib/user/views.py,sha256=oPiyyO7RnfI48iKCO7O5_HMk2vioNEUDowKRe-Xwzm0,3435
233
+ accrete/contrib/user/views.py,sha256=O59SwLGpgaihCHn-1vNVsbVSrNFx1-n2YQFQYmFlC6E,3460
234
234
  accrete/contrib/user/locale/de/LC_MESSAGES/django.mo,sha256=p3rgUg6WltAVIMkQsjvjBqTsd_usLhSr1GH4Cyltc2c,433
235
235
  accrete/contrib/user/locale/de/LC_MESSAGES/django.po,sha256=f_Nxpo3HTm2L3f3zoHLfeWsZ-4IQp_EEVSku6TCZSvw,1870
236
236
  accrete/contrib/user/migrations/0001_initial.py,sha256=JWfM9PcMDfkJUdCjLWuWieGs6643qP0KdbCyr5uAZoY,2950
@@ -246,7 +246,8 @@ accrete/contrib/user/templates/user/accrete_navbar_end_dropdown.html,sha256=suPo
246
246
  accrete/contrib/user/templates/user/change_email.html,sha256=w9gBnU_O45YchY0EqD9mUK5oeDaD4cN92tHN80QjReA,815
247
247
  accrete/contrib/user/templates/user/change_password.html,sha256=1U7cI-xshsy_nhSj3TUqL3tPtYaBF17XFDgJHXXDzIw,1021
248
248
  accrete/contrib/user/templates/user/login.html,sha256=SXbxgq3baEch3ksGMsZqIws5heqAtpkdCLAFX3SLhtQ,2669
249
- accrete/contrib/user/templates/user/user_form.html,sha256=fPbbUnx2URhdW9-by26q3xe3_w23de42Nj25BOC3qrs,2641
249
+ accrete/contrib/user/templates/user/password_forgotten.html,sha256=aoNR9VUhLkDFLIQ3NUA2Oh19bFlro0ZXvcRUdGDNPnc,30
250
+ accrete/contrib/user/templates/user/user_preferences.html,sha256=s-WmVASO0-5R2PY-y_ExS5kl9yOtMQpElVH3nKLqW0g,1646
250
251
  accrete/contrib/user_registration/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
251
252
  accrete/contrib/user_registration/admin.py,sha256=kwmGTsg4Hii-lsw9-UaJG7AhQ4k4SPi48GSrtpZ4YR4,119
252
253
  accrete/contrib/user_registration/apps.py,sha256=mYu3fuuubfjImeJHk4D_Wd6Edw2r3oUNXGcFbAkhir4,181
@@ -267,14 +268,15 @@ accrete/migrations/0004_rename_accessgroupmember_memberaccessgrouprel_and_more.p
267
268
  accrete/migrations/0005_accessgroup_apply_on_alter_member_access_groups_and_more.py,sha256=1ZL_PG2W_5h1x1oGAUALn2Ks0kzbFusHF7XEXE1J9Pg,996
268
269
  accrete/migrations/0006_alter_member_user.py,sha256=l1m1uaP1q8yaCqX2cWdzRcL-fe4VLb1SqQmP966weNQ,643
269
270
  accrete/migrations/0007_accessgroup_description.py,sha256=T8BX0gSckC_fM_uD6a5-fdD-ucAn54vyY7_8o0tDIXA,429
271
+ accrete/migrations/0008_alter_member_access_groups_and_more.py,sha256=U2VpQJkLsajpL-rvzx-co5V3jYSxMnvkvjSznyVkr34,782
270
272
  accrete/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
271
- accrete/utils/__init__.py,sha256=saw9zi2XItJOPbv4fjTXOpl7StNtC803jHhapFcGx08,312
273
+ accrete/utils/__init__.py,sha256=xXpPIImuZFRFIc8Sg8j6-OWOiJZGAtX4iphdXcxAYM0,328
272
274
  accrete/utils/dates.py,sha256=apM6kt6JhGrKgoT0jfav1W-8AUVTxNc9xt3fJQ2n0JI,1492
273
- accrete/utils/forms.py,sha256=JJ3EY1xcVP6L10i5cSVgh57G0uvFUjiVwUCpEqmBCos,3407
275
+ accrete/utils/forms.py,sha256=naV4urdfvmpxcx5Vf3Fo72M5Fy8DjGg5-vkysMKptbA,3914
274
276
  accrete/utils/log.py,sha256=BH0MBDweAjx30wGBO4F3sFhbgkSoEs7T1lLLjlYZNnA,407
275
277
  accrete/utils/models.py,sha256=2xTacvcpmDK_Bp4rAK7JdVLf8HU009LYNJ6eSpMgYZI,1014
276
- accrete/utils/views.py,sha256=PsKpUFjxCm6_l_nfVs-cNIY0lNTdkocm2uohR3o9eEo,5025
277
- accrete-0.0.142.dist-info/METADATA,sha256=dA1QJQ7xbXLO5cXqWqKdPuJWEbUfLZpjmKQcVjsbGdc,4953
278
- accrete-0.0.142.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
279
- accrete-0.0.142.dist-info/licenses/LICENSE,sha256=vHwb4Qnv8UfYKFiCWyTuRGsi49x19UQwHRCky3b2_NE,1057
280
- accrete-0.0.142.dist-info/RECORD,,
278
+ accrete/utils/views.py,sha256=mHfcKNDOiq-38LQ6tz9pDPQt-xs03b2qMxwJClprqu8,5022
279
+ accrete-0.0.144.dist-info/METADATA,sha256=cq1cGVRjyQjJ2j6-CAASXQVJvjUIq4VkL2ok6--mcOo,4953
280
+ accrete-0.0.144.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
281
+ accrete-0.0.144.dist-info/licenses/LICENSE,sha256=vHwb4Qnv8UfYKFiCWyTuRGsi49x19UQwHRCky3b2_NE,1057
282
+ accrete-0.0.144.dist-info/RECORD,,
@@ -1,123 +0,0 @@
1
- import logging
2
- import re
3
- from dataclasses import dataclass, field
4
- from django.core import paginator
5
- from django.db.models import QuerySet, Model
6
- from .filter import Filter
7
-
8
- _logger = logging.getLogger(__name__)
9
-
10
-
11
- @dataclass(kw_only=True)
12
- class BaseContext:
13
-
14
- extra: dict = field(default_factory=dict)
15
-
16
- def __post_init__(self):
17
- for key, value in self.extra.items():
18
- setattr(self, key, value)
19
-
20
- def dict(self):
21
- return {
22
- attr: getattr(self, attr, None) for attr
23
- in filter(lambda x: not x.startswith('_'), self.__dict__)
24
- }
25
-
26
-
27
- @dataclass(kw_only=True)
28
- class Context(BaseContext):
29
-
30
- title: str = ''
31
-
32
-
33
- @dataclass
34
- class ListContext(Context):
35
-
36
- page: paginator.Page
37
- queryset: QuerySet
38
- endless_scroll: bool = True
39
- filter: Filter = None
40
- column_count: int = 1
41
- column_height: int = 150
42
- column_height_unit: str = 'px'
43
-
44
- def __post_init__(self):
45
- super().__post_init__()
46
- if self.column_count not in range(1, 13):
47
- _logger.warning(
48
- 'ListContext parameter column_count should be in range 1 - 12'
49
- )
50
-
51
-
52
- @dataclass
53
- class ListUpdateContext(BaseContext):
54
-
55
- object: Model
56
- template: str
57
-
58
-
59
- @dataclass
60
- class TableContext(Context):
61
-
62
- object_label: str
63
- fields: list[str]
64
- page: paginator.Page
65
- queryset: QuerySet
66
- footer: dict = field(default_factory=dict)
67
- endless_scroll: bool = True
68
- filter: Filter = None
69
-
70
-
71
- @dataclass
72
- class TableRowContext(BaseContext):
73
-
74
- object: Model
75
- fields: list[str]
76
- queryset: QuerySet
77
- footer: dict = field(default_factory=dict)
78
-
79
-
80
- @dataclass
81
- class ModalContext(BaseContext):
82
-
83
- title: str
84
- modal_id: str
85
- blocking: bool = False
86
-
87
- def __post_init__(self):
88
- super().__post_init__()
89
- self.modal_id = re.sub(r'[^A-Za-z-]+', '', self.modal_id).strip('-')
90
-
91
-
92
- @dataclass(kw_only=True)
93
- class OobContext(BaseContext):
94
-
95
- template: str
96
- id: str = None
97
- swap: str = 'true'
98
- tag: str = 'div'
99
-
100
- def dict(self) -> dict:
101
- res = {
102
- attr: getattr(self, attr, None) for attr
103
- in filter(
104
- lambda x:
105
- not x.startswith('_')
106
- and x not in ['template', 'id', 'swap', 'tag'],
107
- self.__dict__
108
- )
109
- }
110
- res.update({'oob': {
111
- 'template': self.template,
112
- 'id': self.id,
113
- 'swap': self.swap,
114
- 'tag': self.tag
115
- }})
116
- return res
117
-
118
-
119
- @dataclass(kw_only=True)
120
- class MessageContext(BaseContext):
121
-
122
- persistent: bool = False
123
- append: bool = False