Add general layout for global search [SCI-10468]

This commit is contained in:
Anton 2024-03-21 15:56:35 +01:00
parent 63c0c554e6
commit fe1aee4f23
19 changed files with 341 additions and 422 deletions

View file

@ -4,38 +4,45 @@ class SearchController < ApplicationController
before_action :load_vars, only: :index
def index
redirect_to new_search_path unless @search_query
respond_to do |format|
format.html do
redirect_to new_search_path unless @search_query
end
format.json do
redirect_to new_search_path unless @search_query
@search_id = params[:search_id] ? params[:search_id] : generate_search_id
@search_id = params[:search_id] ? params[:search_id] : generate_search_id
count_search_results
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
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
@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_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
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

View file

@ -0,0 +1,10 @@
import { createApp } from 'vue/dist/vue.esm-bundler.js';
import PerfectScrollbar from 'vue3-perfect-scrollbar';
import GlobalSearch from '../../vue/global_search/container.vue';
import { mountWithTurbolinks } from './helpers/turbolinks.js';
const app = createApp();
app.component('global_search', GlobalSearch);
app.config.globalProperties.i18n = window.I18n;
app.use(PerfectScrollbar);
mountWithTurbolinks(app, '#GlobalSearch');

View file

@ -0,0 +1,114 @@
<template>
<div class="content-pane flexible with-grey-background">
<div class="content-header">
<div class="title-row">
<h1 class="mt-0">
{{ i18n.t('search.index.results_title_html', { query: localQuery }) }}
</h1>
</div>
</div>
<div class="bg-white rounded p-4 flex gap-2.5 items-center mb-4">
<div class="left-icon sci-input-container-v2 w-72 input-sm" :title="i18n.t('nav.search')">
<input ref="searchField" type="text" class="!pr-9" v-model="localQuery" :placeholder="i18n.t('nav.search')" @keyup.enter="saveQuery"/>
<i class="sn-icon sn-icon-search"></i>
<i v-if="localQuery.length > 0" class="sn-icon cursor-pointer sn-icon-close absolute right-0 -top-0.5" @click="localQuery = ''"></i>
</div>
<div class="flex items-center gap-2.5">
<button class="btn btn-secondary btn-sm" :class="{'active': activeGroup == 'ExperimentsComponent'}" @click="setActiveGroup('ExperimentsComponent')">
{{ i18n.t('search.index.experiments') }}
</button>
<button class="btn btn-secondary btn-sm" :class="{'active': activeGroup == 'MyModulesComponent'}" @click="setActiveGroup('MyModulesComponent')">
{{ i18n.t('search.index.tasks') }}
</button>
<button class="btn btn-secondary btn-sm" :class="{'active': activeGroup == 'ResultsComponent'}" @click="setActiveGroup('ResultsComponent')">
{{ i18n.t('search.index.task_results') }}
</button>
</div>
<button class="btn btn-light btn-sm">
<i class="sn-icon sn-icon-search-options"></i>
{{ i18n.t('search.index.more_search_options') }}
</button>
<template v-if="activeGroup">
<div class="h-4 w-[1px] bg-sn-grey"></div>
<button class="btn btn-light btn-sm" @click="activeGroup = null">
<i class="sn-icon sn-icon-close"></i>
{{ i18n.t('search.index.clear_filters') }}
</button>
</template>
</div>
<template v-for="group in searchGroups">
<component
:key="group"
:is="group"
v-if="activeGroup === group || !activeGroup"
:selected="activeGroup === group"
:query="localQuery"
/>
</template>
</div>
</template>
<script>
import FoldersComponent from './groups/folders.vue';
import ProjectsComponent from './groups/projects.vue';
import ExperimentsComponent from './groups/experiments.vue';
import MyModulesComponent from './groups/my_modules.vue';
import MyModuleProtocolsComponent from './groups/my_module_protocols.vue';
import ResultsComponent from './groups/results.vue';
import AssetsComponent from './groups/assets.vue';
import RepositoryRowsComponent from './groups/repository_rows.vue';
import ProtocolsComponent from './groups/protocols.vue';
import LabelTemplatesComponent from './groups/label_templates.vue';
import ReportsComponent from './groups/reports.vue';
export default {
name: 'GlobalSearch',
props: {
query: {
type: String,
required: true
}
},
components: {
FoldersComponent,
ProjectsComponent,
ExperimentsComponent,
MyModulesComponent,
MyModuleProtocolsComponent,
ResultsComponent,
AssetsComponent,
RepositoryRowsComponent,
ProtocolsComponent,
LabelTemplatesComponent,
ReportsComponent
},
data() {
return {
localQuery: this.query,
activeGroup: null,
searchGroups: [
'FoldersComponent',
'ProjectsComponent',
'ExperimentsComponent',
'MyModulesComponent',
'MyModuleProtocolsComponent',
'ResultsComponent',
'AssetsComponent',
'RepositoryRowsComponent',
'ProtocolsComponent',
'LabelTemplatesComponent',
'ReportsComponent'
]
};
},
methods: {
setActiveGroup(group) {
if (group === this.activeGroup) {
this.activeGroup = null;
} else {
this.activeGroup = group;
}
}
}
};
</script>

