<commit_before>angular.module('loomioApp').factory 'ThreadQueryService', (Records) ->
  new class ThreadQueryService

    filterQuery: (filter, options = {}) ->
      threadQueryFor createBaseView(filter, options['queryType'] or 'all')

    timeframeQuery: (options = {}) ->
      threadQueryFor createTimeframeView(options['name'], options['filter'] or 'show_all', 'timeframe', options['timeframe']['from'], options['timeframe']['to'])

    groupQuery: (group = {}, options = {}) ->
      threadQueryFor createGroupView(group, options['filter'] or 'show_unread', options['queryType'] or 'inbox')

    threadQueryFor = (view) ->
      threads: -> view.data()
      length: ->  @threads().length
      any: ->     @length() > 0

    createBaseView = (filters, queryType) ->
      view = Records.discussions.collection.addDynamicView 'default'
      applyFilters(view, filters, queryType)
      view

    createGroupView = (group, filters, queryType) ->
      view = Records.discussions.collection.addDynamicView group.name
      view.applyFind({groupId: { $in: group.organisationIds() }})
      applyFilters(view, filters, queryType)
      view

    createTimeframeView = (name, filters, queryType, from, to) ->
      today = moment().startOf 'day'
      view = Records.discussions.collection.addDynamicView name
      view.applyFind(lastActivityAt: { $gt: parseTimeOption(from) })
      view.applyFind(lastActivityAt: { $lt: parseTimeOption(to) })
      applyFilters(view, filters, queryType)
      view

    parseTimeOption = (options) ->
      # we pass times in something human-readable like '1 month ago'
      # this translates that into today.subtract(1, 'month')
      parts = options.split ' '
      moment().startOf('day').subtract(parseInt(parts[0]), parts[1])

    applyFilters = (view, filters, queryType) ->
      filters = [].concat filters

      view.applyFind(discussionReaderId: { $ne: null })

      switch queryType
        when 'important' then view.applyWhere (thread) -> thread.isImportant()
        when 'timeframe' then view.applyWhere (thread) -> !thread.isImportant()
        when 'inbox'
          view.applyFind(lastActivityAt: { $gt: moment().startOf('day').subtract(6, 'week').toDate() })
          view.applyWhere (thread) -> thread.isUnread()

      if _.contains(filters, 'show_muted')
        view.applyFind(volume: { $eq: 'mute' })
      else
        view.applyFind(volume: { $ne: 'mute' })

      _.each filters, (filter) ->
        switch filter
          when 'show_participating' then view.applyFind(participating: true)
          when 'show_starred'       then view.applyFind(starred: true)
          when 'show_proposals'     then view.applyWhere (thread) -> thread.hasActiveProposal()
          when 'hide_proposals'     then view.applyWhere (thread) -> !thread.hasActiveProposal()

      view<commit_msg>Hotfix: Ensure discussion reader id > 0, rather than not null<commit_after>angular.module('loomioApp').factory 'ThreadQueryService', (Records) ->
  new class ThreadQueryService

    filterQuery: (filter, options = {}) ->
      threadQueryFor createBaseView(filter, options['queryType'] or 'all')

    timeframeQuery: (options = {}) ->
      threadQueryFor createTimeframeView(options['name'], options['filter'] or 'show_all', 'timeframe', options['timeframe']['from'], options['timeframe']['to'])

    groupQuery: (group = {}, options = {}) ->
      threadQueryFor createGroupView(group, options['filter'] or 'show_unread', options['queryType'] or 'inbox')

    threadQueryFor = (view) ->
      threads: -> view.data()
      length: ->  @threads().length
      any: ->     @length() > 0

    createBaseView = (filters, queryType) ->
      view = Records.discussions.collection.addDynamicView 'default'
      applyFilters(view, filters, queryType)
      view

    createGroupView = (group, filters, queryType) ->
      view = Records.discussions.collection.addDynamicView group.name
      view.applyFind({groupId: { $in: group.organisationIds() }})
      applyFilters(view, filters, queryType)
      view

    createTimeframeView = (name, filters, queryType, from, to) ->
      today = moment().startOf 'day'
      view = Records.discussions.collection.addDynamicView name
      view.applyFind(lastActivityAt: { $gt: parseTimeOption(from) })
      view.applyFind(lastActivityAt: { $lt: parseTimeOption(to) })
      applyFilters(view, filters, queryType)
      view

    parseTimeOption = (options) ->
      # we pass times in something human-readable like '1 month ago'
      # this translates that into today.subtract(1, 'month')
      parts = options.split ' '
      moment().startOf('day').subtract(parseInt(parts[0]), parts[1])

    applyFilters = (view, filters, queryType) ->
      filters = [].concat filters

      view.applyFind(discussionReaderId: { $gt: 0 })

      switch queryType
        when 'important' then view.applyWhere (thread) -> thread.isImportant()
        when 'timeframe' then view.applyWhere (thread) -> !thread.isImportant()
        when 'inbox'
          view.applyFind(lastActivityAt: { $gt: moment().startOf('day').subtract(6, 'week').toDate() })
          view.applyWhere (thread) -> thread.isUnread()

      if _.contains(filters, 'show_muted')
        view.applyFind(volume: { $eq: 'mute' })
      else
        view.applyFind(volume: { $ne: 'mute' })

      _.each filters, (filter) ->
        switch filter
          when 'show_participating' then view.applyFind(participating: true)
          when 'show_starred'       then view.applyFind(starred: true)
          when 'show_proposals'     then view.applyWhere (thread) -> thread.hasActiveProposal()
          when 'hide_proposals'     then view.applyWhere (thread) -> !thread.hasActiveProposal()

      view
{'fraction_non_alphanumeric': 0.13743250304824944, 'fraction_numerical': 0.002438599547117227, 'mean_word_length': 3.288274831964152, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 44, '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': '7143154', 'n_tokens_mistral': 1680, 'n_tokens_neox': 1646, 'n_words': 374}