<commit_before>import qs from 'querystring'
import { isInCommunity } from './index'
import { compact, includes, omitBy, upperFirst } from 'lodash'
import {
  navigate,
  FETCH_COMMUNITIES,
  FETCH_POSTS,
  FETCH_PEOPLE,
  FETCH_TAGS,
  SEARCH
} from '../actions'

const commonDefaults = {
  type: ['all+welcome', 'all'],
  sort: 'recent'
}

const blankOrDefault = (defaults = commonDefaults) => (value, key) => {
  let defaultValue = defaults[key]
  return defaultValue === value ||
    (!value && value !== 0) ||
    (Array.isArray(defaultValue) && includes(defaultValue, value))
}

// TODO: sort output by key name
export const cleanAndStringify = (opts, defaults) =>
  qs.stringify(omitBy(opts, blankOrDefault(defaults)))

export const createCacheId = (subject, id, query = {}) => {
  const { type, tag, sort, search, filter, q } = query
  return cleanAndStringify({subject, id, type, tag, sort, search, filter, q})
}

export const connectedListProps = (state, props, itemType) => {
  let actionType
  let getItem = id => state[itemType][id]

  switch (itemType) {
    case 'posts':
      actionType = FETCH_POSTS
      break
    case 'people':
      actionType = FETCH_PEOPLE
      break
    case 'communities':
      actionType = FETCH_COMMUNITIES
      break
    case 'searchResults':
      actionType = SEARCH
      getItem = x => x
      break
    case 'tags':
      actionType = FETCH_TAGS
      getItem = x => x
      break

    default:
      throw new Error(`unknown item type: ${itemType}`)
  }

  let { subject, id, query } = props
  let cacheId = createCacheId(subject, id, query)
  let itemKey = `${itemType}ByQuery`
  let itemCountKey = `total${upperFirst(itemType)}ByQuery`
  let countFreshItemKey = `countFresh${upperFirst(itemType)}ByQuery`

  let itemIds = compact(state[itemKey][cacheId] || [])
  let countFreshItems = (state[countFreshItemKey] || {})[cacheId] || 0

  return {
    [itemType]: compact(itemIds.map(getItem)),
    total: state[itemCountKey][cacheId],
    pending: state.pending[actionType],
    freshCount: countFreshItems
  }
}

export const fetchWithCache = action => (subject, id, query = {}) => {
  let cacheId = createCacheId(subject, id, query)
  return action({subject, id, limit: 20, ...query, cacheId})
}

export const refetch = (opts, location, defaults) => {
  let { query, pathname } = location
  let newQuery = cleanAndStringify({...query, ...opts}, defaults)
  let newPath = `${pathname}${newQuery ? '?' + newQuery : ''}`
  return navigate(newPath)
}

export const paramsForFetch = (location, params, currentUser) => {
  return {
    subject: isInCommunity(location) ? 'community' : 'all-posts',
    id: isInCommunity(location) ? params.id : currentUser.id
  }
}<commit_msg>decrease size of first page of post list<commit_after>import qs from 'querystring'
import { isInCommunity } from './index'
import { compact, includes, omitBy, upperFirst } from 'lodash'
import {
  navigate,
  FETCH_COMMUNITIES,
  FETCH_POSTS,
  FETCH_PEOPLE,
  FETCH_TAGS,
  SEARCH
} from '../actions'

const commonDefaults = {
  type: ['all+welcome', 'all'],
  sort: 'recent'
}

const blankOrDefault = (defaults = commonDefaults) => (value, key) => {
  let defaultValue = defaults[key]
  return defaultValue === value ||
    (!value && value !== 0) ||
    (Array.isArray(defaultValue) && includes(defaultValue, value))
}

// TODO: sort output by key name
export const cleanAndStringify = (opts, defaults) =>
  qs.stringify(omitBy(opts, blankOrDefault(defaults)))

export const createCacheId = (subject, id, query = {}) => {
  const { type, tag, sort, search, filter, q } = query
  return cleanAndStringify({subject, id, type, tag, sort, search, filter, q})
}

export const connectedListProps = (state, props, itemType) => {
  let actionType
  let getItem = id => state[itemType][id]

  switch (itemType) {
    case 'posts':
      actionType = FETCH_POSTS
      break
    case 'people':
      actionType = FETCH_PEOPLE
      break
    case 'communities':
      actionType = FETCH_COMMUNITIES
      break
    case 'searchResults':
      actionType = SEARCH
      getItem = x => x
      break
    case 'tags':
      actionType = FETCH_TAGS
      getItem = x => x
      break

    default:
      throw new Error(`unknown item type: ${itemType}`)
  }

  let { subject, id, query } = props
  let cacheId = createCacheId(subject, id, query)
  let itemKey = `${itemType}ByQuery`
  let itemCountKey = `total${upperFirst(itemType)}ByQuery`
  let countFreshItemKey = `countFresh${upperFirst(itemType)}ByQuery`

  let itemIds = compact(state[itemKey][cacheId] || [])
  let countFreshItems = (state[countFreshItemKey] || {})[cacheId] || 0

  return {
    [itemType]: compact(itemIds.map(getItem)),
    total: state[itemCountKey][cacheId],
    pending: state.pending[actionType],
    freshCount: countFreshItems
  }
}

export const fetchWithCache = action => (subject, id, query = {}) => {
  let cacheId = createCacheId(subject, id, query)
  return action({subject, id, limit: 10, ...query, cacheId})
}

export const refetch = (opts, location, defaults) => {
  let { query, pathname } = location
  let newQuery = cleanAndStringify({...query, ...opts}, defaults)
  let newPath = `${pathname}${newQuery ? '?' + newQuery : ''}`
  return navigate(newPath)
}

export const paramsForFetch = (location, params, currentUser) => {
  return {
    subject: isInCommunity(location) ? 'community' : 'all-posts',
    id: isInCommunity(location) ? params.id : currentUser.id
  }
}
{'fraction_non_alphanumeric': 0.13657111557421947, 'fraction_numerical': 0.001460653642505021, 'mean_word_length': 3.8306878306878307, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 27, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '468784', 'n_tokens_mistral': 1792, 'n_tokens_neox': 1743, 'n_words': 463}