0001-wcs-add-categories-field-to-CareForms-cell-53213.patch
combo/apps/wcs/forms.py | ||
---|---|---|
23 | 23 |
from .models import ( |
24 | 24 |
WcsCardInfosCell, |
25 | 25 |
WcsCardsCell, |
26 |
WcsCareFormsCell, |
|
26 | 27 |
WcsCategoryCell, |
27 | 28 |
WcsCurrentDraftsCell, |
28 | 29 |
WcsCurrentFormsCell, |
... | ... | |
153 | 154 |
self._init_categories() |
154 | 155 | |
155 | 156 | |
157 |
class WcsCareFormsCellForm(WcsFormsMixin, forms.ModelForm): |
|
158 |
class Meta: |
|
159 |
model = WcsCareFormsCell |
|
160 |
fields = ['wcs_site', 'categories'] |
|
161 | ||
162 |
def __init__(self, *args, **kwargs): |
|
163 |
super().__init__(*args, **kwargs) |
|
164 |
self._init_wcs_site() |
|
165 |
self._init_categories() |
|
166 | ||
167 | ||
156 | 168 |
class BackofficeSubmissionCellForm(WcsFormsMixin, forms.ModelForm): |
157 | 169 |
class Meta: |
158 | 170 |
model = WcsCurrentDraftsCell |
combo/apps/wcs/migrations/0027_careforms_categories.py | ||
---|---|---|
1 |
import jsonfield.fields |
|
2 |
from django.db import migrations |
|
3 | ||
4 | ||
5 |
class Migration(migrations.Migration): |
|
6 | ||
7 |
dependencies = [ |
|
8 |
('wcs', '0026_text_to_jsonb'), |
|
9 |
] |
|
10 | ||
11 |
operations = [ |
|
12 |
migrations.AddField( |
|
13 |
model_name='wcscareformscell', |
|
14 |
name='categories', |
|
15 |
field=jsonfield.fields.JSONField(blank=True, default=dict, verbose_name='Categories'), |
|
16 |
), |
|
17 |
] |
combo/apps/wcs/models.py | ||
---|---|---|
16 | 16 |
# You should have received a copy of the GNU Affero General Public License |
17 | 17 |
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
18 | 18 | |
19 |
import collections |
|
19 | 20 |
import copy |
20 | 21 |
import logging |
21 | 22 | |
... | ... | |
279 | 280 |
def get_api_url(self, context): |
280 | 281 |
return self.api_url |
281 | 282 | |
283 |
def get_api_url_for_site(self, context, wcs_slug): |
|
284 |
return self.get_api_url(context) |
|
285 | ||
282 | 286 |
def get_data(self, context): |
283 | 287 |
if context.get('placeholder_search_mode'): |
284 | 288 |
# don't call webservices when we're just looking for placeholders |
... | ... | |
292 | 296 |
else: |
293 | 297 |
wcs_sites = get_wcs_services() |
294 | 298 | |
295 |
wcs_sites = copy.deepcopy(wcs_sites)
|
|
299 |
result = {}
|
|
296 | 300 |
returns = set([]) |
297 |
api_url = self.get_api_url(context) |
|
298 |
for wcs_slug, wcs_site in wcs_sites.items(): |
|
299 |
url = wcs_site.get('url') |
|
301 |
for wcs_slug, _wcs_site in wcs_sites.items(): |
|
302 |
api_url = self.get_api_url_for_site(context, wcs_slug) |
|
303 |
if not api_url: |
|
304 |
# nothing to call for this site |
|
305 |
continue |
|
306 |
url = _wcs_site.get('url') |
|
300 | 307 |
if not url.endswith('/'): |
301 | 308 |
url += '/' |
309 |
wcs_site = copy.deepcopy(_wcs_site) |
|
310 |
result[wcs_slug] = wcs_site |
|
302 | 311 |
wcs_site['base_url'] = url |
303 | 312 |
wcs_site['slug'] = wcs_slug |
304 | 313 | |
... | ... | |
335 | 344 |
else: |
336 | 345 |
self.mark_as_valid() |
337 | 346 | |
338 |
return wcs_sites
|
|
347 |
return result
|
|
339 | 348 | |
340 | 349 |
def get_cell_extra_context(self, context): |
341 | 350 |
return {self.variable_name: self.get_data(context)} |
... | ... | |
693 | 702 | |
694 | 703 | |
695 | 704 |
@register_cell_class |
696 |
class WcsCareFormsCell(WcsDataBaseCell): |
|
705 |
class WcsCareFormsCell(WcsDataBaseCell, CategoriesValidityMixin): |
|
706 |
categories = JSONField(_('Categories'), blank=True) |
|
707 | ||
697 | 708 |
api_url = '/api/forms/?limit=10' |
698 | 709 |
variable_name = 'care_forms' |
699 | 710 |
template_name = 'combo/wcs/care_forms.html' |
... | ... | |
703 | 714 |
class Meta: |
704 | 715 |
verbose_name = _('Forms to process') |
705 | 716 | |
717 |
def get_default_form_class(self): |
|
718 |
from .forms import WcsCareFormsCellForm |
|
719 | ||
720 |
return WcsCareFormsCellForm |
|
721 | ||
722 |
def get_api_url_for_site(self, context, wcs_slug): |
|
723 |
url = self.get_api_url(context) |
|
724 | ||
725 |
if self.categories: |
|
726 |
categories_by_site = collections.defaultdict(list) |
|
727 |
for category in self.categories.get('data', []): |
|
728 |
key, slug = category.split(':') |
|
729 |
categories_by_site[key].append(slug) |
|
730 |
if not categories_by_site.get(wcs_slug): |
|
731 |
return None |
|
732 |
url += '&category_slugs=%s' % ','.join(categories_by_site.get(wcs_slug)) |
|
733 | ||
734 |
return url |
|
735 | ||
736 |
def get_cell_extra_context(self, context): |
|
737 |
context = super().get_cell_extra_context(context) |
|
738 | ||
739 |
categories_filter = [] |
|
740 |
if self.categories: |
|
741 |
for category in self.categories.get('data', []): |
|
742 |
categories_filter.append(tuple(category.split(':'))) |
|
743 | ||
744 |
for wcs_site in context['care_forms']: |
|
745 |
if not context['care_forms'].get(wcs_site): |
|
746 |
continue |
|
747 |
context['care_forms'][wcs_site]['categories'] = [v for k, v in categories_filter if k == wcs_site] |
|
748 | ||
749 |
return context |
|
750 | ||
706 | 751 | |
707 | 752 |
@register_cell_class |
708 | 753 |
class CategoriesCell(WcsDataBaseCell): |
combo/apps/wcs/templates/combo/wcs/care_forms.html | ||
---|---|---|
26 | 26 |
</tbody> |
27 | 27 |
</table> |
28 | 28 |
{% endif %} |
29 |
<p><a class="pk-button" href="{{ forms.url }}backoffice/management/">{% trans "See all forms" %}</a></p> |
|
29 |
<p><a class="pk-button" href="{{ forms.url }}backoffice/management/listing{% if forms.categories %}?category_slugs={{ forms.categories|join:"," }}{% endif %}">{% trans "See all forms" %}</a></p>
|
|
30 | 30 |
{% endfor %} |
31 | 31 |
{% endblock %} |
tests/test_wcs.py | ||
---|---|---|
719 | 719 | |
720 | 720 |
assert 'http://127.0.0.1:8999/backoffice/management/foobar/1' in result |
721 | 721 |
assert 'http://127.0.0.1:8999/backoffice/management/foobar/2' in result |
722 |
assert '"http://127.0.0.1:8999/backoffice/management/"' in result |
|
722 |
assert '"http://127.0.0.1:8999/backoffice/management/listing"' in result
|
|
723 | 723 |
assert 'http://127.0.0.2:8999/backoffice/management/foobar/1' in result |
724 | 724 |
assert 'http://127.0.0.2:8999/backoffice/management/foobar/2' in result |
725 |
assert '"http://127.0.0.2:8999/backoffice/management/"' in result |
|
725 |
assert '"http://127.0.0.2:8999/backoffice/management/listing"' in result
|
|
726 | 726 | |
727 | 727 |
data = cell.get_data(context) |
728 | 728 |
assert 'default' in data |
729 | 729 |
assert 'other' in data |
730 | 730 | |
731 |
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get: |
|
732 |
mock_json = mock.Mock(status_code=200) |
|
733 |
requests_get.return_value = mock_json |
|
734 |
cell.render(context) |
|
735 |
assert requests_get.call_args_list[0][0][0] == '/api/forms/?limit=10' |
|
736 |
assert requests_get.call_args_list[1][0][0] == '/api/forms/?limit=10' |
|
737 | ||
738 |
# limit to a list of categories |
|
739 |
cell.categories = {'data': ['default:test-3', 'other:test-4']} |
|
740 | ||
741 |
result = cell.render(context) |
|
742 |
assert '"http://127.0.0.1:8999/backoffice/management/listing?category_slugs=test-3"' in result |
|
743 |
assert '"http://127.0.0.2:8999/backoffice/management/listing?category_slugs=test-4"' in result |
|
744 | ||
745 |
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get: |
|
746 |
mock_json = mock.Mock(status_code=200) |
|
747 |
requests_get.return_value = mock_json |
|
748 |
cell.render(context) |
|
749 |
assert len(requests_get.call_args_list) == 2 |
|
750 |
assert requests_get.call_args_list[0][0][0] == '/api/forms/?limit=10&category_slugs=test-3' |
|
751 |
assert requests_get.call_args_list[0][1]['remote_service']['url'] == 'http://127.0.0.1:8999/' |
|
752 |
assert requests_get.call_args_list[1][0][0] == '/api/forms/?limit=10&category_slugs=test-4' |
|
753 |
assert requests_get.call_args_list[1][1]['remote_service']['url'] == 'http://127.0.0.2:8999/' |
|
754 | ||
755 |
# limit to a single category |
|
756 |
cell.categories = {'data': ['default:test-3']} |
|
757 | ||
758 |
result = cell.render(context) |
|
759 |
assert '"http://127.0.0.1:8999/backoffice/management/listing?category_slugs=test-3"' in result |
|
760 |
assert '"http://127.0.0.2:8999/backoffice/management/listing' not in result |
|
761 | ||
762 |
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get: |
|
763 |
mock_json = mock.Mock(status_code=200) |
|
764 |
requests_get.return_value = mock_json |
|
765 |
cell.render(context) |
|
766 |
assert len(requests_get.call_args_list) == 1 |
|
767 |
assert requests_get.call_args_list[0][0][0] == '/api/forms/?limit=10&category_slugs=test-3' |
|
768 |
assert requests_get.call_args_list[0][1]['remote_service']['url'] == 'http://127.0.0.1:8999/' |
|
769 | ||
731 | 770 | |
732 | 771 |
def test_care_forms_cell_validity(context): |
733 | 772 |
page = Page.objects.create(title='xxx', slug='test_care_forms_cell_render', template_name='standard') |
... | ... | |
767 | 806 |
assert validity_info.invalid_since is not None |
768 | 807 | |
769 | 808 | |
809 |
@mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send) |
|
810 |
def test_care_forms_cell_check_validity(mock_send, context): |
|
811 |
page = Page.objects.create(title='xxx', slug='test_care_forms_cell_render', template_name='standard') |
|
812 |
cell = WcsCareFormsCell.objects.create(page=page, placeholder='content', order=0) |
|
813 | ||
814 |
# no category |
|
815 |
cell.check_validity() |
|
816 |
assert ValidityInfo.objects.exists() is False |
|
817 | ||
818 |
# valid categories |
|
819 |
cell.categories = {'data': ['default:test-3', 'default:test-9']} |
|
820 |
cell.save() |
|
821 |
cell.check_validity() |
|
822 |
assert ValidityInfo.objects.exists() is False |
|
823 | ||
824 |
# can not retrieve data, don't set cell as invalid |
|
825 |
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get: |
|
826 |
mock_resp = Response() |
|
827 |
mock_resp.status_code = 500 |
|
828 |
requests_get.return_value = mock_resp |
|
829 |
cell.check_validity() |
|
830 |
assert ValidityInfo.objects.exists() is False |
|
831 |
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get: |
|
832 |
requests_get.side_effect = ConnectionError() |
|
833 |
cell.check_validity() |
|
834 |
assert ValidityInfo.objects.exists() is False |
|
835 | ||
836 |
# can not retrieve categories, don't set cell as invalid |
|
837 |
with mock.patch('combo.apps.wcs.models.requests.get') as requests_get: |
|
838 |
mock_resp = Response() |
|
839 |
mock_resp.status_code = 404 |
|
840 |
requests_get.return_value = mock_resp |
|
841 |
cell.check_validity() |
|
842 |
assert ValidityInfo.objects.exists() is False |
|
843 | ||
844 |
# invalid category |
|
845 |
cell.categories = {'data': ['default:foobar', 'default:test-9']} |
|
846 |
cell.save() |
|
847 |
cell.check_validity() |
|
848 |
validity_info = ValidityInfo.objects.latest('pk') |
|
849 |
assert validity_info.invalid_reason_code == 'wcs_category_not_found' |
|
850 |
assert validity_info.invalid_since is not None |
|
851 | ||
852 | ||
770 | 853 |
@mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send) |
771 | 854 |
def test_care_forms_cell_render_single_site(mock_send, context): |
772 | 855 |
page = Page(title='xxx', slug='test_care_forms_cell_render', template_name='standard') |
... | ... | |
785 | 868 |
context['synchronous'] = True # to get fresh content |
786 | 869 | |
787 | 870 |
result = cell.render(context) |
788 |
assert '"http://127.0.0.1:8999/backoffice/management/"' in result |
|
789 |
assert '"http://127.0.0.2:8999/backoffice/management/"' not in result |
|
871 |
assert '"http://127.0.0.1:8999/backoffice/management/listing"' in result
|
|
872 |
assert '"http://127.0.0.2:8999/backoffice/management/listing"' not in result
|
|
790 | 873 | |
791 | 874 |
data = cell.get_data(context) |
792 | 875 |
assert 'default' in data |
... | ... | |
1065 | 1148 |
assert resp.status_int == 302 |
1066 | 1149 | |
1067 | 1150 | |
1068 |
def test_manager_current_forms(app, admin_user): |
|
1151 |
@mock.patch('combo.apps.wcs.utils.requests.send', side_effect=mocked_requests_send) |
|
1152 |
def test_manager_current_forms(mock_send, app, admin_user): |
|
1069 | 1153 |
page = Page(title='One', slug='one', template_name='standard') |
1070 | 1154 |
page.save() |
1071 | 1155 |
app = login(app) |
... | ... | |
2017 | 2101 |
klass.objects.create(page=page, placeholder='content', order=0) |
2018 | 2102 |
for klass in cell_classes: |
2019 | 2103 |
if klass in [ |
2104 |
WcsCareFormsCell, |
|
2020 | 2105 |
WcsCurrentFormsCell, |
2021 | 2106 |
WcsCurrentDraftsCell, |
2022 | 2107 |
WcsFormsOfCategoryCell, |
2023 |
- |