Skip to content

Commit

Permalink
Merge pull request #90 from solver-it-sro/query-for-no-visible-tags
Browse files Browse the repository at this point in the history
GO-247 Allow filtering out threads with visible tags with query -label:*
  • Loading branch information
mirrec authored Oct 12, 2023
2 parents 692c2bf + 52ed392 commit 10dc26b
Show file tree
Hide file tree
Showing 7 changed files with 52 additions and 54 deletions.
18 changes: 1 addition & 17 deletions app/components/layout/tag_list_component.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,11 @@
<p class=" text-sm text-center text-gray-400">Štítky</p>
</div>
<% @tags.each do |tag| %>
<%= link_to message_threads_path(q: "label:(#{tag.name})"), class:"flex justify-start items-start px-4 py-2 gap-2 overflow-hidden" do %>
<%= link_to message_threads_path(q: "label:(#{tag.name})"), class: "flex justify-start items-start px-4 py-2 gap-2 overflow-hidden" do %>
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class=" w-6 h-6 relative" preserveAspectRatio="xMidYMid meet">
<path d="M7 7H7.01M7 3H12C12.512 3 13.024 3.195 13.414 3.586L20.414 10.586C20.7889 10.9611 20.9996 11.4697 20.9996 12C20.9996 12.5303 20.7889 13.0389 20.414 13.414L13.414 20.414C13.0389 20.7889 12.5303 20.9996 12 20.9996C11.4697 20.9996 10.9611 20.7889 10.586 20.414L3.586 13.414C3.4 13.2285 3.25249 13.0081 3.15192 12.7655C3.05136 12.5228 2.99973 12.2627 3 12V7C3 5.93913 3.42143 4.92172 4.17157 4.17157C4.92172 3.42143 5.93913 3 7 3Z" stroke="#9CA3AF" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
</svg>
<p class="truncate text-base font-medium text-left text-gray-900"><%= tag.name %></p>
<% end %>
<% end %>
<% if Current.user.admin? %>
<%= link_to message_threads_path(no_visible_tags: "1"), class: "group relative" do %>
<div class="flex justify-start items-start px-4 py-2 gap-2">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class=" w-6 h-6 relative" preserveAspectRatio="xMidYMid meet">
<path d="M7 7H7.01M7 3H12C12.512 3 13.024 3.195 13.414 3.586L20.414 10.586C20.7889 10.9611 20.9996 11.4697 20.9996 12C20.9996 12.5303 20.7889 13.0389 20.414 13.414L13.414 20.414C13.0389 20.7889 12.5303 20.9996 12 20.9996C11.4697 20.9996 10.9611 20.7889 10.586 20.414L3.586 13.414C3.4 13.2285 3.25249 13.0081 3.15192 12.7655C3.05136 12.5228 2.99973 12.2627 3 12V7C3 5.93913 3.42143 4.92172 4.17157 4.17157C4.92172 3.42143 5.93913 3 7 3Z" stroke="#9CA3AF" stroke-width="1" stroke-linecap="round" stroke-linejoin="round"></path>
</svg>
<p class="text-base font-medium text-left text-gray-900">Bez GO štítku
</p>
</div>
<span class="absolute hidden group-hover:flex group-hover:flex-col -left-5 -top-2 -translate-y-full w-48 px-2 py-1 bg-gray-700 rounded-lg text-center text-white text-sm after:content-[''] after:absolute after:left-1/2 after:top-[100%] after:-translate-x-1/2 after:border-8 after:border-x-transparent after:border-b-transparent after:border-t-gray-700">
<p>Pohľad pre adminov:</p>
<p>"Čo nedostalo žaiden štítok v Govbox PRO ..." alebo aj</p>
<p>"Čo nebolo nikomu priradené ..."</p>
</span>
<% end %>
<% end %>
</div>
9 changes: 4 additions & 5 deletions app/controllers/message_threads_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ def load_threads
scope: message_thread_policy_scope.includes(:tags, :box),
search_permissions: search_permissions,
query: search_params[:q],
no_visible_tags: search_params[:no_visible_tags] == "1" && Current.user.admin?,
cursor: cursor
)

Expand Down Expand Up @@ -82,9 +81,9 @@ def message_thread_policy_scope
end

def search_permissions
result = { tenant_id: Current.tenant }
result[:box_id] = Current.box if Current.box
result[:tag_ids] = policy_scope(Tag).pluck(:id) unless Current.user.admin?
result = { tenant: Current.tenant }
result[:box] = Current.box if Current.box
result[:tag_ids] = policy_scope(Tag).pluck(:id)
result
end

Expand All @@ -93,6 +92,6 @@ def message_thread_params
end

def search_params
params.permit(:q, :no_visible_tags, :format, cursor: MessageThreadCollection::CURSOR_PARAMS)
params.permit(:q, :format, cursor: MessageThreadCollection::CURSOR_PARAMS)
end
end
5 changes: 2 additions & 3 deletions app/models/message_thread_collection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,11 @@ def self.serialize_cursor(cursor)
cursor
end

def self.all(scope: nil, search_permissions:, query: nil, no_visible_tags: false, cursor:)
def self.all(scope: nil, search_permissions:, query: nil, cursor:)
parsed_query = Searchable::MessageThreadQuery.parse(query.to_s)
filter = Searchable::MessageThreadQuery.labels_to_ids(
parsed_query,
tenant_id: search_permissions.fetch(:tenant_id),
no_visible_tags: no_visible_tags
tenant: search_permissions.fetch(:tenant)
)

