mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2024-09-20 14:45:56 +08:00
Small css fixes and microinteractions [SCI-10630]
This commit is contained in:
parent
57c138f54f
commit
9bd64104f3
|
@ -8,7 +8,8 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="bg-white rounded p-4 flex gap-2.5 items-center mb-4 sticky top-0">
|
||||
<div class="left-icon sci-input-container-v2 w-72 input-sm" :title="i18n.t('nav.search')">
|
||||
<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>
|
||||
|
@ -145,6 +146,9 @@ export default {
|
|||
};
|
||||
},
|
||||
computed: {
|
||||
invalidQuery() {
|
||||
return this.localQuery.length < 2;
|
||||
},
|
||||
activeFilters() {
|
||||
return Object.keys(this.filters).filter((key) => {
|
||||
if (key === 'created_at' || key === 'updated_at') {
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<div ref="modal" class="modal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog" role="document">
|
||||
<form @submit.prevent="submit">
|
||||
<div class="modal-content">
|
||||
<div class="modal-content !pb-2.5">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<i class="sn-icon sn-icon-close"></i>
|
||||
|
|
|
@ -46,11 +46,13 @@ export default {
|
|||
}
|
||||
},
|
||||
query() {
|
||||
this.results = [];
|
||||
this.page = 1;
|
||||
this.total = 0;
|
||||
this.fullDataLoaded = false;
|
||||
this.loadData();
|
||||
if (this.query.length > 1) {
|
||||
this.results = [];
|
||||
this.page = 1;
|
||||
this.total = 0;
|
||||
this.fullDataLoaded = false;
|
||||
this.loadData();
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
|
@ -104,6 +106,8 @@ export default {
|
|||
this.loadData();
|
||||
},
|
||||
loadData() {
|
||||
if (this.query.length < 2) return;
|
||||
|
||||
if (this.loading && this.page) return;
|
||||
|
||||
this.loading = true;
|
||||
|
|
|
@ -2,13 +2,15 @@
|
|||
<GeneralDropdown ref="container" :canOpen="canOpen" :fieldOnlyOpen="true" @close="filtersOpened = false">
|
||||
<template v-slot:field>
|
||||
<div class="sci--navigation--top-menu-search left-icon sci-input-container-v2" :class="{'disabled' : !currentTeam}" :title="i18n.t('nav.search')">
|
||||
<input ref="searchField" type="text" class="!pr-20" v-model="searchQuery" :placeholder="i18n.t('nav.search')" @keyup.enter="saveQuery"/>
|
||||
<input ref="searchField" type="text" class="!pr-20" v-model="searchQuery" @keydown="focusHistoryItem"
|
||||
@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 = ''">
|
||||
<i class="sn-icon sn-icon-close m-0"></i>
|
||||
</div>
|
||||
<div class="btn btn-light icon-btn btn-xs" :class="{'active': filtersOpened}" @click="filtersOpened = !filtersOpened">
|
||||
<div class="btn btn-light icon-btn btn-xs" :title="i18n.t('search.quick_search.search_options')"
|
||||
:class="{'active': filtersOpened}" @click="filtersOpened = !filtersOpened">
|
||||
<i class="sn-icon sn-icon-search-options m-0"></i>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -27,6 +29,10 @@
|
|||
></SearchFilters>
|
||||
<div v-else-if="showHistory" class="max-w-[600px]">
|
||||
<div v-for="(query, i) in reversedPreviousQueries" @click="setQuery(query)" :key="i"
|
||||
ref="historyItems"
|
||||
tabindex="1"
|
||||
@keydown="focusHistoryItem"
|
||||
@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 }}
|
||||
|
@ -62,7 +68,7 @@
|
|||
text-sn-black hover:no-underline active:no-underline hover:text-black block"
|
||||
>
|
||||
<div class="flex items-center gap-2">
|
||||
<i class="sn-icon shrink-0" :class="getIcon(result.type)"></i>
|
||||
<i class="sn-icon shrink-0" :class="getIcon(result.type)" :title="getTitle(result.type)"></i>
|
||||
<span v-if="result.attributes.archived">(A)</span>
|
||||
<StringWithEllipsis class="grow max-w-[400px]" :text="getName(result.attributes)"></StringWithEllipsis>
|
||||
<div class="ml-auto pl-4 text-sn-grey text-xs shrink-0">
|
||||
|
@ -80,9 +86,9 @@
|
|||
</a>
|
||||
<div v-else v-for="i in Array(5).fill(5)" class="px-3 py-2">
|
||||
<div class="flex items-center gap-2 mb-2">
|
||||
<div class="h-6 w-6 bg-sn-light-grey rounded shrink-0"></div>
|
||||
<div class="h-6 grow max-w-[200px] bg-sn-light-grey rounded shrink-0"></div>
|
||||
<div class="h-6 w-12 bg-sn-light-grey rounded shrink-0 ml-auto"></div>
|
||||
<div class="h-5 w-5 bg-sn-light-grey rounded shrink-0"></div>
|
||||
<div class="h-5 grow max-w-[200px] bg-sn-light-grey rounded shrink-0"></div>
|
||||
<div class="h-5 w-12 bg-sn-light-grey rounded shrink-0 ml-auto"></div>
|
||||
</div>
|
||||
<div class="flex items-center gap-2 pl-8">
|
||||
<div class="h-3 grow max-w-[200px] bg-sn-light-grey rounded shrink-0"></div>
|
||||
|
@ -153,7 +159,7 @@ export default {
|
|||
},
|
||||
watch: {
|
||||
searchQuery() {
|
||||
this.$refs.container.isOpen = this.canOpen;
|
||||
this.openHistory();
|
||||
|
||||
if (this.searchQuery.length > 1) {
|
||||
this.fetchQuickSearchResults();
|
||||
|
@ -167,13 +173,17 @@ export default {
|
|||
quickFilter: null,
|
||||
results: [],
|
||||
loading: false,
|
||||
filtersOpened: false
|
||||
filtersOpened: false,
|
||||
focusedHistoryItem: null
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.previousQueries = JSON.parse(localStorage.getItem('quickSearchHistory') || '[]');
|
||||
},
|
||||
methods: {
|
||||
openHistory() {
|
||||
this.$refs.container.isOpen = this.canOpen;
|
||||
},
|
||||
getIcon(type) {
|
||||
switch (type) {
|
||||
case 'projects':
|
||||
|
@ -194,8 +204,38 @@ export default {
|
|||
return 'sn-icon-reports';
|
||||
case 'steps':
|
||||
return 'sn-icon-steps';
|
||||
case 'label-templates':
|
||||
case 'zebra_label_templates':
|
||||
return 'sn-icon-label-templates';
|
||||
case 'fluics_label_templates':
|
||||
return 'sn-icon-label-templates';
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
},
|
||||
getTitle(type) {
|
||||
switch (type) {
|
||||
case 'projects':
|
||||
return this.i18n.t('search.quick_search.project');
|
||||
case 'experiments':
|
||||
return this.i18n.t('search.quick_search.experiment');
|
||||
case 'my_modules':
|
||||
return this.i18n.t('search.quick_search.task');
|
||||
case 'project_folders':
|
||||
return this.i18n.t('search.quick_search.folder');
|
||||
case 'protocols':
|
||||
return this.i18n.t('search.quick_search.protocol');
|
||||
case 'results':
|
||||
return this.i18n.t('search.quick_search.result');
|
||||
case 'repository_rows':
|
||||
return this.i18n.t('search.quick_search.inventory_item');
|
||||
case 'reports':
|
||||
return this.i18n.t('search.quick_search.report');
|
||||
case 'steps':
|
||||
return this.i18n.t('search.quick_search.step');
|
||||
case 'zebra_label_templates':
|
||||
return this.i18n.t('search.quick_search.label_template');
|
||||
case 'fluics_label_templates':
|
||||
return this.i18n.t('search.quick_search.label_template');
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
@ -263,6 +303,26 @@ export default {
|
|||
},
|
||||
searchValue() {
|
||||
window.open(`${this.searchUrl}?q=${this.searchQuery}`, '_self');
|
||||
},
|
||||
focusHistoryItem(event) {
|
||||
if (this.focusedHistoryItem === null && (event.key === 'ArrowDown' || event.key === 'ArrowUp')) {
|
||||
this.focusedHistoryItem = 0;
|
||||
this.$refs.historyItems[this.focusedHistoryItem].focus();
|
||||
} else if (event.key === 'ArrowDown') {
|
||||
event.preventDefault();
|
||||
this.focusedHistoryItem += 1;
|
||||
if (this.focusedHistoryItem >= this.$refs.historyItems.length) {
|
||||
this.focusedHistoryItem = 0;
|
||||
}
|
||||
this.$refs.historyItems[this.focusedHistoryItem].focus();
|
||||
} else if (event.key === 'ArrowUp') {
|
||||
event.preventDefault();
|
||||
this.focusedHistoryItem -= 1;
|
||||
if (this.focusedHistoryItem < 0) {
|
||||
this.focusedHistoryItem = this.$refs.historyItems.length - 1;
|
||||
}
|
||||
this.$refs.historyItems[this.focusedHistoryItem].focus();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -13,7 +13,7 @@ class QuickSearchSerializer < ActiveModel::Serializer
|
|||
end
|
||||
|
||||
def code
|
||||
@object.code unless @object.is_a?(ProjectFolder) || object.is_a?(Result) || object.is_a?(LabelTemplate)
|
||||
@object.respond_to?(:code) ? @object.code : @object.id
|
||||
end
|
||||
|
||||
def updated_at
|
||||
|
|
|
@ -434,13 +434,24 @@ en:
|
|||
all_results: "All search results for \"%{query}\""
|
||||
empty_title: "No quick search results found."
|
||||
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"
|
||||
experiment: "Experiment"
|
||||
task: "Task"
|
||||
result: "Result"
|
||||
inventory_item: "Inventory item"
|
||||
protocol: "Protocol"
|
||||
label_template: "Label template"
|
||||
report: "Report"
|
||||
step: "Step"
|
||||
result: "Result"
|
||||
whole_word: "Match any whole word"
|
||||
whole_phrase: "Match whole phrase"
|
||||
match_case: "Match case sensitive"
|
||||
object_id: "ID:"
|
||||
filters:
|
||||
title: "More search options"
|
||||
sub_filters: "Refine your search by applying the filters below."
|
||||
sub_title: "Refine your search by applying the filters below."
|
||||
by_type: "Filter by type"
|
||||
by_created_date: "Filter by created date"
|
||||
by_updated_date: "Filter by updated date"
|
||||
|
|
Loading…
Reference in a new issue