From 37cbc11227f5b2f3a8cff0c9411c130006262da5 Mon Sep 17 00:00:00 2001 From: Valentin Deniaud Date: Mon, 24 Jan 2022 18:14:05 +0100 Subject: [PATCH] wip --- wcs/backoffice/management.py | 2 +- wcs/statistics/views.py | 126 ++++++++++++++++++++++++++++++++++- 2 files changed, 124 insertions(+), 4 deletions(-) diff --git a/wcs/backoffice/management.py b/wcs/backoffice/management.py index 7d545d216..0efdb4fc8 100644 --- a/wcs/backoffice/management.py +++ b/wcs/backoffice/management.py @@ -925,7 +925,7 @@ class FormPage(Directory): return ('start', 'end') return () - def get_item_filter_options(self, filter_field, selected_filter, criterias): + def get_item_filter_options(self, filter_field, selected_filter, criterias=None): criterias = (criterias or [])[:] # remove potential filter on self (Equal for item, Intersects for items) criterias = [ diff --git a/wcs/statistics/views.py b/wcs/statistics/views.py index ed0e2e8b9..63c5e40cf 100644 --- a/wcs/statistics/views.py +++ b/wcs/statistics/views.py @@ -17,13 +17,15 @@ from django.http import HttpResponseBadRequest, HttpResponseForbidden, JsonResponse from django.urls import reverse from django.views.generic import View -from quixote import get_publisher +from quixote import get_publisher, get_request from wcs.api_utils import is_url_signed +from wcs.backoffice.management import FormPage from wcs.categories import Category +from wcs.formdef import FormDef from wcs.qommon import _, misc from wcs.qommon.misc import C_ -from wcs.qommon.storage import Equal +from wcs.qommon.storage import Equal, NotEqual, Or class RestrictedView(View): @@ -42,6 +44,11 @@ class IndexView(RestrictedView): category_options = [{'id': '_all', 'label': C_('categories|All')}] + [ {'id': x.id, 'label': x.name} for x in categories ] + forms = FormDef.select() + forms.sort(key=lambda x: misc.simplify(x.name)) + form_options = [{'id': '_all', 'label': C_('forms|All')}] + [ + {'id': x.url_name, 'label': x.name} for x in forms + ] return JsonResponse( { 'data': [ @@ -81,6 +88,13 @@ class IndexView(RestrictedView): 'required': True, 'default': '_all', }, + { + 'id': 'form', + 'label': _('Form'), + 'options': form_options, + 'required': True, + 'default': '_all', + }, ], } ] @@ -99,8 +113,20 @@ class FormsCountView(RestrictedView): 'criterias': [], } category_id = request.GET.get('category', '_all') - if category_id != '_all': + formdef_slug = request.GET.get('form', '_all') + subfilters = [] + if formdef_slug != '_all': + try: + formdef = FormDef.get_by_urlname(formdef_slug, ignore_migration=True) + except KeyError: + return HttpResponseBadRequest('invalid form') + form_page = FormPage(formdef=formdef, update_breadcrumbs=False) + totals_kwargs['criterias'].append(Equal('formdef_id', formdef.id)) + totals_kwargs['criterias'].extend(self.get_filters_criterias(formdef, form_page)) + subfilters = self.get_subfilters(form_page) + elif category_id != '_all': totals_kwargs['criterias'].append(Equal('category_id', category_id)) + time_interval_methods = { 'month': sql.get_monthly_totals, 'year': sql.get_yearly_totals, @@ -122,7 +148,101 @@ class FormsCountView(RestrictedView): 'data': [x[1] for x in totals], } ], + 'subfilters': subfilters, }, 'err': 0, } ) + + def get_filters_criterias(self, formdef, form_page): + criterias = form_page.get_criterias_from_query() + + selected_status = self.request.GET['filter-status'] + applied_filters = None + if selected_status and selected_status != 'all': + if selected_status == 'pending': + applied_filters = ['wf-%s' % x.id for x in formdef.workflow.get_not_endpoint_status()] + elif selected_status == 'done': + applied_filters = ['wf-%s' % x.id for x in formdef.workflow.get_endpoint_status()] + else: + try: + formdef.workflow.get_status(selected_status) + applied_filters = ['wf-%s' % selected_status] + except KeyError: + pass + + if applied_filters: + criterias.append(Or([Equal('status', x) for x in applied_filters])) + else: + criterias = [NotEqual('status', 'draft')] + criterias + + return criterias + + @staticmethod + def get_subfilters(form_page): + waitpoint_status = form_page.formdef.workflow.get_waitpoint_status() + + filter_fields = [] + for field in form_page.get_formdef_fields(): + if field.type not in form_page.get_filterable_field_types() + ['status']: + continue + if field.type == 'status' and not waitpoint_status: + continue + filter_fields.append(field) + + # add contextual_id/contextual_varname attributes + # they are id/varname for normal fields + # but in case of blocks they are concatenation of block id/varname + field id/varname + is_in_block_field = getattr(field, 'block_field', None) + field.contextual_id = field.id + field.contextual_varname = None + if is_in_block_field: + field.contextual_id = '%s-%s' % (field.block_field.id, field.id) + field.label = '%s / %s' % (field.block_field.label, field.label) + if field.varname and field.block_field.varname: + field.contextual_varname = '%s_%s' % (field.block_field.varname, field.varname) + else: + field.contextual_varname = field.varname + + subfilters = [] + for filter_field in filter_fields: + if not filter_field.contextual_varname: + continue + + filter_field_key = 'filter-%s' % filter_field.contextual_varname + filter_field.required = False + filter_field.default_filter_value = '' + + if filter_field.type == 'status': + filter_field.required = True + filter_field.default_filter_value = 'all' + options = [ + ('waiting', _('Waiting for an action')), + ('all', _('All')), + ('pending', C_('formdata|Open')), + ('done', _('Done')), + ] + for status in waitpoint_status: + options.append((status.id, status.name)) + elif filter_field.type in ('item', 'items'): + if get_publisher().is_using_postgresql(): + options = form_page.get_item_filter_options(filter_field, selected_filter='all') + else: + continue + elif filter_field.type == 'bool': + options = [('true', _('Yes')), ('false', _('No'))] + else: + continue + + filter_description = { + 'id': filter_field_key, + 'label': filter_field.label, + 'options': [{'id': x[0], 'label': x[1]} for x in options], + 'required': filter_field.required, + } + if filter_field.default_filter_value: + filter_description['default'] = filter_field.default_filter_value + + subfilters.append(filter_description) + + return subfilters -- 2.30.2