@@ -86,6 +86,47 @@ const getPublishDate = (pub: PubWithMetadata): Date | null => {
8686 return pub . customPublishedAt || pub . firstReleaseDate || null ;
8787} ;
8888
89+ const getLowestRelevantCollectionRank = (
90+ pub : PubWithMetadata ,
91+ collectionIdsSet : Set < string > | null ,
92+ ) : string | null => {
93+ let lowestRank : string | null = null ;
94+
95+ for ( const collectionPub of pub . collectionPubs ) {
96+ if ( collectionIdsSet && ! collectionIdsSet . has ( collectionPub . collectionId ) ) {
97+ continue ;
98+ }
99+
100+ const rank = collectionPub . rank || '' ;
101+ if ( lowestRank === null || rank . localeCompare ( lowestRank ) < 0 ) {
102+ lowestRank = rank ;
103+ }
104+ }
105+
106+ return lowestRank ;
107+ } ;
108+
109+ const compareCollectionRanks = (
110+ aRank : string | null ,
111+ bRank : string | null ,
112+ direction : PubsQueryOrdering [ 'direction' ] ,
113+ ) : number => {
114+ if ( aRank === null && bRank === null ) {
115+ return 0 ;
116+ }
117+
118+ if ( aRank === null ) {
119+ return direction === 'ASC' ? 1 : - 1 ;
120+ }
121+
122+ if ( bRank === null ) {
123+ return direction === 'ASC' ? - 1 : 1 ;
124+ }
125+
126+ const rankComparison = aRank . localeCompare ( bRank ) ;
127+ return direction === 'ASC' ? rankComparison : rankComparison * - 1 ;
128+ } ;
129+
89130const filterPubsByCollection = (
90131 pubs : PubWithMetadata [ ] ,
91132 collectionIds : string [ ] ,
@@ -117,23 +158,28 @@ const sortPubs = (
117158 const sorted = [ ...pubs ] ;
118159 const ordering = getQueryOrdering ( sort ) ;
119160
161+ if ( ordering . field === 'collectionRank' ) {
162+ const collectionIdsSet = collectionIds . length > 0 ? new Set ( collectionIds ) : null ;
163+ const lowestRankByPubId = new Map (
164+ sorted . map ( ( pub ) => [ pub . id , getLowestRelevantCollectionRank ( pub , collectionIdsSet ) ] ) ,
165+ ) ;
166+
167+ sorted . sort ( ( a , b ) =>
168+ compareCollectionRanks (
169+ lowestRankByPubId . get ( a . id ) ?? null ,
170+ lowestRankByPubId . get ( b . id ) ?? null ,
171+ ordering . direction ,
172+ ) ,
173+ ) ;
174+
175+ return sorted ;
176+ }
177+
120178 sorted . sort ( ( a , b ) => {
121179 let aValue : number | null = null ;
122180 let bValue : number | null = null ;
123181
124- if ( ordering . field === 'collectionRank' ) {
125- const getMinRank = ( pub : PubWithMetadata ) => {
126- const relevantRanks = pub . collectionPubs
127- . filter (
128- ( cp ) =>
129- collectionIds . length === 0 || collectionIds . includes ( cp . collectionId ) ,
130- )
131- . map ( ( cp ) => parseFloat ( cp . rank ) ) ;
132- return relevantRanks . length > 0 ? Math . min ( ...relevantRanks ) : Number . MAX_VALUE ;
133- } ;
134- aValue = getMinRank ( a ) ;
135- bValue = getMinRank ( b ) ;
136- } else if ( ordering . field === 'creationDate' ) {
182+ if ( ordering . field === 'creationDate' ) {
137183 aValue = a . createdAt . getTime ( ) ;
138184 bValue = b . createdAt . getTime ( ) ;
139185 } else if ( ordering . field === 'publishDate' ) {
0 commit comments