From d187e59049ccd109aff13ddae5a89621db11e769 Mon Sep 17 00:00:00 2001 From: Artur Pata Date: Fri, 15 Nov 2024 00:20:06 +0200 Subject: [PATCH] Fix routes not opening that take dynamic route params when the param contains forward slash (#4824) --- CHANGELOG.md | 1 + assets/js/dashboard/stats/behaviours/goal-conversions.js | 2 +- assets/js/dashboard/stats/modals/props.js | 2 +- assets/js/dashboard/stats/modals/referrer-drilldown.js | 3 ++- assets/js/dashboard/stats/sources/referrer-list.js | 8 +++++--- assets/js/dashboard/util/url.ts | 4 ++++ 6 files changed, 14 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1649e119c..7090b49ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ All notable changes to this project will be documented in this file. - Fix returning filter suggestions for multiple custom property values in the dashboard Filter modal - Fix typo on login screen +- Fix Direct / None details modal not opening ## v2.1.4 - 2024-10-08 diff --git a/assets/js/dashboard/stats/behaviours/goal-conversions.js b/assets/js/dashboard/stats/behaviours/goal-conversions.js index 73c470a42..11fe75b4a 100644 --- a/assets/js/dashboard/stats/behaviours/goal-conversions.js +++ b/assets/js/dashboard/stats/behaviours/goal-conversions.js @@ -72,7 +72,7 @@ function SpecialPropBreakdown({ prop, afterFetchData }) { getFilterFor={getFilterFor} keyLabel={prop} metrics={chooseMetrics()} - detailsLinkProps={{ path: customPropsRoute.path, params: {propKey: prop}, search: (search) => search }} + detailsLinkProps={{ path: customPropsRoute.path, params: {propKey: url.maybeEncodeRouteParam(prop)}, search: (search) => search }} externalLinkDest={externalLinkDest()} maybeHideDetails={true} color="bg-red-50" diff --git a/assets/js/dashboard/stats/modals/props.js b/assets/js/dashboard/stats/modals/props.js index 47965337b..0d691abe8 100644 --- a/assets/js/dashboard/stats/modals/props.js +++ b/assets/js/dashboard/stats/modals/props.js @@ -23,7 +23,7 @@ function PropsModal() { const reportInfo = { title: specialTitleWhenGoalFilter(query, 'Custom Property Breakdown'), dimension: propKey, - endpoint: url.apiPath(site, `/custom-prop-values/${propKey}`), + endpoint: url.apiPath(site, `/custom-prop-values/${url.maybeEncodeRouteParam(propKey)}`), dimensionLabel: propKey, defaultOrder: ["visitors", SortDirection.desc] } diff --git a/assets/js/dashboard/stats/modals/referrer-drilldown.js b/assets/js/dashboard/stats/modals/referrer-drilldown.js index 016f3e1df..6077bb737 100644 --- a/assets/js/dashboard/stats/modals/referrer-drilldown.js +++ b/assets/js/dashboard/stats/modals/referrer-drilldown.js @@ -19,7 +19,8 @@ function ReferrerDrilldownModal() { const reportInfo = { title: "Referrer Drilldown", dimension: 'referrer', - endpoint: url.apiPath(site, `/referrers/${referrer}`), + endpoint: url.apiPath(site, `/referrers/${url.maybeEncodeRouteParam(referrer)}` + ), dimensionLabel: "Referrer", defaultOrder: ["visitors", SortDirection.desc] } diff --git a/assets/js/dashboard/stats/sources/referrer-list.js b/assets/js/dashboard/stats/sources/referrer-list.js index 7ed79484a..9f49e0762 100644 --- a/assets/js/dashboard/stats/sources/referrer-list.js +++ b/assets/js/dashboard/stats/sources/referrer-list.js @@ -9,6 +9,8 @@ import { useQueryContext } from '../../query-context'; import { useSiteContext } from '../../site-context'; import { referrersDrilldownRoute } from '../../router'; +const NO_REFERRER = 'Direct / None' + export default function Referrers({ source }) { const { query } = useQueryContext(); const site = useSiteContext() @@ -27,12 +29,12 @@ export default function Referrers({ source }) { } function externalLinkDest(referrer) { - if (referrer.name === 'Direct / None') { return null } + if (referrer.name === NO_REFERRER) { return null } return `https://${referrer.name}` } function getFilterFor(referrer) { - if (referrer.name === 'Direct / None') { return null } + if (referrer.name === NO_REFERRER) { return null } return { prefix: 'referrer', @@ -70,7 +72,7 @@ export default function Referrers({ source }) { getFilterFor={getFilterFor} keyLabel="Referrer" metrics={chooseMetrics()} - detailsLinkProps={{ path: referrersDrilldownRoute.path, params: {referrer: source}, search: (search) => search }} + detailsLinkProps={{ path: referrersDrilldownRoute.path, params: {referrer: url.maybeEncodeRouteParam(source)}, search: (search) => search }} externalLinkDest={externalLinkDest} renderIcon={renderIcon} color="bg-blue-50" diff --git a/assets/js/dashboard/util/url.ts b/assets/js/dashboard/util/url.ts index 7d7168b0a..2ce9def2e 100644 --- a/assets/js/dashboard/util/url.ts +++ b/assets/js/dashboard/util/url.ts @@ -151,3 +151,7 @@ export function parseSearch(searchString: string): Record { urlSearchParams.forEach((v, k) => (searchRecord[k] = parseSearchFragment(v))) return searchRecord } + +export function maybeEncodeRouteParam(param: string) { + return param.includes('/') ? encodeURIComponent(param) : param +}