mirror of
https://github.com/hay-kot/mealie.git
synced 2025-08-22 14:33:33 -07:00
debounce search
This commit is contained in:
parent
b9b0a67409
commit
2f59c72400
5 changed files with 82 additions and 40 deletions
|
@ -5,22 +5,19 @@
|
|||
:width="modalWidth + 'px'"
|
||||
:content-class="top ? 'top-dialog' : undefined"
|
||||
>
|
||||
<v-card class="pb-10" :loading="loading" height="100%">
|
||||
<v-card class="pb-10" height="100%">
|
||||
<v-app-bar dark :color="color" class="mt-n1 mb-2">
|
||||
<v-icon large left v-if="!loading">
|
||||
<v-icon large left>
|
||||
{{ titleIcon }}
|
||||
</v-icon>
|
||||
<v-progress-circular
|
||||
v-else
|
||||
indeterminate
|
||||
color="white"
|
||||
large
|
||||
class="mr-2"
|
||||
>
|
||||
</v-progress-circular>
|
||||
<v-toolbar-title class="headline"> {{ title }} </v-toolbar-title>
|
||||
<v-spacer></v-spacer>
|
||||
</v-app-bar>
|
||||
<v-progress-linear
|
||||
v-if="loading"
|
||||
indeterminate
|
||||
color="primary"
|
||||
></v-progress-linear>
|
||||
<slot> </slot>
|
||||
<v-card-actions>
|
||||
<slot name="card-actions">
|
||||
|
@ -33,6 +30,7 @@
|
|||
</v-btn>
|
||||
</slot>
|
||||
</v-card-actions>
|
||||
|
||||
<slot name="below-actions"> </slot>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
|
|
|
@ -221,7 +221,13 @@
|
|||
},
|
||||
"toolbox": {
|
||||
"toolbox": "Toolbox",
|
||||
"new-name": "New Name"
|
||||
"new-name": "New Name",
|
||||
"recipes-effected": "Recipes Effected",
|
||||
"title-case-all": "Title Case All",
|
||||
"no-unused-items": "No Unused Items",
|
||||
"remove-unused": "Remove Unused",
|
||||
"assign-all": "Assign All",
|
||||
"bulk-assign": "Bulk Assign"
|
||||
}
|
||||
},
|
||||
"user": {
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
</v-card-text>
|
||||
<template slot="card-actions">
|
||||
<v-btn text color="grey" @click="closeDialog">
|
||||
Cancel
|
||||
{{ $t("general.cancel") }}
|
||||
</v-btn>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn
|
||||
|
@ -37,7 +37,7 @@
|
|||
:loading="loading"
|
||||
:disabled="results.length < 1"
|
||||
>
|
||||
Assign All
|
||||
{{ $t("settings.toolbox.assign-all") }}
|
||||
</v-btn>
|
||||
</template>
|
||||
<template slot="below-actions">
|
||||
|
@ -53,7 +53,7 @@
|
|||
</base-dialog>
|
||||
|
||||
<v-btn @click="openDialog" small color="success" class="mr-1">
|
||||
Bulk Assign
|
||||
{{ $t("settings.toolbox.bulk-assign") }}
|
||||
</v-btn>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -76,6 +76,7 @@ export default {
|
|||
},
|
||||
data() {
|
||||
return {
|
||||
results: [],
|
||||
search: "",
|
||||
loading: false,
|
||||
assignTargetRecipes: [],
|
||||
|
@ -86,20 +87,25 @@ export default {
|
|||
mounted() {
|
||||
this.$store.dispatch("requestAllRecipes");
|
||||
},
|
||||
watch: {
|
||||
search() {
|
||||
this.getResults();
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
allRecipes() {
|
||||
return this.$store.getters.getRecentRecipes;
|
||||
},
|
||||
results() {
|
||||
if (this.search === null || this.search === "") {
|
||||
return [];
|
||||
}
|
||||
return this.allRecipes.filter(x => {
|
||||
return (
|
||||
this.checkForKeywords(x.name) || this.checkForKeywords(x.description)
|
||||
);
|
||||
});
|
||||
},
|
||||
// results() {
|
||||
// if (this.search === null || this.search === "") {
|
||||
// return [];
|
||||
// }
|
||||
// return this.allRecipes.filter(x => {
|
||||
// return (
|
||||
// this.checkForKeywords(x.name) || this.checkForKeywords(x.description)
|
||||
// );
|
||||
// });
|
||||
// },
|
||||
keywords() {
|
||||
const lowered = this.search.toLowerCase();
|
||||
return lowered.split(" ");
|
||||
|
@ -123,6 +129,7 @@ export default {
|
|||
await api.recipes.patch(element);
|
||||
});
|
||||
this.loading = false;
|
||||
this.closeDialog();
|
||||
},
|
||||
closeDialog() {
|
||||
this.$refs.assignDialog.close();
|
||||
|
@ -131,6 +138,27 @@ export default {
|
|||
this.$refs.assignDialog.open();
|
||||
this.reset();
|
||||
},
|
||||
getResults() {
|
||||
this.loading = true;
|
||||
|
||||
// cancel pending call
|
||||
clearTimeout(this._timerId);
|
||||
this._timerId = setTimeout(() => {
|
||||
this.results = this.filterResults();
|
||||
}, 300);
|
||||
this.loading = false;
|
||||
// delay new call 500ms
|
||||
},
|
||||
filterResults() {
|
||||
if (this.search === null || this.search === "") {
|
||||
return [];
|
||||
}
|
||||
return this.allRecipes.filter(x => {
|
||||
return (
|
||||
this.checkForKeywords(x.name) || this.checkForKeywords(x.description)
|
||||
);
|
||||
});
|
||||
},
|
||||
checkForKeywords(str) {
|
||||
const searchStr = str.toLowerCase();
|
||||
return this.keywords.some(x => searchStr.includes(x));
|
||||
|
|
|
@ -4,7 +4,11 @@
|
|||
ref="deleteDialog"
|
||||
title-icon="mdi-tag"
|
||||
color="error"
|
||||
:title="title"
|
||||
:title="
|
||||
$t('general.delete') +
|
||||
' ' +
|
||||
(isTags ? $t('recipe.tags') : $t('recipe.categories'))
|
||||
"
|
||||
:loading="loading"
|
||||
modal-width="400"
|
||||
>
|
||||
|
@ -16,11 +20,11 @@
|
|||
</v-list-item>
|
||||
</v-list>
|
||||
<v-card-text v-else class=" mt-4 text-center">
|
||||
No Unused Items
|
||||
{{ $t("settings.toolbox.no-unused-items") }}
|
||||
</v-card-text>
|
||||
<template slot="card-actions">
|
||||
<v-btn text color="grey" @click="closeDialog">
|
||||
Cancel
|
||||
{{ $t("general.cancel") }}
|
||||
</v-btn>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn
|
||||
|
@ -29,13 +33,13 @@
|
|||
:loading="loading"
|
||||
:disabled="deleteList.length < 1"
|
||||
>
|
||||
Delete
|
||||
{{ $t("general.delete") }}
|
||||
</v-btn>
|
||||
</template>
|
||||
</base-dialog>
|
||||
|
||||
<v-btn @click="openDialog" small color="error" class="mr-1">
|
||||
Remove Unused
|
||||
{{ $t("settings.toolbox.remove-unused") }}
|
||||
</v-btn>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -58,11 +62,6 @@ export default {
|
|||
loading: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
title() {
|
||||
return this.isTags ? "Delete Tags" : "Delete Categories";
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
closeDialog() {
|
||||
this.$refs.deleteDialog.close();
|
||||
|
|
|
@ -18,7 +18,8 @@
|
|||
</v-form>
|
||||
<template slot="below-actions">
|
||||
<v-card-title class="headline">
|
||||
{{ renameTarget.recipes.length || 0 }} Recipes Effected
|
||||
{{ renameTarget.recipes.length || 0 }}
|
||||
{{ $t("settings.toolbox.recipes-effected") }}
|
||||
</v-card-title>
|
||||
<MobileRecipeCard
|
||||
class="ml-2 mr-2 mt-2 mb-2"
|
||||
|
@ -41,12 +42,18 @@
|
|||
class="mr-1"
|
||||
>
|
||||
<v-btn @click="openNewDialog" small color="success">
|
||||
New
|
||||
{{ $t("general.create") }}
|
||||
</v-btn>
|
||||
</new-category-tag-dialog>
|
||||
<BulkAssign isTags="isTags" />
|
||||
<v-btn @click="titleCaseAll" class="mr-1" small color="success">
|
||||
Title Case All
|
||||
<v-btn
|
||||
@click="titleCaseAll"
|
||||
class="mr-1"
|
||||
small
|
||||
color="success"
|
||||
:loading="loadingTitleCase"
|
||||
>
|
||||
{{ $t("settings.toolbox.title-case-all") }}
|
||||
</v-btn>
|
||||
<RemoveUnused :isTags="isTags" />
|
||||
<v-spacer> </v-spacer>
|
||||
|
@ -125,6 +132,7 @@ export default {
|
|||
},
|
||||
data() {
|
||||
return {
|
||||
loadingTitleCase: false,
|
||||
searchString: "",
|
||||
searchResults: [],
|
||||
renameTarget: {
|
||||
|
@ -181,10 +189,11 @@ export default {
|
|||
await api.categories.delete(name);
|
||||
}
|
||||
},
|
||||
renameFromDialog(name, newName) {
|
||||
async renameFromDialog(name, newName) {
|
||||
if (this.$refs.renameForm.validate()) {
|
||||
this.rename(name, newName);
|
||||
await this.rename(name, newName);
|
||||
}
|
||||
this.$refs.renameDialog.close();
|
||||
},
|
||||
async rename(name, newName) {
|
||||
if (this.isTags) {
|
||||
|
@ -197,6 +206,7 @@ export default {
|
|||
return lowerName.replace(/(?:^|\s|-)\S/g, x => x.toUpperCase());
|
||||
},
|
||||
async titleCaseAll() {
|
||||
this.loadingTitleCase = true;
|
||||
const renameList = this.allItems.map(x => ({
|
||||
slug: x.slug,
|
||||
name: x.name,
|
||||
|
@ -216,6 +226,7 @@ export default {
|
|||
});
|
||||
this.$store.dispatch("requestCategories");
|
||||
}
|
||||
this.loadingTitleCase = false;
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue