diff --git a/client/src/controllers/LinkController.ts b/client/src/controllers/LinkController.ts new file mode 100644 index 0000000000..b828870205 --- /dev/null +++ b/client/src/controllers/LinkController.ts @@ -0,0 +1,68 @@ +import { Controller } from '@hotwired/stimulus'; + +export class LinkController extends Controller { + static values = { + attrName: { default: 'href', type: String }, + preserveKeys: { default: [], type: Array }, + reflectKeys: { default: ['__all__'], type: Array }, + }; + + declare attrNameValue: string; + declare preserveKeysValue: string[]; + declare reflectKeysValue: string[]; + + get url() { + return new URL( + this.element.getAttribute(this.attrNameValue) || '', + window.location.href, + ); + } + + connect() { + this.setParamsFromLocation(); + } + + get reflectAll() { + return this.reflectKeysValue.includes('__all__'); + } + + setParamsFromURL(url: URL) { + // New params to build the new URL + const newParams = new URLSearchParams(); + const reflectAll = this.reflectAll; + + const sourceParams = url.searchParams; + sourceParams.forEach((value, key) => { + if ( + key.startsWith('_w_') || // Wagtail internal + // Delete the key if we want to preserve it from the current URL, or + // if we don't want to reflect it to the new URL + this.preserveKeysValue.includes(key) || + (!reflectAll && !this.reflectKeysValue.includes(key)) + ) { + return; + } + newParams.append(key, value); + }); + + // Add the ones we want to preserve from the current URL to the new params + const currentUrl = this.url; + currentUrl.searchParams.forEach((value, key) => { + if (this.preserveKeysValue.includes(key)) { + newParams.append(key, value); + } + }); + + currentUrl.search = newParams.toString(); + this.element.setAttribute(this.attrNameValue, currentUrl.toString()); + } + + setParamsFromSwapRequest(e: CustomEvent<{ requestUrl?: string }>) { + if (!e.detail?.requestUrl) return; + this.setParamsFromURL(new URL(e.detail.requestUrl, window.location.href)); + } + + setParamsFromLocation() { + this.setParamsFromURL(new URL(window.location.href)); + } +} diff --git a/client/src/controllers/index.ts b/client/src/controllers/index.ts index d93c74f417..a5635fbb87 100644 --- a/client/src/controllers/index.ts +++ b/client/src/controllers/index.ts @@ -12,6 +12,7 @@ import { DismissibleController } from './DismissibleController'; import { DrilldownController } from './DrilldownController'; import { DropdownController } from './DropdownController'; import { InitController } from './InitController'; +import { LinkController } from './LinkController'; import { OrderableController } from './OrderableController'; import { ProgressController } from './ProgressController'; import { RevealController } from './RevealController'; @@ -43,6 +44,7 @@ export const coreControllerDefinitions: Definition[] = [ { controllerConstructor: DrilldownController, identifier: 'w-drilldown' }, { controllerConstructor: DropdownController, identifier: 'w-dropdown' }, { controllerConstructor: InitController, identifier: 'w-init' }, + { controllerConstructor: LinkController, identifier: 'w-link' }, { controllerConstructor: OrderableController, identifier: 'w-orderable' }, { controllerConstructor: ProgressController, identifier: 'w-progress' }, { controllerConstructor: RevealController, identifier: 'w-breadcrumbs' }, diff --git a/wagtail/admin/views/generic/models.py b/wagtail/admin/views/generic/models.py index 0af9486e77..63e2182ba0 100644 --- a/wagtail/admin/views/generic/models.py +++ b/wagtail/admin/views/generic/models.py @@ -367,6 +367,7 @@ class IndexView( self.add_item_label, url=self.add_url, icon_name="plus", + attrs={"data-w-link-reflect-keys-value": '["locale"]'}, ) ) return buttons @@ -381,6 +382,10 @@ class IndexView( url=self.xlsx_export_url, icon_name="download", priority=90, + attrs={ + "data-controller": "w-link", + "data-w-link-preserve-keys-value": '["export"]', + }, ) ) buttons.append( @@ -389,6 +394,10 @@ class IndexView( url=self.csv_export_url, icon_name="download", priority=100, + attrs={ + "data-controller": "w-link", + "data-w-link-preserve-keys-value": '["export"]', + }, ) ) diff --git a/wagtail/admin/widgets/button.py b/wagtail/admin/widgets/button.py index bb8c6a4063..5b3b45263d 100644 --- a/wagtail/admin/widgets/button.py +++ b/wagtail/admin/widgets/button.py @@ -109,8 +109,9 @@ class HeaderButton(Button): attrs = attrs.copy() attrs.update( { - "data-controller": "w-tooltip", + "data-controller": "w-tooltip w-link", "data-w-tooltip-content-value": label, + "data-action": "w-swap:success@document->w-link#setParamsFromSwapRequest", "aria-label": label, } )