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 @@
-
+
@@ -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 }}]
+
+
+
+
+
+
+
+ {{ i18n.t('search.index.id') }}:
+ {{ row.attributes.code }}
+
+
+ {{ i18n.t('search.index.created_at') }}:
+ {{ row.attributes.created_at }}
+
+
+
{{ i18n.t('search.index.team') }}:
+
+
+
+
+
+
+
+
{{ i18n.t('search.index.folder') }}:
+
+
+
+
+
+
+
+
+
+
+
+
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: