From 30fedf6b45a1c291e07bcebe3027e7ba1ce305a6 Mon Sep 17 00:00:00 2001 From: infinite-persistence <64950861+infinite-persistence@users.noreply.github.com> Date: Mon, 13 Sep 2021 23:23:53 +0800 Subject: [PATCH] Channel Page: enable filters; add "sort by" filter (#7069) * Sort props to clarify "client vs. redux". No functional change. * ClaimListHeader: remove SIMPLE_SITE gating * Channel Page: enable filters; add "sort by" filter. ## Issue 7059 Add option to sort oldest first on channel page ## Changes - Enabled filters for Odysee. - Added a new "Sort By" filter, which will only appear for "New" ordering. It doesn't make sense for "Trending" or "Top". --- ui/component/claimListDiscover/view.jsx | 27 +++++++++++----- ui/component/claimListHeader/view.jsx | 41 +++++++++++++++++++++++-- ui/constants/claim_search.js | 11 ++++++- 3 files changed, 68 insertions(+), 11 deletions(-) diff --git a/ui/component/claimListDiscover/view.jsx b/ui/component/claimListDiscover/view.jsx index 423d7bee3..f04929183 100644 --- a/ui/component/claimListDiscover/view.jsx +++ b/ui/component/claimListDiscover/view.jsx @@ -38,8 +38,9 @@ type Props = { showNoSourceClaims?: boolean, tileLayout: boolean, - orderBy?: Array, + orderBy?: Array, // Trending, New, Top defaultOrderBy?: string, + sortBy?: Array, // Newest First, Oldest First freshness?: string, defaultFreshness?: string, @@ -115,6 +116,7 @@ function ClaimListDiscover(props: Props) { blockedUris, hiddenNsfwMessage, defaultOrderBy, + sortBy, orderBy, headerLabel, header, @@ -170,6 +172,7 @@ function ClaimListDiscover(props: Props) { (urlParams.get(CS.TAGS_KEY) !== null && urlParams.get(CS.TAGS_KEY)) || (defaultTags && getParamFromTags(defaultTags)); const freshnessParam = freshness || urlParams.get(CS.FRESH_KEY) || defaultFreshness; + const sortByParam = sortBy || urlParams.get(CS.SORT_BY_KEY) || CS.SORT_BY.NEWEST.key; const mutedAndBlockedChannelIds = Array.from( new Set(mutedUris.concat(blockedUris).map((uri) => splitBySeparator(uri)[1])) ); @@ -255,12 +258,7 @@ function ClaimListDiscover(props: Props) { no_totals: true, not_channel_ids: isChannel ? undefined : mutedAndBlockedChannelIds, not_tags: !showNsfw ? MATURE_TAGS : [], - order_by: - orderParam === CS.ORDER_BY_TRENDING - ? CS.ORDER_BY_TRENDING_VALUE - : orderParam === CS.ORDER_BY_NEW - ? CS.ORDER_BY_NEW_VALUE - : CS.ORDER_BY_TOP_VALUE, // Sort by top + order_by: resolveOrderByOption(orderParam, sortByParam), }; if (ENABLE_NO_SOURCE_CLAIMS && hasNoSource) { @@ -551,6 +549,21 @@ function ClaimListDiscover(props: Props) { } } + function resolveOrderByOption(orderBy: string | Array, sortBy: string | Array) { + const order_by = + orderBy === CS.ORDER_BY_TRENDING + ? CS.ORDER_BY_TRENDING_VALUE + : orderBy === CS.ORDER_BY_NEW + ? CS.ORDER_BY_NEW_VALUE + : CS.ORDER_BY_TOP_VALUE; + + if (orderBy === CS.ORDER_BY_NEW && sortBy === CS.SORT_BY.OLDEST.key) { + return order_by.map((x) => `${CS.SORT_BY.OLDEST.opt}${x}`); + } + + return order_by; + } + // ************************************************************************** // ************************************************************************** diff --git a/ui/component/claimListHeader/view.jsx b/ui/component/claimListHeader/view.jsx index a299ae98b..2865211a3 100644 --- a/ui/component/claimListHeader/view.jsx +++ b/ui/component/claimListHeader/view.jsx @@ -1,5 +1,4 @@ // @flow -import { SIMPLE_SITE } from 'config'; import * as CS from 'constants/claim_search'; import * as ICONS from 'constants/icons'; import type { Node } from 'react'; @@ -21,6 +20,7 @@ type Props = { streamType?: string | Array, defaultStreamType?: string | Array, feeAmount: string, + sortBy?: string, orderBy?: Array, defaultOrderBy?: string, hideAdvancedFilter: boolean, @@ -45,6 +45,7 @@ function ClaimListHeader(props: Props) { streamType, defaultStreamType, feeAmount, + sortBy, orderBy, defaultOrderBy, hideAdvancedFilter, @@ -71,6 +72,7 @@ function ClaimListHeader(props: Props) { streamType || (CS.FILE_TYPES.includes(contentTypeParam) && contentTypeParam) || defaultStreamType || null; const durationParam = urlParams.get(CS.DURATION_KEY) || null; const languageParam = urlParams.get(CS.LANGUAGE_KEY) || null; + const sortByParam = sortBy || urlParams.get(CS.SORT_BY_KEY) || null; const channelIdsInUrl = urlParams.get(CS.CHANNEL_IDS_KEY); const channelIdsParam = channelIdsInUrl ? channelIdsInUrl.split(',') : channelIds; const feeAmountParam = urlParams.get('fee_amount') || feeAmount || CS.FEE_AMOUNT_ANY; @@ -153,6 +155,13 @@ function ClaimListHeader(props: Props) { case CS.ORDER_BY_KEY: newUrlParams.set(CS.ORDER_BY_KEY, delta.value); break; + case CS.SORT_BY_KEY: + if (delta.value === CS.SORT_BY.NEWEST.key) { + newUrlParams.delete(CS.SORT_BY_KEY); + } else { + newUrlParams.set(CS.SORT_BY_KEY, delta.value); + } + break; case CS.FRESH_KEY: if (delta.value === defaultFreshness || delta.value === CS.FRESH_DEFAULT) { newUrlParams.delete(CS.FRESH_KEY); @@ -240,7 +249,7 @@ function ClaimListHeader(props: Props) { )}
- {!hideAdvancedFilter && !SIMPLE_SITE && ( + {!hideAdvancedFilter && (
- {expanded && !SIMPLE_SITE && ( + {expanded && ( <>
{/* FRESHNESS FIELD */} @@ -449,6 +458,32 @@ function ClaimListHeader(props: Props) {
+ {/* SORT FIELD */} + {orderParam === CS.ORDER_BY_NEW && ( +
+ handleChange({ key: CS.SORT_BY_KEY, value: e.target.value })} + > + {Object.entries(CS.SORT_BY).map(([key, value]) => { + return ( + // $FlowFixMe https://github.com/facebook/flow/issues/2221 + + ); + })} + +
+ )} + {channelIdsInUrl && (
diff --git a/ui/constants/claim_search.js b/ui/constants/claim_search.js index 6b95242eb..c1038613a 100644 --- a/ui/constants/claim_search.js +++ b/ui/constants/claim_search.js @@ -1,7 +1,8 @@ export const PAGE_SIZE = 20; export const FRESH_KEY = 'fresh'; -export const ORDER_BY_KEY = 'order'; +export const ORDER_BY_KEY = 'order'; // Trending, Top, New +export const SORT_BY_KEY = 'sort'; // Newest vs Oldest First export const DURATION_KEY = 'duration'; export const LANGUAGE_KEY = 'language'; export const TAGS_KEY = 't'; @@ -39,6 +40,14 @@ export const DURATION_LONG = 'long'; export const DURATION_ALL = 'all'; export const DURATION_TYPES = [DURATION_ALL, DURATION_SHORT, DURATION_LONG]; +export const SORT_BY = { + // key: Enumeration; can be anything as long as unique. Also used as URLParam. + // opt: Value to use for 'claim_search' options; for this case, it is the prefix to 'order_by'. + // str: Customer-facing string representation. + NEWEST: { key: 'new', opt: '', str: 'Newest first' }, + OLDEST: { key: 'old', opt: '^', str: 'Oldest first' }, +}; + export const FILE_VIDEO = 'video'; export const FILE_AUDIO = 'audio'; export const FILE_DOCUMENT = 'document';