djgentelella 0.4.30__py3-none-any.whl → 0.5.1__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 (66) hide show
  1. djgentelella/__init__.py +4 -1
  2. djgentelella/admin.py +41 -2
  3. djgentelella/firmador_digital/consumers/sign.py +24 -3
  4. djgentelella/firmador_digital/forms.py +140 -0
  5. djgentelella/firmador_digital/models.py +19 -24
  6. djgentelella/firmador_digital/utils.py +11 -0
  7. djgentelella/firmador_digital/views.py +31 -0
  8. djgentelella/firmador_digital/viewsets.py +15 -4
  9. djgentelella/forms/forms.py +10 -2
  10. djgentelella/groute.py +4 -1
  11. djgentelella/history/api.py +145 -0
  12. djgentelella/history/filterset.py +23 -0
  13. djgentelella/history/serializers.py +50 -0
  14. djgentelella/history/utils.py +70 -0
  15. djgentelella/locale/es/LC_MESSAGES/django.mo +0 -0
  16. djgentelella/locale/es/LC_MESSAGES/django.po +105 -0
  17. djgentelella/locale/es/LC_MESSAGES/djangojs.mo +0 -0
  18. djgentelella/locale/es/LC_MESSAGES/djangojs.po +46 -0
  19. djgentelella/migrations/0014_trash.py +31 -0
  20. djgentelella/migrations/0015_trash_deleted_by.py +21 -0
  21. djgentelella/migrations/0016_trash_created_at.py +20 -0
  22. djgentelella/migrations/0017_alter_chunkedupload_status.py +18 -0
  23. djgentelella/migrations/0018_alter_chunkedupload_status.py +18 -0
  24. djgentelella/models.py +97 -0
  25. djgentelella/models_manager.py +40 -0
  26. djgentelella/serializers/firmador_digital.py +9 -1
  27. djgentelella/serializers/selects.py +14 -0
  28. djgentelella/static/djgentelella.readonly.vendors.min.css +9 -5
  29. djgentelella/static/djgentelella.readonly.vendors.min.js +1 -1
  30. djgentelella/static/gentelella/css/custom.css +23 -2
  31. djgentelella/static/gentelella/css/modern.css +15 -0
  32. djgentelella/static/gentelella/css/modern_black_white.css +15 -0
  33. djgentelella/static/gentelella/css/pdfviewer.css +43 -1
  34. djgentelella/static/gentelella/images/default.png +0 -0
  35. djgentelella/static/gentelella/js/base/digital_signature.js +318 -79
  36. djgentelella/static/gentelella/js/base/form.common.js +9 -4
  37. djgentelella/static/gentelella/js/base/select2_wrap.js +15 -1
  38. djgentelella/static/gentelella/js/base/select2related.js +5 -0
  39. djgentelella/static/gentelella/js/base.js +347 -83
  40. djgentelella/static/gentelella/js/custom.js +6 -1
  41. djgentelella/static/gentelella/js/datatables.js +15 -0
  42. djgentelella/static/gentelella/js/digital_signature_update.js +29 -0
  43. djgentelella/static/gentelella/js/obj_api_management.js +403 -344
  44. djgentelella/static/gentelella/js/widgets.js +10 -1
  45. djgentelella/static/vendors/timeline/css/timeline.css +9 -5
  46. djgentelella/static/vendors/timeline/js/timeline.js +1 -1
  47. djgentelella/templates/forms/as_grid.html +2 -2
  48. djgentelella/templates/forms/as_inline.html +3 -5
  49. djgentelella/templates/gentelella/app/sidebar.html +16 -13
  50. djgentelella/templates/gentelella/digital_signature/update_signature_settings.html +45 -0
  51. djgentelella/templates/gentelella/registration/reset_done.html +24 -0
  52. djgentelella/templates/gentelella/widgets/digital_signature.html +47 -11
  53. djgentelella/trash/api.py +77 -0
  54. djgentelella/trash/filterset.py +20 -0
  55. djgentelella/trash/serializer.py +45 -0
  56. djgentelella/urls.py +13 -2
  57. djgentelella/views/select2autocomplete.py +40 -0
  58. djgentelella/widgets/core.py +6 -5
  59. djgentelella/widgets/digital_signature.py +5 -21
  60. djgentelella/widgets/selects.py +47 -0
  61. {djgentelella-0.4.30.dist-info → djgentelella-0.5.1.dist-info}/METADATA +2 -2
  62. {djgentelella-0.4.30.dist-info → djgentelella-0.5.1.dist-info}/RECORD +66 -48
  63. {djgentelella-0.4.30.dist-info → djgentelella-0.5.1.dist-info}/AUTHORS +0 -0
  64. {djgentelella-0.4.30.dist-info → djgentelella-0.5.1.dist-info}/LICENSE.txt +0 -0
  65. {djgentelella-0.4.30.dist-info → djgentelella-0.5.1.dist-info}/WHEEL +0 -0
  66. {djgentelella-0.4.30.dist-info → djgentelella-0.5.1.dist-info}/top_level.txt +0 -0
