diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb index 27ae5e1e5..5b55c1536 100644 --- a/app/controllers/search_controller.rb +++ b/app/controllers/search_controller.rb @@ -11,37 +11,56 @@ class SearchController < ApplicationController format.json do redirect_to new_search_path unless @search_query - @search_id = params[:search_id] ? params[:search_id] : generate_search_id + case params[:group] + when 'projects' + @project_search_count = fetch_cached_count Project + search_projects + if params[:preview] == 'true' + results = @project_results.limit(4) + else + results = @project_results.page(params[:page]).per(Constants::SEARCH_LIMIT) + end - count_search_results - - search_projects if @search_category == :projects - search_project_folders if @search_category == :project_folders - search_experiments if @search_category == :experiments - search_modules if @search_category == :modules - search_results if @search_category == :results - search_tags if @search_category == :tags - search_reports if @search_category == :reports - search_protocols if @search_category == :protocols - search_steps if @search_category == :steps - search_checklists if @search_category == :checklists - if @search_category == :repositories && params[:repository] - search_repository + render json: results, + each_serializer: GlobalSearch::ProjectSerializer, + meta: { + total: @search_count, + next_page: (results.next_page if results.respond_to?(:next_page)), + } + return end - search_assets if @search_category == :assets - search_tables if @search_category == :tables - search_comments if @search_category == :comments - @search_pages = (@search_count.to_f / Constants::SEARCH_LIMIT.to_f).ceil - @start_page = @search_page - 2 - @start_page = 1 if @start_page < 1 - @end_page = @start_page + 4 + #@search_id = params[:search_id] ? params[:search_id] : generate_search_id + # + #count_search_results + # + #search_projects if @search_category == :projects + #search_project_folders if @search_category == :project_folders + #search_experiments if @search_category == :experiments + #search_modules if @search_category == :modules + #search_results if @search_category == :results + #search_tags if @search_category == :tags + #search_reports if @search_category == :reports + #search_protocols if @search_category == :protocols + #search_steps if @search_category == :steps + #search_checklists if @search_category == :checklists + #if @search_category == :repositories && params[:repository] + # search_repository + #end + #search_assets if @search_category == :assets + #search_tables if @search_category == :tables + #search_comments if @search_category == :comments - if @end_page > @search_pages - @end_page = @search_pages - @start_page = @end_page - 4 - @start_page = 1 if @start_page < 1 - end + #@search_pages = (@search_count.to_f / Constants::SEARCH_LIMIT.to_f).ceil + #@start_page = @search_page - 2 + #@start_page = 1 if @start_page < 1 + #@end_page = @start_page + 4 + + #if @end_page > @search_pages + # @end_page = @search_pages + # @start_page = @end_page - 4 + # @start_page = 1 if @start_page < 1 + #end end end end diff --git a/app/javascript/vue/global_search/container.vue b/app/javascript/vue/global_search/container.vue index 8652967a6..be302d1b1 100644 --- a/app/javascript/vue/global_search/container.vue +++ b/app/javascript/vue/global_search/container.vue @@ -7,9 +7,9 @@ -
+
- +
@@ -43,6 +43,8 @@ v-if="activeGroup === group || !activeGroup" :selected="activeGroup === group" :query="localQuery" + :searchUrl="searchUrl" + @selectGroup="setActiveGroup" />
@@ -67,6 +69,10 @@ export default { query: { type: String, required: true + }, + searchUrl: { + type: String, + required: true } }, components: { @@ -108,6 +114,9 @@ export default { } else { this.activeGroup = group; } + }, + changeQuery(event) { + this.localQuery = event.target.value; } } }; diff --git a/app/javascript/vue/global_search/groups/projects.vue b/app/javascript/vue/global_search/groups/projects.vue index 365c3aa18..f98dbf54a 100644 --- a/app/javascript/vue/global_search/groups/projects.vue +++ b/app/javascript/vue/global_search/groups/projects.vue @@ -3,12 +3,57 @@

{{ i18n.t('search.index.projects') }} + [{{ total }}]

+
+
+ +
+
+ +
+
diff --git a/app/javascript/vue/global_search/groups/search_mixin.js b/app/javascript/vue/global_search/groups/search_mixin.js new file mode 100644 index 000000000..6e8a3fa70 --- /dev/null +++ b/app/javascript/vue/global_search/groups/search_mixin.js @@ -0,0 +1,87 @@ +import axios from '../../../packs/custom_axios.js'; +import StringWithEllipsis from '../../shared/string_with_ellipsis.vue'; + +export default { + props: { + searchUrl: String, + query: String, + selected: Boolean + }, + components: { + StringWithEllipsis + }, + data() { + return { + results: [], + total: 0, + loading: false, + page: 1, + fullDataLoaded: false + }; + }, + watch: { + selected() { + if (this.selected) { + if (!this.fullDataLoaded) { + this.results = []; + this.loadData(); + } + } + }, + query() { + this.results = []; + this.page = 1; + this.fullDataLoaded = false; + this.loadData(); + } + }, + mounted() { + this.loadData(); + window.addEventListener('scroll', this.handleScroll); + }, + unmounted() { + window.removeEventListener('scroll', this.handleScroll); + }, + computed: { + preparedResults() { + if (this.selected) { + return this.results; + } + return this.results.slice(0, 4); + } + }, + methods: { + handleScroll() { + if (this.loading) return; + + if ((window.innerHeight + window.scrollY) >= document.body.offsetHeight) { + if (this.results.length < this.total) { + this.loadData(); + } + } + }, + loadData() { + if (this.loading && this.page) return; + + this.loading = true; + axios.get(this.searchUrl, { + params: { + q: this.query, + group: this.group, + preview: !this.selected, + page: this.page + } + }) + .then((response) => { + if (this.selected) this.fullDataLoaded = true; + this.results = this.results.concat(response.data.data); + this.total = response.data.meta.total; + this.loading = false; + this.page = response.data.meta.next_page; + }) + .finally(() => { + this.loading = false; + }); + } + } +}; diff --git a/app/serializers/global_search/project_serializer.rb b/app/serializers/global_search/project_serializer.rb new file mode 100644 index 000000000..bd94e4b56 --- /dev/null +++ b/app/serializers/global_search/project_serializer.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +class GlobalSearch::ProjectSerializer < ActiveModel::Serializer + include Rails.application.routes.url_helpers + + attributes :id, :name, :code, :created_at, :team, :folder, :archived, :url + + def team + { + name: object.team.name, + url: projects_path(team: object.team) + } + end + + def created_at + I18n.l(object.created_at, format: :full_date) + end + + def url + project_path(object) + end + + def folder + if object.project_folder + { + name: object.project_folder.name, + url: project_folder_path(object.project_folder) + } + end + end +end diff --git a/app/views/search/index.html.erb b/app/views/search/index.html.erb index 15d967f0d..70db91ef7 100644 --- a/app/views/search/index.html.erb +++ b/app/views/search/index.html.erb @@ -3,6 +3,7 @@
diff --git a/config/locales/en.yml b/config/locales/en.yml index 649f66ce7..3aa90769e 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -455,6 +455,10 @@ en: reports: "Reports" more_search_options: "More search options" clear_filters: "Clear filters" + id: "ID" + created_at: "Created on" + team: "Team" + folder: "Folder" comments: save_changes: "Save changes" empty_state: