diff --git a/jdav_web/members/admin.py b/jdav_web/members/admin.py index ca206d4..65b32c6 100644 --- a/jdav_web/members/admin.py +++ b/jdav_web/members/admin.py @@ -533,76 +533,51 @@ class MemberNoteListAdmin(admin.ModelAdmin): list_display = ['__str__', 'date'] search_fields = ('name',) ordering = ('-date',) - actions = ['generate_summary'] + actions = ['summary'] - def generate_summary(self, request, queryset): - """Generates a pdf summary of the given NoteMemberLists - """ - for memberlist in queryset: - # unique filename - filename = memberlist.title + "_notes_" + datetime.today().strftime("%d_%m_%Y") - filename = filename.replace(' ', '_').replace('&', '').replace('/', '_') - # drop umlauts, accents etc. - filename = unicodedata.normalize('NFKD', filename).\ - encode('ASCII', 'ignore').decode() - filename_tex = filename + '.tex' - filename_pdf = filename + '.pdf' - - # generate table - table = "" - for memberonlist in memberlist.membersonlist.all(): - m = memberonlist.member - comment = ". ".join(c for c - in (m.comments, - memberonlist.comments) if - c).replace("..", ".") - line = '{0} {1} & {2} \\\\'.format( - esc_ampersand(m.prename), esc_ampersand(m.lastname), - esc_ampersand(comment) or "---") - table += esc_underscore(line) - - # copy template - shutil.copy(media_path('memberlistnote_template.tex'), - media_path(filename_tex)) - - # read in template - with open(media_path(filename_tex), 'r', encoding='utf-8') as f: - template_content = f.read() - - # adapt template - title = esc_all(memberlist.title) - template_content = template_content.replace('MEMBERLIST-TITLE', title) - template_content = template_content.replace('MEMBERLIST-DATE', - datetime.today().strftime('%d.%m.%Y')) - template_content = template_content.replace('TABLE', table) - - # write adapted template to file - with open(media_path(filename_tex), 'w', encoding='utf-8') as f: - f.write(template_content) - - # compile using pdflatex - oldwd = os.getcwd() - os.chdir(media_dir()) - subprocess.call(['pdflatex', filename_tex]) - time.sleep(1) - - # do some cleanup - for f in glob.glob('*.log'): - os.remove(f) - for f in glob.glob('*.aux'): - os.remove(f) - os.remove(filename_tex) - - os.chdir(oldwd) - - # provide the user with the resulting pdf file - with open(media_path(filename_pdf), 'rb') as pdf: - response = HttpResponse(FileWrapper(pdf)) - response['Content-Type'] = 'application/pdf' - response['Content-Disposition'] = 'attachment; filename=' + filename_pdf - - return response - generate_summary.short_description = "PDF Übersicht erstellen" + def get_urls(self): + urls = super().get_urls() + + 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) + + custom_urls = [ + path( + "/action/", + wrap(self.action_view), + name="%s_%s_action" % (self.opts.app_label, self.opts.model_name), + ), + ] + return custom_urls + urls + + def action_view(self, request, object_id): + if "summary" in request.POST: + return self.summary(request, [MemberNoteList.objects.get(pk=object_id)]) + return HttpResponseRedirect(reverse('admin:%s_%s_change' % (self.opts.app_label, self.opts.model_name), + args=(object_id,))) + + def may_view_notelist(self, request, memberlist): + return request.user.has_perm('members.may_view_everyone') or \ + ( hasattr(request.user, 'member') and \ + all([request.user.member.may_view(m.member) for m in memberlist.membersonlist.all()]) ) + + def not_allowed_view(self, request, memberlist): + messages.error(request, + _("You are not allowed to view all members on note list %(name)s.") % {'name': memberlist.title}) + return HttpResponseRedirect(reverse('admin:%s_%s_changelist' % (self.opts.app_label, self.opts.model_name))) + + def summary(self, request, queryset): + # this ensures legacy compatibilty + memberlist = queryset[0] + if not self.may_view_notelist(request, memberlist): + return self.not_allowed_view(request, memberlist) + context = dict(memberlist=memberlist, settings=settings) + return render_tex(memberlist.title + "_Zusammenfassung", 'members/notelist_summary.tex', context) + summary.short_description = _('Generate PDF summary') class FreizeitAdmin(CommonAdminMixin, nested_admin.NestedModelAdmin): @@ -773,23 +748,3 @@ admin.site.register(MemberNoteList, MemberNoteListAdmin) admin.site.register(Klettertreff, KlettertreffAdmin) admin.site.register(ActivityCategory, ActivityCategoryAdmin) admin.site.register(TrainingCategory, TrainingCategoryAdmin) - - -def media_path(fp): - return os.path.join(os.path.join(settings.MEDIA_MEMBERLISTS, "memberlists"), fp) - - -def media_dir(): - return os.path.join(settings.MEDIA_MEMBERLISTS, "memberlists") - - -def esc_underscore(txt): - return txt.replace('_', '\_') - - -def esc_ampersand(txt): - return txt.replace('&', '\&') - - -def esc_all(txt): - return esc_underscore(esc_ampersand(txt)) diff --git a/jdav_web/members/templates/members/notelist_summary.tex b/jdav_web/members/templates/members/notelist_summary.tex new file mode 100644 index 0000000..16311d0 --- /dev/null +++ b/jdav_web/members/templates/members/notelist_summary.tex @@ -0,0 +1,38 @@ +{% load tex_extras %} + +\documentclass{article} + +\usepackage[utf8]{inputenc} +\usepackage{booktabs} +\usepackage{tabularx} +\usepackage{ragged2e} +\usepackage{amssymb} +\usepackage{cmbright} +\usepackage{graphicx} +\usepackage{textpos} +\usepackage[colorlinks]{hyperref} +\usepackage{float} +\usepackage[margin=1cm]{geometry} + +\renewcommand{\arraystretch}{1.5} + +\newcolumntype{Y}{>{\RaggedRight\arraybackslash}X} +\begin{document} + +% HEADLINE +{\noindent\LARGE\textsc{ {{ memberlist.title|esc_all }} }}\\ +\textit{Erstellt: {{ creation_date }} }\\ + +\begin{table}[H] + \begin{tabularx}{\textwidth}{@{} l l Y @{}} + \toprule + \textbf{Name} & \textbf{Kommentare} \\ + \midrule + {% for m in memberlist.membersonlist.all %} + {{ m.member.name|esc_all }} & {{ m.comments_tex|esc_all }} \\ + {% endfor %} + \bottomrule + \end{tabularx} +\end{table} + +\end{document}