mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2025-10-24 21:24:52 +08:00
Merge pull request #7538 from aignatov-bio/ai-sci-10681-small-fixes-global-search
Small fixes for global search [SCI-10681][SCI-10679]
This commit is contained in:
commit
24d76f0321
11 changed files with 108 additions and 24 deletions
|
|
@ -8,12 +8,36 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="bg-white rounded p-4 flex gap-2.5 z-10 items-center mb-4 sticky top-0">
|
||||
<div class="left-icon sci-input-container-v2 w-72 input-sm"
|
||||
:title="i18n.t('nav.search')" :class="{'error': invalidQuery}">
|
||||
<input ref="searchField" type="text" class="!pr-9" :value="localQuery" @change="changeQuery" :placeholder="i18n.t('nav.search')"/>
|
||||
<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>
|
||||
<GeneralDropdown ref="historyContainer" :canOpen="canOpenHistory" :fieldOnlyOpen="true" >
|
||||
<template v-slot:field>
|
||||
<div class="left-icon sci-input-container-v2 w-72 input-sm"
|
||||
:title="i18n.t('nav.search')" :class="{'error': invalidQuery}">
|
||||
<input ref="searchField"
|
||||
type="text"
|
||||
class="!pr-9"
|
||||
:value="localQuery"
|
||||
@change="changeQuery"
|
||||
@keydown.enter="changeQuery"
|
||||
@blur="changeQuery"
|
||||
:placeholder="i18n.t('nav.search')"
|
||||
/>
|
||||
<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 = ''; $refs.searchField.focus()"></i>
|
||||
</div>
|
||||
</template>
|
||||
<template v-slot:flyout >
|
||||
<div v-for="(query, i) in reversedPreviousQueries" @click="setQuery(query)" :key="i"
|
||||
ref="historyItems"
|
||||
tabindex="1"
|
||||
@keydown.enter="setQuery(query)"
|
||||
class="flex px-3 h-11 items-center gap-2 hover:bg-sn-super-light-grey cursor-pointer">
|
||||
<i class="sn-icon sn-icon-history-search"></i>
|
||||
{{ query }}
|
||||
</div>
|
||||
</template>
|
||||
</GeneralDropdown>
|
||||
<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') }}
|
||||
|
|
@ -42,6 +66,10 @@
|
|||
<span class="tw-hidden lg:inline">{{ i18n.t('search.index.clear_filters') }}</span>
|
||||
</button>
|
||||
</template>
|
||||
<button v-if="activeGroup" class="btn btn-light btn-sm" @click="resetGroup">
|
||||
<i class="sn-icon sn-icon-undo"></i>
|
||||
<span class="tw-hidden lg:inline">{{ i18n.t('search.index.all_results') }}</span>
|
||||
</button>
|
||||
</div>
|
||||
<template v-for="group in searchGroups">
|
||||
<component
|
||||
|
|
@ -57,7 +85,7 @@
|
|||
@updated="calculateTotalElements"
|
||||
/>
|
||||
</template>
|
||||
<div v-if="totalElements === 0 && !loading" class="bg-white rounded p-4">
|
||||
<div v-if="totalElements === 0" class="bg-white rounded p-4">
|
||||
<NoSearchResult />
|
||||
</div>
|
||||
<teleport to='body'>
|
||||
|
|
@ -136,6 +164,8 @@ export default {
|
|||
filters: {},
|
||||
localQuery: this.query,
|
||||
filterModalOpened: false,
|
||||
previousQueries: [],
|
||||
invalidQuery: false,
|
||||
activeGroup: null,
|
||||
totalElements: 0,
|
||||
searchGroups: [
|
||||
|
|
@ -154,9 +184,6 @@ export default {
|
|||
};
|
||||
},
|
||||
computed: {
|
||||
invalidQuery() {
|
||||
return this.localQuery.length < 2;
|
||||
},
|
||||
activeFilters() {
|
||||
return Object.keys(this.filters).filter((key) => {
|
||||
if (key === 'created_at' || key === 'updated_at') {
|
||||
|
|
@ -166,6 +193,12 @@ export default {
|
|||
}
|
||||
return this.filters[key];
|
||||
});
|
||||
},
|
||||
canOpenHistory() {
|
||||
return this.previousQueries.length > 0 && this.localQuery.length === 0;
|
||||
},
|
||||
reversedPreviousQueries() {
|
||||
return [...this.previousQueries].reverse();
|
||||
}
|
||||
},
|
||||
created() {
|
||||
|
|
@ -197,6 +230,8 @@ export default {
|
|||
if (this.filters.group) {
|
||||
this.activeGroup = this.filters.group;
|
||||
}
|
||||
|
||||
this.previousQueries = JSON.parse(localStorage.getItem('quickSearchHistory') || '[]');
|
||||
},
|
||||
methods: {
|
||||
calculateTotalElements() {
|
||||
|
|
@ -217,8 +252,38 @@ export default {
|
|||
|
||||
this.filters.group = this.activeGroup;
|
||||
},
|
||||
setQuery(query) {
|
||||
this.localQuery = query;
|
||||
this.invalidQuery = false;
|
||||
this.$refs.historyContainer.isOpen = false;
|
||||
},
|
||||
changeQuery(event) {
|
||||
if (event.target.value === this.localQuery) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.localQuery = event.target.value;
|
||||
|
||||
if (event.target.value.length < 2) {
|
||||
this.invalidQuery = true;
|
||||
return;
|
||||
}
|
||||
|
||||
this.invalidQuery = false;
|
||||
this.saveQuery();
|
||||
},
|
||||
saveQuery() {
|
||||
if (this.localQuery.length > 1) {
|
||||
if (this.previousQueries[this.previousQueries.length - 1] === this.localQuery) return;
|
||||
|
||||
this.previousQueries.push(this.localQuery);
|
||||
|
||||
if (this.previousQueries.length > 5) {
|
||||
this.previousQueries.shift();
|
||||
}
|
||||
localStorage.setItem('quickSearchHistory', JSON.stringify(this.previousQueries));
|
||||
this.$refs.historyContainer.isOpen = false;
|
||||
}
|
||||
},
|
||||
applyFilters(filters) {
|
||||
this.filters = filters;
|
||||
|
|
@ -226,6 +291,10 @@ export default {
|
|||
|
||||
this.activeGroup = this.filters.group;
|
||||
},
|
||||
resetGroup() {
|
||||
this.activeGroup = null;
|
||||
this.filters.group = null;
|
||||
},
|
||||
resetFilters() {
|
||||
this.filters = {
|
||||
created_at: {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,13 @@
|
|||
<template>
|
||||
<a target="_blank" :href="url" class="h-full py-2 px-4 overflow-hidden font-bold flex gap-1 items-center group-hover:bg-sn-super-light-grey hover:no-underline">
|
||||
<a target="_blank" :href="url"
|
||||
class="h-full py-2 px-4 flex gap-1 items-center font-bold overflow-hidden group-hover:bg-sn-super-light-grey hover:no-underline"
|
||||
>
|
||||
<span v-if="icon" :class="icon" class="sn-icon shrink-0"></span>
|
||||
<StringWithEllipsis class="w-full"
|
||||
<StringWithEllipsis
|
||||
:class="{
|
||||
'w-full': !icon,
|
||||
'w-[calc(100%-2rem)]': icon
|
||||
}"
|
||||
:text="value">
|
||||
</StringWithEllipsis>
|
||||
</a>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
@focus="openHistory" :placeholder="i18n.t('nav.search')" @keyup.enter="saveQuery"/>
|
||||
<i class="sn-icon sn-icon-search"></i>
|
||||
<div v-if="this.searchQuery.length > 1" class="flex items-center gap-1 absolute right-2 top-1.5">
|
||||
<div class="btn btn-light icon-btn btn-xs" @click="this.searchQuery = ''">
|
||||
<div class="btn btn-light icon-btn btn-xs" @click="this.searchQuery = ''; $refs.searchField.focus()">
|
||||
<i class="sn-icon sn-icon-close m-0"></i>
|
||||
</div>
|
||||
<div class="btn btn-light icon-btn btn-xs" :title="i18n.t('search.quick_search.search_options')"
|
||||
|
|
@ -96,7 +96,7 @@
|
|||
<div v-if="!loading && results.length === 0" class="p-2 flex items-center gap-6">
|
||||
<i class="sn-icon sn-icon-search text-sn-sleepy-grey" style="font-size: 64px !important;"></i>
|
||||
<div>
|
||||
<b>{{ i18n.t('search.quick_search.empty_title') }}</b>
|
||||
<b>{{ i18n.t('search.quick_search.empty_title', {team: currentTeamName}) }}</b>
|
||||
<div class="text-xs text-sn-dark-grey">
|
||||
{{ i18n.t('search.quick_search.empty_description', {query: searchQuery}) }}
|
||||
</div>
|
||||
|
|
@ -147,13 +147,16 @@ export default {
|
|||
},
|
||||
computed: {
|
||||
reversedPreviousQueries() {
|
||||
return this.previousQueries.reverse();
|
||||
return [...this.previousQueries].reverse();
|
||||
},
|
||||
canOpen() {
|
||||
return this.previousQueries.length > 0 || this.searchQuery.length > 1;
|
||||
},
|
||||
showHistory() {
|
||||
return this.searchQuery.length < 2;
|
||||
},
|
||||
currentTeamName() {
|
||||
return document.querySelector('body').dataset.currentTeamName;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
|
@ -262,11 +265,11 @@ export default {
|
|||
});
|
||||
},
|
||||
saveQuery() {
|
||||
if (this.searchQuery.length > 0) {
|
||||
if (this.searchQuery.length > 1) {
|
||||
this.previousQueries.push(this.searchQuery);
|
||||
|
||||
if (this.previousQueries.length > 5) {
|
||||
this.previousQueries.shift();
|
||||
this.previousQueries = this.previousQueries.slice(1);
|
||||
}
|
||||
|
||||
localStorage.setItem('quickSearchHistory', JSON.stringify(this.previousQueries));
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@
|
|||
class="<%= yield :body_class %> <%= 'navigator-collapsed' if !@navigator || session[:navigator_collapsed] %> <%= 'w-[98%]' if params[:controller] == 'label_templates' && params[:action] == 'show'%>"
|
||||
<% if user_signed_in? && current_team.present? %>
|
||||
data-current-team-id="<%= current_team.id %>"
|
||||
data-current-team-name="<%= current_team.name %>"
|
||||
data-atwho-users-url="<%= atwho_users_team_path(current_team) %>"
|
||||
data-atwho-task-url="<%= atwho_my_modules_team_path(current_team) %>"
|
||||
data-atwho-project-url="<%= atwho_projects_team_path(current_team) %>"
|
||||
|
|
|
|||
|
|
@ -448,7 +448,7 @@ en:
|
|||
results: "Results"
|
||||
inventory_items: "Inventory items"
|
||||
all_results: "All search results for \"%{query}\""
|
||||
empty_title: "No quick search results found."
|
||||
empty_title: "No quick search results found in %{team}."
|
||||
empty_description: "Quick search only checks titles. Press enter or click \"All search results for '%{query}'\" to find all available matches."
|
||||
search_options: "Search options"
|
||||
project: "Project"
|
||||
|
|
@ -508,6 +508,7 @@ en:
|
|||
repository: "Inventory"
|
||||
more_search_options: "More search options"
|
||||
clear_filters: "Clear filters"
|
||||
all_results: "All results"
|
||||
id: "ID"
|
||||
created_at: "Created on"
|
||||
created_by: "Created by"
|
||||
|
|
|
|||
BIN
vendor/assets/stylesheets/fonts/SN-icon-font.eot
vendored
BIN
vendor/assets/stylesheets/fonts/SN-icon-font.eot
vendored
Binary file not shown.
|
|
@ -194,4 +194,5 @@
|
|||
<glyph unicode="" glyph-name="experiment-mini" data-tags="experiment-mini" d="M307.929 140.8c-22.141 0-37.673 9.815-46.598 29.44-8.958 19.625-6.625 37.545 7 53.76l141.471 257.28v222.72h-70.255c-7.664 0-13.847 2.56-18.547 7.68-4.667 5.12-7 11.094-7 17.92 0 7.68 2.333 13.875 7 18.586 4.701 4.676 10.883 7.014 18.547 7.014h344.89c7.665 0 13.844-2.56 18.545-7.68 4.669-5.12 6.999-11.094 6.999-17.92 0-7.68-2.33-13.858-6.999-18.534-4.7-4.71-10.88-7.066-18.545-7.066h-70.257v-222.72l141.471-257.28c13.624-16.215 15.974-34.135 7.050-53.76-8.955-19.625-24.509-29.44-46.648-29.44h-408.124zM307.929 192h408.124l-152.965 271.36v240.64h-102.191v-240.64l-152.968-271.36z" />
|
||||
<glyph unicode="" glyph-name="task-mini" data-tags="task-mini" d="M339.2 140.8c-23.894 0-43.725 7.885-59.494 23.654-15.804 15.805-23.706 35.651-23.706 59.546v448c0 23.894 7.902 43.742 23.706 59.546 15.77 15.77 35.601 23.654 59.494 23.654h249.6l179.2-179.2v-352c0-23.895-7.885-43.74-23.654-59.546-15.805-15.77-35.651-23.654-59.546-23.654h-345.6zM563.2 550.4v153.6h-224c-8.534 0-15.991-3.209-22.374-9.626-6.417-6.383-9.626-13.841-9.626-22.374v-448c0-8.535 3.209-15.99 9.626-22.374 6.383-6.415 13.841-9.626 22.374-9.626h345.6c8.535 0 15.99 3.21 22.374 9.626 6.415 6.385 9.626 13.839 9.626 22.374v326.4h-153.6zM652.984 468.48l-171.313-228.413-123.272 123.269 36.204 36.209 81.528-81.531 135.892 181.187 40.96-30.72z" />
|
||||
<glyph unicode="" glyph-name="flag" data-tags="flag" d="M256 128v661.333h306.871l17.067-85.333h230.729v-341.333h-221.538l-17.067 85.333h-273.395v-320h-42.667zM625.067 405.333h142.933v256h-224l-17.067 85.333h-228.267v-256h309.333l17.067-85.333z" />
|
||||
<glyph unicode="" glyph-name="undo" data-tags="undo" d="M315.893 192v42.667h309.506c44.25 0 81.954 15.181 113.109 45.538 31.142 30.357 46.72 67.413 46.72 111.177s-15.578 80.687-46.72 110.775c-31.155 30.084-68.86 45.129-113.109 45.129h-330.338l126.517-126.528-30.197-30.199-178.048 178.061 178.048 178.048 30.197-30.197-126.517-126.517h330.338c55.851 0 103.561-19.257 143.134-57.771 39.573-38.507 59.362-85.44 59.362-140.8 0-55.351-19.789-102.421-59.362-141.205s-87.283-58.176-143.134-58.176h-309.506z" />
|
||||
</font></defs></svg>
|
||||
|
Before Width: | Height: | Size: 125 KiB After Width: | Height: | Size: 126 KiB |
BIN
vendor/assets/stylesheets/fonts/SN-icon-font.ttf
vendored
BIN
vendor/assets/stylesheets/fonts/SN-icon-font.ttf
vendored
Binary file not shown.
BIN
vendor/assets/stylesheets/fonts/SN-icon-font.woff
vendored
BIN
vendor/assets/stylesheets/fonts/SN-icon-font.woff
vendored
Binary file not shown.
BIN
vendor/assets/stylesheets/fonts/SN-icon-font.woff2
vendored
BIN
vendor/assets/stylesheets/fonts/SN-icon-font.woff2
vendored
Binary file not shown.
15
vendor/assets/stylesheets/sn-icon-font.css
vendored
15
vendor/assets/stylesheets/sn-icon-font.css
vendored
|
|
@ -1,11 +1,11 @@
|
|||
@font-face {
|
||||
font-family: 'SN-icon-font';
|
||||
src: url('fonts/SN-icon-font.eot?o0xor4');
|
||||
src: url('fonts/SN-icon-font.eot?o0xor4#iefix') format('embedded-opentype'),
|
||||
url('fonts/SN-icon-font.woff2?o0xor4') format('woff2'),
|
||||
url('fonts/SN-icon-font.ttf?o0xor4') format('truetype'),
|
||||
url('fonts/SN-icon-font.woff?o0xor4') format('woff'),
|
||||
url('fonts/SN-icon-font.svg?o0xor4#SN-icon-font') format('svg');
|
||||
src: url('fonts/SN-icon-font.eot?m1g5fz');
|
||||
src: url('fonts/SN-icon-font.eot?m1g5fz#iefix') format('embedded-opentype'),
|
||||
url('fonts/SN-icon-font.woff2?m1g5fz') format('woff2'),
|
||||
url('fonts/SN-icon-font.ttf?m1g5fz') format('truetype'),
|
||||
url('fonts/SN-icon-font.woff?m1g5fz') format('woff'),
|
||||
url('fonts/SN-icon-font.svg?m1g5fz#SN-icon-font') format('svg');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-display: block;
|
||||
|
|
@ -530,3 +530,6 @@
|
|||
.sn-icon-flag:before {
|
||||
content: "\e9a7";
|
||||
}
|
||||
.sn-icon-undo:before {
|
||||
content: "\e9a8";
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue