diff --git a/app/assets/javascripts/sitewide/constants.js.erb b/app/assets/javascripts/sitewide/constants.js.erb index 6d3eeff90..b88b22bd5 100644 --- a/app/assets/javascripts/sitewide/constants.js.erb +++ b/app/assets/javascripts/sitewide/constants.js.erb @@ -18,4 +18,5 @@ const GLOBAL_CONSTANTS = { SLOW_STATUS_POLLING_INTERVAL: <%= Constants::SLOW_STATUS_POLLING_INTERVAL %>, ASSET_POLLING_INTERVAL: <%= Constants::ASSET_POLLING_INTERVAL %>, ASSET_SYNC_URL: '<%= Constants::ASSET_SYNC_URL %>', + GLOBAL_SEARCH_PREVIEW_LIMIT: <%= Constants::GLOBAL_SEARCH_PREVIEW_LIMIT %> }; diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb index 5b55c1536..f7f281563 100644 --- a/app/controllers/search_controller.rb +++ b/app/controllers/search_controller.rb @@ -13,20 +13,65 @@ class SearchController < ApplicationController case params[:group] when 'projects' - @project_search_count = fetch_cached_count Project + @project_search_count = fetch_cached_count(Project) search_projects if params[:preview] == 'true' - results = @project_results.limit(4) + results = @project_results&.limit(4) || [] else results = @project_results.page(params[:page]).per(Constants::SEARCH_LIMIT) end - render json: results, + render json: results.includes(:team, :project_folder), each_serializer: GlobalSearch::ProjectSerializer, meta: { total: @search_count, next_page: (results.next_page if results.respond_to?(:next_page)), } + when 'project_folders' + @project_folder_search_count = fetch_cached_count ProjectFolder + search_project_folders + results = if params[:preview] == 'true' + @project_folder_results.limit(Constants::GLOBAL_SEARCH_PREVIEW_LIMIT) + else + @project_folder_results.page(params[:page]).per(Constants::SEARCH_LIMIT) + end + render json: results.includes(:team, :parent_folder), + each_serializer: GlobalSearch::ProjectFolderSerializer, + meta: { + total: @search_count, + next_page: results.try(:next_page) + } + return + when 'experiments' + @experiment_search_count = fetch_cached_count Experiment + search_experiments + results = if params[:preview] == 'true' + @experiment_results.limit(Constants::GLOBAL_SEARCH_PREVIEW_LIMIT) + else + @experiment_results.page(params[:page]).per(Constants::SEARCH_LIMIT) + end + render json: results.includes(project: :team), + each_serializer: GlobalSearch::ExperimentSerializer, + meta: { + total: @search_count, + next_page: results.try(:next_page) + } + return + when 'protocols' + @protocol_search_count = fetch_cached_count(Protocol) + search_protocols + results = if params[:preview] == 'true' + @protocol_results&.limit(4) || [] + else + @protocol_results.page(params[:page]).per(Constants::SEARCH_LIMIT) + end + + render json: results, + each_serializer: GlobalSearch::ProtocolSerializer, + meta: { + total: @search_count, + next_page: (results.next_page if results.respond_to?(:next_page)), + } return end @@ -251,19 +296,19 @@ class SearchController < ApplicationController end def search_projects - @project_results = [] + @project_results = Project.none @project_results = search_by_name(Project) if @project_search_count.positive? @search_count = @project_search_count end def search_project_folders - @project_folder_results = [] + @project_folder_results = ProjectFolder.none @project_folder_results = search_by_name(ProjectFolder) if @project_folder_search_count.positive? @search_count = @project_folder_search_count end def search_experiments - @experiment_results = [] + @experiment_results = Experiment.none @experiment_results = search_by_name(Experiment) if @experiment_search_count.positive? @search_count = @experiment_search_count end diff --git a/app/javascript/vue/global_search/groups/experiments.vue b/app/javascript/vue/global_search/groups/experiments.vue index f97db8fa4..74231b487 100644 --- a/app/javascript/vue/global_search/groups/experiments.vue +++ b/app/javascript/vue/global_search/groups/experiments.vue @@ -1,14 +1,57 @@ diff --git a/app/javascript/vue/global_search/groups/folders.vue b/app/javascript/vue/global_search/groups/folders.vue index 15ea2f7f0..3b1a441c4 100644 --- a/app/javascript/vue/global_search/groups/folders.vue +++ b/app/javascript/vue/global_search/groups/folders.vue @@ -1,14 +1,55 @@ diff --git a/app/javascript/vue/global_search/groups/projects.vue b/app/javascript/vue/global_search/groups/projects.vue index f98dbf54a..e30786e65 100644 --- a/app/javascript/vue/global_search/groups/projects.vue +++ b/app/javascript/vue/global_search/groups/projects.vue @@ -1,5 +1,5 @@ diff --git a/app/javascript/vue/global_search/groups/search_mixin.js b/app/javascript/vue/global_search/groups/search_mixin.js index 6e8a3fa70..bf638ee92 100644 --- a/app/javascript/vue/global_search/groups/search_mixin.js +++ b/app/javascript/vue/global_search/groups/search_mixin.js @@ -1,5 +1,6 @@ import axios from '../../../packs/custom_axios.js'; import StringWithEllipsis from '../../shared/string_with_ellipsis.vue'; +/* global GLOBAL_CONSTANTS */ export default { props: { @@ -48,6 +49,9 @@ export default { return this.results; } return this.results.slice(0, 4); + }, + viewAll() { + return !this.selected && this.total > GLOBAL_CONSTANTS.GLOBAL_SEARCH_PREVIEW_LIMIT; } }, methods: { diff --git a/app/serializers/global_search/experiment_serializer.rb b/app/serializers/global_search/experiment_serializer.rb new file mode 100644 index 000000000..e1ac156e5 --- /dev/null +++ b/app/serializers/global_search/experiment_serializer.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +module GlobalSearch + class ExperimentSerializer < ActiveModel::Serializer + include Rails.application.routes.url_helpers + + attributes :id, :name, :code, :created_at, :team, :project, :archived, :url + + def team + { + name: object.project.team.name, + url: projects_path(team_id: object.project.team.id) + } + end + + def project + { + name: object.project.name, + url: project_experiments_path(project_id: object.project.id) + } + end + + def created_at + I18n.l(object.created_at, format: :full_date) + end + + def url + my_modules_experiment_path(object.id) + end + end +end diff --git a/app/serializers/global_search/project_folder_serializer.rb b/app/serializers/global_search/project_folder_serializer.rb new file mode 100644 index 000000000..c818ee2bd --- /dev/null +++ b/app/serializers/global_search/project_folder_serializer.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +module GlobalSearch + class ProjectFolderSerializer < ActiveModel::Serializer + include Rails.application.routes.url_helpers + + attributes :id, :name, :code, :created_at, :team, :parent_folder, :archived, :url + + def team + { + name: object.team.name, + url: projects_path(project_folder_id: object.id) + } + end + + def created_at + I18n.l(object.created_at, format: :full_date) + end + + def url + project_folder_path(object) + end + + def parent_folder + if object.parent_folder_id? + { + name: object.parent_folder.name, + url: project_folder_path(object.parent_folder.id) + } + end + end + end +end diff --git a/app/serializers/global_search/protocol_serializer.rb b/app/serializers/global_search/protocol_serializer.rb new file mode 100644 index 000000000..feac6d3fd --- /dev/null +++ b/app/serializers/global_search/protocol_serializer.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true + +module GlobalSearch + class ProtocolSerializer < ActiveModel::Serializer + include Rails.application.routes.url_helpers + + attributes :id, :name, :code, :created_at, :updated_at, :created_by, :team, :archived, :url + + def team + { + name: object.team.name, + url: protocols_path(team: object.team) + } + end + + def created_by + { + name: object.created_by.name, + avatar_url: avatar_path(object.created_by, :icon_small) + } + end + + def created_at + I18n.l(object.created_at, format: :full_date) + end + + def updated_at + I18n.l(object.updated_at, format: :full_date) + end + + def url + protocol_path(object) + end + end +end diff --git a/config/initializers/constants.rb b/config/initializers/constants.rb index 7eebf696b..00f966099 100644 --- a/config/initializers/constants.rb +++ b/config/initializers/constants.rb @@ -52,6 +52,8 @@ class Constants # General limited/unlimited query/display elements for pages SEARCH_LIMIT = 20 + # General global search limit for object groups + GLOBAL_SEARCH_PREVIEW_LIMIT = 4 SEARCH_NO_LIMIT = -1 # General limited query/display elements for popup modals MODAL_SEARCH_LIMIT = 5 diff --git a/config/locales/en.yml b/config/locales/en.yml index 0ee92b813..794679f58 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -457,8 +457,11 @@ en: clear_filters: "Clear filters" id: "ID" created_at: "Created on" + created_by: "Created by" + updated_at: "Updated on" team: "Team" folder: "Folder" + project: "Project" comments: save_changes: "Save changes" empty_state: