From ed58c692ca657ed0d115dd7c4456523766748839 Mon Sep 17 00:00:00 2001 From: Aadi jindal <111938909+Aadijindal07@users.noreply.github.com> Date: Tue, 7 Feb 2023 09:11:01 +0530 Subject: [PATCH] Allow Action controller to trigger a redirect - Migrate site switcher to use Stimulus approach via w-action - Closes #10035 --- .eslintrc.js | 1 - CHANGELOG.txt | 1 + .../src/controllers/ActionController.test.js | 72 +++++++++++++++++++ client/src/controllers/ActionController.ts | 21 ++++++ client/webpack.config.js | 5 -- docs/releases/5.0.md | 1 + wagtail/contrib/settings/forms.py | 19 +++-- .../wagtailsettings/js/site-switcher.js | 12 ---- 8 files changed, 104 insertions(+), 28 deletions(-) delete mode 100644 wagtail/contrib/settings/static_src/wagtailsettings/js/site-switcher.js diff --git a/.eslintrc.js b/.eslintrc.js index 685e340dd9..c169583886 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -151,7 +151,6 @@ module.exports = { 'docs/_static/**', 'wagtail/contrib/modeladmin/static_src/wagtailmodeladmin/js/prepopulate.js', 'wagtail/contrib/search_promotions/templates/wagtailsearchpromotions/includes/searchpromotions_formset.js', - 'wagtail/contrib/settings/static_src/wagtailsettings/js/site-switcher.js', 'wagtail/documents/static_src/wagtaildocs/js/add-multiple.js', 'wagtail/embeds/static_src/wagtailembeds/js/embed-chooser-modal.js', 'wagtail/images/static_src/wagtailimages/js/add-multiple.js', diff --git a/CHANGELOG.txt b/CHANGELOG.txt index b569be77e0..b909747161 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -115,6 +115,7 @@ Changelog * Maintenance: Migrate initDismissibles behaviour to a Stimulus controller `w-disimissible` (Loveth Omokaro) * Maintenance: Replace jQuery autosize v3 with Stimulus `w-autosize` controller using autosize npm package v6 (Suyash Srivastava) * Maintenance: Update `w-action` controller to support a click method (Suyash Srivastava) + * Maintenance: Migrate the site settings switcher select from jQuery to a refined version of the `w-action` controller usage (Aadi jindal, LB (Ben) Johnston) 4.2.2 (03.04.2023) diff --git a/client/src/controllers/ActionController.test.js b/client/src/controllers/ActionController.test.js index 26d9a979d5..45e4dbcca3 100644 --- a/client/src/controllers/ActionController.test.js +++ b/client/src/controllers/ActionController.test.js @@ -3,9 +3,23 @@ import { ActionController } from './ActionController'; describe('ActionController', () => { let app; + const oldWindowLocation = window.location; + + beforeAll(() => { + delete window.location; + + window.location = Object.defineProperties( + {}, + { + ...Object.getOwnPropertyDescriptors(oldWindowLocation), + assign: { configurable: true, value: jest.fn() }, + }, + ); + }); afterEach(() => { app?.stop(); + jest.clearAllMocks(); }); describe('post method', () => { @@ -70,4 +84,62 @@ describe('ActionController', () => { expect(clickMock).toHaveBeenCalled(); }); }); + + describe('redirect method', () => { + beforeEach(() => { + document.body.innerHTML = ` + + `; + + app = Application.start(); + app.register('w-action', ActionController); + }); + + it('should have a redirect method that falls back to any element value', () => { + const select = document.querySelector('select'); + + expect(window.location.href).toEqual('http://localhost/'); + expect(window.location.assign).not.toHaveBeenCalled(); + + select.dispatchEvent(new CustomEvent('change')); + + expect(window.location.assign).toHaveBeenCalledWith( + 'http://localhost/place?option=2', + ); + }); + + it('should allow redirection via the custom event detail', () => { + const select = document.querySelector('select'); + + expect(window.location.href).toEqual('http://localhost/'); + expect(window.location.assign).not.toHaveBeenCalled(); + + select.dispatchEvent( + new CustomEvent('change', { detail: { url: '/its/in/the/detail/' } }), + ); + + expect(window.location.assign).toHaveBeenCalledWith( + '/its/in/the/detail/', + ); + }); + + it('should allow redirection via the Stimulus param approach', () => { + const select = document.querySelector('select'); + + expect(window.location.href).toEqual('http://localhost/'); + expect(window.location.assign).not.toHaveBeenCalled(); + + select.dataset.wActionUrlParam = '/check/out/the/param/'; + + select.dispatchEvent( + new CustomEvent('change', { detail: { url: '/its/in/the/detail/' } }), + ); + expect(window.location.assign).toHaveBeenCalledWith( + '/check/out/the/param/', + ); + }); + }); }); diff --git a/client/src/controllers/ActionController.ts b/client/src/controllers/ActionController.ts index de39880e87..dcd2857ea0 100644 --- a/client/src/controllers/ActionController.ts +++ b/client/src/controllers/ActionController.ts @@ -25,6 +25,15 @@ import { WAGTAIL_CONFIG } from '../config/wagtailConfig'; * > * Enable * + * + * @example - triggering a dynamic redirect + * // note: a link is preferred normally + *
*/ export class ActionController extends Controller< HTMLButtonElement | HTMLInputElement @@ -70,4 +79,16 @@ export class ActionController extends Controller< document.body.appendChild(formElement); formElement.submit(); } + + /** + * Trigger a redirect based on the custom event's detail, the Stimulus param + * or finally check the controlled element for a value to use. + */ + redirect( + event: CustomEvent<{ url?: string }> & { params?: { url?: string } }, + ) { + const url = event?.params?.url || event?.detail?.url || this.element.value; + if (!url) return; + window.location.assign(url); + } } diff --git a/client/webpack.config.js b/client/webpack.config.js index a175070cc2..1a0dfe51ab 100644 --- a/client/webpack.config.js +++ b/client/webpack.config.js @@ -186,11 +186,6 @@ module.exports = function exports(env, argv) { to: 'wagtail/users/static/', globOptions: { ignore: ['**/{app,scss}/**', '*.{css,txt}'] }, }, - { - from: 'wagtail/contrib/settings/static_src/', - to: 'wagtail/contrib/settings/static/', - globOptions: { ignore: ['**/{app,scss}/**', '*.{css,txt}'] }, - }, { from: 'wagtail/contrib/modeladmin/static_src/', to: 'wagtail/contrib/modeladmin/static/', diff --git a/docs/releases/5.0.md b/docs/releases/5.0.md index 289b8b7d6a..fa1d25c8e9 100644 --- a/docs/releases/5.0.md +++ b/docs/releases/5.0.md @@ -162,6 +162,7 @@ Those improvements were implemented by Albina Starykova as part of an [Outreachy * Migrate initDismissibles behaviour to a Stimulus controller `w-disimissible` (Loveth Omokaro) * Replace jQuery autosize v3 with Stimulus `w-autosize` controller using autosize npm package v6 (Suyash Srivastava) * Update `w-action` controller to support a click method (Suyash Srivastava) + * Migrate the site settings switcher select from jQuery to a refined version of the `w-action` controller usage (Aadi jindal, LB (Ben) Johnston) ## Upgrade considerations diff --git a/wagtail/contrib/settings/forms.py b/wagtail/contrib/settings/forms.py index f9e0a1712a..451f243602 100644 --- a/wagtail/contrib/settings/forms.py +++ b/wagtail/contrib/settings/forms.py @@ -2,20 +2,19 @@ from django import forms from django.urls import reverse from django.utils.translation import gettext_lazy as _ -from wagtail.admin.staticfiles import versioned_static from wagtail.models import Site class SiteSwitchForm(forms.Form): - site = forms.ChoiceField(choices=[]) - - @property - def media(self): - return forms.Media( - js=[ - versioned_static("wagtailsettings/js/site-switcher.js"), - ] - ) + site = forms.ChoiceField( + choices=[], + widget=forms.Select( + attrs={ + "data-controller": "w-action", + "data-action": "change->w-action#redirect", + } + ), + ) def __init__(self, current_site, model, **kwargs): initial_data = {"site": self.get_change_url(current_site, model)} diff --git a/wagtail/contrib/settings/static_src/wagtailsettings/js/site-switcher.js b/wagtail/contrib/settings/static_src/wagtailsettings/js/site-switcher.js deleted file mode 100644 index f95917cc0e..0000000000 --- a/wagtail/contrib/settings/static_src/wagtailsettings/js/site-switcher.js +++ /dev/null @@ -1,12 +0,0 @@ -$(function () { - var $switcher = $('form#settings-site-switch select'); - if (!$switcher.length) return; - - var initial = $switcher.val(); - $switcher.on('change', function () { - var url = $switcher.val(); - if (url !== initial) { - window.location = url; - } - }); -});