From 97c6905a583929182431181a1f6cedaac2b7ebfa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ses=C3=B3stris=20Vieira?= Date: Wed, 12 Jan 2022 21:13:14 -0300 Subject: [PATCH] =?UTF-8?q?Adicionado=20utilit=C3=A1rio=20de=20carrinho=20?= =?UTF-8?q?para=20exporta=C3=A7=C3=A3o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- requirements/requirements.txt | 12 +- sigi/apps/utils/apps.py | 6 + sigi/apps/utils/mixins.py | 137 ++++++++++++++++++ .../admin/cart/change_list_cart_export.html | 24 +++ .../admin/cart/change_list_cart_item.html | 5 + .../templates/admin/cart/export_fields.html | 33 +++++ sigi/apps/utils/tests.py | 3 + 7 files changed, 214 insertions(+), 6 deletions(-) create mode 100644 sigi/apps/utils/apps.py create mode 100644 sigi/apps/utils/mixins.py create mode 100644 sigi/apps/utils/templates/admin/cart/change_list_cart_export.html create mode 100644 sigi/apps/utils/templates/admin/cart/change_list_cart_item.html create mode 100644 sigi/apps/utils/templates/admin/cart/export_fields.html create mode 100644 sigi/apps/utils/tests.py diff --git a/requirements/requirements.txt b/requirements/requirements.txt index b6ec1b1..9f021d5 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -1,11 +1,11 @@ ipython==7.30.1 +Pillow==9.0.0 +psycopg2==2.9.3 +requests==2.27.1 weasyprint==54.0 Django==4.0.1 -django-localflavor==3.1 -django-extensions==3.1.5 -django-weasyprint==2.1.0 -psycopg2==2.9.3 django-bootstrap5==21.3 -Pillow==9.0.0 +django-extensions==3.1.5 +django-import-export==2.7.1 django-localflavor==3.1 -requests==2.27.1 \ No newline at end of file +django-weasyprint==2.1.0 \ No newline at end of file diff --git a/sigi/apps/utils/apps.py b/sigi/apps/utils/apps.py new file mode 100644 index 0000000..fdf4443 --- /dev/null +++ b/sigi/apps/utils/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig +from django.utils.translation import gettext_lazy as _ + +class UtilsConfig(AppConfig): + name = 'sigi.apps.utils' + verbose_name = _('utiliátios SIGI') diff --git a/sigi/apps/utils/mixins.py b/sigi/apps/utils/mixins.py new file mode 100644 index 0000000..fffbade --- /dev/null +++ b/sigi/apps/utils/mixins.py @@ -0,0 +1,137 @@ +from collections import OrderedDict +from functools import update_wrapper +from django.contrib import admin +from django.contrib.admin import helpers +from django.contrib.admin.options import csrf_protect_m +from django.http.response import HttpResponseRedirect +from django.utils.translation import gettext as _, ngettext +from import_export.admin import ExportMixin + +class CartExportMixin(ExportMixin): + actions = ['add_to_cart'] + change_list_template = 'admin/cart/change_list_cart_export.html' + _cart_session_name = None + _cart_viewing_name = None + + def __init__(self, *args, **kwargs): + super(CartExportMixin, self).__init__(*args, **kwargs) + self._cart_session_name = 'cart_%s' % self.opts.model_name + self._cart_viewing_name = 'view_cart_%s' % self.opts.model_name + + def get_queryset(self, request): + qs = super(CartExportMixin, self).get_queryset(request) + if self._cart_viewing_name in request.session: + ids = request.session.get(self._cart_session_name, []) + qs = qs.filter(id__in=ids) + return qs + + def get_actions(self, request): + if self._cart_viewing_name in request.session: + action = self.get_action('remove_from_cart') + return OrderedDict([(action[1], action)]) + else: + return super(CartExportMixin, self).get_actions(request) + + @csrf_protect_m + def changelist_view(self, request, extra_context=None): + if 'cart' in request.GET: + request.GET._mutable = True + cart = request.GET.get('cart', '0') + request.GET.pop('cart', None) + request.GET._mutable = False + if cart == '1': + request.session[self._cart_viewing_name] = True + else: + request.session.pop(self._cart_viewing_name, None) + + cart_item_count = len(request.session.get(self._cart_session_name, [])) + + extra_context = extra_context or {} + extra_context['cart_item_count'] = ( + _('Vazio') if cart_item_count == 0 + else _(f'{cart_item_count} itens') + ) + + if self._cart_viewing_name in request.session: + extra_context['viewing_cart'] = True + return super(CartExportMixin, self).changelist_view(request, extra_context) + + def get_urls(self): + from django.urls import path + def wrap(view): + def wrapper(*args, **kwargs): + return self.admin_site.admin_view(view)(*args, **kwargs) + wrapper.model_admin = self + return update_wrapper(wrapper, view) + + info = self.model._meta.app_label, self.model._meta.model_name + + paths = super(CartExportMixin, self).get_urls() + paths.insert(2, path( + 'clearcart/', + wrap(self.clear_cart), + name='%s_%s_clearcart' % info + )) + return paths + + @csrf_protect_m + def add_to_cart(self, request, queryset): + if request.POST.get('select_across', '0') == '0': + selected_ids = set( + request.POST.getlist(helpers.ACTION_CHECKBOX_NAME, []) + ) + else: + selected_ids = set( + map(str, queryset.values_list('id', flat=True)) + ) + + if self._cart_session_name in request.session: + cart_ids = set(request.session[self._cart_session_name]) + else: + cart_ids = set() + + quant = len(selected_ids.difference(cart_ids)) + + if quant: + cart_ids.update(selected_ids) + request.session[self._cart_session_name] = list(cart_ids) + self.message_user( + request, + _(u"%s itens adicionados no carrinho") % quant) + else: + self.message_user( + request, + _(u"Os itens selecionados já estavam no carrinho")) + return HttpResponseRedirect('.') + add_to_cart.short_description = _( + "Armazenar itens no carrinho para exportar" + ) + + @csrf_protect_m + def remove_from_cart(self, request, queryset): + if self._cart_session_name not in request.session: + self.message_user(request, _(u"O carrinho está vazio")) + return HttpResponseRedirect('.') + + if request.POST.get('select_across', '0') == '0': + remove_ids = set(request.POST.getlist(helpers.ACTION_CHECKBOX_NAME)) + else: + remove_ids = set(map(str, queryset.values_list('id', flat=True))) + cart_ids = set(request.session[self._cart_session_name]) + + request.session[self._cart_session_name] = list( + cart_ids.difference(remove_ids) + ) + + self.message_user(request, _(u"%s itens removidos do carrinho.") % + len(cart_ids.intersection(remove_ids))) + + return HttpResponseRedirect('.') + remove_from_cart.short_description = _("Remove itens do carrinho") + + @csrf_protect_m + def clear_cart(self, request): + request.session.pop(self._cart_session_name, None) + request.session.pop(self._cart_viewing_name, None) + self.message_user(request, _(u"Carrinho vazio")) + return HttpResponseRedirect('..') diff --git a/sigi/apps/utils/templates/admin/cart/change_list_cart_export.html b/sigi/apps/utils/templates/admin/cart/change_list_cart_export.html new file mode 100644 index 0000000..c0950cc --- /dev/null +++ b/sigi/apps/utils/templates/admin/cart/change_list_cart_export.html @@ -0,0 +1,24 @@ +{% extends "admin/import_export/change_list_export.html" %} +{% load admin_list admin_urls i18n %} + +{% block content_title %} + {% if viewing_cart %} + {% blocktrans with s=opts.verbose_name_plural|lower c=cart_item_count %} +