ids, next_cursor, highlights = Searchable::MessageThread.search_ids(
Expand Down
4 changes: 2 additions & 2 deletions app/models/searchable/message_thread.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ def self.fulltext_search(query)
def self.search_ids(query_filter, search_permissions:, cursor:, per_page:, direction: )
scope = self

scope = scope.where(tenant_id: search_permissions.fetch(:tenant_id))
scope = scope.where(box_id: search_permissions.fetch(:box_id)) if search_permissions[:box_id]
scope = scope.where(tenant_id: search_permissions.fetch(:tenant))
scope = scope.where(box_id: search_permissions.fetch(:box)) if search_permissions[:box]

if search_permissions.key?(:tag_ids)
if search_permissions[:tag_ids].any?
Expand Down
50 changes: 23 additions & 27 deletions app/models/searchable/message_thread_query.rb
Original file line number Diff line number Diff line change
@@ -1,50 +1,45 @@
class Searchable::MessageThreadQuery
def self.remove_label_from_text(text, match)
text.gsub("#{match[0]}:(#{match[1]})", '')
end
# frozen_string_literal: true

class Searchable::MessageThreadQuery
def self.parse(query)
filter_labels = []
filter_out_labels = []

with_text = query.to_s

query.to_s.scan(/(-?label):\(([^)]+)\)/).each do |match|
raise "unexpected label case" if match.length != 2
query.to_s.scan(/(-?label):(\(([^)]+)\)|([^ ]+)|\*)/).each do |match|
raise "unexpected label case" if match.length != 4

if match[0] == "label"
filter_labels << match[1]
label_name = [match[2], match[3]].find(&:presence)

with_text = remove_label_from_text(with_text, match)
if match[0] == "label"
filter_labels << label_name
elsif match[0] == "-label"
filter_out_labels << label_name
end

if match[0] == "-label"
filter_out_labels << match[1]

with_text = remove_label_from_text(with_text, match)
end
with_text = with_text.gsub("#{match[0]}:#{match[1]}", "")
end

{
fulltext: with_text.gsub(/\s+/, ' ').strip,
filter_labels: filter_labels,
filter_out_labels: filter_out_labels
filter_out_labels: filter_out_labels,
}
end

def self.labels_to_ids(parsed_query, tenant_id:, no_visible_tags: false)
def self.labels_to_ids(parsed_query, tenant:)
fulltext, filter_labels, filter_out_labels =
parsed_query.fetch_values(:fulltext, :filter_labels, :filter_out_labels)

filter_tag_ids = label_names_to_tag_ids(tenant_id, filter_labels)
filter_out_tag_ids = label_names_to_tag_ids(tenant_id, filter_out_labels)

filter_out_tag_ids.concat(visible_tag_ids(tenant_id)) if no_visible_tags
# TODO maybe with one query
found_all, filter_tag_ids = label_names_to_tag_ids(tenant, filter_labels)
_, filter_out_tag_ids = label_names_to_tag_ids(tenant, filter_out_labels)

result = {}

if filter_labels.present?
if filter_labels.length == filter_tag_ids.length
if found_all
result[:filter_tag_ids] = filter_tag_ids
else
result[:filter_tag_ids] = :missing_tag
Expand All @@ -57,11 +52,12 @@ def self.labels_to_ids(parsed_query, tenant_id:, no_visible_tags: false)
result
end

def self.label_names_to_tag_ids(tenant_id, label_names)
Tag.where(tenant_id: tenant_id, name: label_names).pluck(:id)
end

def self.visible_tag_ids(tenant_id)
Tag.where(tenant_id: tenant_id, visible: true).pluck(:id)
def self.label_names_to_tag_ids(tenant, label_names)
if label_names.find { |name| name == "*" }.present?
[true, tenant.tags.visible.pluck(:id)]
else
ids = tenant.tags.where(name: label_names).pluck(:id)
[ids.length == label_names.length, ids]
end
end
end
2 changes: 2 additions & 0 deletions app/models/tag.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ class Tag < ApplicationRecord
validates :name, presence: true
validates :name, uniqueness: { scope: :tenant_id, case_sensitive: false }

scope :visible, -> { where(visible: true) }

after_create_commit ->(tag) { tag.mark_readable_by_groups(tag.tenant.admin_groups) }
after_update_commit ->(tag) { EventBus.publish(:tag_renamed, tag) if previous_changes.key?("name") }
after_destroy ->(tag) { EventBus.publish(:tag_removed, tag) }
Expand Down
18 changes: 18 additions & 0 deletions test/models/searchable/message_thread_query_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,22 @@ class Searchable::MessageThreadQueryTest < ActiveSupport::TestCase
filter_out_labels: ['without this tag']
}
end

test "parser no visible tags" do
query = 'something -label:* else'
assert_equal Searchable::MessageThreadQuery.parse(query), {
fulltext: 'something else',
filter_labels: [],
filter_out_labels: ["*"]
}
end

test "parser no visible tags with other labels to filter out" do
query = 'something -label:* else -label:two'
assert_equal Searchable::MessageThreadQuery.parse(query), {
fulltext: 'something else',
filter_labels: [],
filter_out_labels: ["*", "two"]
}
end
end

0 comments on commit 10dc26b

Please sign in to comment.