@@ -14,12 +14,12 @@
14
14
  {% endif %}
15
15
  {% for column in form.grid %}
16
16
  <div class="row">{% for row in column %}
17
- <div class="col">{% for field in row %}
17
+ <div class="col">{% for field, errors in row %}
18
18
  <div {% with classes=field.css_classes %}{% if classes %} class="{{ classes }} asgrid gtformfield" {% else %}
19
19
  class="mb-3 asgrid gtformfield"
20
20
  {% endif %}
21
21
  {% endwith %}>
22
- {{ errors }}
22
+ {% if errors %}{{ errors }}{% endif %}
23
23
  {% if field.label %}{{ field.label_tag }}{% endif %}
24
24
  {{ field }}
25
25
  {% if field.help_text %}
@@ -21,15 +21,13 @@
21
21
 
22
22
  {{ field }}
23
23
  {% if field.help_text %}
24
- {% if forloop.last %}
25
- {% for field in hidden_fields %}{{ field }}{% endfor %}
26
- {% endif %}
27
-
28
24
  <div class="feedback text-info" {% if field.auto_id %} id="{{ field.auto_id }}_helptext" {% endif %}>
29
25
  {{ field.help_text|safe }}
30
26
  </div>
31
27
  {% endif %}
32
-
28
+ {% if forloop.last %}
29
+ {% for field in hidden_fields %}{{ field }}{% endfor %}
30
+ {% endif %}
33
31
  </div>
34
32
  {% endfor %}
35
33
  {% if not fields and not errors %}
@@ -1,24 +1,27 @@
1
1
  {% load gentelellamenu gtsettings %}
2
+
2
3
  <div class="left_col overflow-hidden">
3
- <div class="navbar nav_title" style="border: 0;">
4
+
5
+ <div class="navbar nav_title mb-4" style="border: 0;">
4
6
  <a href="{% url 'home' %}" class="site_title"><i class="{% get_settings 'sidebar_icon' 'fa fa-spinner' %}"></i> <span>{% get_settings 'sidebar_title' 'My Site' %}</span></a>
5
7
  </div>
6
8
 
9
+ <div class="clearfix"></div>
7
10
 
8
- <div class="clearfix"></div>
11
+ <!-- sidebar menu -->
9
12
 
10
- <!-- sidebar menu -->
13
+ <div id="sidebar-menu" class="main_menu_side d-print-none main_menu">
11
14
 
12
- <div id="sidebar-menu" class="main_menu_side d-print-none main_menu">
15
+ {% sidebar_menu %}
13
16
 
14
- {% sidebar_menu %}
17
+ </div>
18
+ <!-- /sidebar menu -->
15
19
 
16
- </div>
17
- <!-- /sidebar menu -->
18
20
 
