') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })(); [C-4557] Add sort by recency to search by dylanjeffers · Pull Request #8928 · AudiusProject/apps · GitHub
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line numberDiff line numberDiff line change
Expand Up@@ -8,7 +8,10 @@ import {
UserChallenge
} from '../../models'
import { UndisbursedUserChallenge } from '../../store'
import { SearchKind } from '../../store/pages/search-results/types'
import {
SearchKind,
SearchSortMethod
} from '../../store/pages/search-results/types'
import { decodeHashId, encodeHashId } from '../../utils/hashIds'
import { Nullable, removeNullable } from '../../utils/typeUtils'
import { AuthHeaders } from '../audius-backend'
Expand DownExpand Up@@ -292,6 +295,7 @@ type GetSearchArgs = {
isVerified?: boolean
hasDownloads?: boolean
isPremium?: boolean
sortMethod?: SearchSortMethod
}

type TrendingIdsResponse = {
Expand DownExpand Up@@ -1139,7 +1143,8 @@ export class AudiusAPIClient {
key,
isVerified,
hasDownloads,
isPremium
isPremium,
sortMethod
}: GetSearchArgs) {
this._assertInitialized()
const encodedUserId = encodeHashId(currentUserId)
Expand All@@ -1157,7 +1162,8 @@ export class AudiusAPIClient {
key,
is_verified: isVerified,
has_downloads: hasDownloads,
is_purchaseable: isPremium
is_purchaseable: isPremium,
sort_method: sortMethod
}

const searchResponse =
Expand Down
3 changes: 2 additions & 1 deletion packages/common/src/store/pages/search-results/actions.ts
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
import { Genre, Mood } from '@audius/sdk'

import { SearchKind } from './types'
import { SearchKind, SearchSortMethod } from './types'

export const FETCH_SEARCH_PAGE_RESULTS = 'SEARCH/FETCH_SEARCH_PAGE_RESULTS'
export const FETCH_SEARCH_PAGE_RESULTS_SUCCEEDED =
Expand DownExpand Up@@ -75,6 +75,7 @@ type FetchSearchPageResultsArgs = {
isVerified?: boolean
hasDownloads?: boolean
isPremium?: boolean
sortMethod?: SearchSortMethod
}

export const fetchSearchPageResults = (
Expand Down
2 changes: 2 additions & 0 deletions packages/common/src/store/pages/search-results/types.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -18,3 +18,5 @@ export enum SearchKind {
ALBUMS = 'albums',
ALL = 'all'
}

export type SearchSortMethod = 'relevant' | 'popular' | 'recent'

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice

8 changes: 8 additions & 0 deletions packages/discovery-provider/src/api/v1/helpers.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -17,6 +17,7 @@
from src.queries.query_helpers import (
CollectionLibrarySortMethod,
LibraryFilterType,
SearchSortMethod,
SortDirection,
SortMethod,
)
Expand DownExpand Up@@ -882,6 +883,13 @@ def __schema__(self):
type=str,
description="Only include tracks that have a bpm less than or equal to",
)
full_search_parser.add_argument(
"sort_method",
required=False,
description="The sort method",
type=str,
choices=SearchSortMethod._member_names_,
)

verify_token_parser = reqparse.RequestParser(argument_class=DescriptiveArgument)
verify_token_parser.add_argument("token", required=True, description="JWT to verify")
Expand Down
2 changes: 2 additions & 0 deletions packages/discovery-provider/src/api/v1/search.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -53,6 +53,7 @@ def get(self):
keys = args.get("key")
bpm_min = args.get("bpm_min")
bpm_max = args.get("bpm_max")
sort_method = args.get("sort_method")

search_args = {
"is_auto_complete": False,
Expand All@@ -72,6 +73,7 @@ def get(self):
"keys": keys,
"bpm_min": bpm_min,
"bpm_max": bpm_max,
"sort_method": sort_method,
}
resp = search(search_args)
return success_response(resp)
Expand Down
6 changes: 6 additions & 0 deletions packages/discovery-provider/src/queries/query_helpers.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -142,6 +142,12 @@ class TransactionSortMethod(str, enum.Enum):
transaction_type = "transaction_type"


class SearchSortMethod(str, enum.Enum):
relevant = "relevant"
popular = "popular"
recent = "recent"


class SortDirection(str, enum.Enum):
asc = "asc"
desc = "desc"
Expand Down
44 changes: 41 additions & 3 deletions packages/discovery-provider/src/queries/search_es.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -81,6 +81,7 @@ def search_es_full(args: dict):
only_verified = args.get("only_verified", False)
only_with_downloads = args.get("only_with_downloads", False)
only_purchaseable = args.get("only_purchaseable", False)
sort_method = args.get("sort_method", "relevant")
do_tracks = search_type == "all" or search_type == "tracks"
do_users = search_type == "all" or search_type == "users"
do_playlists = search_type == "all" or search_type == "playlists"
Expand DownExpand Up@@ -111,6 +112,7 @@ def search_es_full(args: dict):
keys=keys,
only_with_downloads=only_with_downloads,
only_purchaseable=only_purchaseable,
sort_method=sort_method,
),
]
)
Expand All@@ -126,6 +128,7 @@ def search_es_full(args: dict):
must_saved=False,
only_verified=only_verified,
genres=genres,
sort_method=sort_method,
),
]
)
Expand All@@ -140,6 +143,7 @@ def search_es_full(args: dict):
current_user_id=current_user_id,
genres=genres,
moods=moods,
sort_method=sort_method,
),
]
)
Expand All@@ -156,6 +160,7 @@ def search_es_full(args: dict):
moods=moods,
only_with_downloads=only_with_downloads,
only_purchaseable=only_purchaseable,
sort_method=sort_method,
),
]
)
Expand DownExpand Up@@ -426,6 +431,7 @@ def track_dsl(
moods=[],
keys=[],
only_with_downloads=False,
sort_method="relevant",
):
dsl = {
"must": [
Expand DownExpand Up@@ -565,7 +571,12 @@ def track_dsl(

personalize_dsl(dsl, current_user_id, must_saved)

return default_function_score(dsl, "repost_count")
query = default_function_score(dsl, "repost_count")

if sort_method == "recent":
query["sort"] = [{"updated_at": {"order": "desc"}}]

return query


def user_dsl(
Expand All@@ -574,6 +585,7 @@ def user_dsl(
only_verified,
must_saved=False,
genres=[],
sort_method="relevant",
):
# must_search_str = search_str + " " + search_str.replace(" ", "")
dsl = {
Expand DownExpand Up@@ -746,6 +758,10 @@ def user_dsl(

# Set the dsl on the query object
query["query"]["function_score"]["query"] = {"bool": dsl}

if sort_method == "recent":
query["sort"] = [{"created_at": {"order": "desc"}}]

return query


Expand All@@ -758,6 +774,7 @@ def base_playlist_dsl(
only_purchaseable,
current_user_id,
must_saved=False,
sort_method="relevant",
):
dsl = {
"must": [
Expand DownExpand Up@@ -925,12 +942,31 @@ def base_playlist_dsl(

# Set the dsl on the query object
query["query"]["function_score"]["query"] = {"bool": dsl}

if sort_method == "recent":
query["sort"] = [{"updated_at": {"order": "desc"}}]

return query


def playlist_dsl(search_str, current_user_id, must_saved=False, genres=[], moods=[]):
def playlist_dsl(
search_str,
current_user_id,
must_saved=False,
genres=[],
moods=[],
sort_method="relevant",
):
return base_playlist_dsl(
search_str, False, genres, moods, False, False, current_user_id, must_saved
search_str,
False,
genres,
moods,
False,
False,
current_user_id,
must_saved,
sort_method,
)


Expand All@@ -942,6 +978,7 @@ def album_dsl(
must_saved=False,
genres=[],
moods=[],
sort_method="relevant",
):
return base_playlist_dsl(
search_str,
Expand All@@ -952,6 +989,7 @@ def album_dsl(
only_purchaseable,
current_user_id,
must_saved,
sort_method,
)


Expand Down
14 changes: 9 additions & 5 deletions packages/web/src/common/store/pages/search-page/sagas.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,7 +5,8 @@ import {
searchResultsPageTracksLineupActions as tracksLineupActions,
searchResultsPageActions as searchPageActions,
SearchKind,
getContext
getContext,
SearchSortMethod
} from '@audius/common/store'
import { Genre, trimToAlphaNumeric } from '@audius/common/utils'
import { Mood } from '@audius/sdk'
Expand DownExpand Up@@ -113,6 +114,7 @@ type GetSearchResultsArgs = {
isVerified?: boolean
hasDownloads?: boolean
isPremium?: boolean
sortMethod?: SearchSortMethod
}

export function* getSearchResults({
Expand All@@ -126,7 +128,8 @@ export function* getSearchResults({
key,
isVerified,
hasDownloads,
isPremium
isPremium,
sortMethod
}: GetSearchResultsArgs) {
yield* waitForRead()
const getFeatureEnabled = yield* getContext('getFeatureEnabled')
Expand DownExpand Up@@ -163,7 +166,8 @@ export function* getSearchResults({
key: formatKey(key),
isVerified,
hasDownloads,
isPremium
isPremium,
sortMethod
})
const { tracks, albums, playlists, users } = results

Expand All@@ -185,8 +189,8 @@ function* fetchSearchPageResults(
) {
yield* call(waitForRead)

const { type: ignoredType, ...rest } = action
const rawResults = yield* call(getSearchResults, rest)
const { type: ignoredType, ...params } = action
const rawResults = yield* call(getSearchResults, params)
if (rawResults) {
const results = {
users:
Expand Down
6 changes: 3 additions & 3 deletions packages/web/src/pages/search-page-v2/ResultsAlbumsView.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -25,15 +25,15 @@ const messages = {
export const ResultsAlbumsView = () => {
const results = useSelector(getSearchResults)
const [urlSearchParams] = useSearchParams()
const updateSortParam = useUpdateSearchParams('sort')
const updateSortParam = useUpdateSearchParams('sortMethod')
const routeMatch = useRouteMatch<{ category: string }>(SEARCH_PAGE)
const isCategoryActive = useCallback(
(category: CategoryView) => routeMatch?.category === category,
[routeMatch]
)

const isLoading = results.status === Status.LOADING
const sort = urlSearchParams.get('sort')
const sortMethod = urlSearchParams.get('sortMethod')
const albumLimit = isCategoryActive(CategoryView.ALBUMS) ? 100 : 5
const albumIds = results.albumIds?.slice(0, albumLimit) ?? []

Expand All@@ -46,7 +46,7 @@ export const ResultsAlbumsView = () => {
{isCategoryActive(CategoryView.ALBUMS) ? (
<Flex gap='s'>
<OptionsFilterButton
selection={sort ?? 'relevant'}
selection={sortMethod ?? 'relevant'}
variant='replaceLabel'
optionsLabel={messages.sortOptionsLabel}
onChange={updateSortParam}
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -27,15 +27,15 @@ export const ResultsPlaylistsView = () => {
// const [playlistsLayout, setPlaylistsLayout] = useState<ViewLayout>('grid')
const results = useSelector(getSearchResults)
const [urlSearchParams] = useSearchParams()
const updateSortParam = useUpdateSearchParams('sort')
const updateSortParam = useUpdateSearchParams('sortMethod')
const routeMatch = useRouteMatch<{ category: string }>(SEARCH_PAGE)
const isCategoryActive = useCallback(
(category: CategoryView) => routeMatch?.category === category,
[routeMatch]
)

const isLoading = results.status === Status.LOADING
const sort = urlSearchParams.get('sort')
const sortMethod = urlSearchParams.get('sortMethod')
const playlistLimit = isCategoryActive(CategoryView.PLAYLISTS) ? 100 : 5
const playlistIds = results.playlistIds?.slice(0, playlistLimit) ?? []

Expand All@@ -57,7 +57,7 @@ export const ResultsPlaylistsView = () => {
{isCategoryActive(CategoryView.PLAYLISTS) ? (
<Flex gap='s'>
<OptionsFilterButton
selection={sort ?? 'relevant'}
selection={sortMethod ?? 'relevant'}
variant='replaceLabel'
optionsLabel={messages.sortOptionsLabel}
onChange={updateSortParam}
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -25,15 +25,15 @@ const messages = {
export const ResultsProfilesView = () => {
const results = useSelector(getSearchResults)
const [urlSearchParams] = useSearchParams()
const updateSortParam = useUpdateSearchParams('sort')
const updateSortParam = useUpdateSearchParams('sortMethod')
const routeMatch = useRouteMatch<{ category: string }>(SEARCH_PAGE)
const isCategoryActive = useCallback(
(category: CategoryView) => routeMatch?.category === category,
[routeMatch]
)

const isLoading = results.status === Status.LOADING
const sort = urlSearchParams.get('sort')
const sortMethod = urlSearchParams.get('sortMethod')
const profileLimit = isCategoryActive(CategoryView.PROFILES) ? 100 : 5
const profileIds = results.artistIds?.slice(0, profileLimit) ?? []

Expand All@@ -46,7 +46,7 @@ export const ResultsProfilesView = () => {
{isCategoryActive(CategoryView.PROFILES) ? (
<Flex gap='s'>
<OptionsFilterButton
selection={sort ?? 'relevant'}
selection={sortMethod ?? 'relevant'}
variant='replaceLabel'
optionsLabel={messages.sortOptionsLabel}
onChange={updateSortParam}
Expand Down
Loading