Visualizando carrinho de {{ s }} {{ c }}

+ {% endblocktrans %} + {% else %} + {% if title %}

{{ title }}

{% endif %} + {% endif %} +{% endblock %} + + {{ block.super }} + +{% block object-tools-items %} + {% if viewing_cart %} + {% include "admin/import_export/change_list_export_item.html" %} + {% include "admin/cart/change_list_cart_item.html" %} + {% else %} +
  • {% blocktrans with c=cart_item_count %}Ver Carrinho {{ c }}{% endblocktrans %}
  • + {{ block.super }} + {% endif %} +{% endblock %} diff --git a/sigi/apps/utils/templates/admin/cart/change_list_cart_item.html b/sigi/apps/utils/templates/admin/cart/change_list_cart_item.html new file mode 100644 index 0000000..c785e3f --- /dev/null +++ b/sigi/apps/utils/templates/admin/cart/change_list_cart_item.html @@ -0,0 +1,5 @@ +{% load i18n %} +{% load admin_urls %} + +
  • {% trans 'Voltar à lista completa' %}
  • +
  • {% trans "Esvaziar carrinho" %}
  • diff --git a/sigi/apps/utils/templates/admin/cart/export_fields.html b/sigi/apps/utils/templates/admin/cart/export_fields.html new file mode 100644 index 0000000..1075eef --- /dev/null +++ b/sigi/apps/utils/templates/admin/cart/export_fields.html @@ -0,0 +1,33 @@ +{% extends "admin/base_site.html" %} +{% load i18n admin_urls %} + +{% block coltype %}flex{% endblock %} +{% block content_title %}

    {% trans "Exportar para CSV" %}

    {% endblock %} +{% block content %} +
    {% csrf_token %} +
    +
    +

    {% trans "Selecione os campos para exportar" %}

    +
    +
    +
    + {% for field, label in export_fields %} +
    + +
    + {% endfor %} +
    +
    + +
    + +
    +{% endblock %} \ No newline at end of file diff --git a/sigi/apps/utils/tests.py b/sigi/apps/utils/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/sigi/apps/utils/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here.