import { createSelector } from "reselect" ; import { State } from "containers/project-data-container" ; import { sortByString , sortByNumber } from "./sort-utils" ; const getTagCounters = createSelector < State , BestOfJS . StateProject [ ] , Record < string , number > > ( [ ( state ) => Object . values ( state . entities . projects ) ] , ( projects ) => { const tagCounters = { } ; projects . forEach ( ( { tags } ) => { tags . forEach ( ( tag ) => { tagCounters [ tag ] = tagCounters [ tag ] ? tagCounters [ tag ] + 1 : 1 ; } ) ; } ) ; return tagCounters ; } ) ; export const getTagsByCode = ( codes ) => createSelector < State , any , BestOfJS . Tag [ ] > ( [ ( state ) => state . entities . tags ] , ( allTags ) => codes . map ( ( code ) => allTags [ code ] ) ) ; export const getAllTags = createSelector ( [ ( state ) => state . entities . projects , ( state ) => state . entities . tags , getTagCounters , ] , ( projectIds , tagIds , countsByTag ) => Object . values ( tagIds ) . map ( ( tag ) => { const counter = countsByTag [ tag . code ] ; return { ... tag , counter } ; } ) ) ; const sortFunctions = { "project-count" : ( tags ) => sortByNumber ( tags , "counter" , "desc" ) , alpha : ( tags ) => sortByString ( tags , "name" , "asc" ) , } ; export const getAllTagsSortedBy = ( criteria , count ? ) => createSelector ( [ getAllTags ] , ( tags ) => { const fn = sortFunctions [ criteria ] ; if ( ! fn ) throw new Error ( `Invalid criteria to sort tags "${ criteria }"` ) ; const sortedTags = fn ( tags ) ; return count ? sortedTags . slice ( 0 , count ) : sortedTags ; } ) ; export const getPopularTags = ( count ) => getAllTagsSortedBy ( "project-count" , count ) ;