19
- <!-- /menu footer buttons -->
20
- <div class="sidebar-footer d-print-none nohidden">
21
- {% footer_sidebar_menu %}
22
- </div>
23
- <!-- /menu footer buttons -->
24
- </div>
21
+ <!-- /menu footer buttons -->
22
+ <div class="sidebar-footer d-print-none nohidden">
23
+ {% footer_sidebar_menu %}
24
+ </div>
25
+ <!-- /menu footer buttons -->
26
+
27
+ </div>
@@ -0,0 +1,45 @@
1
+ {% extends 'gentelella/base.html' %}
2
+ {% load i18n %}
3
+ {% load static %}
4
+ {% load gtsettings %}
5
+ {% block title %} {% trans 'Signature settings' %} {% endblock %}
6
+
7
+ {% block pre_head %}
8
+ {% endblock %}
9
+
10
+ {% block content %}
11
+ <div class="card mt-2">
12
+ <div class="card-body">
13
+
14
+ <div class="card-title titles">
15
+ <h1 class="text-center">
16
+ {% trans 'Signature settings' %}
17
+ </h1>
18
+ </div>
19
+
20
+ <div class="row justify-content-center my-4">
21
+ <div class="col-lg-6 col-md-10 col-12">
22
+
23
+ <form action="" id="form_signature" method="POST" enctype="multipart/form-data">
24
+ {% csrf_token %}
25
+ {{ form.as_grid }}
26
+
27
+ <div class="text-center">
28
+ <button type="submit" name="action" value="update" class="btn btn-success btn-sm">
29
+ {% trans 'Save' %}
30
+ <i class="fa fa-floppy-o" aria-hidden="true"></i>
31
+ </button>
32
+ </div>
33
+
34
+ </form>
35
+
36
+ </div>
37
+ </div>
38
+
39
+ </div>
40
+ </div>
41
+ {% endblock %}
42
+
43
+ {% block js %}
44
+ <script src="{% static 'gentelella/js/digital_signature_update.js' %}?v={% get_version %}"></script>
45
+ {% endblock %}
@@ -0,0 +1,24 @@
1
+ {% extends 'gentelella/base.html' %}
2
+ {% load i18n %}
3
+
4
+ {% block body_class %}login{% endblock body_class %}
5
+ {% block body %}
6
+
7
+ <div class="main_container">
8
+
9
+ <div class="col-md-8 offset-md-2">
10
+ <div class="col-middle">
11
+ <div class="text-center ">
12
+ <h1>{% trans 'Password changed' %}</h1>
13
+ <p>{% trans "You updated correctly your password please login again." %}</p>
14
+ <br>
15
+ <a href="/"> {% trans 'Go to home' %}</a>
16
+ {% include 'gentelella/registration/footer.html' %}
17
+
18
+
19
+ </div>
20
+ </div>
21
+ </div>
22
+ </div>
23
+
24
+ {% endblock %}
@@ -13,7 +13,7 @@
13
13
  {% endif %}
14
14
 