View file

@ -0,0 +1,14 @@
<template>
<div class="bg-white rounded p-4 mb-4">
<h2 class="flex items-center gap-2 mt-0 mb-4">
<i class="sn-icon sn-icon-files"></i>
{{ i18n.t('search.index.files') }}
</h2>
</div>
</template>
<script>
export default {
name: 'AssetsComponent'
};
</script>

View file

@ -0,0 +1,14 @@
<template>
<div class="bg-white rounded p-4 mb-4">
<h2 class="flex items-center gap-2 mt-0 mb-4">
<i class="sn-icon sn-icon-experiment"></i>
{{ i18n.t('search.index.experiments') }}
</h2>
</div>
</template>
<script>
export default {
name: 'ExperimentsComponent'
};
</script>

View file

@ -0,0 +1,14 @@
<template>
<div class="bg-white rounded p-4 mb-4">
<h2 class="flex items-center gap-2 mt-0 mb-4">
<i class="sn-icon sn-icon-folder"></i>
{{ i18n.t('search.index.folders') }}
</h2>
</div>
</template>
<script>
export default {
name: 'FoldersComponent'
};
</script>

View file

@ -0,0 +1,14 @@
<template>
<div class="bg-white rounded p-4 mb-4">
<h2 class="flex items-center gap-2 mt-0 mb-4">
<i class="sn-icon sn-icon-label-templates"></i>
{{ i18n.t('search.index.label_templates') }}
</h2>
</div>
</template>
<script>
export default {
name: 'LabelTemplatesComponent'
};
</script>

View file

@ -0,0 +1,14 @@
<template>
<div class="bg-white rounded p-4 mb-4">
<h2 class="flex items-center gap-2 mt-0 mb-4">
<i class="sn-icon sn-icon-protocols-templates"></i>
{{ i18n.t('search.index.task_protocols') }}
</h2>
</div>
</template>
<script>
export default {
name: 'MyModuleProtocolsComponent'
};
</script>

View file

@ -0,0 +1,14 @@
<template>
<div class="bg-white rounded p-4 mb-4">
<h2 class="flex items-center gap-2 mt-0 mb-4">
<i class="sn-icon sn-icon-task"></i>
{{ i18n.t('search.index.tasks') }}
</h2>
</div>
</template>
<script>
export default {
name: 'MyModulesComponent'
};
</script>

View file

@ -0,0 +1,14 @@
<template>
<div class="bg-white rounded p-4 mb-4">
<h2 class="flex items-center gap-2 mt-0 mb-4">
<i class="sn-icon sn-icon-projects"></i>
{{ i18n.t('search.index.projects') }}
</h2>
</div>
</template>
<script>
export default {
name: 'ProjectsComponent'
};
</script>

View file

