mirror of
https://github.com/hay-kot/mealie.git
synced 2025-08-22 14:33:33 -07:00
improved search bar
This commit is contained in:
parent
757b5f8335
commit
ff6959dcb2
2 changed files with 71 additions and 41 deletions
|
@ -1,31 +1,37 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<v-menu v-model="menuModel" offset-y readonly max-width="450">
|
||||||
<v-autocomplete
|
<template #activator="{ attrs }">
|
||||||
:items="autoResults"
|
<v-text-field
|
||||||
v-model="searchSlug"
|
class="mt-6"
|
||||||
item-value="item.slug"
|
v-model="search"
|
||||||
item-text="item.name"
|
v-bind="attrs"
|
||||||
dense
|
dense
|
||||||
light
|
light
|
||||||
:label="$t('search.search-mealie')"
|
:label="$t('search.search-mealie')"
|
||||||
:search-input.sync="search"
|
solo
|
||||||
hide-no-data
|
autofocus
|
||||||
cache-items
|
style="max-width: 450px;"
|
||||||
solo
|
@focus="onFocus"
|
||||||
autofocus
|
|
||||||
auto-select-first
|
|
||||||
>
|
|
||||||
<template
|
|
||||||
v-if="showResults"
|
|
||||||
v-slot:item="{ item }"
|
|
||||||
style="max-width: 750px"
|
|
||||||
>
|
>
|
||||||
<v-list-item-avatar>
|
</v-text-field>
|
||||||
<v-img :src="getImage(item.item.image)"></v-img>
|
</template>
|
||||||
</v-list-item-avatar>
|
<v-card v-if="showResults" max-height="500" min-width="98%" class="">
|
||||||
<v-list-item-content @click="selected(item.item.slug)">
|
<v-card-text class="py-1">Results</v-card-text>
|
||||||
<v-list-item-title>
|
<v-divider></v-divider>
|
||||||
{{ item.item.name }}
|
<v-list scrollable>
|
||||||
|
<v-list-item
|
||||||
|
v-for="(item, index) in autoResults"
|
||||||
|
:key="index"
|
||||||
|
:to="showResults ? `/recipe/${item.item.slug}` : null"
|
||||||
|
>
|
||||||
|
<v-list-item-avatar>
|
||||||
|
<v-img :src="getImage(item.item.image)"></v-img>
|
||||||
|
</v-list-item-avatar>
|
||||||
|
<v-list-item-content
|
||||||
|
@click="showResults ? null : selected(item.item.slug)"
|
||||||
|
>
|
||||||
|
<v-list-item-title v-html="highlight(item.item.name)">
|
||||||
|
</v-list-item-title>
|
||||||
<v-rating
|
<v-rating
|
||||||
dense
|
dense
|
||||||
v-if="item.item.rating"
|
v-if="item.item.rating"
|
||||||
|
@ -33,14 +39,13 @@
|
||||||
size="12"
|
size="12"
|
||||||
>
|
>
|
||||||
</v-rating>
|
</v-rating>
|
||||||
</v-list-item-title>
|
<v-list-item-subtitle v-html="highlight(item.item.description)">
|
||||||
<v-list-item-subtitle>
|
</v-list-item-subtitle>
|
||||||
{{ item.item.description }}
|
</v-list-item-content>
|
||||||
</v-list-item-subtitle>
|
</v-list-item>
|
||||||
</v-list-item-content>
|
</v-list>
|
||||||
</template>
|
</v-card>
|
||||||
</v-autocomplete>
|
</v-menu>
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
@ -56,7 +61,8 @@ export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
searchSlug: "",
|
searchSlug: "",
|
||||||
search: " ",
|
search: "",
|
||||||
|
menuModel: false,
|
||||||
data: [],
|
data: [],
|
||||||
result: [],
|
result: [],
|
||||||
autoResults: [],
|
autoResults: [],
|
||||||
|
@ -66,9 +72,10 @@ export default {
|
||||||
threshold: 0.6,
|
threshold: 0.6,
|
||||||
location: 0,
|
location: 0,
|
||||||
distance: 100,
|
distance: 100,
|
||||||
|
findAllMatches: true,
|
||||||
maxPatternLength: 32,
|
maxPatternLength: 32,
|
||||||
minMatchCharLength: 1,
|
minMatchCharLength: 2,
|
||||||
keys: ["name", "slug", "description"],
|
keys: ["name", "description"],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
@ -80,8 +87,15 @@ export default {
|
||||||
fuse() {
|
fuse() {
|
||||||
return new Fuse(this.data, this.options);
|
return new Fuse(this.data, this.options);
|
||||||
},
|
},
|
||||||
|
isSearching() {
|
||||||
|
return this.search && this.search.length > 0;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
|
isSearching(val) {
|
||||||
|
val ? (this.menuModel = true) : null;
|
||||||
|
},
|
||||||
|
|
||||||
search() {
|
search() {
|
||||||
try {
|
try {
|
||||||
this.result = this.fuse.search(this.search.trim());
|
this.result = this.fuse.search(this.search.trim());
|
||||||
|
@ -101,18 +115,34 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
highlight(string) {
|
||||||
|
if (!this.search) {
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
return string.replace(
|
||||||
|
new RegExp(this.search, "gi"),
|
||||||
|
match => `<mark>${match}</mark>`
|
||||||
|
);
|
||||||
|
},
|
||||||
getImage(image) {
|
getImage(image) {
|
||||||
return utils.getImageURL(image);
|
return utils.getImageURL(image);
|
||||||
},
|
},
|
||||||
selected(slug) {
|
selected(slug) {
|
||||||
this.$emit("selected", slug);
|
this.$emit("selected", slug);
|
||||||
},
|
},
|
||||||
|
async onFocus() {
|
||||||
|
clearTimeout(this.timeout);
|
||||||
|
this.isFocused = true;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style scoped>
|
||||||
.color-transition {
|
.color-transition {
|
||||||
transition: background-color 0.3s ease;
|
transition: background-color 0.3s ease;
|
||||||
}
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style lang="sass" scoped>
|
||||||
</style>
|
</style>
|
|
@ -87,9 +87,6 @@ export default {
|
||||||
},
|
},
|
||||||
mounted() {},
|
mounted() {},
|
||||||
computed: {
|
computed: {
|
||||||
loggedIn() {
|
|
||||||
return this.$store.getters.getIsLoggedIn;
|
|
||||||
},
|
|
||||||
filteredItems() {
|
filteredItems() {
|
||||||
if (this.loggedIn) {
|
if (this.loggedIn) {
|
||||||
return this.items.filter(x => x.restricted == true);
|
return this.items.filter(x => x.restricted == true);
|
||||||
|
@ -97,6 +94,9 @@ export default {
|
||||||
return this.items.filter(x => x.restricted == false);
|
return this.items.filter(x => x.restricted == false);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
loggedIn() {
|
||||||
|
return this.$store.getters.getIsLoggedIn;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue