wcs: option to get forms user can access in current form cell (#56477)
This commit is contained in:
parent
69425c6200
commit
cb7e32cd2e
|
@ -14,10 +14,7 @@
|
|||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import json
|
||||
|
||||
from django import forms
|
||||
from django.utils.datastructures import MultiValueDict
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from combo.utils.forms import MultiSortWidget
|
||||
|
@ -130,17 +127,6 @@ class WcsFormsOfCategoryCellForm(forms.ModelForm):
|
|||
self.fields['manual_order'].widget = MultiSortWidget(choices=formdef_references)
|
||||
|
||||
|
||||
class CategoriesSelectMultiple(forms.SelectMultiple):
|
||||
def format_value(self, value):
|
||||
value = json.loads(value)
|
||||
return super().format_value(value.get('data') or [])
|
||||
|
||||
def value_from_datadict(self, data, files, name):
|
||||
if isinstance(data, MultiValueDict):
|
||||
return {'data': data.getlist(name)}
|
||||
return data.get(name, None)
|
||||
|
||||
|
||||
class WcsFormsMixin:
|
||||
def _init_wcs_site(self):
|
||||
if len(get_wcs_services()) == 1:
|
||||
|
@ -156,27 +142,63 @@ class WcsFormsMixin:
|
|||
|
||||
def _init_categories(self):
|
||||
categories = get_wcs_options('/api/categories/')
|
||||
self.fields['categories'].help_text = _('By default forms from all categories are displayed.')
|
||||
self.fields['categories'].widget = CategoriesSelectMultiple(
|
||||
choices=categories, attrs={'class': 'categories-select'}
|
||||
self.fields['categories'] = forms.MultipleChoiceField(
|
||||
choices=categories,
|
||||
help_text=_('By default forms from all categories are displayed.'),
|
||||
widget=forms.SelectMultiple(attrs={'class': 'categories-select'}),
|
||||
initial=self.instance.categories.get('data') or [],
|
||||
required=False,
|
||||
)
|
||||
if self.field_order:
|
||||
self.order_fields(self.field_order)
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
super().save(commit=False)
|
||||
self.instance.categories = {'data': self.cleaned_data.get('categories') or []}
|
||||
self.instance.save()
|
||||
return self.instance
|
||||
|
||||
|
||||
class WcsCurrentFormsCellForm(WcsFormsMixin, forms.ModelForm):
|
||||
field_order = [
|
||||
'wcs_site',
|
||||
'categories',
|
||||
'current_forms',
|
||||
'done_forms',
|
||||
'include_drafts',
|
||||
'include_forms_user_can_access',
|
||||
]
|
||||
|
||||
class Meta:
|
||||
model = WcsCurrentFormsCell
|
||||
fields = ['wcs_site', 'categories', 'current_forms', 'done_forms', 'include_drafts']
|
||||
fields = [
|
||||
'wcs_site',
|
||||
'current_forms',
|
||||
'done_forms',
|
||||
'include_drafts',
|
||||
'include_forms_user_can_access',
|
||||
]
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self._init_wcs_site()
|
||||
self._init_categories()
|
||||
|
||||
def clean(self):
|
||||
cleaned_data = super().clean()
|
||||
|
||||
if not cleaned_data.get('current_forms') and not cleaned_data.get('done_forms'):
|
||||
raise forms.ValidationError(
|
||||
_('Please choose at least one option among the following: Current Forms, Done Forms')
|
||||
)
|
||||
|
||||
return cleaned_data
|
||||
|
||||
|
||||
class WcsCurrentDraftsCellForm(WcsFormsMixin, forms.ModelForm):
|
||||
class Meta:
|
||||
model = WcsCurrentDraftsCell
|
||||
fields = ['wcs_site', 'categories']
|
||||
fields = ['wcs_site']
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
@ -187,7 +209,7 @@ class WcsCurrentDraftsCellForm(WcsFormsMixin, forms.ModelForm):
|
|||
class WcsCareFormsCellForm(WcsFormsMixin, forms.ModelForm):
|
||||
class Meta:
|
||||
model = WcsCareFormsCell
|
||||
fields = ['wcs_site', 'categories']
|
||||
fields = ['wcs_site']
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
@ -198,7 +220,7 @@ class WcsCareFormsCellForm(WcsFormsMixin, forms.ModelForm):
|
|||
class BackofficeSubmissionCellForm(WcsFormsMixin, forms.ModelForm):
|
||||
class Meta:
|
||||
model = WcsCurrentDraftsCell
|
||||
fields = ['wcs_site', 'categories']
|
||||
fields = ['wcs_site']
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('wcs', '0036_remove_wcscurrentformscell_include_forms_user_can_access'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='wcscurrentformscell',
|
||||
name='include_forms_user_can_access',
|
||||
field=models.BooleanField(
|
||||
default=False, verbose_name='Include requests for which the user is not the author'
|
||||
),
|
||||
),
|
||||
]
|
|
@ -465,6 +465,9 @@ class WcsCurrentFormsCell(CategoriesAndWcsSiteValidityMixin, CategoriesFiltering
|
|||
current_forms = models.BooleanField(_('Current Forms'), default=True)
|
||||
done_forms = models.BooleanField(_('Done Forms'), default=False)
|
||||
include_drafts = models.BooleanField(_('Include drafts'), default=False)
|
||||
include_forms_user_can_access = models.BooleanField(
|
||||
_('Include requests for which the user is not the author'), default=False
|
||||
)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('User Forms')
|
||||
|
@ -475,15 +478,23 @@ class WcsCurrentFormsCell(CategoriesAndWcsSiteValidityMixin, CategoriesFiltering
|
|||
return WcsCurrentFormsCellForm
|
||||
|
||||
def get_api_url(self, context):
|
||||
url = '/api/user/forms/'
|
||||
user = self.get_concerned_user(context)
|
||||
base_url = '/api/user/forms'
|
||||
if user:
|
||||
user_name_id = user.get_name_id()
|
||||
if user_name_id:
|
||||
base_url = '/api/users/%s/forms' % user_name_id
|
||||
url = base_url + '?limit=100&sort=desc'
|
||||
url = '/api/users/%s/forms' % user_name_id
|
||||
if self.current_forms and self.done_forms:
|
||||
url += '?status=all'
|
||||
elif self.done_forms:
|
||||
url += '?status=done'
|
||||
else:
|
||||
url += '?status=open'
|
||||
if self.include_forms_user_can_access:
|
||||
url += '&include-accessible=on'
|
||||
if self.include_drafts:
|
||||
url += '&include-drafts=on'
|
||||
url += '&limit=100&sort=desc'
|
||||
return url
|
||||
|
||||
@property
|
||||
|
@ -517,22 +528,6 @@ class WcsCurrentFormsCell(CategoriesAndWcsSiteValidityMixin, CategoriesFiltering
|
|||
def get_cell_extra_context(self, context):
|
||||
context = super().get_cell_extra_context(context)
|
||||
|
||||
for wcs_site in context['user_forms']:
|
||||
if not context['user_forms'].get(wcs_site):
|
||||
continue
|
||||
if not context['user_forms'][wcs_site].get('data'):
|
||||
continue
|
||||
forms = context['user_forms'][wcs_site]['data']
|
||||
if self.current_forms and self.done_forms:
|
||||
pass # keep them all
|
||||
elif self.current_forms:
|
||||
forms = [x for x in forms if not x.get('form_status_is_endpoint')]
|
||||
elif self.done_forms:
|
||||
forms = [x for x in forms if x.get('form_status_is_endpoint')]
|
||||
else:
|
||||
forms = [] # nothing left
|
||||
context['user_forms'][wcs_site]['data'] = forms # put it back
|
||||
|
||||
context['current_forms'] = context['user_forms'] # legacy
|
||||
|
||||
# regroup all forms in a flat list
|
||||
|
@ -574,14 +569,6 @@ class WcsCurrentDraftsCell(CategoriesAndWcsSiteValidityMixin, CategoriesFilterin
|
|||
def get_cell_extra_context(self, context):
|
||||
context = super().get_cell_extra_context(context)
|
||||
|
||||
for wcs_site in context['current_drafts']:
|
||||
if not context['current_drafts'].get(wcs_site):
|
||||
continue
|
||||
if not context['current_drafts'][wcs_site].get('data'):
|
||||
continue
|
||||
forms = context['current_drafts'][wcs_site]['data']
|
||||
context['current_drafts'][wcs_site]['data'] = forms # put it back
|
||||
|
||||
# regroup all forms in a flat list
|
||||
context['drafts'] = []
|
||||
for wcs_site in context['current_drafts']:
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
{% if forms %}
|
||||
{% for slug, forms in current_forms.items %}
|
||||
<div class="links-list current-forms-{{ slug }} current-forms list-of-forms">
|
||||
{% include "combo/wcs/list_of_forms.html" with forms=forms %}
|
||||
{% include "combo/wcs/list_of_forms.html" %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% include "combo/pagination.html" %}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
{% if forms %}
|
||||
{% for slug, forms in user_forms.items %}
|
||||
<div class="links-list user-forms-{{ slug }} user-all-forms list-of-forms">
|
||||
{% include "combo/wcs/list_of_forms.html" with forms=forms %}
|
||||
{% include "combo/wcs/list_of_forms.html" %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% include "combo/pagination.html" %}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
{% if forms %}
|
||||
{% for slug, forms in user_forms.items %}
|
||||
<div class="links-list user-forms-{{ slug }} list-of-forms">
|
||||
{% include "combo/wcs/list_of_forms.html" with forms=forms %}
|
||||
{% include "combo/wcs/list_of_forms.html" %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% include "combo/pagination.html" %}
|
||||
|
|
|
@ -81,15 +81,6 @@ WCS_USER_FORMS_DATA = [
|
|||
},
|
||||
{'name': 'name', 'url': '/form/2/', 'form_receipt_datetime': '2015-01-01T00:00:00', 'readable': True},
|
||||
{'name': 'name', 'title': 'Title', 'url': '/form/3/', 'form_receipt_datetime': '2015-01-01T00:00:00'},
|
||||
{
|
||||
'name': 'name',
|
||||
'title': 'Title',
|
||||
'url': '/form/4/',
|
||||
'form_receipt_datetime': '2015-01-01T00:00:00',
|
||||
'readable': True,
|
||||
'form_status_is_endpoint': True,
|
||||
'category_slug': 'test-9',
|
||||
},
|
||||
]
|
||||
|
||||
WCS_FORMS_DATA = [
|
||||
|
@ -514,27 +505,13 @@ def test_current_forms_cell_render(mock_send, context):
|
|||
|
||||
context['synchronous'] = True # to get fresh content
|
||||
|
||||
# default is to get current forms from all wcs sites
|
||||
result = cell.render(context)
|
||||
assert 'http://127.0.0.1:8999/form/1/' in result
|
||||
assert 'http://127.0.0.1:8999/form/2/' not in result # no title
|
||||
assert 'http://127.0.0.1:8999/form/3/' not in result # not readable
|
||||
assert 'http://127.0.0.1:8999/form/4/' not in result # done
|
||||
assert 'http://127.0.0.2:8999/form/1/' in result
|
||||
assert 'http://127.0.0.2:8999/form/2/' not in result
|
||||
assert 'http://127.0.0.2:8999/form/3/' not in result
|
||||
assert 'http://127.0.0.2:8999/form/4/' not in result
|
||||
|
||||
# done forms
|
||||
cell.current_forms = False
|
||||
cell.done_forms = True
|
||||
cell.include_drafts = False
|
||||
cell.save()
|
||||
result = cell.render(context)
|
||||
assert 'http://127.0.0.1:8999/form/1/' not in result # wip
|
||||
assert 'http://127.0.0.1:8999/form/4/' in result # done
|
||||
assert 'http://127.0.0.2:8999/form/1/' not in result # wip
|
||||
assert 'http://127.0.0.2:8999/form/4/' in result # done
|
||||
|
||||
# limit to categories
|
||||
cell.categories = {'data': ['default:test-3', 'other:test-6']}
|
||||
|
@ -543,9 +520,15 @@ def test_current_forms_cell_render(mock_send, context):
|
|||
requests_get.return_value = mock_json
|
||||
cell.get_cell_extra_context(context)
|
||||
assert len(requests_get.call_args_list) == 2
|
||||
assert requests_get.call_args_list[0][0][0] == '/api/user/forms?limit=100&sort=desc&category_slugs=test-3'
|
||||
assert (
|
||||
requests_get.call_args_list[0][0][0]
|
||||
== '/api/user/forms/?status=open&limit=100&sort=desc&category_slugs=test-3'
|
||||
)
|
||||
assert requests_get.call_args_list[0][1]['remote_service']['url'] == 'http://127.0.0.1:8999/'
|
||||
assert requests_get.call_args_list[1][0][0] == '/api/user/forms?limit=100&sort=desc&category_slugs=test-6'
|
||||
assert (
|
||||
requests_get.call_args_list[1][0][0]
|
||||
== '/api/user/forms/?status=open&limit=100&sort=desc&category_slugs=test-6'
|
||||
)
|
||||
assert requests_get.call_args_list[1][1]['remote_service']['url'] == 'http://127.0.0.2:8999/'
|
||||
|
||||
# check include drafts
|
||||
|
@ -556,9 +539,9 @@ def test_current_forms_cell_render(mock_send, context):
|
|||
requests_get.return_value = mock_json
|
||||
cell.get_cell_extra_context(context)
|
||||
assert len(requests_get.call_args_list) == 2
|
||||
assert requests_get.call_args_list[0][0][0] == '/api/user/forms?limit=100&sort=desc'
|
||||
assert requests_get.call_args_list[0][0][0] == '/api/user/forms/?status=open&limit=100&sort=desc'
|
||||
assert requests_get.call_args_list[0][1]['remote_service']['url'] == 'http://127.0.0.1:8999/'
|
||||
assert requests_get.call_args_list[1][0][0] == '/api/user/forms?limit=100&sort=desc'
|
||||
assert requests_get.call_args_list[1][0][0] == '/api/user/forms/?status=open&limit=100&sort=desc'
|
||||
assert requests_get.call_args_list[1][1]['remote_service']['url'] == 'http://127.0.0.2:8999/'
|
||||
|
||||
cell.include_drafts = True
|
||||
|
@ -567,9 +550,15 @@ def test_current_forms_cell_render(mock_send, context):
|
|||
requests_get.return_value = mock_json
|
||||
cell.get_cell_extra_context(context)
|
||||
assert len(requests_get.call_args_list) == 2
|
||||
assert requests_get.call_args_list[0][0][0] == '/api/user/forms?limit=100&sort=desc&include-drafts=on'
|
||||
assert (
|
||||
requests_get.call_args_list[0][0][0]
|
||||
== '/api/user/forms/?status=open&include-drafts=on&limit=100&sort=desc'
|
||||
)
|
||||
assert requests_get.call_args_list[0][1]['remote_service']['url'] == 'http://127.0.0.1:8999/'
|
||||
assert requests_get.call_args_list[1][0][0] == '/api/user/forms?limit=100&sort=desc&include-drafts=on'
|
||||
assert (
|
||||
requests_get.call_args_list[1][0][0]
|
||||
== '/api/user/forms/?status=open&include-drafts=on&limit=100&sort=desc'
|
||||
)
|
||||
assert requests_get.call_args_list[1][1]['remote_service']['url'] == 'http://127.0.0.2:8999/'
|
||||
|
||||
cell.categories = {'data': ['default:test-3']}
|
||||
|
@ -580,7 +569,7 @@ def test_current_forms_cell_render(mock_send, context):
|
|||
assert len(requests_get.call_args_list) == 1
|
||||
assert (
|
||||
requests_get.call_args_list[0][0][0]
|
||||
== '/api/user/forms?limit=100&sort=desc&include-drafts=on&category_slugs=test-3'
|
||||
== '/api/user/forms/?status=open&include-drafts=on&limit=100&sort=desc&category_slugs=test-3'
|
||||
)
|
||||
assert requests_get.call_args_list[0][1]['remote_service']['url'] == 'http://127.0.0.1:8999/'
|
||||
|
||||
|
@ -591,6 +580,54 @@ def test_current_forms_cell_render(mock_send, context):
|
|||
cell.get_cell_extra_context(context)
|
||||
assert len(requests_get.call_args_list) == 2
|
||||
|
||||
# current_forms only
|
||||
cell.include_drafts = False
|
||||
cell.current_forms = True
|
||||
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
|
||||
mock_json = mock.Mock(status_code=200)
|
||||
requests_get.return_value = mock_json
|
||||
cell.get_cell_extra_context(context)
|
||||
assert len(requests_get.call_args_list) == 2
|
||||
assert requests_get.call_args_list[0][0][0] == '/api/user/forms/?status=open&limit=100&sort=desc'
|
||||
assert requests_get.call_args_list[0][1]['remote_service']['url'] == 'http://127.0.0.1:8999/'
|
||||
assert requests_get.call_args_list[1][0][0] == '/api/user/forms/?status=open&limit=100&sort=desc'
|
||||
assert requests_get.call_args_list[1][1]['remote_service']['url'] == 'http://127.0.0.2:8999/'
|
||||
|
||||
# all forms
|
||||
cell.done_forms = True
|
||||
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
|
||||
mock_json = mock.Mock(status_code=200)
|
||||
requests_get.return_value = mock_json
|
||||
cell.get_cell_extra_context(context)
|
||||
assert len(requests_get.call_args_list) == 2
|
||||
assert requests_get.call_args_list[0][0][0] == '/api/user/forms/?status=all&limit=100&sort=desc'
|
||||
assert requests_get.call_args_list[0][1]['remote_service']['url'] == 'http://127.0.0.1:8999/'
|
||||
assert requests_get.call_args_list[1][0][0] == '/api/user/forms/?status=all&limit=100&sort=desc'
|
||||
assert requests_get.call_args_list[1][1]['remote_service']['url'] == 'http://127.0.0.2:8999/'
|
||||
|
||||
# done forms only
|
||||
cell.current_forms = False
|
||||
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
|
||||
mock_json = mock.Mock(status_code=200)
|
||||
requests_get.return_value = mock_json
|
||||
cell.get_cell_extra_context(context)
|
||||
assert len(requests_get.call_args_list) == 2
|
||||
assert requests_get.call_args_list[0][0][0] == '/api/user/forms/?status=done&limit=100&sort=desc'
|
||||
assert requests_get.call_args_list[0][1]['remote_service']['url'] == 'http://127.0.0.1:8999/'
|
||||
assert requests_get.call_args_list[1][0][0] == '/api/user/forms/?status=done&limit=100&sort=desc'
|
||||
assert requests_get.call_args_list[1][1]['remote_service']['url'] == 'http://127.0.0.2:8999/'
|
||||
|
||||
# include forms user can see
|
||||
cell.include_forms_user_can_access = True
|
||||
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
|
||||
mock_json = mock.Mock(status_code=200)
|
||||
requests_get.return_value = mock_json
|
||||
cell.render(context)
|
||||
assert (
|
||||
requests_get.call_args_list[0][0][0]
|
||||
== '/api/user/forms/?status=done&include-accessible=on&limit=100&sort=desc'
|
||||
)
|
||||
|
||||
# check empty messages
|
||||
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get:
|
||||
mock_json = mock.Mock(status_code=200)
|
||||
|
@ -719,7 +756,7 @@ def test_current_forms_cell_render_single_site(mock_send, context):
|
|||
assert 'http://127.0.0.2:8999/form/1/' not in result
|
||||
|
||||
|
||||
def test_current_forms_unknown_name_id(context):
|
||||
def test_current_forms_name_id(context):
|
||||
page = Page(title='xxx', slug='test_current_forms_cell_render', template_name='standard')
|
||||
page.save()
|
||||
cell = WcsCurrentFormsCell(page=page, placeholder='content', order=0)
|
||||
|
@ -739,7 +776,7 @@ def test_current_forms_unknown_name_id(context):
|
|||
mock_json = mock.Mock(status_code=200)
|
||||
requests_get.return_value = mock_json
|
||||
cell.render(context)
|
||||
assert requests_get.call_args_list[0][0][0] == '/api/users/xyz/forms?limit=100&sort=desc'
|
||||
assert requests_get.call_args_list[0][0][0] == '/api/users/xyz/forms?status=open&limit=100&sort=desc'
|
||||
|
||||
|
||||
def test_care_forms_cell_setup():
|
||||
|
@ -1267,7 +1304,7 @@ def test_manager_forms_of_category_cell(mock_send, app, admin_user):
|
|||
|
||||
|
||||
@mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send)
|
||||
def test_manager_current_forms(mock_send, app, admin_user):
|
||||
def test_manager_current_forms(mock_send, settings, app, admin_user):
|
||||
page = Page(title='One', slug='one', template_name='standard')
|
||||
page.save()
|
||||
app = login(app)
|
||||
|
@ -1289,21 +1326,21 @@ def test_manager_current_forms(mock_send, app, admin_user):
|
|||
'default:test-3',
|
||||
'default:test-9',
|
||||
]
|
||||
resp.form['c%s-current_forms' % cells[0].get_reference()] = False
|
||||
resp.form['c%s-done_forms' % cells[0].get_reference()] = False
|
||||
resp = resp.form.submit()
|
||||
assert 'Please choose at least one option among the following: Current Forms, Done Forms' in resp
|
||||
resp = app.get('/manage/pages/%s/' % page.id)
|
||||
resp.form['c%s-done_forms' % cells[0].get_reference()] = True
|
||||
resp = resp.form.submit().follow()
|
||||
|
||||
# check wcs_site field is a select box
|
||||
assert resp.form['c%s-wcs_site' % cells[0].get_reference()].tag == 'select'
|
||||
|
||||
try:
|
||||
# check the wcs_site field is hidden if there's a single one defined in
|
||||
# the configuration
|
||||
temp_settings = settings.KNOWN_SERVICES.copy()
|
||||
default = settings.KNOWN_SERVICES['wcs']['default']
|
||||
settings.KNOWN_SERVICES = {'wcs': {'default': default}}
|
||||
resp = app.get('/manage/pages/%s/' % page.id)
|
||||
assert resp.form['c%s-wcs_site' % cells[0].get_reference()].attrs['type'] == 'hidden'
|
||||
finally:
|
||||
# restore original settings
|
||||
settings.KNOWN_SERVICES = temp_settings
|
||||
default = settings.KNOWN_SERVICES['wcs']['default']
|
||||
settings.KNOWN_SERVICES = {'wcs': {'default': default}}
|
||||
resp = app.get('/manage/pages/%s/' % page.id)
|
||||
assert resp.form['c%s-wcs_site' % cells[0].get_reference()].attrs['type'] == 'hidden'
|
||||
|
||||
|
||||
@mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send)
|
||||
|
|
Loading…
Reference in New Issue