@ -0,0 +1,14 @@
<template>
<div class="bg-white rounded p-4 mb-4">
<h2 class="flex items-center gap-2 mt-0 mb-4">
<i class="sn-icon sn-icon-protocols-templates"></i>
{{ i18n.t('search.index.protocol_templates') }}
</h2>
</div>
</template>
<script>
export default {
name: 'ProtocolsComponent'
};
</script>

View file

@ -0,0 +1,14 @@
<template>
<div class="bg-white rounded p-4 mb-4">
<h2 class="flex items-center gap-2 mt-0 mb-4">
<i class="sn-icon sn-icon-reports"></i>
{{ i18n.t('search.index.reports') }}
</h2>
</div>
</template>
<script>
export default {
name: 'ReportsComponent'
};
</script>

View file

@ -0,0 +1,14 @@
<template>
<div class="bg-white rounded p-4 mb-4">
<h2 class="flex items-center gap-2 mt-0 mb-4">
<i class="sn-icon sn-icon-inventory"></i>
{{ i18n.t('search.index.inventory_items') }}
</h2>
</div>
</template>
<script>
export default {
name: 'RepositoryRowsComponent'
};
</script>

View file

@ -0,0 +1,14 @@
<template>
<div class="bg-white rounded p-4 mb-4">
<h2 class="flex items-center gap-2 mt-0 mb-4">
<i class="sn-icon sn-icon-results"></i>
{{ i18n.t('search.index.task_results') }}
</h2>
</div>
</template>
<script>
export default {
name: 'ResultsComponent'
};
</script>

View file

@ -1,6 +1,5 @@
<template>
<div class="sci--navigation--top-menu-container">
<QuickSearch v-if="user" :quickSearchUrl="quickSearchUrl" :searchUrl="searchUrl" :currentTeam="currentTeam"></QuickSearch>
<div v-if="currentTeam" class="w-64">
<SelectDropdown
:value="currentTeam"
@ -8,6 +7,7 @@
@change="switchTeam"
></SelectDropdown>
</div>
<QuickSearch v-if="user && !hideSearch" :quickSearchUrl="quickSearchUrl" :searchUrl="searchUrl" :currentTeam="currentTeam"></QuickSearch>
<MenuDropdown
class="ml-auto"
v-if="settingsMenu && settingsMenu.length > 0"
@ -97,7 +97,8 @@ export default {
helpMenu: null,
settingsMenu: null,
userMenu: null,
unseenNotificationsCount: 0
unseenNotificationsCount: 0,
hideSearch: false,
};
},
created() {
@ -108,11 +109,15 @@ export default {
this.notificationsOpened = false;
this.checkUnseenNotifications();
this.refreshCurrentTeam();
this.hideSearch = !!document.getElementById('GlobalSearch');
});
// Track name update in user profile settings
$(document).on('inlineEditing::updated', '.inline-editing-container[data-field-to-update="full_name"]', this.fetchData);
},
mounted() {
this.hideSearch = !!document.getElementById('GlobalSearch');
},
beforeUnmount() {
clearTimeout(this.unseenNotificationsTimeout);
},

View file

