diff --git a/.eslintignore b/.eslintignore index 50aacb7a7e..c7d1f5e483 100644 --- a/.eslintignore +++ b/.eslintignore @@ -17,5 +17,3 @@ wagtail/users/static wagtail/admin/templates/wagtailadmin/edit_handlers/inline_panel.js wagtail/contrib/search_promotions/templates/wagtailsearchpromotions/includes/searchpromotions_formset.js wagtail/users/templates/wagtailusers/groups/includes/page_permissions_formset.js -wagtail/documents/templates/wagtaildocs/chooser/chooser.js -wagtail/documents/templates/wagtaildocs/chooser/document_chosen.js diff --git a/client/src/components/Draftail/sources/ModalWorkflowSource.js b/client/src/components/Draftail/sources/ModalWorkflowSource.js index ebb121bcd6..ea2393449c 100644 --- a/client/src/components/Draftail/sources/ModalWorkflowSource.js +++ b/client/src/components/Draftail/sources/ModalWorkflowSource.js @@ -70,7 +70,7 @@ export const getChooserConfig = (entityType, entity, selectedText) => { return { url: global.chooserUrls.documentChooser, urlParams: {}, - onload: {}, + onload: global.DOCUMENT_CHOOSER_MODAL_ONLOAD_HANDLERS, }; default: diff --git a/client/src/components/Draftail/sources/ModalWorkflowSource.test.js b/client/src/components/Draftail/sources/ModalWorkflowSource.test.js index 4451e76a82..8be7c86247 100644 --- a/client/src/components/Draftail/sources/ModalWorkflowSource.test.js +++ b/client/src/components/Draftail/sources/ModalWorkflowSource.test.js @@ -50,7 +50,7 @@ describe('ModalWorkflowSource', () => { expect(getChooserConfig({ type: 'DOCUMENT' }, null, '')).toEqual({ url: '/admin/documents/chooser/', urlParams: {}, - onload: {}, + onload: global.DOCUMENT_CHOOSER_MODAL_ONLOAD_HANDLERS, }); }); diff --git a/client/tests/stubs.js b/client/tests/stubs.js index 46b20ed718..28724878c6 100644 --- a/client/tests/stubs.js +++ b/client/tests/stubs.js @@ -62,6 +62,7 @@ global.chooserUrls = { global.IMAGE_CHOOSER_MODAL_ONLOAD_HANDLERS = { type: 'image' }; global.PAGE_CHOOSER_MODAL_ONLOAD_HANDLERS = { type: 'page' }; global.EMBED_CHOOSER_MODAL_ONLOAD_HANDLERS = { type: 'embed' }; +global.DOCUMENT_CHOOSER_MODAL_ONLOAD_HANDLERS = { type: 'document' }; const jQueryObj = { on: jest.fn(), diff --git a/wagtail/documents/static_src/wagtaildocs/js/document-chooser-modal.js b/wagtail/documents/static_src/wagtaildocs/js/document-chooser-modal.js new file mode 100644 index 0000000000..e4963af17d --- /dev/null +++ b/wagtail/documents/static_src/wagtaildocs/js/document-chooser-modal.js @@ -0,0 +1,92 @@ +DOCUMENT_CHOOSER_MODAL_ONLOAD_HANDLERS = { + 'chooser': function(modal, jsonData) { + function ajaxifyLinks (context) { + $('a.document-choice', context).on('click', function() { + modal.loadUrl(this.href); + return false; + }); + + $('.pagination a', context).on('click', function() { + var page = this.getAttribute("data-page"); + setPage(page); + return false; + }); + }; + + var searchUrl = $('form.document-search', modal.body).attr('action'); + function search() { + $.ajax({ + url: searchUrl, + data: { + q: $('#id_q').val(), + collection_id: $('#collection_chooser_collection_id').val() + }, + success: function(data, status) { + $('#search-results').html(data); + ajaxifyLinks($('#search-results')); + } + }); + return false; + }; + function setPage(page) { + + if($('#id_q').val().length){ + dataObj = {q: $('#id_q').val(), p: page}; + }else{ + dataObj = {p: page}; + } + + $.ajax({ + url: searchUrl, + data: dataObj, + success: function(data, status) { + $('#search-results').html(data); + ajaxifyLinks($('#search-results')); + } + }); + return false; + } + + ajaxifyLinks(modal.body); + + $('form.document-upload', modal.body).on('submit', function() { + var formdata = new FormData(this); + + $.ajax({ + url: this.action, + data: formdata, + processData: false, + contentType: false, + type: 'POST', + dataType: 'text', + success: modal.loadResponseText, + error: function(response, textStatus, errorThrown) { + message = jsonData['error_message'] + '
' + errorThrown + ' - ' + response.status; + $('#upload').append( + '
' + + '' + jsonData['error_label'] + ': ' + message + '
'); + } + }); + + return false; + }); + + $('form.document-search', modal.body).on('submit', search); + + $('#id_q').on('input', function() { + clearTimeout($.data(this, 'timer')); + var wait = setTimeout(search, 50); + $(this).data('timer', wait); + }); + + $('#collection_chooser_collection_id').on('change', search); + + $('#id_tags', modal.body).tagit({ + autocomplete: {source: jsonData['tag_autocomplete_url']} + }); + }, + 'document_chosen': function(modal, jsonData) { + modal.respond('documentChosen', jsonData['result']); + modal.close(); + } +}; diff --git a/wagtail/documents/static_src/wagtaildocs/js/document-chooser.js b/wagtail/documents/static_src/wagtaildocs/js/document-chooser.js index 3c2416b449..ed50176748 100644 --- a/wagtail/documents/static_src/wagtaildocs/js/document-chooser.js +++ b/wagtail/documents/static_src/wagtaildocs/js/document-chooser.js @@ -7,6 +7,7 @@ function createDocumentChooser(id) { $('.action-choose', chooserElement).on('click', function() { ModalWorkflow({ url: window.chooserUrls.documentChooser, + onload: DOCUMENT_CHOOSER_MODAL_ONLOAD_HANDLERS, responses: { documentChosen: function(docData) { input.val(docData.id); diff --git a/wagtail/documents/static_src/wagtaildocs/js/hallo-plugins/hallo-wagtaildoclink.js b/wagtail/documents/static_src/wagtaildocs/js/hallo-plugins/hallo-wagtaildoclink.js index acef531707..4f7d630cbd 100644 --- a/wagtail/documents/static_src/wagtaildocs/js/hallo-plugins/hallo-wagtaildoclink.js +++ b/wagtail/documents/static_src/wagtaildocs/js/hallo-plugins/hallo-wagtaildoclink.js @@ -25,6 +25,7 @@ lastSelection = widget.options.editable.getSelection(); return ModalWorkflow({ url: window.chooserUrls.documentChooser, + onload: DOCUMENT_CHOOSER_MODAL_ONLOAD_HANDLERS, responses: { documentChosen: function(docData) { var a; diff --git a/wagtail/documents/templates/wagtaildocs/chooser/chooser.js b/wagtail/documents/templates/wagtaildocs/chooser/chooser.js deleted file mode 100644 index 48f4f0b9e7..0000000000 --- a/wagtail/documents/templates/wagtaildocs/chooser/chooser.js +++ /dev/null @@ -1,86 +0,0 @@ -function(modal, jsonData) { - function ajaxifyLinks (context) { - $('a.document-choice', context).on('click', function() { - modal.loadUrl(this.href); - return false; - }); - - $('.pagination a', context).on('click', function() { - var page = this.getAttribute("data-page"); - setPage(page); - return false; - }); - }; - - var searchUrl = $('form.document-search', modal.body).attr('action'); - function search() { - $.ajax({ - url: searchUrl, - data: { - q: $('#id_q').val(), - collection_id: $('#collection_chooser_collection_id').val() - }, - success: function(data, status) { - $('#search-results').html(data); - ajaxifyLinks($('#search-results')); - } - }); - return false; - }; - function setPage(page) { - - if($('#id_q').val().length){ - dataObj = {q: $('#id_q').val(), p: page}; - }else{ - dataObj = {p: page}; - } - - $.ajax({ - url: searchUrl, - data: dataObj, - success: function(data, status) { - $('#search-results').html(data); - ajaxifyLinks($('#search-results')); - } - }); - return false; - } - - ajaxifyLinks(modal.body); - - $('form.document-upload', modal.body).on('submit', function() { - var formdata = new FormData(this); - - $.ajax({ - url: this.action, - data: formdata, - processData: false, - contentType: false, - type: 'POST', - dataType: 'text', - success: modal.loadResponseText, - error: function(response, textStatus, errorThrown) { - message = jsonData['error_message'] + '
' + errorThrown + ' - ' + response.status; - $('#upload').append( - '
' + - '' + jsonData['error_label'] + ': ' + message + '
'); - } - }); - - return false; - }); - - $('form.document-search', modal.body).on('submit', search); - - $('#id_q').on('input', function() { - clearTimeout($.data(this, 'timer')); - var wait = setTimeout(search, 50); - $(this).data('timer', wait); - }); - - $('#collection_chooser_collection_id').on('change', search); - - $('#id_tags', modal.body).tagit({ - autocomplete: {source: jsonData['tag_autocomplete_url']} - }); -} diff --git a/wagtail/documents/templates/wagtaildocs/chooser/document_chosen.js b/wagtail/documents/templates/wagtaildocs/chooser/document_chosen.js deleted file mode 100644 index a86daf60f8..0000000000 --- a/wagtail/documents/templates/wagtaildocs/chooser/document_chosen.js +++ /dev/null @@ -1,4 +0,0 @@ -function(modal, jsonData) { - modal.respond('documentChosen', jsonData['result']); - modal.close(); -} diff --git a/wagtail/documents/tests/test_admin_views.py b/wagtail/documents/tests/test_admin_views.py index 161a0aa343..88a142ffa6 100644 --- a/wagtail/documents/tests/test_admin_views.py +++ b/wagtail/documents/tests/test_admin_views.py @@ -618,7 +618,8 @@ class TestDocumentChooserView(TestCase, WagtailTestUtils): response = self.client.get(reverse('wagtaildocs:chooser')) self.assertEqual(response.status_code, 200) self.assertTemplateUsed(response, 'wagtaildocs/chooser/chooser.html') - self.assertTemplateUsed(response, 'wagtaildocs/chooser/chooser.js') + response_json = json.loads(response.content.decode()) + self.assertEqual(response_json['step'], 'chooser') def test_search(self): response = self.client.get(reverse('wagtaildocs:chooser'), {'q': "Hello"}) @@ -715,7 +716,8 @@ class TestDocumentChooserChosenView(TestCase, WagtailTestUtils): def test_simple(self): response = self.client.get(reverse('wagtaildocs:document_chosen', args=(self.document.id,))) self.assertEqual(response.status_code, 200) - self.assertTemplateUsed(response, 'wagtaildocs/chooser/document_chosen.js') + response_json = json.loads(response.content.decode()) + self.assertEqual(response_json['step'], 'document_chosen') class TestDocumentChooserUploadView(TestCase, WagtailTestUtils): @@ -726,7 +728,8 @@ class TestDocumentChooserUploadView(TestCase, WagtailTestUtils): response = self.client.get(reverse('wagtaildocs:chooser_upload')) self.assertEqual(response.status_code, 200) self.assertTemplateUsed(response, 'wagtaildocs/chooser/chooser.html') - self.assertTemplateUsed(response, 'wagtaildocs/chooser/chooser.js') + response_json = json.loads(response.content.decode()) + self.assertEqual(response_json['step'], 'chooser') def test_post(self): # Build a fake file @@ -740,9 +743,9 @@ class TestDocumentChooserUploadView(TestCase, WagtailTestUtils): } response = self.client.post(reverse('wagtaildocs:chooser_upload'), post_data) - # Check that the response is a javascript file saying the document was chosen - self.assertTemplateUsed(response, 'wagtaildocs/chooser/document_chosen.js') - self.assertContains(response, "modal.respond('documentChosen'") + # Check that the response is the 'document_chosen' step + response_json = json.loads(response.content.decode()) + self.assertEqual(response_json['step'], 'document_chosen') # Document should be created self.assertTrue(models.Document.objects.filter(title="Test document").exists()) @@ -781,20 +784,22 @@ class TestDocumentChooserUploadViewWithLimitedPermissions(TestCase, WagtailTestU response = self.client.get(reverse('wagtaildocs:chooser_upload')) self.assertEqual(response.status_code, 200) self.assertTemplateUsed(response, 'wagtaildocs/chooser/chooser.html') - self.assertTemplateUsed(response, 'wagtaildocs/chooser/chooser.js') + response_json = json.loads(response.content.decode()) + self.assertEqual(response_json['step'], 'chooser') # user only has access to one collection -> should not see the collections field - self.assertNotContains(response, 'id_collection') + self.assertNotIn('id_collection', response_json['html']) def test_chooser_view(self): # The main chooser view also includes the form, so need to test there too response = self.client.get(reverse('wagtaildocs:chooser')) self.assertEqual(response.status_code, 200) self.assertTemplateUsed(response, 'wagtaildocs/chooser/chooser.html') - self.assertTemplateUsed(response, 'wagtaildocs/chooser/chooser.js') + response_json = json.loads(response.content.decode()) + self.assertEqual(response_json['step'], 'chooser') # user only has access to one collection -> should not see the collections field - self.assertNotContains(response, 'id_collection') + self.assertNotIn('id_collection', response_json['html']) def test_post(self): # Build a fake file @@ -808,9 +813,9 @@ class TestDocumentChooserUploadViewWithLimitedPermissions(TestCase, WagtailTestU } response = self.client.post(reverse('wagtaildocs:chooser_upload'), post_data) - # Check that the response is a javascript file saying the document was chosen - self.assertTemplateUsed(response, 'wagtaildocs/chooser/document_chosen.js') - self.assertContains(response, "modal.respond('documentChosen'") + # Check that the response is the 'document_chosen' step + response_json = json.loads(response.content.decode()) + self.assertEqual(response_json['step'], 'document_chosen') # Document should be created doc = models.Document.objects.filter(title="Test document") diff --git a/wagtail/documents/views/chooser.py b/wagtail/documents/views/chooser.py index 6699efbddd..5040253047 100644 --- a/wagtail/documents/views/chooser.py +++ b/wagtail/documents/views/chooser.py @@ -19,6 +19,7 @@ permission_checker = PermissionPolicyChecker(permission_policy) def get_chooser_context(): """construct context variables needed by the chooser JS""" return { + 'step': 'chooser', 'error_label': _("Server Error"), 'error_message': _("Report this error to your webmaster with the following information:"), 'tag_autocomplete_url': reverse('wagtailadmin_tag_autocomplete'), @@ -90,7 +91,7 @@ def chooser(request): documents = documents.order_by('-created_at') paginator, documents = paginate(request, documents, per_page=10) - return render_modal_workflow(request, 'wagtaildocs/chooser/chooser.html', 'wagtaildocs/chooser/chooser.js', { + return render_modal_workflow(request, 'wagtaildocs/chooser/chooser.html', None, { 'documents': documents, 'uploadform': uploadform, 'searchform': searchform, @@ -103,8 +104,8 @@ def document_chosen(request, document_id): document = get_object_or_404(get_document_model(), id=document_id) return render_modal_workflow( - request, None, 'wagtaildocs/chooser/document_chosen.js', - None, json_data={'result': get_document_result_data(document)} + request, None, None, + None, json_data={'step': 'document_chosen', 'result': get_document_result_data(document)} ) @@ -126,8 +127,8 @@ def chooser_upload(request): search_index.insert_or_update_object(document) return render_modal_workflow( - request, None, 'wagtaildocs/chooser/document_chosen.js', - None, json_data={'result': get_document_result_data(document)} + request, None, None, + None, json_data={'step': 'document_chosen', 'result': get_document_result_data(document)} ) else: form = DocumentForm(user=request.user) @@ -135,7 +136,7 @@ def chooser_upload(request): documents = Document.objects.order_by('title') return render_modal_workflow( - request, 'wagtaildocs/chooser/chooser.html', 'wagtaildocs/chooser/chooser.js', + request, 'wagtaildocs/chooser/chooser.html', None, {'documents': documents, 'uploadform': form}, json_data=get_chooser_context() ) diff --git a/wagtail/documents/wagtail_hooks.py b/wagtail/documents/wagtail_hooks.py index 3911b85beb..ba4b4022ed 100644 --- a/wagtail/documents/wagtail_hooks.py +++ b/wagtail/documents/wagtail_hooks.py @@ -74,7 +74,10 @@ def register_document_feature(features): 'hallo', 'document-link', HalloPlugin( name='hallowagtaildoclink', - js=['wagtaildocs/js/hallo-plugins/hallo-wagtaildoclink.js'], + js=[ + 'wagtaildocs/js/document-chooser-modal.js', + 'wagtaildocs/js/hallo-plugins/hallo-wagtaildoclink.js', + ], ) ) features.register_editor_plugin( @@ -82,7 +85,7 @@ def register_document_feature(features): 'type': 'DOCUMENT', 'icon': 'doc-full', 'description': ugettext('Document'), - }) + }, js=['wagtaildocs/js/document-chooser-modal.js']) ) features.register_converter_rule( diff --git a/wagtail/documents/widgets.py b/wagtail/documents/widgets.py index 611a761316..eba89315d4 100644 --- a/wagtail/documents/widgets.py +++ b/wagtail/documents/widgets.py @@ -32,4 +32,7 @@ class AdminDocumentChooser(AdminChooser): return "createDocumentChooser({0});".format(json.dumps(id_)) class Media: - js = ['wagtaildocs/js/document-chooser.js'] + js = [ + 'wagtaildocs/js/document-chooser-modal.js', + 'wagtaildocs/js/document-chooser.js', + ]