15
15
  {# digital signature card #}
16
- <div class="col-12 col-md-4">
16
+ <div class="col-12 col-md-4 digital-signature-card" id="digital-signature-card">
17
17
 
18
18
  <div id="container_select_card_tem">
19
19
  <div class="d-flex justify-content-end">
@@ -125,7 +125,7 @@
125
125
  <li>
126
126
  <a class="small"
127
127
  title="{% trans 'Run Firmador Libre' %}"
128
- href="firmador:{{ widget.attrs.cors }}">
128
+ href="firmador:localhost" data-widget="FirmadorCORS" data-port="3516">
129
129
  {% trans 'Run app' %}
130
130
  <i class="fa fa-cog" aria-hidden="true"></i>
131
131
  </a>
@@ -140,13 +140,41 @@
140
140
  </div>
141
141
 
142
142
  {# preview file #}
143
- <div class="col-12 col-md-8">
143
+ <div class="col-12 col-md-8" id="signature-viewer">
144
144
  <div class="pdf-signature-container" id="pdf-signature-container">
145
145
  {# actions for change page#}
146
146
  <div class="my-3 d-flex align-items-center justify-content-evenly">
147
147
  <input type="hidden" name="{{ widget.name }}_page_number" class="page_number">
148
- <input type="hidden" name="{{ widget.name }}"
149
- {% if widget.value != None %} value="{{ widget.value|stringformat:'s' }}"{% endif %} {% include "gentelella/widgets/attrs.html" %}>
148
+ <input type="hidden" name="{{ widget.name }}"
149
+ {% if widget.value != None %}
150
+ value="{{ widget.value|stringformat:'s' }}"{% endif %} {% include "gentelella/widgets/attrs.html" %}>
151
+
152
+ {# select card #}
153
+ <div id="container_select_card_expanded"
154
+ class="container_select_card_expanded hide d-flex flex-row align-items-center px-2 py-1 rounded shadow-sm bg-white"
155
+ style="z-index: 2000; position: sticky; top: 0; min-height: 42px;">
156
+
157
+ <div id="container_select_card_expanded_hide"
158
+ class="container_select_card_expanded_hide hide d-flex flex-row align-items-center gap-2 flex-grow-1">
159
+ <label for="select_card_{{ widget.attrs.id }}" class="fw-semibold mb-0 me-2 small"
160
+ style="white-space: nowrap;">
161
+ {% trans 'Choose your signature card' %}
162
+ </label>
163
+ <div class="select-container m-0 p-0" style="width: 220px; max-width: 380px;">
164
+ <select id="select_card_expand{{ widget.attrs.id }}"
165
+ class="form-select form-select-sm select_card px-2"
166
+ style="font-size: 0.9em; padding-left: 32px;"
167
+ name="{{ widget.name }}_select"></select>
168
+ </div>
169
+ <button class="btn btn-primary btn-sm px-2 py-1 ms-2 formadd btn_signer"
170
+ type="button" style="font-size: 0.85em;">
171
+ {% trans 'Sign' %}
172
+ </button>
173
+ </div>
174
+ <i class="fa fa-refresh text-muted fs-6 cursor-pointer btn_signer_refresh ms-2"
175
+ title="{% trans 'Reload' %}" aria-hidden="true" style="font-size: 1.1em;"></i>
176
+ </div>
177
+
150
178
 
151
179
  {# button to change page #}
152
180
  <div>
@@ -159,14 +187,21 @@
159
187
  </div>
160
188
 
161
189
  {# number of pages #}
162
- <div class="border rounded px-3 py-1 shadow-sm ">
163
- <i class="fa fa-file-o me-1" aria-hidden="true" title="{% trans 'Page' %}"></i>
164
- <span class="page_num"></span> / <span class="page_count"></span>
190
+
191
+ <div class="d-flex align-items-center gap-2">
192
+ <button id="btn_expand" type="button" class="btn btn-light px-3 shadow-sm border btn-sm prev btn_expand"
193
+ title="{% trans 'Expand' %} ">
194
+ <i class="fa fa-arrows-alt" aria-hidden="true"></i>
195
+ </button>
196
+ <div class="border rounded px-3 py-1 shadow-sm">
197
+ <i class="fa fa-file-o me-1" aria-hidden="true" title="{% trans 'Page' %}"></i>
198
+ <span class="page_num"></span> / <span class="page_count"></span>
199
+ </div>
165
200
  </div>
166
201
  </div>
167
202
 
168
203
  {# preview document #}
169
- <div class="d-flex justify-content-center canvas_container">
204
+ <div class="d-flex justify-content-center canvas_container mt-10">
170
205
  <div class="sub_canvas_container">
171
206
  <div class="signature">
172
207
  <div class="image"></div>
@@ -177,7 +212,7 @@
177
212
  </div>
178
213
 
179
214
  {# warning message #}
180
- <div class="text-muted text-center my-3">
215
+ <div class="text-muted text-center my-3 expand-help-message" id="expand-help-message">
181
216
  <p class="small">
182
217
  <i class="fa fa-exclamation-circle me-2" aria-hidden="true"></i>
183
218
  {% trans "Please go to the last page, in the signature space, try to place your signature vertically centered." %}
@@ -187,7 +222,8 @@
187
222
  </div>
188
223
  </div>
189
224
  {# loading #}
190
- <div class="modal fade" id="loading_sign" style="background-color: rgba(0, 0, 0, 0.3);" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1"
225
+ <div class="modal fade" id="loading_sign" style="background-color: rgba(0, 0, 0, 0.3);" data-bs-backdrop="static"
226
+ data-bs-keyboard="false" tabindex="-1"
191
227
  aria-hidden="true">
192
228
  <div class="modal-dialog modal-dialog-centered">
193
229
  <div class="modal-content bg-transparent border-0">
@@ -0,0 +1,77 @@
1
+ from djgentelella.objectmanagement import AuthAllPermBaseObjectManagement
2
+ from djgentelella.trash.serializer import TrashSerializer, TrashDataTableSerializer
3
+ from djgentelella.models import Trash
4
+ from djgentelella.trash.filterset import TrashFilter
5
+ from rest_framework.filters import SearchFilter, OrderingFilter
6
+ from rest_framework.pagination import LimitOffsetPagination
7
+ from django_filters.rest_framework import DjangoFilterBackend
8
+ from rest_framework.decorators import action
9
+ from rest_framework.response import Response
10
+ from rest_framework import status
11
+ from django.shortcuts import get_object_or_404
12
+ from django.utils.translation import gettext_lazy as _
13
+ from djgentelella.history.utils import add_log, HARD_DELETION, RESTORE
14
+
15
+
16
+ class TrashViewSet(AuthAllPermBaseObjectManagement):
17
+ serializer_class = {
18
+ "list": TrashDataTableSerializer,
19
+ "destroy": TrashSerializer,
20
+ "create": None,
21
+ "update": None,
22
+ "restore": None,
23
+ }
24
+
25
+ perms = {
26
+ "list": ["djgentelella.view_trash"],
27
+ "create": ["djgentelella.add_trash"],
28
+ "update": ["djgentelella.change_trash"],
29
+ "destroy": ["djgentelella.delete_trash"],
30
+ "restore": ["djgentelella.change_trash"],
31
+ }
32
+
33
+ queryset = Trash.objects.all()
34
+ pagination_class = LimitOffsetPagination
35
+ filter_backends = (DjangoFilterBackend, SearchFilter, OrderingFilter)
36
+ search_fields = ["content_type__model", "object_id", "deleted_by__username"]
37
+ filterset_class = TrashFilter
38
+ ordering_fields = ["created_at"]
39
+ ordering = ("-created_at",)
40
+
41
+ def perform_destroy(self, instance):
42
+ add_log(
43
+ self.request.user,
44
+ instance,
45
+ HARD_DELETION,
46
+ instance._meta.verbose_name.title().lower(),
47
+ [],
48
+ change_message=_("Hard deleted"),
49
+ )
50
+
51
+ instance.hard_delete()
52
+
53
+
54
+ @action(detail=True, methods=["POST"])
55
+ def restore(self, request, org_pk=None, pk=None):
56
+ try:
57
+ trash = get_object_or_404(Trash, pk=pk)
58
+
59
+ if not trash:
60
+ return Response({"result": False, "detail": _("This registry of trash does not exist.")},
61
+ status=status.HTTP_400_BAD_REQUEST)
62
+
63
+ add_log(
64
+ self.request.user,
65
+ trash.content_object,
66
+ RESTORE,
67
+ "trash",
68
+ [],
69
+ change_message=_("Restored"),
70
+ )
71
+
72
+ trash.restore()
73
+
74
+ return Response({"result": True, "detail": _("The registry was successfully restored.")}, status=status.HTTP_200_OK)
75
+ except Exception as e:
76
+ print(str(e))
77
+ return Response({"result": False, "detail": _("The registry could not be restored.")}, status=status.HTTP_400_BAD_REQUEST)
@@ -0,0 +1,20 @@
1
+ from django.contrib.contenttypes.models import ContentType
2
+ from django_filters import DateTimeFromToRangeFilter
3
+ from django_filters.rest_framework import FilterSet
4
+ from djgentelella.fields.drfdatetime import DateTimeRangeTextWidget
5
+
6
+ from djgentelella.models import Trash
7
+
8
+
9
+ class TrashFilter(FilterSet):
10
+ created_at = DateTimeFromToRangeFilter(
11
+ widget=DateTimeRangeTextWidget(attrs={"placeholder": "DD/MM/YYYY/"})
12
+ )
13
+
14
+ class Meta:
15
+ model = Trash
16
+ fields = {
17
+ 'content_type__model': ['exact'],
18
+ 'object_id': ['exact'],
19
+ 'created_at': ['exact'],
20
+ }
@@ -0,0 +1,45 @@
1
+ from rest_framework import serializers
2
+ from django.utils.translation import gettext_lazy as _
3
+ from djgentelella.models import Trash
4
+ from djgentelella.serializers import GTDateTimeField
5
+
6
+
7
+ class TrashSerializer(serializers.ModelSerializer):
8
+ actions = serializers.SerializerMethodField()
9
+ object_id = serializers.IntegerField(read_only=True)
10
+ model_name = serializers.SerializerMethodField()
11
+ created_at = GTDateTimeField()
12
+ deleted_by = serializers.SerializerMethodField()
13
+
14
+ def get_actions(self, obj):
15
+ user = self.context["request"].user
16
+ return {
17
+ "restore": user.has_perm("djgentelella.update_trash"),
18
+ "destroy": user.has_perm("djgentelella.delete_trash"),
19
+ }
20
+
21
+ def get_model_name(self, obj):
22
+ if obj.content_object is None:
23
+ return _("Deleted object")
24
+
25
+ if obj.content_type.model:
26
+ return obj.content_type.model
27
+
28
+ return "-"
29
+
30
+ def get_deleted_by(self, obj):
31
+ if obj.deleted_by:
32
+ return str(obj.deleted_by)
33
+ return "-"
34
+
35
+ class Meta:
36
+ model = Trash
37
+ fields = "__all__"
38
+
39
+
40
+ class TrashDataTableSerializer(serializers.Serializer):
41
+ data = serializers.ListField(child=TrashSerializer(), required=True)
42
+ draw = serializers.IntegerField(required=True)
43
+ recordsFiltered = serializers.IntegerField(required=True)
44
+ recordsTotal = serializers.IntegerField(required=True)
45
+
djgentelella/urls.py CHANGED
@@ -13,9 +13,12 @@ from djgentelella.notification.base import NotificacionAPIView, NotificationView
13
13
  from djgentelella.permission_management import views as permissions
14
14
  from djgentelella.widgets.helper import HelperWidgetView
15
15
  from djgentelella.wysiwyg import views as wysiwyg
16
+ from djgentelella.firmador_digital import views as firmador_digital
16
17
  from .groute import routes
17
18
  from .templatetags.gtsettings import get_version
18
19
  from .views import auth
20
+ from .trash.api import TrashViewSet
21
+ from .history.api import HistoryViewSet
19
22
 
20
23
  auth_urls = [
21
24
  path('accounts/login/', auth.GentelellaLoginView.as_view(), name="login"),
@@ -45,7 +48,7 @@ auth_urls = [
45
48
  template_name='gentelella/registration/password_reset_confirm.html'
46
49
  ), name='password_reset_confirm'),
47
50
  path('accounts/reset/done/', auth_views.PasswordResetDoneView.as_view(
48
- template_name='gentelella/registration/password_reset_done.html'
51
+ template_name='gentelella/registration/reset_done.html'
49
52
  ), name="password_reset_complete")
50
53
  ]
51
54
  wysiwyg_urls = [
@@ -55,6 +58,7 @@ wysiwyg_urls = [
55
58
  name="tinymce_upload_video"),
56
59
  ]
57
60
 
61
+
58
62
  def import_module_app_gt(app, name):
59
63
  try:
60
64
  __import__(app + '.' + name)
@@ -71,6 +75,11 @@ for app in settings.INSTALLED_APPS:
71
75
 
72
76
  router = DefaultRouter()
73
77
  router.register('notificationtableview', NotificationViewSet, 'api-notificationtable')
78
+ router_trash = DefaultRouter()
79
+ router_trash.register("api_trash", TrashViewSet, basename="api-trash")
80
+ history_router = DefaultRouter()
81
+ history_router.register("api_history", HistoryViewSet, basename="api-history")
82
+
74
83
 
75
84
  base_urlpatterns = [
76
85
  re_path('gtapis/', include(routes.urls)),
@@ -87,6 +96,9 @@ base_urlpatterns = [
87
96
  re_path('^notification/list/$', notification_list_view,
88
97
  name="notification_list"),
89
98
  path('tableapi/', include(router.urls)),
99
+ path("update_config/", firmador_digital.update_signature_settings, name="signature_config"),
100
+ path("api/trash/", include(router_trash.urls)),
101
+ path("api/history/", include(history_router.urls)),
90
102
  ]
91
103
 
92
104
  permission_management_urls = [
@@ -96,7 +108,6 @@ permission_management_urls = [
96
108
  name="permissionsmanagement-list"),
97
109
  path('permissionsmanagement/save', permissions.save_permcategorymanagement,
98
110
  name="permcategorymanagement-save"),
99
-
100
111
  ]
101
112
 
102
113
  urlpatterns = auth_urls + base_urlpatterns + wysiwyg_urls + permission_management_urls
@@ -59,6 +59,29 @@ class GSerializerBase(serializers.Serializer):
59
59
  selected = serializers.SerializerMethodField()
60
60
 
61
61
 
62
+ class GSerializerImgBase(serializers.Serializer):
63
+ def get_id(self, obj):
64
+ return self.view.get_id_display(obj)
65
+
66
+ def get_text(self, obj):
67
+ return self.view.get_text_display(obj)
68
+
69
+ def get_url(self, obj):
70
+ return self.view.get_url(obj)
71
+
72
+ def get_selected(self, obj):
73
+ return self.view.get_selected_display(obj)
74
+
75
+ def get_disabled(self, obj):
76
+ return self.view.get_disabled_display(obj)
77
+
78
+ id = serializers.SerializerMethodField()
79
+ text = serializers.SerializerMethodField()
80
+ url = serializers.SerializerMethodField()
81
+ disabled = serializers.SerializerMethodField()
82
+ selected = serializers.SerializerMethodField()
83
+
84
+
62
85
  class BaseSelect2View(generics.ListAPIView, viewsets.GenericViewSet):
63
86
  model = None
64
87
  fields = []
@@ -165,3 +188,20 @@ class BaseSelect2View(generics.ListAPIView, viewsets.GenericViewSet):
165
188
 
166
189
  def get_disabled_display(self, obj):
167
190
  return False
191
+
192
+
193
+ class BaseSelectImg2View(BaseSelect2View):
194
+ model = None
195
+ fields = []
196
+ pagination_class = GPaginator
197
+ serializer_class = GSerializerImgBase
198
+
199
+ def get_serializer_class(self):
200
+ class S(self.serializer_class, serializers.ModelSerializer):
201
+ view = self
202
+
203
+ class Meta:
204
+ model = self.model
205
+ fields = ['id', 'text', 'url', 'disabled', 'selected']
206
+
207
+ return S
@@ -194,11 +194,12 @@ class FileInput(DJFileInput):
194
194
  def value_from_datadict(self, data, files, name):
195
195
  dev = None
196
196
  token = data.get(name)
197
- load_token = json.loads(token)
198
- tmpupload = ChunkedUpload.objects.filter(upload_id=load_token['token']).first()
199
- if tmpupload:
200
- dev = tmpupload.get_uploaded_file()
201
- tmpupload.delete()
197
+ if token:
198
+ load_token = json.loads(token)
199
+ tmpupload = ChunkedUpload.objects.filter(upload_id=load_token['token']).first()
200
+ if tmpupload:
201
+ dev = tmpupload.get_uploaded_file()
202
+ tmpupload.delete()
202
203
  return dev
203
204
 
204
205
  def value_omitted_from_data(self, data, files, name):
@@ -22,15 +22,13 @@ class DigitalSignatureInput(HiddenInput, ValueDSParser):
22
22
  def is_hidden(self):
23
23
  return True
24
24
 
25
- def __init__(self, attrs=None, extraskwargs=True, ws_url=None, cors=None,
25
+ def __init__(self, attrs=None, extraskwargs=True,
26
26
  title=None, render_basename=None, icon_url=None,
27
27
  extra_render_args=None,
28
28
  default_page="first"):
29
29
  attrs = attrs or {}
30
- attrs['data-ws-url'] = ws_url
31
- attrs['cors'] = cors
32
30
  attrs['title'] = title
33
-
31
+ attrs['data-ws-url'] = settings.FIRMADOR_WS_URL
34
32
  self.render_basename = render_basename
35
33
  self.icon_url = icon_url
36
34
  self.extra_render_args = extra_render_args or []
@@ -40,31 +38,17 @@ class DigitalSignatureInput(HiddenInput, ValueDSParser):
40
38
  if self.render_basename is None:
41
39
  logger.warning(
42
40
  "No base name for DigitalSignatureInput, this will generate a 500 error in the future")
43
- self.validate_attrs(attrs, ws_url, cors, default_page)
41
+ self.validate_attrs(attrs, default_page)
44
42
 
45
43
  if extraskwargs:
46
44
  attrs = update_kwargs(
47
45
  attrs, self.__class__.__name__, )
48
46
  super().__init__(attrs)
49
47
 
50
- def validate_attrs(self, attrs, ws_url, cors, default_page):
51
- if not ws_url:
52
- if not ws_url and settings.FIRMADOR_WS_URL:
53
- attrs['data-ws-url'] = settings.FIRMADOR_WS_URL
54
- else:
55
- raise ValueError(
56
- "Must provide a ws_url in attrs of DigitalSignatureInput.")
57
-
58
- if not cors:
59
- if not cors and settings.FIRMADOR_CORS:
60
- attrs['cors'] = settings.FIRMADOR_CORS
61
- else:
62
- raise ValueError(
63
- "Must provide a cors in attrs of DigitalSignatureInput.")
48
+ def validate_attrs(self, attrs, default_page):
64
49
 
65
50
  if isinstance(default_page, int) and default_page > 0:
66
- attrs['data-default-page'] = str(
67
- default_page)
51
+ attrs['data-default-page'] = str(default_page)
68
52
  elif default_page in ["first", "last"]:
69
53
  attrs['data-default-page'] = default_page
70
54
  else:
@@ -80,3 +80,50 @@ def AutocompleteSelectMultiple(url, url_suffix="-list", url_args=[], url_kwargs=
80
80
  extra_url_args = url_args.copy()
81
81
 
82
82
  return AutocompleteSelectMultiple
83
+
84
+
85
+ def AutocompleteSelectImage(url, url_suffix="-list", url_args=[], url_kwargs={},
86
+ attrs={}):
87
+ class ImgAutocompleteSelect(AutocompleteSelectBase):
88
+ baseurl = url + url_suffix
89
+ extra_attrs = attrs.copy()
90
+ extra_url_kwargs = url_kwargs.copy()
91
+ extra_url_args = url_args.copy()
92
+
93
+ def __init__(self, attrs=None, choices=(), extraskwargs=False):
94
+ if attrs is None:
95
+ attrs = {}
96
+ attrs = update_kwargs(attrs, 'AutocompleteSelectImage',
97
+ base_class='form-control ')
98
+ if 'templateresult' not in attrs:
99
+ attrs['data-templateresult'] = 'decore_img_select2'
100
+ super().__init__(attrs=attrs, choices=choices, extraskwargs=extraskwargs)
101
+
102
+ def optgroups(self, name, value, attrs=None):
103
+ return super().optgroups(name, value, attrs=attrs)
104
+
105
+ return ImgAutocompleteSelect
106
+
107
+
108
+ def AutocompleteSelectMultipleImage(url, url_suffix="-list", url_args=[], url_kwargs={},
109
+ attrs={}):
110
+ class ImgAutocompleteSelectMultiple(AutocompleteSelectMultipleBase):
111
+ baseurl = url + url_suffix
112
+ extra_attrs = attrs.copy()
113
+ extra_url_kwargs = url_kwargs.copy()
114
+ extra_url_args = url_args.copy()
115
+
116
+ def __init__(self, attrs=None, choices=(), extraskwargs=True):
117
+ if attrs is None:
118
+ attrs = {}
119
+ attrs['data-widget'] = 'AutocompleteSelectMultipleImage'
120
+ attrs['class'] = "form-control select2_multiple"
121
+ if 'templateresult' not in attrs:
122
+ attrs['data-templateresult'] = 'decore_img_select2'
123
+ if self.baseurl is None:
124
+ raise ValueError('Autocomplete requires baseurl to work')
125
+ else:
126
+ self.baseurl = self.baseurl
127
+ super(SelectMultiple, self).__init__(attrs, choices=choices)
128
+
129
+ return ImgAutocompleteSelectMultiple
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: djgentelella
3
- Version: 0.4.30
3
+ Version: 0.5.1
4
4
  Summary: Help building extra widgets for forms and speciall methods to render forms in templates
5
5
  Author-email: Solvosoft <info@solvosoft.com>
6
6
  Maintainer-email: Luis Zarate Montero <luis.zarate@solvosoft.com>
@@ -387,7 +387,7 @@ Requires-Dist: uvicorn==0.32.1; extra == "firmador"
387
387
  Requires-Dist: uvicorn-worker==0.2.0; extra == "firmador"
388
388
  Requires-Dist: channels==4.2.0; extra == "firmador"
389
389
  Requires-Dist: wsproto==1.2.0; extra == "firmador"
390
- Requires-Dist: requests==2.32.3; extra == "firmador"
390
+ Requires-Dist: requests==2.32.4; extra == "firmador"
391
391
  Provides-Extra: test
392
392
 
393
393
  Django Gentelella widgets