@ -1,354 +1,9 @@
<% provide(:head_title, t("search.index.head_title")) %>
<div class="content-pane">
<div class="page-header">
<h1><%= t('search.index.results_title_html', query: @display_query) %></h1>
<br>
<!-- search form -->
<div class="row">
<div class="col-xs-12 col-sm-8 col-md-6">
<%= form_tag search_path,
method: :get,
role: 'search' do %>
<div class="form-group">
<div class="input-group">
<input class="form-control min-h-[2.5rem]"
type="text"
name="q"
placeholder="<%= t('nav.search') %>"
value="<%= @display_query %>">
<span class="input-group-btn">
<button class="btn btn-secondary" type="submit">
<span class="sn-icon sn-icon-search"></span>
</button>
</span>
</div>
<label class="checkbox-inline">
<input id="search_whole_word" type="checkbox" name="whole_word" value="true" <%= 'checked' if @search_whole_word %>><%= I18n.t('search.whole_word') %>
</label>
<label class="checkbox-inline">
<input id="search_whole_phrase" type="checkbox" name="whole_phrase" value="true" <%= 'checked' if @search_whole_phrase %>><%= I18n.t('search.whole_phrase') %>
</label>
<label class="checkbox-inline">
<input id="search_match_case" type="checkbox" name="match_case" value="true" <%= 'checked' if @search_case %>><%= I18n.t('search.match_case') %>
</label>
</div>
<% end %>
</div>
</div>
</div>
<%= form_tag search_path, method: :get do %>
<%= hidden_field_tag :q, @search_query %>
<%= hidden_field_tag :category, @search_category %>
<div class="row">
<div class="col-xs-12 col-sm-3 col-md-3" id="search-menu">
<ul class="nav nav-pills nav-stacked nav-stacked-arrow nav-search">
<li role="presentation"
class="
<%= "active" if @search_category.present? and @search_category == :projects %>
<%= "disabled" if @project_search_count == 0 %>"
>
<a href="?<%= {category: 'projects', q: @search_query,
whole_word: @search_whole_word, whole_phrase: @search_whole_phrase,
match_case: @search_case, utf8: '✓',
search_id: @search_id}.to_query %>">
<span class="badge pull-right"><%= @project_search_count %></span>
<span class="sn-icon sn-icon-projects"></span>
<%= t'Projects' %>
</a>
</li>
<li role="presentation"
class="
<%= "active" if @search_category.present? and @search_category == :project_folders %>
<%= "disabled" if @project_folder_search_count == 0 %>"
>
<a href="?<%= { category: 'project_folders', q: @search_query,
whole_word: @search_whole_word, whole_phrase: @search_whole_phrase,
match_case: @search_case, utf8: '✓',
search_id: @search_id }.to_query %>">
<span class="badge pull-right"><%= @project_folder_search_count %></span>
<span class="sn-icon sn-icon-folder"></span>
<%= t('ProjectFolders') %>
</a>
</li>
<li role="presentation"
class="
<%= "active" if @search_category.present? and @search_category == :experiments %>
<%= "disabled" if @experiment_search_count == 0 %>"
>
<a href="?<%= {category: 'experiments', q: @search_query,
whole_word: @search_whole_word, whole_phrase: @search_whole_phrase,
match_case: @search_case, utf8: '✓',
search_id: @search_id}.to_query %>">
<span class="badge pull-right"><%= @experiment_search_count %></span>
<i class="sn-icon sn-icon-experiment"></i>
<%= t'Experiments' %>
</a>
</li>
<li role="presentation"
class="
<%= "active" if @search_category.present? and @search_category == :modules %>
<%= "disabled" if @module_search_count == 0 %>"
>
<a href="?<%= {category: 'modules', q: @search_query,
whole_word: @search_whole_word, whole_phrase: @search_whole_phrase,
match_case: @search_case, utf8: '✓',
search_id: @search_id}.to_query %>">
<span class="badge pull-right"><%= @module_search_count %></span>
<span class="sn-icon sn-icon-task"></span>
<%= t'Modules' %>
</a>
</li>
<li role="presentation"
class="
<%= "active" if @search_category.present? and @search_category == :results %>
<%= "disabled" if @result_search_count == 0 %>"
>
<a href="?<%= {category: 'results', q: @search_query,
whole_word: @search_whole_word, whole_phrase: @search_whole_phrase,
match_case: @search_case, utf8: '✓',
search_id: @search_id}.to_query %>">
<span class="badge pull-right"><%= @result_search_count %></span>
<span class="sn-icon sn-icon sn-icon-reports"></span>
<%= t'Results' %>
</a>
</li>
<li role="presentation"
class="
<%= "active" if @search_category.present? and @search_category == :tags %>
<%= "disabled" if @tag_search_count == 0 %>"
>
<a href="?<%= {category: 'tags', q: @search_query,
whole_word: @search_whole_word, whole_phrase: @search_whole_phrase,
match_case: @search_case, utf8: '✓',
search_id: @search_id}.to_query %>">
<span class="badge pull-right"><%= @tag_search_count %></span>
<span class="sn-icon sn-icon-tag"></span>
<%= t'Tags' %>
</a>
</li>
<li role="presentation"
class="
<%= "active" if @search_category.present? and @search_category == :reports %>
<%= "disabled" if @report_search_count == 0 %>"
>
<a href="?<%= {category: 'reports', q: @search_query,
whole_word: @search_whole_word, whole_phrase: @search_whole_phrase,
match_case: @search_case, utf8: '✓',
search_id: @search_id}.to_query %>">
<span class="badge pull-right"><%= @report_search_count %></span>
<span class="sn-icon sn-icon-reports"></span>
<%= t'Reports' %>
</a>
</li>
<li role="presentation"
class="
<%= "active" if @search_category.present? and @search_category == :protocols %>
<%= "disabled" if @protocol_search_count == 0 %>"
>
<a href="?<%= {category: 'protocols', q: @search_query,
whole_word: @search_whole_word, whole_phrase: @search_whole_phrase,
match_case: @search_case, utf8: '✓',
search_id: @search_id}.to_query %>">
<span class="badge pull-right"><%= @protocol_search_count %></span>
<span class="sn-icon sn-icon-protocols-templates"></span>
<%= t'Protocols' %>
</a>
</li>
<li role="presentation"
class="
<%= "active" if @search_category.present? and @search_category == :steps %>
<%= "disabled" if @step_search_count == 0 %>"
>
<a href="?<%= {category: 'steps', q: @search_query,
whole_word: @search_whole_word, whole_phrase: @search_whole_phrase,
match_case: @search_case, utf8: '✓',
search_id: @search_id}.to_query %>">
<span class="badge pull-right"><%= @step_search_count %></span>
<span class="sn-icon sn-icon-steps"></span>
<%= t'Steps' %>
</a>
</li>
<li role="presentation"
class="
<%= "active" if @search_category.present? and @search_category == :checklists %>
<%= "disabled" if @checklist_search_count == 0 %>"
>
<a href="?<%= {category: 'checklists', q: @search_query,
whole_word: @search_whole_word, whole_phrase: @search_whole_phrase,
match_case: @search_case, utf8: '✓',
search_id: @search_id}.to_query %>">
<span class="badge pull-right"><%= @checklist_search_count %></span>
<span class="sn-icon sn-icon-checkllist"></span>
<%= t'Checklists' %>
</a>
</li>
<li role="presentation"
class="
<%= "active" if @search_category.present? and @search_category == :assets %>
<%= "disabled" if @asset_search_count == 0 %>"
>
<a href="?<%= {category: 'assets', q: @search_query,
whole_word: @search_whole_word, whole_phrase: @search_whole_phrase,
match_case: @search_case, utf8: '✓',
search_id: @search_id}.to_query %>">
<span class="badge pull-right"><%= @asset_search_count %></span>
<span class="sn-icon sn-icon-files"></span>
<%= t'Assets' %>
</a>
</li>
<li role="presentation"
class="
<%= "active" if @search_category.present? and @search_category == :tables %>
<%= "disabled" if @table_search_count == 0 %>"
>
<a href="?<%= {category: 'tables', q: @search_query,
whole_word: @search_whole_word, whole_phrase: @search_whole_phrase,
match_case: @search_case, utf8: '✓',
search_id: @search_id}.to_query %>">
<span class="badge pull-right"><%= @table_search_count %></span>
<span class="sn-icon sn-icon-tables"></span>
<%= t'Tables' %>
</a>
</li>
<li role="presentation"
class="
<%= "active" if @search_category.present? and @search_category == :comments %>
<%= "disabled" if @comment_search_count == 0 %>"
>
<a href="?<%= {category: 'comments', q: @search_query,
whole_word: @search_whole_word, whole_phrase: @search_whole_phrase,
match_case: @search_case, utf8: '✓',
search_id: @search_id}.to_query %>">
<span class="badge pull-right"><%= @comment_search_count %></span>
<span class="sn-icon sn-icon-comments"></span>
<%= t'Comments' %>
</a>
</li>
<% @repository_search_count.each do |team, results| %>
<li class="repositories-team <%= 'active' if results[:count].positive? %>">
<i class="sn-icon sn-icon-inventory"></i>
<%= t('Repositories_team', team: team) %>
</li>
<% results[:repositories].each do |repository, values| %>
<li role="presentation"
class="
<%= "active" if @search_category == :repositories && @repository.id == values[:id] %>
<%= "disabled" if values[:count] == 0 %> repository-search"
>
<a href="?<%= {category: 'repositories',
repository: values[:id], q: @search_query,
whole_word: @search_whole_word, whole_phrase: @search_whole_phrase,
match_case: @search_case, utf8: '✓',
search_id: @search_id}.to_query %>">
<span class="badge pull-right"><%= values[:count] %></span>
<%= repository %>
<%= inventory_shared_status_icon(values[:repository], results[:team]) %>
</a>
</li>
<% end %>
<% end %>
</ul>
</div>
<% if not @search_category.blank? %>
<div class="col-xs-12 col-sm-9" id="search-content">
<div class="container-fluid" id="search-container">
<% if @search_results_count == 0 %>
<p><%= t'search.index.error.no_results', q: @search_query %></p>
<% end %>
<hr class="visible-xs">
<% if @search_category == :projects and @project_search_count.positive? %>
<%= render 'search/results/projects', search_query: @search_query, results: @project_results %>
<% end %>
<% if @search_category == :project_folders and @project_folder_search_count.positive? %>
<%= render 'search/results/project_folders', search_query: @search_query, results: @project_folder_results %>
<% end %>
<% if @search_category == :experiments and @experiment_search_count.positive? %>
<%= render 'search/results/experiments', search_query: @search_query, results: @experiment_results %>
<% end %>
<% if @search_category == :modules and @module_search_count.positive? %>
<%= render 'search/results/modules', search_query: @search_query, results: @module_results %>
<% end %>
<% if @search_category == :results and @result_search_count.positive? %>
<%= render 'search/results/results', search_query: @search_query, results: @result_results %>
<% end %>
<% if @search_category == :tags and @tag_search_count.positive? %>
<%= render 'search/results/tags', search_query: @search_query, results: @tag_results %>
<% end %>
<% if @search_category == :reports and @report_search_count.positive? %>
<%= render 'search/results/reports', search_query: @search_query, results: @report_results %>
<% end %>
<% if @search_category == :protocols and @protocol_search_count.positive? %>
<%= render 'search/results/protocols', search_query: @search_query, results: @protocol_results %>
<% end %>
<% if @search_category == :steps and @step_search_count.positive? %>
<%= render 'search/results/steps', search_query: @search_query, results: @step_results %>
<% end %>
<% if @search_category == :checklists and @checklist_search_count.positive? %>
<%= render 'search/results/checklists', search_query: @search_query, results: @checklist_results %>
<% end %>
<% if @search_category == :repositories and @repository_search_count_total.positive? %>
<%= render 'search/results/repositories', search_query: @search_query, results: @repository_results, repository: @repository %>
<% end %>
<% if @search_category == :assets and @asset_search_count.positive? %>
<%= render 'search/results/assets', search_query: @search_query, results: @asset_results %>
<% end %>
<% if @search_category == :tables and @table_search_count.positive? %>
<%= render 'search/results/tables', search_query: @search_query, results: @table_results %>
<% end %>
<% if @search_category == :comments and @comment_search_count.positive? %>
<%= render 'search/results/comments', search_query: @search_query, results: @comment_results %>
<% end %>
</div>
</div>
<% end %>
</div>
<% end %>
<% if @search_pages > 1 %>
<% params = { q: @search_query,
category: @search_category,
utf8: '✓',
search_id: @search_id } %>
<% if @search_category == :repositories %>
<% params[:repository] = @repository.id %>
<% end %>
<nav class="text-center">
<ul class="pagination">
<% if @search_page > 1 %>
<% params[:page] = @search_page - 1 %>
<li>
<a href="?<%= params.to_query %>" aria-label="Previous">
<span aria-hidden="true">&laquo;</span>
</a>
</li>
<% end %>
<% (@start_page..@end_page).each do |page_i| %>
<% params[:page] = page_i %>
<li <% if @search_page == page_i %>class="active"<% end %>>
<a href="?<%= params.to_query %>"><%= page_i %></a>
</li>
<% end %>
<% if @search_page < @search_pages %>
<% params[:page] = @search_page + 1 %>
<li>
<a href="?<%= params.to_query %>" aria-label="Next">
<span aria-hidden="true">&raquo;</span>
</a>
</li>
<% end %>
</ul>
</nav>
<% end %>
<div id="GlobalSearch" class="contents">
<global_search
:query="'<%= @display_query %>'"
/>
</div>
<%= javascript_include_tag('search') %>
<%= javascript_include_tag "vue_global_search" %>

