From 5b7ad02ad24b9d2c2d91fee871abe8ed7b0f6b1d Mon Sep 17 00:00:00 2001 From: Kyle Shanks Date: Wed, 12 Jun 2024 16:34:06 -0400 Subject: [PATCH] [C-4521] Update search route format and add redirect for legacy route format (#8803) --- packages/web/src/app/web-player/WebPlayer.jsx | 60 +++++++++++++------ .../search-bar/ConnectedSearchBar.jsx | 40 ++++--------- .../src/pages/search-page-v2/SearchHeader.tsx | 4 +- .../src/pages/search-page-v2/SearchPageV2.tsx | 20 ++++--- .../pages/search-page-v2/SearchResults.tsx | 19 +++--- .../pages/search-page/SearchPageProvider.jsx | 13 +--- packages/web/src/pages/search-page/helpers.ts | 11 ++-- packages/web/src/ssr/util.ts | 2 - .../web/src/store/lineup/lineupForRoute.js | 3 +- packages/web/src/utils/route.ts | 5 +- 10 files changed, 86 insertions(+), 91 deletions(-) diff --git a/packages/web/src/app/web-player/WebPlayer.jsx b/packages/web/src/app/web-player/WebPlayer.jsx index d7858722e84..eb9a8cb919b 100644 --- a/packages/web/src/app/web-player/WebPlayer.jsx +++ b/packages/web/src/app/web-player/WebPlayer.jsx @@ -14,7 +14,7 @@ import { } from '@audius/common/store' import cn from 'classnames' import { connect } from 'react-redux' -import { matchPath } from 'react-router' +import { generatePath, matchPath } from 'react-router' import { Switch, Route, Redirect, withRouter } from 'react-router-dom' import semver from 'semver' @@ -129,7 +129,6 @@ import { SETTINGS_PAGE, HOME_PAGE, NOT_FOUND_PAGE, - SEARCH_CATEGORY_PAGE, SEARCH_PAGE, PLAYLIST_PAGE, ALBUM_PAGE, @@ -180,7 +179,9 @@ import { AUTHORIZED_APPS_SETTINGS_PAGE, ACCOUNTS_MANAGING_YOU_SETTINGS_PAGE, ACCOUNTS_YOU_MANAGE_SETTINGS_PAGE, - TRACK_EDIT_PAGE + TRACK_EDIT_PAGE, + SEARCH_CATEGORY_PAGE_LEGACY, + SEARCH_BASE_ROUTE } from 'utils/route' import styles from './WebPlayer.module.css' @@ -200,6 +201,14 @@ const includeSearch = (search) => { return search.includes('oauth_token') || search.includes('code') } +const validSearchCategories = [ + 'all', + 'tracks', + 'profiles', + 'albums', + 'playlists' +] + initializeSentry() class WebPlayer extends Component { @@ -656,25 +665,38 @@ class WebPlayer extends Component { /> )} /> - - isSearchV2Enabled ? ( - - ) : ( - - ) - } + exact + path={SEARCH_CATEGORY_PAGE_LEGACY} + render={(props) => ( + + )} /> - isSearchV2Enabled ? ( + render={(props) => { + const { category } = props.match.params + + return category && + !validSearchCategories.includes(category) ? ( + + ) : isSearchV2Enabled ? ( ) : ( ) - } + }} /> { - const match = matchPath(getPathname(this.context.history.location), { - path: '/search/:query' - }) - if (!match) { + const params = new URLSearchParams(this.context.history.location.search) + if (!params.has('query')) { this.onSearchChange('') } }) // Set the initial search bar value if we loaded into a search page. - const match = matchPath(getPathname(this.context.history.location), { - path: '/search/:query' - }) - if (has(match, 'params.query')) { - this.onSearchChange(match.params.query) + const params = new URLSearchParams(this.context.history.location.search) + if (params.has('query')) { + this.onSearchChange(params.get('query')) } } @@ -92,27 +86,15 @@ class ConnectedSearchBar extends Component { // Encode everything besides tag searches const pathname = '/search' - let newPath = `${pathname}/${value}` + let newPath = pathname if (value) { - const categoryMatch = matchPath( - getPathname(this.props.history.location), - { - path: SEARCH_CATEGORY_PAGE - } - ) const searchMatch = matchPath(getPathname(this.props.history.location), { path: SEARCH_PAGE }) - if (categoryMatch) { - newPath = generatePath(SEARCH_CATEGORY_PAGE, { - ...categoryMatch.params, - query: value - }) - } else if (searchMatch) { + if (searchMatch) { newPath = generatePath(SEARCH_PAGE, { - ...searchMatch.params, - query: value + ...searchMatch.params }) } } @@ -128,7 +110,9 @@ class ConnectedSearchBar extends Component { value = encodeURIComponent(value) this.props.history.push({ pathname: newPath, - search: this.props.history.location.search, + search: value + ? new URLSearchParams({ query: value }).toString() + : undefined, state: {} }) } diff --git a/packages/web/src/pages/search-page-v2/SearchHeader.tsx b/packages/web/src/pages/search-page-v2/SearchHeader.tsx index afb2c4a1c5d..24d08348237 100644 --- a/packages/web/src/pages/search-page-v2/SearchHeader.tsx +++ b/packages/web/src/pages/search-page-v2/SearchHeader.tsx @@ -47,9 +47,9 @@ export const SearchHeader = (props: SearchHeaderProps) => { const handleChange = useCallback( (e: ChangeEvent) => { const value = e.target.value - if (query) setCategory(value as CategoryKey) + setCategory(value as CategoryKey) }, - [setCategory, query] + [setCategory] ) const filterKeys = categories[categoryKey].filters diff --git a/packages/web/src/pages/search-page-v2/SearchPageV2.tsx b/packages/web/src/pages/search-page-v2/SearchPageV2.tsx index bee948f2ef9..1adeed66fc8 100644 --- a/packages/web/src/pages/search-page-v2/SearchPageV2.tsx +++ b/packages/web/src/pages/search-page-v2/SearchPageV2.tsx @@ -1,7 +1,8 @@ import { useCallback, useContext, useEffect } from 'react' import { Flex } from '@audius/harmony' -import { useParams } from 'react-router-dom' +import { generatePath, useParams } from 'react-router-dom' +import { useSearchParams } from 'react-router-dom-v5-compat' import { useHistoryContext } from 'app/HistoryProvider' import MobilePageContainer from 'components/mobile-page-container/MobilePageContainer' @@ -12,6 +13,7 @@ import NavContext, { } from 'components/nav/mobile/NavContext' import Page from 'components/page/Page' import { useMedia } from 'hooks/useMedia' +import { SEARCH_PAGE } from 'utils/route' import { RecentSearches } from './RecentSearches' import { SearchCatalogTile } from './SearchCatalogTile' @@ -20,12 +22,10 @@ import { SearchResults } from './SearchResults' export const SearchPageV2 = () => { const { isMobile } = useMedia() - - const { category, query } = useParams<{ - category: CategoryKey - query: string - }>() + const { category } = useParams<{ category: CategoryKey }>() const { history } = useHistoryContext() + const [urlSearchParams] = useSearchParams() + const query = urlSearchParams.get('query') // Set nav header const { setLeft, setCenter, setRight } = useContext(NavContext)! @@ -37,14 +37,18 @@ export const SearchPageV2 = () => { const setCategory = useCallback( (category: CategoryKey) => { - history.push(`/search/${query}/${category}`) + history.push({ + pathname: generatePath(SEARCH_PAGE, { category }), + search: query ? new URLSearchParams({ query }).toString() : undefined, + state: {} + }) }, [history, query] ) const header = ( { const playing = useSelector(getPlaying) const buffering = useSelector(getBuffering) const results = useSelector(searchResultsPageSelectors.getSearchResults) - const categoryMatch = useRouteMatch<{ query: string; category: string }>( - SEARCH_CATEGORY_PAGE + const routeMatch = useRouteMatch<{ query: string; category: string }>( + SEARCH_PAGE ) const isLoading = results.status === Status.LOADING @@ -102,15 +102,16 @@ export const SearchResults = ({ query }: SearchResultsProps) => { }, [dispatch, query]) const isCategoryActive = useCallback( - (category: Category) => categoryMatch?.category === category, - [categoryMatch] + (category: Category) => routeMatch?.category === category, + [routeMatch] ) const isCategoryVisible = useCallback( (category: Category) => - !categoryMatch || - categoryMatch.category === Category.ALL || - categoryMatch.category === category, - [categoryMatch] + !routeMatch || + routeMatch.category === undefined || + routeMatch.category === Category.ALL || + routeMatch.category === category, + [routeMatch] ) const profileLimit = isCategoryActive(Category.PROFILES) diff --git a/packages/web/src/pages/search-page/SearchPageProvider.jsx b/packages/web/src/pages/search-page/SearchPageProvider.jsx index 1d5b7da8366..2d63c4736ae 100644 --- a/packages/web/src/pages/search-page/SearchPageProvider.jsx +++ b/packages/web/src/pages/search-page/SearchPageProvider.jsx @@ -18,12 +18,7 @@ import { withRouter } from 'react-router-dom' import { HistoryContext } from 'app/HistoryProvider' import { make } from 'common/store/analytics/actions' -import { - NOT_FOUND_PAGE, - SEARCH_CATEGORY_PAGE, - SEARCH_PAGE, - doesMatchRoute -} from 'utils/route' +import { NOT_FOUND_PAGE, SEARCH_PAGE, doesMatchRoute } from 'utils/route' import * as helpers from './helpers' const { makeGetCurrent } = queueSelectors @@ -134,11 +129,7 @@ class SearchPageProvider extends Component { // search page, then we should not redirect & allow react router to render // the correct page. const query = helpers.getQuery(this.context.history.location) - if ( - !query && - (doesMatchRoute(this.context.history.location, SEARCH_CATEGORY_PAGE) || - doesMatchRoute(this.context.history.location, SEARCH_PAGE)) - ) { + if (!query && doesMatchRoute(this.context.history.location, SEARCH_PAGE)) { return } diff --git a/packages/web/src/pages/search-page/helpers.ts b/packages/web/src/pages/search-page/helpers.ts index 7eb323ac49b..5345760334a 100644 --- a/packages/web/src/pages/search-page/helpers.ts +++ b/packages/web/src/pages/search-page/helpers.ts @@ -3,7 +3,7 @@ import { Location } from 'history' import { matchPath } from 'react-router' import { env } from 'services/env' -import { getPathname } from 'utils/route' +import { SEARCH_PAGE, getPathname } from 'utils/route' const USE_HASH_ROUTING = env.USE_HASH_ROUTING @@ -34,7 +34,7 @@ export const getCategory = (location: Location) => { category = location.hash.slice(1).split('/')[1] } else { const categoryMatch = matchPath(getPathname(location), { - path: '/search/:query/:category', + path: SEARCH_PAGE, exact: true }) as match @@ -66,11 +66,8 @@ export const getSearchTag = (location: Location) => { } export const getSearchText = (location: Location) => { - const match = matchPath(getPathname(location), { - path: '/search/:query' - }) as match - if (!match) return '' - const query = match.params.query + const params = new URLSearchParams(location.search) + const query = params.get('query') if (!query) return '' // Need to decode the URI to convert %20 into spaces diff --git a/packages/web/src/ssr/util.ts b/packages/web/src/ssr/util.ts index f9e5df4375a..e021d819d24 100644 --- a/packages/web/src/ssr/util.ts +++ b/packages/web/src/ssr/util.ts @@ -5,7 +5,6 @@ import { staticRoutes, SEARCH_BASE_ROUTE, SEARCH_PAGE, - SEARCH_CATEGORY_PAGE, PROFILE_PAGE_COLLECTIBLE_DETAILS, CHANGE_EMAIL_SETTINGS_PAGE, CHANGE_PASSWORD_SETTINGS_PAGE @@ -18,7 +17,6 @@ const invalidPaths = new Set(['undefined']) const nonSsrPaths = [ PROFILE_PAGE_COLLECTIBLE_DETAILS, SEARCH_BASE_ROUTE, - SEARCH_CATEGORY_PAGE, SEARCH_PAGE, CHANGE_EMAIL_SETTINGS_PAGE, CHANGE_PASSWORD_SETTINGS_PAGE diff --git a/packages/web/src/store/lineup/lineupForRoute.js b/packages/web/src/store/lineup/lineupForRoute.js index b17c47f687b..a202933eef5 100644 --- a/packages/web/src/store/lineup/lineupForRoute.js +++ b/packages/web/src/store/lineup/lineupForRoute.js @@ -15,7 +15,6 @@ import { TRENDING_PAGE, SAVED_PAGE, HISTORY_PAGE, - SEARCH_CATEGORY_PAGE, SEARCH_PAGE, PLAYLIST_PAGE, ALBUM_PAGE, @@ -63,7 +62,7 @@ export const getLineupSelectorForRoute = (location) => { if (matchPage(TRENDING_PAGE)) { return getCurrentDiscoverTrendingLineup } - if (matchPage(SEARCH_CATEGORY_PAGE) || matchPage(SEARCH_PAGE)) { + if (matchPage(SEARCH_PAGE)) { return getSearchTracksLineup } if (matchPage(SAVED_PAGE) || matchPage(LIBRARY_PAGE)) { diff --git a/packages/web/src/utils/route.ts b/packages/web/src/utils/route.ts index 1321d67c433..26a0d7117f0 100644 --- a/packages/web/src/utils/route.ts +++ b/packages/web/src/utils/route.ts @@ -125,8 +125,8 @@ export const SIGN_UP_COMPLETED_REDIRECT = `/signup/${SignUpPath.completedRedirec // Param routes. export const NOTIFICATION_USERS_PAGE = '/notification/:notificationId/users' -export const SEARCH_CATEGORY_PAGE = '/search/:query/:category' -export const SEARCH_PAGE = '/search/:query?' +export const SEARCH_CATEGORY_PAGE_LEGACY = '/search/:query/:category' +export const SEARCH_PAGE = '/search/:category?' export const SEARCH_BASE_ROUTE = '/search' export const PLAYLIST_PAGE = '/:handle/playlist/:playlistName' export const PLAYLIST_BY_PERMALINK_PAGE = '/:handle/playlist/:slug' @@ -254,7 +254,6 @@ export const orderedRoutes = [ TRENDING_PAGE, EXPLORE_PAGE, EMPTY_PAGE, - SEARCH_CATEGORY_PAGE, SEARCH_PAGE, UPLOAD_ALBUM_PAGE, UPLOAD_PLAYLIST_PAGE,