debounce search

This commit is contained in:
hay-kot 2021-04-26 16:56:43 -08:00
commit 2f59c72400
5 changed files with 82 additions and 40 deletions

View file

@ -5,22 +5,19 @@
:width="modalWidth + 'px'" :width="modalWidth + 'px'"
:content-class="top ? 'top-dialog' : undefined" :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-app-bar dark :color="color" class="mt-n1 mb-2">
<v-icon large left v-if="!loading"> <v-icon large left>
{{ titleIcon }} {{ titleIcon }}
</v-icon> </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-toolbar-title class="headline"> {{ title }} </v-toolbar-title>
<v-spacer></v-spacer> <v-spacer></v-spacer>
</v-app-bar> </v-app-bar>
<v-progress-linear
v-if="loading"
indeterminate
color="primary"
></v-progress-linear>
<slot> </slot> <slot> </slot>
<v-card-actions> <v-card-actions>
<slot name="card-actions"> <slot name="card-actions">
@ -33,6 +30,7 @@
</v-btn> </v-btn>
</slot> </slot>
</v-card-actions> </v-card-actions>
<slot name="below-actions"> </slot> <slot name="below-actions"> </slot>
</v-card> </v-card>
</v-dialog> </v-dialog>

View file

@ -221,7 +221,13 @@
}, },
"toolbox": { "toolbox": {
"toolbox": "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": { "user": {

View file

@ -28,7 +28,7 @@
</v-card-text> </v-card-text>
<template slot="card-actions"> <template slot="card-actions">
<v-btn text color="grey" @click="closeDialog"> <v-btn text color="grey" @click="closeDialog">
Cancel {{ $t("general.cancel") }}
</v-btn> </v-btn>
<v-spacer></v-spacer> <v-spacer></v-spacer>
<v-btn <v-btn
@ -37,7 +37,7 @@
:loading="loading" :loading="loading"
:disabled="results.length < 1" :disabled="results.length < 1"
> >
Assign All {{ $t("settings.toolbox.assign-all") }}
</v-btn> </v-btn>
</template> </template>
<template slot="below-actions"> <template slot="below-actions">
@ -53,7 +53,7 @@
</base-dialog> </base-dialog>
<v-btn @click="openDialog" small color="success" class="mr-1"> <v-btn @click="openDialog" small color="success" class="mr-1">
Bulk Assign {{ $t("settings.toolbox.bulk-assign") }}
</v-btn> </v-btn>
</div> </div>
</template> </template>
@ -76,6 +76,7 @@ export default {
}, },
data() { data() {
return { return {
results: [],
search: "", search: "",
loading: false, loading: false,
assignTargetRecipes: [], assignTargetRecipes: [],
@ -86,20 +87,25 @@ export default {
mounted() { mounted() {
this.$store.dispatch("requestAllRecipes"); this.$store.dispatch("requestAllRecipes");
}, },
watch: {
search() {
this.getResults();
},
},
computed: { computed: {
allRecipes() { allRecipes() {
return this.$store.getters.getRecentRecipes; return this.$store.getters.getRecentRecipes;
}, },
results() { // results() {
if (this.search === null || this.search === "") { // if (this.search === null || this.search === "") {
return []; // return [];
} // }
return this.allRecipes.filter(x => { // return this.allRecipes.filter(x => {
return ( // return (
this.checkForKeywords(x.name) || this.checkForKeywords(x.description) // this.checkForKeywords(x.name) || this.checkForKeywords(x.description)
); // );
}); // });
}, // },
keywords() { keywords() {
const lowered = this.search.toLowerCase(); const lowered = this.search.toLowerCase();
return lowered.split(" "); return lowered.split(" ");
@ -123,6 +129,7 @@ export default {
await api.recipes.patch(element); await api.recipes.patch(element);
}); });
this.loading = false; this.loading = false;
this.closeDialog();
}, },
closeDialog() { closeDialog() {
this.$refs.assignDialog.close(); this.$refs.assignDialog.close();
@ -131,6 +138,27 @@ export default {
this.$refs.assignDialog.open(); this.$refs.assignDialog.open();
this.reset(); 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) { checkForKeywords(str) {
const searchStr = str.toLowerCase(); const searchStr = str.toLowerCase();
return this.keywords.some(x => searchStr.includes(x)); return this.keywords.some(x => searchStr.includes(x));

View file

@ -4,7 +4,11 @@
ref="deleteDialog" ref="deleteDialog"
title-icon="mdi-tag" title-icon="mdi-tag"
color="error" color="error"
:title="title" :title="
$t('general.delete') +
' ' +
(isTags ? $t('recipe.tags') : $t('recipe.categories'))
"
:loading="loading" :loading="loading"
modal-width="400" modal-width="400"
> >
@ -16,11 +20,11 @@
</v-list-item> </v-list-item>
</v-list> </v-list>
<v-card-text v-else class=" mt-4 text-center"> <v-card-text v-else class=" mt-4 text-center">
No Unused Items {{ $t("settings.toolbox.no-unused-items") }}
</v-card-text> </v-card-text>
<template slot="card-actions"> <template slot="card-actions">
<v-btn text color="grey" @click="closeDialog"> <v-btn text color="grey" @click="closeDialog">
Cancel {{ $t("general.cancel") }}
</v-btn> </v-btn>
<v-spacer></v-spacer> <v-spacer></v-spacer>
<v-btn <v-btn
@ -29,13 +33,13 @@
:loading="loading" :loading="loading"
:disabled="deleteList.length < 1" :disabled="deleteList.length < 1"
> >
Delete {{ $t("general.delete") }}
</v-btn> </v-btn>
</template> </template>
</base-dialog> </base-dialog>
<v-btn @click="openDialog" small color="error" class="mr-1"> <v-btn @click="openDialog" small color="error" class="mr-1">
Remove Unused {{ $t("settings.toolbox.remove-unused") }}
</v-btn> </v-btn>
</div> </div>
</template> </template>
@ -58,11 +62,6 @@ export default {
loading: false, loading: false,
}; };
}, },
computed: {
title() {
return this.isTags ? "Delete Tags" : "Delete Categories";
},
},
methods: { methods: {
closeDialog() { closeDialog() {
this.$refs.deleteDialog.close(); this.$refs.deleteDialog.close();

View file

@ -18,7 +18,8 @@
</v-form> </v-form>
<template slot="below-actions"> <template slot="below-actions">
<v-card-title class="headline"> <v-card-title class="headline">
{{ renameTarget.recipes.length || 0 }} Recipes Effected {{ renameTarget.recipes.length || 0 }}
{{ $t("settings.toolbox.recipes-effected") }}
</v-card-title> </v-card-title>
<MobileRecipeCard <MobileRecipeCard
class="ml-2 mr-2 mt-2 mb-2" class="ml-2 mr-2 mt-2 mb-2"
@ -41,12 +42,18 @@
class="mr-1" class="mr-1"
> >
<v-btn @click="openNewDialog" small color="success"> <v-btn @click="openNewDialog" small color="success">
New {{ $t("general.create") }}
</v-btn> </v-btn>
</new-category-tag-dialog> </new-category-tag-dialog>
<BulkAssign isTags="isTags" /> <BulkAssign isTags="isTags" />
<v-btn @click="titleCaseAll" class="mr-1" small color="success"> <v-btn
Title Case All @click="titleCaseAll"
class="mr-1"
small
color="success"
:loading="loadingTitleCase"
>
{{ $t("settings.toolbox.title-case-all") }}
</v-btn> </v-btn>
<RemoveUnused :isTags="isTags" /> <RemoveUnused :isTags="isTags" />
<v-spacer> </v-spacer> <v-spacer> </v-spacer>
@ -125,6 +132,7 @@ export default {
}, },
data() { data() {
return { return {
loadingTitleCase: false,
searchString: "", searchString: "",
searchResults: [], searchResults: [],
renameTarget: { renameTarget: {
@ -181,10 +189,11 @@ export default {
await api.categories.delete(name); await api.categories.delete(name);
} }
}, },
renameFromDialog(name, newName) { async renameFromDialog(name, newName) {
if (this.$refs.renameForm.validate()) { if (this.$refs.renameForm.validate()) {
this.rename(name, newName); await this.rename(name, newName);
} }
this.$refs.renameDialog.close();
}, },
async rename(name, newName) { async rename(name, newName) {
if (this.isTags) { if (this.isTags) {
@ -197,6 +206,7 @@ export default {
return lowerName.replace(/(?:^|\s|-)\S/g, x => x.toUpperCase()); return lowerName.replace(/(?:^|\s|-)\S/g, x => x.toUpperCase());
}, },
async titleCaseAll() { async titleCaseAll() {
this.loadingTitleCase = true;
const renameList = this.allItems.map(x => ({ const renameList = this.allItems.map(x => ({
slug: x.slug, slug: x.slug,
name: x.name, name: x.name,
@ -216,6 +226,7 @@ export default {
}); });
this.$store.dispatch("requestCategories"); this.$store.dispatch("requestCategories");
} }
this.loadingTitleCase = false;
}, },
}, },
}; };