View file

@ -615,6 +615,7 @@ class Extends
protocols/show
preferences/index
addons/index
search/index
)
DEFAULT_USER_NOTIFICATION_SETTINGS = {

View file

@ -441,48 +441,20 @@ en:
index:
head_title: "Search"
page_title: "Search"
results_title_html: "Search Results for '<em>%{query}</em>'"
public: "Public"
private: "Private"
archived: "Archived"
in_repository: "Protocol templates"
created_by: "Created by: "
created_at: "Created at: "
last_modified_by: "Last modified by: "
last_modified_at: "Last modified at: "
keywords: "Keywords: "
authors: "Authors: "
description: "Description: "
no_description: "No description"
text: "Text"
team: "Team: "
folder: "Folders: "
repository: "Inventory: "
repository_row: "Inventory item: "
project: "Project: "
experiment: "Experiment: "
protocol: "Protocol: "
modules: "Tasks: "
tag_no_modules: "not added to any tasks"
module: "Task: "
step: "Step: "
result: "Result: "
report: "Report: "
no_name: "(no name)"
error:
no_results: "No results for %{q}."
repositories:
repository_row: "Inventory item: "
added_on: "Added on: "
added_by: "Added by: "
custom_column: "%{column}: "
no_modules: "not assigned to any task"
comments:
project: "Project comment"
my_module: "Task comment"
step: "Step comment"
result: "Result comment"
results_title_html: "Search Results for '%{query}'"
experiments: "Experiments"
tasks: "Tasks"
task_results: "Task results"
folders: "Folders"
projects: "Projects"
task_protocols: "Task protocols"
files: "Files"
inventory_items: "Inventory items"
protocol_templates: "Protocol templates"
label_templates: "Label templates"
reports: "Reports"
more_search_options: "More search options"
clear_filters: "Clear filters"
comments:
save_changes: "Save changes"
empty_state:

View file

@ -59,9 +59,10 @@ const entryList = {
vue_open_locally_menu: './app/javascript/packs/vue/open_locally_menu.js',
vue_scinote_edit_download: './app/javascript/packs/vue/scinote_edit_download.js',
vue_design_system_modals: './app/javascript/packs/vue/design_system/modals.js',
vue_global_search: './app/javascript/packs/vue/global_search.js',
vue_legacy_tags_modal: './app/javascript/packs/vue/legacy/tags_modal.js',
vue_legacy_access_modal: './app/javascript/packs/vue/legacy/access_modal.js',
vue_legacy_repository_menu_dropdown: './app/javascript/packs/vue/legacy/repository_menu_dropdown.js'
vue_legacy_repository_menu_dropdown: './app/javascript/packs/vue/legacy/repository_menu_dropdown.js',
};
// Engine pack loading based on https://github.com/rails/webpacker/issues/348#issuecomment-635480949